1# WPS tests
2# Copyright (c) 2013-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
7from remotehost import remote_compatible
8from tshark import run_tshark
9import base64
10import binascii
11try:
12    from Cryptodome.Cipher import AES
13except ImportError:
14    from Crypto.Cipher import AES
15import hashlib
16import hmac
17import os
18import time
19import sys
20import stat
21import subprocess
22import logging
23logger = logging.getLogger()
24import re
25import socket
26import struct
27try:
28    from http.client import HTTPConnection
29    from urllib.request import urlopen
30    from urllib.parse import urlparse, urljoin
31    from urllib.error import HTTPError
32    from io import StringIO
33    from socketserver import StreamRequestHandler, TCPServer
34except ImportError:
35    from httplib import HTTPConnection
36    from urllib import urlopen
37    from urlparse import urlparse, urljoin
38    from urllib2 import build_opener, ProxyHandler, HTTPError
39    from StringIO import StringIO
40    from SocketServer import StreamRequestHandler, TCPServer
41import urllib
42import xml.etree.ElementTree as ET
43
44import hwsim_utils
45import hostapd
46from wpasupplicant import WpaSupplicant
47from utils import *
48from test_ap_eap import int_eap_server_params
49
50def wps_start_ap(apdev, ssid="test-wps-conf", extra_cred=None):
51    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
52              "wpa_passphrase": "12345678", "wpa": "2",
53              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
54    if extra_cred:
55        params['extra_cred'] = extra_cred
56    return hostapd.add_ap(apdev, params)
57
58@remote_compatible
59def test_ap_wps_init(dev, apdev):
60    """Initial AP configuration with first WPS Enrollee"""
61    skip_without_tkip(dev[0])
62    ssid = "test-wps"
63    hapd = hostapd.add_ap(apdev[0],
64                          {"ssid": ssid, "eap_server": "1", "wps_state": "1"})
65    logger.info("WPS provisioning step")
66    hapd.request("WPS_PBC")
67    if "PBC Status: Active" not in hapd.request("WPS_GET_STATUS"):
68        raise Exception("PBC status not shown correctly")
69
70    id = dev[0].add_network()
71    dev[0].set_network_quoted(id, "ssid", "home")
72    dev[0].set_network_quoted(id, "psk", "12345678")
73    dev[0].request("ENABLE_NETWORK %s no-connect" % id)
74
75    id = dev[0].add_network()
76    dev[0].set_network_quoted(id, "ssid", "home2")
77    dev[0].set_network(id, "bssid", "00:11:22:33:44:55")
78    dev[0].set_network(id, "key_mgmt", "NONE")
79    dev[0].request("ENABLE_NETWORK %s no-connect" % id)
80
81    dev[0].request("WPS_PBC")
82    dev[0].wait_connected(timeout=30)
83    status = dev[0].get_status()
84    if status['wpa_state'] != 'COMPLETED' or status['bssid'] != apdev[0]['bssid']:
85        raise Exception("Not fully connected")
86    if status['ssid'] != ssid:
87        raise Exception("Unexpected SSID")
88    if status['pairwise_cipher'] != 'CCMP':
89        raise Exception("Unexpected encryption configuration")
90    if status['key_mgmt'] != 'WPA2-PSK':
91        raise Exception("Unexpected key_mgmt")
92
93    status = hapd.request("WPS_GET_STATUS")
94    if "PBC Status: Disabled" not in status:
95        raise Exception("PBC status not shown correctly")
96    if "Last WPS result: Success" not in status:
97        raise Exception("Last WPS result not shown correctly")
98    if "Peer Address: " + dev[0].p2p_interface_addr() not in status:
99        raise Exception("Peer address not shown correctly")
100    conf = hapd.request("GET_CONFIG")
101    if "wps_state=configured" not in conf:
102        raise Exception("AP not in WPS configured state")
103    if "wpa=2" in conf:
104        if "rsn_pairwise_cipher=CCMP" not in conf:
105            raise Exception("Unexpected rsn_pairwise_cipher")
106        if "group_cipher=CCMP" not in conf:
107            raise Exception("Unexpected group_cipher")
108    else:
109        if "wpa=3" not in conf:
110            raise Exception("AP not in WPA+WPA2 configuration")
111        if "rsn_pairwise_cipher=CCMP TKIP" not in conf:
112            raise Exception("Unexpected rsn_pairwise_cipher")
113        if "wpa_pairwise_cipher=CCMP TKIP" not in conf:
114            raise Exception("Unexpected wpa_pairwise_cipher")
115        if "group_cipher=TKIP" not in conf:
116            raise Exception("Unexpected group_cipher")
117
118    if len(dev[0].list_networks()) != 3:
119        raise Exception("Unexpected number of network blocks")
120
121def test_ap_wps_init_2ap_pbc(dev, apdev):
122    """Initial two-radio AP configuration with first WPS PBC Enrollee"""
123    skip_without_tkip(dev[0])
124    ssid = "test-wps"
125    params = {"ssid": ssid, "eap_server": "1", "wps_state": "1"}
126    hapd = hostapd.add_ap(apdev[0], params)
127    hostapd.add_ap(apdev[1], params)
128    logger.info("WPS provisioning step")
129    hapd.request("WPS_PBC")
130    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
131    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
132    bss = dev[0].get_bss(apdev[0]['bssid'])
133    if "[WPS-PBC]" not in bss['flags']:
134        raise Exception("WPS-PBC flag missing from AP1")
135    bss = dev[0].get_bss(apdev[1]['bssid'])
136    if "[WPS-PBC]" not in bss['flags']:
137        raise Exception("WPS-PBC flag missing from AP2")
138    dev[0].dump_monitor()
139    dev[0].request("SET wps_cred_processing 2")
140    dev[0].request("WPS_PBC")
141    ev = dev[0].wait_event(["WPS-CRED-RECEIVED"], timeout=30)
142    dev[0].request("SET wps_cred_processing 0")
143    if ev is None:
144        raise Exception("WPS cred event not seen")
145    if "100e" not in ev:
146        raise Exception("WPS attributes not included in the cred event")
147    dev[0].wait_connected(timeout=30)
148
149    dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
150    dev[1].scan_for_bss(apdev[1]['bssid'], freq="2412")
151    bss = dev[1].get_bss(apdev[0]['bssid'])
152    if "[WPS-PBC]" in bss['flags']:
153        raise Exception("WPS-PBC flag not cleared from AP1")
154    bss = dev[1].get_bss(apdev[1]['bssid'])
155    if "[WPS-PBC]" in bss['flags']:
156        raise Exception("WPS-PBC flag not cleared from AP2")
157
158def test_ap_wps_init_2ap_pin(dev, apdev):
159    """Initial two-radio AP configuration with first WPS PIN Enrollee"""
160    skip_without_tkip(dev[0])
161    ssid = "test-wps"
162    params = {"ssid": ssid, "eap_server": "1", "wps_state": "1"}
163    hapd = hostapd.add_ap(apdev[0], params)
164    hostapd.add_ap(apdev[1], params)
165    logger.info("WPS provisioning step")
166    pin = dev[0].wps_read_pin()
167    hapd.request("WPS_PIN any " + pin)
168    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
169    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
170    bss = dev[0].get_bss(apdev[0]['bssid'])
171    if "[WPS-AUTH]" not in bss['flags']:
172        raise Exception("WPS-AUTH flag missing from AP1")
173    bss = dev[0].get_bss(apdev[1]['bssid'])
174    if "[WPS-AUTH]" not in bss['flags']:
175        raise Exception("WPS-AUTH flag missing from AP2")
176    dev[0].dump_monitor()
177    dev[0].request("WPS_PIN any " + pin)
178    dev[0].wait_connected(timeout=30)
179
180    dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
181    dev[1].scan_for_bss(apdev[1]['bssid'], freq="2412")
182    bss = dev[1].get_bss(apdev[0]['bssid'])
183    if "[WPS-AUTH]" in bss['flags']:
184        raise Exception("WPS-AUTH flag not cleared from AP1")
185    bss = dev[1].get_bss(apdev[1]['bssid'])
186    if "[WPS-AUTH]" in bss['flags']:
187        raise Exception("WPS-AUTH flag not cleared from AP2")
188
189@remote_compatible
190def test_ap_wps_init_through_wps_config(dev, apdev):
191    """Initial AP configuration using wps_config command"""
192    ssid = "test-wps-init-config"
193    hapd = hostapd.add_ap(apdev[0],
194                          {"ssid": ssid, "eap_server": "1", "wps_state": "1"})
195    if "FAIL" in hapd.request("WPS_CONFIG " + binascii.hexlify(ssid.encode()).decode() + " WPA2PSK CCMP " + binascii.hexlify(b"12345678").decode()):
196        raise Exception("WPS_CONFIG command failed")
197    ev = hapd.wait_event(["WPS-NEW-AP-SETTINGS"], timeout=5)
198    if ev is None:
199        raise Exception("Timeout on WPS-NEW-AP-SETTINGS events")
200    # It takes some time for the AP to update Beacon and Probe Response frames,
201    # so wait here before requesting the scan to be started to avoid adding
202    # extra five second wait to the test due to fetching obsolete scan results.
203    hapd.ping()
204    time.sleep(0.2)
205    dev[0].connect(ssid, psk="12345678", scan_freq="2412", proto="WPA2",
206                   pairwise="CCMP", group="CCMP")
207
208    if "FAIL" not in hapd.request("WPS_CONFIG foo"):
209        raise Exception("Invalid WPS_CONFIG accepted")
210
211@remote_compatible
212def test_ap_wps_init_through_wps_config_2(dev, apdev):
213    """AP configuration using wps_config and wps_cred_processing=2"""
214    ssid = "test-wps-init-config"
215    hapd = hostapd.add_ap(apdev[0],
216                          {"ssid": ssid, "eap_server": "1", "wps_state": "1",
217                           "wps_cred_processing": "2"})
218    if "FAIL" in hapd.request("WPS_CONFIG " + binascii.hexlify(ssid.encode()).decode() + " WPA2PSK CCMP " + binascii.hexlify(b"12345678").decode()):
219        raise Exception("WPS_CONFIG command failed")
220    ev = hapd.wait_event(["WPS-NEW-AP-SETTINGS"], timeout=5)
221    if ev is None:
222        raise Exception("Timeout on WPS-NEW-AP-SETTINGS events")
223    if "100e" not in ev:
224        raise Exception("WPS-NEW-AP-SETTINGS did not include Credential")
225
226@remote_compatible
227def test_ap_wps_invalid_wps_config_passphrase(dev, apdev):
228    """AP configuration using wps_config command with invalid passphrase"""
229    ssid = "test-wps-init-config"
230    hapd = hostapd.add_ap(apdev[0],
231                          {"ssid": ssid, "eap_server": "1", "wps_state": "1"})
232    if "FAIL" not in hapd.request("WPS_CONFIG " + binascii.hexlify(ssid.encode()).decode() + " WPA2PSK CCMP " + binascii.hexlify(b"1234567").decode()):
233        raise Exception("Invalid WPS_CONFIG command accepted")
234
235def test_ap_wps_conf(dev, apdev):
236    """WPS PBC provisioning with configured AP"""
237    ssid = "test-wps-conf"
238    hapd = hostapd.add_ap(apdev[0],
239                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
240                           "wpa_passphrase": "12345678", "wpa": "2",
241                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
242    logger.info("WPS provisioning step")
243    hapd.request("WPS_PBC")
244    dev[0].set("device_name", "Device A")
245    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
246    dev[0].dump_monitor()
247    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
248    dev[0].wait_connected(timeout=30)
249    status = dev[0].get_status()
250    if status['wpa_state'] != 'COMPLETED':
251        raise Exception("Not fully connected")
252    if status['bssid'] != apdev[0]['bssid']:
253        raise Exception("Unexpected BSSID")
254    if status['ssid'] != ssid:
255        raise Exception("Unexpected SSID")
256    if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'CCMP':
257        raise Exception("Unexpected encryption configuration")
258    if status['key_mgmt'] != 'WPA2-PSK':
259        raise Exception("Unexpected key_mgmt")
260
261    sta = hapd.get_sta(dev[0].p2p_interface_addr())
262    if 'wpsDeviceName' not in sta or sta['wpsDeviceName'] != "Device A":
263        raise Exception("Device name not available in STA command")
264
265def test_ap_wps_conf_5ghz(dev, apdev):
266    """WPS PBC provisioning with configured AP on 5 GHz band"""
267    try:
268        hapd = None
269        ssid = "test-wps-conf"
270        params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
271                  "wpa_passphrase": "12345678", "wpa": "2",
272                  "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
273                  "country_code": "FI", "hw_mode": "a", "channel": "36"}
274        hapd = hostapd.add_ap(apdev[0], params)
275        logger.info("WPS provisioning step")
276        hapd.request("WPS_PBC")
277        dev[0].set("device_name", "Device A")
278        dev[0].scan_for_bss(apdev[0]['bssid'], freq="5180")
279        dev[0].request("WPS_PBC " + apdev[0]['bssid'])
280        dev[0].wait_connected(timeout=30)
281
282        sta = hapd.get_sta(dev[0].p2p_interface_addr())
283        if 'wpsDeviceName' not in sta or sta['wpsDeviceName'] != "Device A":
284            raise Exception("Device name not available in STA command")
285    finally:
286        dev[0].request("DISCONNECT")
287        clear_regdom(hapd, dev)
288
289def test_ap_wps_conf_chan14(dev, apdev):
290    """WPS PBC provisioning with configured AP on channel 14"""
291    try:
292        hapd = None
293        ssid = "test-wps-conf"
294        params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
295                  "wpa_passphrase": "12345678", "wpa": "2",
296                  "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
297                  "country_code": "JP", "hw_mode": "b", "channel": "14"}
298        hapd = hostapd.add_ap(apdev[0], params)
299        logger.info("WPS provisioning step")
300        hapd.request("WPS_PBC")
301        dev[0].set("device_name", "Device A")
302        dev[0].request("WPS_PBC")
303        dev[0].wait_connected(timeout=30)
304
305        sta = hapd.get_sta(dev[0].p2p_interface_addr())
306        if 'wpsDeviceName' not in sta or sta['wpsDeviceName'] != "Device A":
307            raise Exception("Device name not available in STA command")
308    finally:
309        dev[0].request("DISCONNECT")
310        clear_regdom(hapd, dev)
311
312@remote_compatible
313def test_ap_wps_twice(dev, apdev):
314    """WPS provisioning with twice to change passphrase"""
315    ssid = "test-wps-twice"
316    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
317              "wpa_passphrase": "12345678", "wpa": "2",
318              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
319    hapd = hostapd.add_ap(apdev[0], params)
320    logger.info("WPS provisioning step")
321    hapd.request("WPS_PBC")
322    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
323    dev[0].dump_monitor()
324    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
325    dev[0].wait_connected(timeout=30)
326    dev[0].request("DISCONNECT")
327
328    logger.info("Restart AP with different passphrase and re-run WPS")
329    hostapd.remove_bss(apdev[0])
330    params['wpa_passphrase'] = 'another passphrase'
331    hapd = hostapd.add_ap(apdev[0], params)
332    logger.info("WPS provisioning step")
333    hapd.request("WPS_PBC")
334    dev[0].dump_monitor()
335    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
336    dev[0].wait_connected(timeout=30)
337    networks = dev[0].list_networks()
338    if len(networks) > 1:
339        raise Exception("Unexpected duplicated network block present")
340
341@remote_compatible
342def test_ap_wps_incorrect_pin(dev, apdev):
343    """WPS PIN provisioning with incorrect PIN"""
344    ssid = "test-wps-incorrect-pin"
345    hapd = hostapd.add_ap(apdev[0],
346                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
347                           "wpa_passphrase": "12345678", "wpa": "2",
348                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
349
350    logger.info("WPS provisioning attempt 1")
351    hapd.request("WPS_PIN any 12345670")
352    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
353    dev[0].dump_monitor()
354    dev[0].request("WPS_PIN %s 55554444" % apdev[0]['bssid'])
355    ev = dev[0].wait_event(["WPS-FAIL"], timeout=30)
356    if ev is None:
357        raise Exception("WPS operation timed out")
358    if "config_error=18" not in ev:
359        raise Exception("Incorrect config_error reported")
360    if "msg=8" not in ev:
361        raise Exception("PIN error detected on incorrect message")
362    dev[0].wait_disconnected(timeout=10)
363    dev[0].request("WPS_CANCEL")
364    # if a scan was in progress, wait for it to complete before trying WPS again
365    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
366
367    status = hapd.request("WPS_GET_STATUS")
368    if "Last WPS result: Failed" not in status:
369        raise Exception("WPS failure result not shown correctly")
370
371    logger.info("WPS provisioning attempt 2")
372    hapd.request("WPS_PIN any 12345670")
373    dev[0].dump_monitor()
374    dev[0].request("WPS_PIN %s 12344444" % apdev[0]['bssid'])
375    ev = dev[0].wait_event(["WPS-FAIL"], timeout=30)
376    if ev is None:
377        raise Exception("WPS operation timed out")
378    if "config_error=18" not in ev:
379        raise Exception("Incorrect config_error reported")
380    if "msg=10" not in ev:
381        raise Exception("PIN error detected on incorrect message")
382    dev[0].wait_disconnected(timeout=10)
383
384@remote_compatible
385def test_ap_wps_conf_pin(dev, apdev):
386    """WPS PIN provisioning with configured AP"""
387    ssid = "test-wps-conf-pin"
388    hapd = hostapd.add_ap(apdev[0],
389                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
390                           "wpa_passphrase": "12345678", "wpa": "2",
391                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
392    logger.info("WPS provisioning step")
393    pin = dev[0].wps_read_pin()
394    hapd.request("WPS_PIN any " + pin)
395    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
396    dev[0].dump_monitor()
397    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
398    dev[0].wait_connected(timeout=30)
399    status = dev[0].get_status()
400    if status['wpa_state'] != 'COMPLETED' or status['bssid'] != apdev[0]['bssid']:
401        raise Exception("Not fully connected")
402    if status['ssid'] != ssid:
403        raise Exception("Unexpected SSID")
404    if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'CCMP':
405        raise Exception("Unexpected encryption configuration")
406    if status['key_mgmt'] != 'WPA2-PSK':
407        raise Exception("Unexpected key_mgmt")
408
409    dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
410    bss = dev[1].get_bss(apdev[0]['bssid'])
411    if "[WPS-AUTH]" in bss['flags']:
412        raise Exception("WPS-AUTH flag not cleared")
413    logger.info("Try to connect from another station using the same PIN")
414    pin = dev[1].request("WPS_PIN " + apdev[0]['bssid'])
415    ev = dev[1].wait_event(["WPS-M2D", "CTRL-EVENT-CONNECTED"], timeout=30)
416    if ev is None:
417        raise Exception("Operation timed out")
418    if "WPS-M2D" not in ev:
419        raise Exception("Unexpected WPS operation started")
420    hapd.request("WPS_PIN any " + pin)
421    dev[1].wait_connected(timeout=30)
422
423def test_ap_wps_conf_pin_mixed_mode(dev, apdev):
424    """WPS PIN provisioning with configured AP (WPA+WPA2)"""
425    skip_without_tkip(dev[0])
426    ssid = "test-wps-conf-pin-mixed"
427    hapd = hostapd.add_ap(apdev[0],
428                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
429                           "wpa_passphrase": "12345678", "wpa": "3",
430                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
431                           "wpa_pairwise": "TKIP"})
432
433    logger.info("WPS provisioning step")
434    pin = dev[0].wps_read_pin()
435    hapd.request("WPS_PIN any " + pin)
436    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
437    dev[0].dump_monitor()
438    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
439    dev[0].wait_connected(timeout=30)
440    status = dev[0].get_status()
441    dev[0].request("REMOVE_NETWORK all")
442    dev[0].wait_disconnected()
443    if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'TKIP' or status['key_mgmt'] != 'WPA2-PSK':
444        raise Exception("Unexpected encryption/key_mgmt configuration: pairwise=%s group=%s key_mgmt=%s" % (status['pairwise_cipher'], status['group_cipher'], status['key_mgmt']))
445
446    logger.info("WPS provisioning step (auth_types=0x1b)")
447    if "OK" not in dev[0].request("SET wps_force_auth_types 0x1b"):
448        raise Exception("Failed to set wps_force_auth_types 0x1b")
449    pin = dev[0].wps_read_pin()
450    hapd.request("WPS_PIN any " + pin)
451    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
452    dev[0].dump_monitor()
453    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
454    dev[0].wait_connected(timeout=30)
455    status = dev[0].get_status()
456    dev[0].request("REMOVE_NETWORK all")
457    dev[0].wait_disconnected()
458    if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'TKIP' or status['key_mgmt'] != 'WPA2-PSK':
459        raise Exception("Unexpected encryption/key_mgmt configuration: pairwise=%s group=%s key_mgmt=%s" % (status['pairwise_cipher'], status['group_cipher'], status['key_mgmt']))
460
461    logger.info("WPS provisioning step (auth_types=0 encr_types=0)")
462    if "OK" not in dev[0].request("SET wps_force_auth_types 0"):
463        raise Exception("Failed to set wps_force_auth_types 0")
464    if "OK" not in dev[0].request("SET wps_force_encr_types 0"):
465        raise Exception("Failed to set wps_force_encr_types 0")
466    pin = dev[0].wps_read_pin()
467    hapd.request("WPS_PIN any " + pin)
468    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
469    dev[0].dump_monitor()
470    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
471    dev[0].wait_connected(timeout=30)
472    status = dev[0].get_status()
473    dev[0].request("REMOVE_NETWORK all")
474    dev[0].wait_disconnected()
475    if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'TKIP' or status['key_mgmt'] != 'WPA2-PSK':
476        raise Exception("Unexpected encryption/key_mgmt configuration: pairwise=%s group=%s key_mgmt=%s" % (status['pairwise_cipher'], status['group_cipher'], status['key_mgmt']))
477
478    dev[0].request("SET wps_force_auth_types ")
479    dev[0].request("SET wps_force_encr_types ")
480
481@remote_compatible
482def test_ap_wps_conf_pin_v1(dev, apdev):
483    """WPS PIN provisioning with configured WPS v1.0 AP"""
484    ssid = "test-wps-conf-pin-v1"
485    hapd = hostapd.add_ap(apdev[0],
486                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
487                           "wpa_passphrase": "12345678", "wpa": "2",
488                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
489    logger.info("WPS provisioning step")
490    pin = dev[0].wps_read_pin()
491    hapd.request("SET wps_version_number 0x10")
492    hapd.request("WPS_PIN any " + pin)
493    found = False
494    for i in range(0, 10):
495        dev[0].scan(freq="2412")
496        if "[WPS-PIN]" in dev[0].request("SCAN_RESULTS"):
497            found = True
498            break
499    if not found:
500        hapd.request("SET wps_version_number 0x20")
501        raise Exception("WPS-PIN flag not seen in scan results")
502    dev[0].dump_monitor()
503    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
504    dev[0].wait_connected(timeout=30)
505    hapd.request("SET wps_version_number 0x20")
506
507@remote_compatible
508def test_ap_wps_conf_pin_2sta(dev, apdev):
509    """Two stations trying to use WPS PIN at the same time"""
510    ssid = "test-wps-conf-pin2"
511    hapd = hostapd.add_ap(apdev[0],
512                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
513                           "wpa_passphrase": "12345678", "wpa": "2",
514                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
515    logger.info("WPS provisioning step")
516    pin = "12345670"
517    pin2 = "55554444"
518    hapd.request("WPS_PIN " + dev[0].get_status_field("uuid") + " " + pin)
519    hapd.request("WPS_PIN " + dev[1].get_status_field("uuid") + " " + pin)
520    dev[0].dump_monitor()
521    dev[1].dump_monitor()
522    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
523    dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412")
524    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
525    dev[1].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
526    dev[0].wait_connected(timeout=30)
527    dev[1].wait_connected(timeout=30)
528
529@remote_compatible
530def test_ap_wps_conf_pin_timeout(dev, apdev):
531    """WPS PIN provisioning with configured AP timing out PIN"""
532    ssid = "test-wps-conf-pin"
533    hapd = hostapd.add_ap(apdev[0],
534                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
535                           "wpa_passphrase": "12345678", "wpa": "2",
536                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
537    addr = dev[0].p2p_interface_addr()
538    pin = dev[0].wps_read_pin()
539    if "FAIL" not in hapd.request("WPS_PIN "):
540        raise Exception("Unexpected success on invalid WPS_PIN")
541    hapd.request("WPS_PIN any " + pin + " 1")
542    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
543    time.sleep(1.1)
544    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
545    ev = hapd.wait_event(["WPS-PIN-NEEDED"], timeout=20)
546    if ev is None:
547        raise Exception("WPS-PIN-NEEDED event timed out")
548    ev = dev[0].wait_event(["WPS-M2D"])
549    if ev is None:
550        raise Exception("M2D not reported")
551    dev[0].request("WPS_CANCEL")
552
553    hapd.request("WPS_PIN any " + pin + " 20 " + addr)
554    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
555    dev[0].wait_connected(timeout=30)
556
557def test_ap_wps_reg_connect(dev, apdev):
558    """WPS registrar using AP PIN to connect"""
559    ssid = "test-wps-reg-ap-pin"
560    appin = "12345670"
561    hostapd.add_ap(apdev[0],
562                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
563                    "wpa_passphrase": "12345678", "wpa": "2",
564                    "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
565                    "ap_pin": appin})
566    logger.info("WPS provisioning step")
567    dev[0].dump_monitor()
568    dev[0].flush_scan_cache()
569    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
570    dev[0].wps_reg(apdev[0]['bssid'], appin)
571    status = dev[0].get_status()
572    if status['wpa_state'] != 'COMPLETED' or status['bssid'] != apdev[0]['bssid']:
573        raise Exception("Not fully connected")
574    if status['ssid'] != ssid:
575        raise Exception("Unexpected SSID")
576    if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'CCMP':
577        raise Exception("Unexpected encryption configuration")
578    if status['key_mgmt'] != 'WPA2-PSK':
579        raise Exception("Unexpected key_mgmt")
580
581def test_ap_wps_reg_connect_zero_len_ap_pin(dev, apdev):
582    """hostapd with zero length ap_pin parameter"""
583    ssid = "test-wps-reg-ap-pin"
584    appin = ""
585    hostapd.add_ap(apdev[0],
586                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
587                    "wpa_passphrase": "12345678", "wpa": "2",
588                    "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
589                    "ap_pin": appin})
590    logger.info("WPS provisioning step")
591    dev[0].dump_monitor()
592    dev[0].flush_scan_cache()
593    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
594    dev[0].wps_reg(apdev[0]['bssid'], appin, no_wait=True)
595    ev = dev[0].wait_event(["WPS-FAIL"], timeout=15)
596    if ev is None:
597        raise Exception("No WPS-FAIL reported")
598    if "msg=5 config_error=15" not in ev:
599        raise Exception("Unexpected WPS-FAIL: " + ev)
600
601def test_ap_wps_reg_connect_mixed_mode(dev, apdev):
602    """WPS registrar using AP PIN to connect (WPA+WPA2)"""
603    skip_without_tkip(dev[0])
604    ssid = "test-wps-reg-ap-pin"
605    appin = "12345670"
606    hostapd.add_ap(apdev[0],
607                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
608                    "wpa_passphrase": "12345678", "wpa": "3",
609                    "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
610                    "wpa_pairwise": "TKIP", "ap_pin": appin})
611    dev[0].flush_scan_cache()
612    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
613    dev[0].wps_reg(apdev[0]['bssid'], appin)
614    status = dev[0].get_status()
615    if status['wpa_state'] != 'COMPLETED' or status['bssid'] != apdev[0]['bssid']:
616        raise Exception("Not fully connected")
617    if status['ssid'] != ssid:
618        raise Exception("Unexpected SSID")
619    if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'TKIP':
620        raise Exception("Unexpected encryption configuration")
621    if status['key_mgmt'] != 'WPA2-PSK':
622        raise Exception("Unexpected key_mgmt")
623
624def test_ap_wps_reg_override_ap_settings(dev, apdev):
625    """WPS registrar and ap_settings override"""
626    ap_settings = "/tmp/ap_wps_reg_override_ap_settings"
627    try:
628        os.remove(ap_settings)
629    except:
630        pass
631    # Override AP Settings with values that point to another AP
632    data = build_wsc_attr(ATTR_NETWORK_INDEX, b'\x01')
633    data += build_wsc_attr(ATTR_SSID, b"test")
634    data += build_wsc_attr(ATTR_AUTH_TYPE, b'\x00\x01')
635    data += build_wsc_attr(ATTR_ENCR_TYPE, b'\x00\x01')
636    data += build_wsc_attr(ATTR_NETWORK_KEY, b'')
637    data += build_wsc_attr(ATTR_MAC_ADDR, binascii.unhexlify(apdev[1]['bssid'].replace(':', '')))
638    with open(ap_settings, "wb") as f:
639        f.write(data)
640    ssid = "test-wps-reg-ap-pin"
641    appin = "12345670"
642    hostapd.add_ap(apdev[0],
643                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
644                    "wpa_passphrase": "12345678", "wpa": "2",
645                    "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
646                    "ap_pin": appin, "ap_settings": ap_settings})
647    hapd2 = hostapd.add_ap(apdev[1], {"ssid": "test"})
648    dev[0].flush_scan_cache()
649    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
650    dev[0].scan_for_bss(apdev[1]['bssid'], freq=2412)
651    dev[0].wps_reg(apdev[0]['bssid'], appin)
652    ev = hapd2.wait_event(['AP-STA-CONNECTED'], timeout=10)
653    os.remove(ap_settings)
654    if ev is None:
655        raise Exception("No connection with the other AP")
656
657def check_wps_reg_failure(dev, ap, appin):
658    dev.request("WPS_REG " + ap['bssid'] + " " + appin)
659    ev = dev.wait_event(["WPS-SUCCESS", "WPS-FAIL"], timeout=15)
660    if ev is None:
661        raise Exception("WPS operation timed out")
662    if "WPS-SUCCESS" in ev:
663        raise Exception("WPS operation succeeded unexpectedly")
664    if "config_error=15" not in ev:
665        raise Exception("WPS setup locked state was not reported correctly")
666
667def test_ap_wps_random_ap_pin(dev, apdev):
668    """WPS registrar using random AP PIN"""
669    ssid = "test-wps-reg-random-ap-pin"
670    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
671    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
672              "wpa_passphrase": "12345678", "wpa": "2",
673              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
674              "device_name": "Wireless AP", "manufacturer": "Company",
675              "model_name": "WAP", "model_number": "123",
676              "serial_number": "12345", "device_type": "6-0050F204-1",
677              "os_version": "01020300",
678              "config_methods": "label push_button",
679              "uuid": ap_uuid, "upnp_iface": "lo"}
680    hapd = hostapd.add_ap(apdev[0], params)
681    appin = hapd.request("WPS_AP_PIN random")
682    if "FAIL" in appin:
683        raise Exception("Could not generate random AP PIN")
684    if appin not in hapd.request("WPS_AP_PIN get"):
685        raise Exception("Could not fetch current AP PIN")
686    logger.info("WPS provisioning step")
687    dev[0].flush_scan_cache()
688    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
689    dev[0].wps_reg(apdev[0]['bssid'], appin)
690
691    hapd.request("WPS_AP_PIN disable")
692    logger.info("WPS provisioning step with AP PIN disabled")
693    dev[1].scan_for_bss(apdev[0]['bssid'], freq=2412)
694    check_wps_reg_failure(dev[1], apdev[0], appin)
695
696    logger.info("WPS provisioning step with AP PIN reset")
697    appin = "12345670"
698    hapd.request("WPS_AP_PIN set " + appin)
699    dev[1].wps_reg(apdev[0]['bssid'], appin)
700    dev[0].request("REMOVE_NETWORK all")
701    dev[1].request("REMOVE_NETWORK all")
702    dev[0].wait_disconnected(timeout=10)
703    dev[1].wait_disconnected(timeout=10)
704
705    logger.info("WPS provisioning step after AP PIN timeout")
706    hapd.request("WPS_AP_PIN disable")
707    appin = hapd.request("WPS_AP_PIN random 1")
708    time.sleep(1.1)
709    if "FAIL" not in hapd.request("WPS_AP_PIN get"):
710        raise Exception("AP PIN unexpectedly still enabled")
711    check_wps_reg_failure(dev[0], apdev[0], appin)
712
713    logger.info("WPS provisioning step after AP PIN timeout(2)")
714    hapd.request("WPS_AP_PIN disable")
715    appin = "12345670"
716    hapd.request("WPS_AP_PIN set " + appin + " 1")
717    time.sleep(1.1)
718    if "FAIL" not in hapd.request("WPS_AP_PIN get"):
719        raise Exception("AP PIN unexpectedly still enabled")
720    check_wps_reg_failure(dev[1], apdev[0], appin)
721
722    with fail_test(hapd, 1, "os_get_random;wps_generate_pin"):
723        hapd.request("WPS_AP_PIN random 1")
724        hapd.request("WPS_AP_PIN disable")
725
726    with alloc_fail(hapd, 1, "upnp_wps_set_ap_pin"):
727        hapd.request("WPS_AP_PIN set 12345670")
728        hapd.request("WPS_AP_PIN disable")
729
730    if "FAIL" not in hapd.request("WPS_AP_PIN set"):
731        raise Exception("Invalid WPS_AP_PIN accepted")
732    if "FAIL" not in hapd.request("WPS_AP_PIN foo"):
733        raise Exception("Invalid WPS_AP_PIN accepted")
734    if "FAIL" not in hapd.request("WPS_AP_PIN set " + 9*'1'):
735        raise Exception("Invalid WPS_AP_PIN accepted")
736
737def test_ap_wps_reg_config(dev, apdev):
738    """WPS registrar configuring an AP using AP PIN"""
739    ssid = "test-wps-init-ap-pin"
740    appin = "12345670"
741    hostapd.add_ap(apdev[0],
742                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
743                    "ap_pin": appin})
744    logger.info("WPS configuration step")
745    dev[0].flush_scan_cache()
746    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
747    dev[0].dump_monitor()
748    new_ssid = "wps-new-ssid"
749    new_passphrase = "1234567890"
750    dev[0].wps_reg(apdev[0]['bssid'], appin, new_ssid, "WPA2PSK", "CCMP",
751                   new_passphrase)
752    status = dev[0].get_status()
753    if status['wpa_state'] != 'COMPLETED' or status['bssid'] != apdev[0]['bssid']:
754        raise Exception("Not fully connected")
755    if status['ssid'] != new_ssid:
756        raise Exception("Unexpected SSID")
757    if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'CCMP':
758        raise Exception("Unexpected encryption configuration")
759    if status['key_mgmt'] != 'WPA2-PSK':
760        raise Exception("Unexpected key_mgmt")
761
762    logger.info("Re-configure back to open")
763    dev[0].request("REMOVE_NETWORK all")
764    dev[0].flush_scan_cache()
765    dev[0].dump_monitor()
766    dev[0].wps_reg(apdev[0]['bssid'], appin, "wps-open", "OPEN", "NONE", "")
767    status = dev[0].get_status()
768    if status['wpa_state'] != 'COMPLETED' or status['bssid'] != apdev[0]['bssid']:
769        raise Exception("Not fully connected")
770    if status['ssid'] != "wps-open":
771        raise Exception("Unexpected SSID")
772    if status['key_mgmt'] != 'NONE':
773        raise Exception("Unexpected key_mgmt")
774
775def test_ap_wps_reg_config_ext_processing(dev, apdev):
776    """WPS registrar configuring an AP with external config processing"""
777    ssid = "test-wps-init-ap-pin"
778    appin = "12345670"
779    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
780              "wps_cred_processing": "1", "ap_pin": appin}
781    hapd = hostapd.add_ap(apdev[0], params)
782    dev[0].flush_scan_cache()
783    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
784    new_ssid = "wps-new-ssid"
785    new_passphrase = "1234567890"
786    dev[0].wps_reg(apdev[0]['bssid'], appin, new_ssid, "WPA2PSK", "CCMP",
787                   new_passphrase, no_wait=True)
788    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
789    if ev is None:
790        raise Exception("WPS registrar operation timed out")
791    ev = hapd.wait_event(["WPS-NEW-AP-SETTINGS"], timeout=15)
792    if ev is None:
793        raise Exception("WPS configuration timed out")
794    if "1026" not in ev:
795        raise Exception("AP Settings missing from event")
796    hapd.request("SET wps_cred_processing 0")
797    if "FAIL" in hapd.request("WPS_CONFIG " + binascii.hexlify(new_ssid.encode()).decode() + " WPA2PSK CCMP " + binascii.hexlify(new_passphrase.encode()).decode()):
798        raise Exception("WPS_CONFIG command failed")
799    dev[0].wait_connected(timeout=15)
800
801def test_ap_wps_reg_config_tkip(dev, apdev):
802    """WPS registrar configuring AP to use TKIP and AP upgrading to TKIP+CCMP"""
803    skip_with_fips(dev[0])
804    skip_without_tkip(dev[0])
805    ssid = "test-wps-init-ap"
806    appin = "12345670"
807    hapd = hostapd.add_ap(apdev[0],
808                          {"ssid": ssid, "eap_server": "1", "wps_state": "1",
809                           "ap_pin": appin})
810    logger.info("WPS configuration step")
811    dev[0].flush_scan_cache()
812    dev[0].request("SET wps_version_number 0x10")
813    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
814    dev[0].dump_monitor()
815    new_ssid = "wps-new-ssid-with-tkip"
816    new_passphrase = "1234567890"
817    dev[0].wps_reg(apdev[0]['bssid'], appin, new_ssid, "WPAPSK", "TKIP",
818                   new_passphrase)
819    logger.info("Re-connect to verify WPA2 mixed mode")
820    dev[0].request("DISCONNECT")
821    id = 0
822    dev[0].set_network(id, "pairwise", "CCMP")
823    dev[0].set_network(id, "proto", "RSN")
824    dev[0].connect_network(id)
825    status = dev[0].get_status()
826    if status['wpa_state'] != 'COMPLETED' or status['bssid'] != apdev[0]['bssid']:
827        raise Exception("Not fully connected: wpa_state={} bssid={}".format(status['wpa_state'], status['bssid']))
828    if status['ssid'] != new_ssid:
829        raise Exception("Unexpected SSID")
830    if status['pairwise_cipher'] != 'CCMP':
831        raise Exception("Unexpected encryption configuration")
832    if status['group_cipher'] != 'TKIP':
833        conf = hapd.request("GET_CONFIG")
834        if "group_cipher=CCMP" not in conf or status['group_cipher'] != 'CCMP':
835            raise Exception("Unexpected encryption configuration")
836    if status['key_mgmt'] != 'WPA2-PSK':
837        raise Exception("Unexpected key_mgmt")
838
839def test_ap_wps_setup_locked(dev, apdev):
840    """WPS registrar locking up AP setup on AP PIN failures"""
841    ssid = "test-wps-incorrect-ap-pin"
842    appin = "12345670"
843    hapd = hostapd.add_ap(apdev[0],
844                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
845                           "wpa_passphrase": "12345678", "wpa": "2",
846                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
847                           "ap_pin": appin})
848    new_ssid = "wps-new-ssid-test"
849    new_passphrase = "1234567890"
850
851    dev[0].flush_scan_cache()
852    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
853    ap_setup_locked = False
854    for pin in ["55554444", "1234", "12345678", "00000000", "11111111"]:
855        dev[0].dump_monitor()
856        logger.info("Try incorrect AP PIN - attempt " + pin)
857        dev[0].wps_reg(apdev[0]['bssid'], pin, new_ssid, "WPA2PSK",
858                       "CCMP", new_passphrase, no_wait=True)
859        ev = dev[0].wait_event(["WPS-FAIL", "CTRL-EVENT-CONNECTED"])
860        if ev is None:
861            raise Exception("Timeout on receiving WPS operation failure event")
862        if "CTRL-EVENT-CONNECTED" in ev:
863            raise Exception("Unexpected connection")
864        if "config_error=15" in ev:
865            logger.info("AP Setup Locked")
866            ap_setup_locked = True
867        elif "config_error=18" not in ev:
868            raise Exception("config_error=18 not reported")
869        dev[0].wait_disconnected(timeout=10)
870        time.sleep(0.1)
871    if not ap_setup_locked:
872        raise Exception("AP setup was not locked")
873    dev[0].request("WPS_CANCEL")
874    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412, force_scan=True,
875                        only_new=True)
876    bss = dev[0].get_bss(apdev[0]['bssid'])
877    if 'wps_ap_setup_locked' not in bss or bss['wps_ap_setup_locked'] != '1':
878        logger.info("BSS: " + str(bss))
879        raise Exception("AP Setup Locked not indicated in scan results")
880
881    status = hapd.request("WPS_GET_STATUS")
882    if "Last WPS result: Failed" not in status:
883        raise Exception("WPS failure result not shown correctly")
884    if "Peer Address: " + dev[0].p2p_interface_addr() not in status:
885        raise Exception("Peer address not shown correctly")
886
887    time.sleep(0.5)
888    dev[0].dump_monitor()
889    logger.info("WPS provisioning step")
890    pin = dev[0].wps_read_pin()
891    hapd.request("WPS_PIN any " + pin)
892    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
893    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=30)
894    if ev is None:
895        raise Exception("WPS success was not reported")
896    dev[0].wait_connected(timeout=30)
897
898    appin = hapd.request("WPS_AP_PIN random")
899    if "FAIL" in appin:
900        raise Exception("Could not generate random AP PIN")
901    ev = hapd.wait_event(["WPS-AP-SETUP-UNLOCKED"], timeout=10)
902    if ev is None:
903        raise Exception("Failed to unlock AP PIN")
904
905def test_ap_wps_setup_locked_timeout(dev, apdev):
906    """WPS re-enabling AP PIN after timeout"""
907    ssid = "test-wps-incorrect-ap-pin"
908    appin = "12345670"
909    hapd = hostapd.add_ap(apdev[0],
910                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
911                           "wpa_passphrase": "12345678", "wpa": "2",
912                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
913                           "ap_pin": appin})
914    new_ssid = "wps-new-ssid-test"
915    new_passphrase = "1234567890"
916
917    dev[0].flush_scan_cache()
918    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
919    ap_setup_locked = False
920    for pin in ["55554444", "1234", "12345678", "00000000", "11111111"]:
921        dev[0].dump_monitor()
922        logger.info("Try incorrect AP PIN - attempt " + pin)
923        dev[0].wps_reg(apdev[0]['bssid'], pin, new_ssid, "WPA2PSK",
924                       "CCMP", new_passphrase, no_wait=True)
925        ev = dev[0].wait_event(["WPS-FAIL", "CTRL-EVENT-CONNECTED"], timeout=15)
926        if ev is None:
927            raise Exception("Timeout on receiving WPS operation failure event")
928        if "CTRL-EVENT-CONNECTED" in ev:
929            raise Exception("Unexpected connection")
930        if "config_error=15" in ev:
931            logger.info("AP Setup Locked")
932            ap_setup_locked = True
933            break
934        elif "config_error=18" not in ev:
935            raise Exception("config_error=18 not reported")
936        dev[0].wait_disconnected(timeout=10)
937        time.sleep(0.1)
938    if not ap_setup_locked:
939        raise Exception("AP setup was not locked")
940    ev = hapd.wait_event(["WPS-AP-SETUP-UNLOCKED"], timeout=80)
941    if ev is None:
942        raise Exception("AP PIN did not get unlocked on 60 second timeout")
943
944def test_ap_wps_setup_locked_2(dev, apdev):
945    """WPS AP configured for special ap_setup_locked=2 mode"""
946    ssid = "test-wps-ap-pin"
947    appin = "12345670"
948    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
949              "wpa_passphrase": "12345678", "wpa": "2",
950              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
951              "ap_pin": appin, "ap_setup_locked": "2"}
952    hapd = hostapd.add_ap(apdev[0], params)
953    new_ssid = "wps-new-ssid-test"
954    new_passphrase = "1234567890"
955
956    dev[0].flush_scan_cache()
957    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
958    dev[0].wps_reg(apdev[0]['bssid'], appin)
959    dev[0].request("REMOVE_NETWORK all")
960    dev[0].wait_disconnected()
961
962    hapd.dump_monitor()
963    dev[0].dump_monitor()
964    dev[0].wps_reg(apdev[0]['bssid'], appin, new_ssid, "WPA2PSK",
965                   "CCMP", new_passphrase, no_wait=True)
966
967    ev = hapd.wait_event(["WPS-FAIL"], timeout=5)
968    if ev is None:
969        raise Exception("hostapd did not report WPS failure")
970    if "msg=12 config_error=15" not in ev:
971        raise Exception("Unexpected failure reason (AP): " + ev)
972
973    ev = dev[0].wait_event(["WPS-FAIL", "CTRL-EVENT-CONNECTED"])
974    if ev is None:
975        raise Exception("Timeout on receiving WPS operation failure event")
976    if "CTRL-EVENT-CONNECTED" in ev:
977        raise Exception("Unexpected connection")
978    if "config_error=15" not in ev:
979        raise Exception("Unexpected failure reason (STA): " + ev)
980    dev[0].request("WPS_CANCEL")
981    dev[0].wait_disconnected()
982
983def setup_ap_wps_pbc_overlap_2ap(apdev):
984    params = {"ssid": "wps1", "eap_server": "1", "wps_state": "2",
985              "wpa_passphrase": "12345678", "wpa": "2",
986              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
987              "wps_independent": "1"}
988    hapd = hostapd.add_ap(apdev[0], params)
989    params = {"ssid": "wps2", "eap_server": "1", "wps_state": "2",
990              "wpa_passphrase": "123456789", "wpa": "2",
991              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
992              "wps_independent": "1"}
993    hapd2 = hostapd.add_ap(apdev[1], params)
994    hapd.request("WPS_PBC")
995    hapd2.request("WPS_PBC")
996    return hapd, hapd2
997
998@remote_compatible
999def test_ap_wps_pbc_overlap_2ap(dev, apdev):
1000    """WPS PBC session overlap with two active APs"""
1001    hapd, hapd2 = setup_ap_wps_pbc_overlap_2ap(apdev)
1002    logger.info("WPS provisioning step")
1003    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
1004    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
1005    dev[0].request("WPS_PBC")
1006    ev = dev[0].wait_event(["WPS-OVERLAP-DETECTED"], timeout=15)
1007    hapd.request("DISABLE")
1008    hapd2.request("DISABLE")
1009    dev[0].flush_scan_cache()
1010    if ev is None:
1011        raise Exception("PBC session overlap not detected")
1012
1013@remote_compatible
1014def test_ap_wps_pbc_overlap_2ap_specific_bssid(dev, apdev):
1015    """WPS PBC session overlap with two active APs (specific BSSID selected)"""
1016    hapd, hapd2 = setup_ap_wps_pbc_overlap_2ap(apdev)
1017    logger.info("WPS provisioning step")
1018    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
1019    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
1020    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
1021    ev = dev[0].wait_event(["WPS-OVERLAP-DETECTED",
1022                            "CTRL-EVENT-CONNECTED"], timeout=15)
1023    dev[0].request("DISCONNECT")
1024    hapd.request("DISABLE")
1025    hapd2.request("DISABLE")
1026    dev[0].flush_scan_cache()
1027    if ev is None:
1028        raise Exception("PBC session overlap result not reported")
1029    if "CTRL-EVENT-CONNECTED" not in ev:
1030        raise Exception("Connection did not complete")
1031
1032@remote_compatible
1033def test_ap_wps_pbc_overlap_2sta(dev, apdev):
1034    """WPS PBC session overlap with two active STAs"""
1035    ssid = "test-wps-pbc-overlap"
1036    hapd = hostapd.add_ap(apdev[0],
1037                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1038                           "wpa_passphrase": "12345678", "wpa": "2",
1039                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
1040    logger.info("WPS provisioning step")
1041    hapd.request("WPS_PBC")
1042    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
1043    dev[0].dump_monitor()
1044    dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412")
1045    dev[1].dump_monitor()
1046    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
1047    dev[1].request("WPS_PBC " + apdev[0]['bssid'])
1048    ev = dev[0].wait_event(["WPS-M2D"], timeout=15)
1049    if ev is None:
1050        raise Exception("PBC session overlap not detected (dev0)")
1051    if "config_error=12" not in ev:
1052        raise Exception("PBC session overlap not correctly reported (dev0)")
1053    dev[0].request("WPS_CANCEL")
1054    dev[0].request("DISCONNECT")
1055    ev = dev[1].wait_event(["WPS-M2D"], timeout=15)
1056    if ev is None:
1057        raise Exception("PBC session overlap not detected (dev1)")
1058    if "config_error=12" not in ev:
1059        raise Exception("PBC session overlap not correctly reported (dev1)")
1060    dev[1].request("WPS_CANCEL")
1061    dev[1].request("DISCONNECT")
1062    ev = hapd.wait_event(["WPS-OVERLAP-DETECTED"], timeout=1)
1063    if ev is None:
1064        raise Exception("PBC session overlap not detected (AP)")
1065    if "PBC Status: Overlap" not in hapd.request("WPS_GET_STATUS"):
1066        raise Exception("PBC status not shown correctly")
1067    hapd.request("WPS_CANCEL")
1068    ret = hapd.request("WPS_PBC")
1069    if "FAIL" not in ret:
1070        raise Exception("PBC mode allowed to be started while PBC overlap still active")
1071    hapd.request("DISABLE")
1072    dev[0].flush_scan_cache()
1073    dev[1].flush_scan_cache()
1074
1075def test_ap_wps_pbc_session_workaround(dev, apdev):
1076    """WPS PBC session overlap workaround"""
1077    ssid = "test-wps-pbc-overlap"
1078    hapd = hostapd.add_ap(apdev[0],
1079                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1080                           "wpa_passphrase": "12345678", "wpa": "2",
1081                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
1082    bssid = hapd.own_addr()
1083    hapd.request("WPS_PBC")
1084    dev[0].scan_for_bss(bssid, freq="2412")
1085    dev[0].request("WPS_PBC " + bssid)
1086    dev[0].wait_connected(timeout=30)
1087
1088    dev[0].request("REMOVE_NETWORK all")
1089    dev[0].wait_disconnected(timeout=30)
1090    dev[0].dump_monitor()
1091    # Trigger AP/Registrar to ignore PBC activation immediately after
1092    # successfully completed provisioning
1093    dev[0].request("WPS_PBC " + bssid)
1094    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
1095    if ev is None:
1096        raise Exception("No scan results reported")
1097    dev[0].request("WPS_CANCEL")
1098    dev[0].dump_monitor()
1099
1100    # Verify that PBC session overlap does not prevent connection
1101    hapd.request("WPS_PBC")
1102    dev[1].scan_for_bss(bssid, freq="2412")
1103    dev[1].request("WPS_PBC " + bssid)
1104    dev[1].wait_connected()
1105    dev[1].request("REMOVE_NETWORK all")
1106    dev[1].wait_disconnected()
1107
1108    hapd.request("DISABLE")
1109    dev[0].flush_scan_cache()
1110    dev[1].flush_scan_cache()
1111
1112@remote_compatible
1113def test_ap_wps_cancel(dev, apdev):
1114    """WPS AP cancelling enabled config method"""
1115    ssid = "test-wps-ap-cancel"
1116    hapd = hostapd.add_ap(apdev[0],
1117                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1118                           "wpa_passphrase": "12345678", "wpa": "2",
1119                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
1120    bssid = apdev[0]['bssid']
1121
1122    logger.info("Verify PBC enable/cancel")
1123    hapd.request("WPS_PBC")
1124    dev[0].scan(freq="2412")
1125    dev[0].scan(freq="2412")
1126    bss = dev[0].get_bss(apdev[0]['bssid'])
1127    if "[WPS-PBC]" not in bss['flags']:
1128        raise Exception("WPS-PBC flag missing")
1129    if "FAIL" in hapd.request("WPS_CANCEL"):
1130        raise Exception("WPS_CANCEL failed")
1131    dev[0].scan(freq="2412")
1132    dev[0].scan(freq="2412")
1133    bss = dev[0].get_bss(apdev[0]['bssid'])
1134    if "[WPS-PBC]" in bss['flags']:
1135        raise Exception("WPS-PBC flag not cleared")
1136
1137    logger.info("Verify PIN enable/cancel")
1138    hapd.request("WPS_PIN any 12345670")
1139    dev[0].scan(freq="2412")
1140    dev[0].scan(freq="2412")
1141    bss = dev[0].get_bss(apdev[0]['bssid'])
1142    if "[WPS-AUTH]" not in bss['flags']:
1143        raise Exception("WPS-AUTH flag missing")
1144    if "FAIL" in hapd.request("WPS_CANCEL"):
1145        raise Exception("WPS_CANCEL failed")
1146    dev[0].scan(freq="2412")
1147    dev[0].scan(freq="2412")
1148    bss = dev[0].get_bss(apdev[0]['bssid'])
1149    if "[WPS-AUTH]" in bss['flags']:
1150        raise Exception("WPS-AUTH flag not cleared")
1151    dev[0].flush_scan_cache()
1152
1153def test_ap_wps_er_add_enrollee(dev, apdev):
1154    """WPS ER configuring AP and adding a new enrollee using PIN"""
1155    try:
1156        _test_ap_wps_er_add_enrollee(dev, apdev)
1157    finally:
1158        dev[0].request("WPS_ER_STOP")
1159
1160def _test_ap_wps_er_add_enrollee(dev, apdev):
1161    ssid = "wps-er-add-enrollee"
1162    ap_pin = "12345670"
1163    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
1164    params = {"ssid": ssid, "eap_server": "1", "wps_state": "1",
1165              "device_name": "Wireless AP", "manufacturer": "Company",
1166              "model_name": "WAP", "model_number": "123",
1167              "serial_number": "12345", "device_type": "6-0050F204-1",
1168              "os_version": "01020300",
1169              'friendly_name': "WPS AP - <>&'\" - TEST",
1170              "config_methods": "label push_button",
1171              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
1172    hapd = hostapd.add_ap(apdev[0], params)
1173    logger.info("WPS configuration step")
1174    new_passphrase = "1234567890"
1175    dev[0].dump_monitor()
1176    dev[0].flush_scan_cache()
1177    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
1178    dev[0].wps_reg(apdev[0]['bssid'], ap_pin, ssid, "WPA2PSK", "CCMP",
1179                   new_passphrase)
1180    status = dev[0].get_status()
1181    if status['wpa_state'] != 'COMPLETED' or status['bssid'] != apdev[0]['bssid']:
1182        raise Exception("Not fully connected")
1183    if status['ssid'] != ssid:
1184        raise Exception("Unexpected SSID")
1185    if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'CCMP':
1186        raise Exception("Unexpected encryption configuration")
1187    if status['key_mgmt'] != 'WPA2-PSK':
1188        raise Exception("Unexpected key_mgmt")
1189
1190    # WPS provisioning
1191    hapd.wait_sta(dev[0].own_addr())
1192    # Data connection
1193    hapd.wait_sta(dev[0].own_addr())
1194
1195    logger.info("Start ER")
1196    dev[0].request("WPS_ER_START ifname=lo")
1197    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
1198    if ev is None:
1199        raise Exception("AP discovery timed out")
1200    if ap_uuid not in ev:
1201        raise Exception("Expected AP UUID not found")
1202    if "|WPS AP - &lt;&gt;&amp;&apos;&quot; - TEST|Company|" not in ev:
1203        raise Exception("Expected friendly name not found")
1204
1205    logger.info("Learn AP configuration through UPnP")
1206    dev[0].dump_monitor()
1207    dev[0].request("WPS_ER_LEARN " + ap_uuid + " " + ap_pin)
1208    ev = dev[0].wait_event(["WPS-ER-AP-SETTINGS"], timeout=15)
1209    if ev is None:
1210        raise Exception("AP learn timed out")
1211    if ap_uuid not in ev:
1212        raise Exception("Expected AP UUID not in settings")
1213    if "ssid=" + ssid not in ev:
1214        raise Exception("Expected SSID not in settings")
1215    if "key=" + new_passphrase not in ev:
1216        raise Exception("Expected passphrase not in settings")
1217    ev = dev[0].wait_event(["WPS-FAIL"], timeout=15)
1218    if ev is None:
1219        raise Exception("WPS-FAIL after AP learn timed out")
1220    time.sleep(0.1)
1221
1222    logger.info("Add Enrollee using ER")
1223    pin = dev[1].wps_read_pin()
1224    dev[0].dump_monitor()
1225    dev[0].request("WPS_ER_PIN any " + pin + " " + dev[1].p2p_interface_addr())
1226    dev[1].scan_for_bss(apdev[0]['bssid'], freq=2412)
1227    dev[1].dump_monitor()
1228    dev[1].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
1229    ev = dev[1].wait_event(["WPS-SUCCESS"], timeout=30)
1230    if ev is None:
1231        raise Exception("Enrollee did not report success")
1232    dev[1].wait_connected(timeout=15)
1233    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
1234    if ev is None:
1235        raise Exception("WPS ER did not report success")
1236    hapd.wait_sta(dev[1].own_addr())
1237    hapd.wait_4way_hs()
1238    hwsim_utils.test_connectivity_sta(dev[0], dev[1])
1239
1240    logger.info("Add a specific Enrollee using ER")
1241    pin = dev[2].wps_read_pin()
1242    addr2 = dev[2].p2p_interface_addr()
1243    dev[0].dump_monitor()
1244    dev[2].scan_for_bss(apdev[0]['bssid'], freq=2412)
1245    dev[2].dump_monitor()
1246    dev[2].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
1247    ev = dev[0].wait_event(["WPS-ER-ENROLLEE-ADD"], timeout=10)
1248    if ev is None:
1249        raise Exception("Enrollee not seen")
1250    if addr2 not in ev:
1251        raise Exception("Unexpected Enrollee MAC address")
1252    dev[0].request("WPS_ER_PIN " + addr2 + " " + pin + " " + addr2)
1253    dev[2].wait_connected(timeout=30)
1254    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
1255    if ev is None:
1256        raise Exception("WPS ER did not report success")
1257    hapd.wait_sta(dev[2].own_addr())
1258
1259    logger.info("Verify registrar selection behavior")
1260    dev[0].request("WPS_ER_PIN any " + pin + " " + dev[1].p2p_interface_addr())
1261    dev[1].request("DISCONNECT")
1262    dev[1].wait_disconnected(timeout=10)
1263    dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412")
1264    dev[1].scan(freq="2412")
1265    bss = dev[1].get_bss(apdev[0]['bssid'])
1266    if "[WPS-AUTH]" not in bss['flags']:
1267        # It is possible for scan to miss an update especially when running
1268        # tests under load with multiple VMs, so allow another attempt.
1269        dev[1].scan(freq="2412")
1270        bss = dev[1].get_bss(apdev[0]['bssid'])
1271        if "[WPS-AUTH]" not in bss['flags']:
1272            raise Exception("WPS-AUTH flag missing")
1273
1274    logger.info("Stop ER")
1275    dev[0].dump_monitor()
1276    dev[0].request("WPS_ER_STOP")
1277    ev = dev[0].wait_event(["WPS-ER-AP-REMOVE"])
1278    if ev is None:
1279        raise Exception("WPS ER unsubscription timed out")
1280    # It takes some time for the UPnP UNSUBSCRIBE command to go through, so wait
1281    # a bit before verifying that the scan results have changed.
1282    time.sleep(0.2)
1283
1284    for i in range(0, 10):
1285        dev[1].request("BSS_FLUSH 0")
1286        dev[1].scan(freq="2412", only_new=True)
1287        bss = dev[1].get_bss(apdev[0]['bssid'])
1288        if bss and 'flags' in bss and "[WPS-AUTH]" not in bss['flags']:
1289            break
1290        logger.debug("WPS-AUTH flag was still in place - wait a bit longer")
1291        time.sleep(0.1)
1292    if "[WPS-AUTH]" in bss['flags']:
1293        raise Exception("WPS-AUTH flag not removed")
1294
1295def test_ap_wps_er_add_enrollee_uuid(dev, apdev):
1296    """WPS ER adding a new enrollee identified by UUID"""
1297    try:
1298        _test_ap_wps_er_add_enrollee_uuid(dev, apdev)
1299    finally:
1300        dev[0].request("WPS_ER_STOP")
1301
1302def _test_ap_wps_er_add_enrollee_uuid(dev, apdev):
1303    ssid = "wps-er-add-enrollee"
1304    ap_pin = "12345670"
1305    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
1306    hostapd.add_ap(apdev[0],
1307                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1308                    "wpa_passphrase": "12345678", "wpa": "2",
1309                    "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
1310                    "device_name": "Wireless AP", "manufacturer": "Company",
1311                    "model_name": "WAP", "model_number": "123",
1312                    "serial_number": "12345", "device_type": "6-0050F204-1",
1313                    "os_version": "01020300",
1314                    "config_methods": "label push_button",
1315                    "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"})
1316    logger.info("WPS configuration step")
1317    dev[0].flush_scan_cache()
1318    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
1319    dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
1320
1321    logger.info("Start ER")
1322    dev[0].request("WPS_ER_START ifname=lo")
1323    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
1324    if ev is None:
1325        raise Exception("AP discovery timed out")
1326    if ap_uuid not in ev:
1327        raise Exception("Expected AP UUID not found")
1328
1329    logger.info("Learn AP configuration through UPnP")
1330    dev[0].dump_monitor()
1331    dev[0].request("WPS_ER_LEARN " + ap_uuid + " " + ap_pin)
1332    ev = dev[0].wait_event(["WPS-ER-AP-SETTINGS"], timeout=15)
1333    if ev is None:
1334        raise Exception("AP learn timed out")
1335    if ap_uuid not in ev:
1336        raise Exception("Expected AP UUID not in settings")
1337    ev = dev[0].wait_event(["WPS-FAIL"], timeout=15)
1338    if ev is None:
1339        raise Exception("WPS-FAIL after AP learn timed out")
1340    time.sleep(0.1)
1341
1342    logger.info("Add a specific Enrollee using ER (PBC/UUID)")
1343    addr1 = dev[1].p2p_interface_addr()
1344    dev[0].dump_monitor()
1345    dev[1].scan_for_bss(apdev[0]['bssid'], freq=2412)
1346    dev[1].dump_monitor()
1347    dev[1].request("WPS_PBC %s" % apdev[0]['bssid'])
1348    ev = dev[0].wait_event(["WPS-ER-ENROLLEE-ADD"], timeout=10)
1349    if ev is None:
1350        raise Exception("Enrollee not seen")
1351    if addr1 not in ev:
1352        raise Exception("Unexpected Enrollee MAC address")
1353    uuid = ev.split(' ')[1]
1354    dev[0].request("WPS_ER_PBC " + uuid)
1355    dev[1].wait_connected(timeout=30)
1356    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
1357    if ev is None:
1358        raise Exception("WPS ER did not report success")
1359
1360    logger.info("Add a specific Enrollee using ER (PIN/UUID)")
1361    pin = dev[2].wps_read_pin()
1362    addr2 = dev[2].p2p_interface_addr()
1363    dev[0].dump_monitor()
1364    dev[2].scan_for_bss(apdev[0]['bssid'], freq=2412)
1365    dev[2].dump_monitor()
1366    dev[2].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
1367    ev = dev[0].wait_event(["WPS-ER-ENROLLEE-ADD"], timeout=10)
1368    if ev is None:
1369        raise Exception("Enrollee not seen")
1370    if addr2 not in ev:
1371        raise Exception("Unexpected Enrollee MAC address")
1372    uuid = ev.split(' ')[1]
1373    dev[0].request("WPS_ER_PIN " + uuid + " " + pin)
1374    dev[2].wait_connected(timeout=30)
1375    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
1376    if ev is None:
1377        raise Exception("WPS ER did not report success")
1378
1379    ev = dev[0].wait_event(["WPS-ER-ENROLLEE-REMOVE"], timeout=15)
1380    if ev is None:
1381        raise Exception("No Enrollee STA entry timeout seen")
1382
1383    logger.info("Stop ER")
1384    dev[0].dump_monitor()
1385    dev[0].request("WPS_ER_STOP")
1386
1387def test_ap_wps_er_multi_add_enrollee(dev, apdev):
1388    """Multiple WPS ERs adding a new enrollee using PIN"""
1389    try:
1390        _test_ap_wps_er_multi_add_enrollee(dev, apdev)
1391    finally:
1392        for i in range(2):
1393            dev[i].request("WPS_ER_STOP")
1394
1395def _test_ap_wps_er_multi_add_enrollee(dev, apdev):
1396    ssid = "wps-er-add-enrollee"
1397    ap_pin = "12345670"
1398    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
1399    hostapd.add_ap(apdev[0],
1400                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1401                    "wpa_passphrase": "12345678", "wpa": "2",
1402                    "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
1403                    "device_name": "Wireless AP", "manufacturer": "Company",
1404                    "model_name": "WAP", "model_number": "123",
1405                    "serial_number": "12345", "device_type": "6-0050F204-1",
1406                    "os_version": "01020300",
1407                    'friendly_name': "WPS AP",
1408                    "config_methods": "label push_button",
1409                    "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"})
1410
1411    for i in range(2):
1412        dev[i].flush_scan_cache()
1413        dev[i].scan_for_bss(apdev[0]['bssid'], freq=2412)
1414        dev[i].wps_reg(apdev[0]['bssid'], ap_pin)
1415    for i in range(2):
1416        dev[i].request("WPS_ER_START ifname=lo")
1417    for i in range(2):
1418        ev = dev[i].wait_event(["WPS-ER-AP-ADD"], timeout=15)
1419        if ev is None:
1420            raise Exception("AP discovery timed out")
1421        dev[i].dump_monitor()
1422    for i in range(2):
1423        dev[i].request("WPS_ER_LEARN " + ap_uuid + " " + ap_pin)
1424    for i in range(2):
1425        ev = dev[i].wait_event(["WPS-ER-AP-SETTINGS"], timeout=15)
1426        if ev is None:
1427            raise Exception("AP learn timed out")
1428        ev = dev[i].wait_event(["WPS-FAIL"], timeout=15)
1429        if ev is None:
1430            raise Exception("WPS-FAIL after AP learn timed out")
1431
1432    time.sleep(0.1)
1433
1434    pin = dev[2].wps_read_pin()
1435    addr = dev[2].own_addr()
1436    dev[0].dump_monitor()
1437    dev[0].request("WPS_ER_PIN any " + pin + " " + addr)
1438    dev[1].dump_monitor()
1439    dev[1].request("WPS_ER_PIN any " + pin + " " + addr)
1440
1441    dev[2].scan_for_bss(apdev[0]['bssid'], freq=2412)
1442    dev[2].dump_monitor()
1443    dev[2].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
1444    ev = dev[2].wait_event(["WPS-SUCCESS"], timeout=30)
1445    if ev is None:
1446        raise Exception("Enrollee did not report success")
1447    dev[2].wait_connected(timeout=15)
1448
1449def test_ap_wps_er_add_enrollee_pbc(dev, apdev):
1450    """WPS ER connected to AP and adding a new enrollee using PBC"""
1451    try:
1452        _test_ap_wps_er_add_enrollee_pbc(dev, apdev)
1453    finally:
1454        dev[0].request("WPS_ER_STOP")
1455
1456def _test_ap_wps_er_add_enrollee_pbc(dev, apdev):
1457    ssid = "wps-er-add-enrollee-pbc"
1458    ap_pin = "12345670"
1459    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
1460    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1461              "wpa_passphrase": "12345678", "wpa": "2",
1462              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
1463              "device_name": "Wireless AP", "manufacturer": "Company",
1464              "model_name": "WAP", "model_number": "123",
1465              "serial_number": "12345", "device_type": "6-0050F204-1",
1466              "os_version": "01020300",
1467              "config_methods": "label push_button",
1468              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
1469    hapd = hostapd.add_ap(apdev[0], params)
1470    logger.info("Learn AP configuration")
1471    dev[0].flush_scan_cache()
1472    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
1473    dev[0].dump_monitor()
1474    dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
1475    status = dev[0].get_status()
1476    if status['wpa_state'] != 'COMPLETED' or status['bssid'] != apdev[0]['bssid']:
1477        raise Exception("Not fully connected")
1478    hapd.wait_sta(addr=dev[0].own_addr())
1479
1480    logger.info("Start ER")
1481    dev[0].request("WPS_ER_START ifname=lo")
1482    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
1483    if ev is None:
1484        raise Exception("AP discovery timed out")
1485    if ap_uuid not in ev:
1486        raise Exception("Expected AP UUID not found")
1487
1488    enrollee = dev[1].p2p_interface_addr()
1489
1490    if "FAIL-UNKNOWN-UUID" not in dev[0].request("WPS_ER_PBC " + enrollee):
1491        raise Exception("Unknown UUID not reported")
1492
1493    logger.info("Add Enrollee using ER and PBC")
1494    dev[0].dump_monitor()
1495    dev[1].dump_monitor()
1496    dev[1].request("WPS_PBC")
1497
1498    for i in range(0, 2):
1499        ev = dev[0].wait_event(["WPS-ER-ENROLLEE-ADD"], timeout=15)
1500        if ev is None:
1501            raise Exception("Enrollee discovery timed out")
1502        if enrollee in ev:
1503            break
1504        if i == 1:
1505            raise Exception("Expected Enrollee not found")
1506    if "FAIL-NO-AP-SETTINGS" not in dev[0].request("WPS_ER_PBC " + enrollee):
1507        raise Exception("Unknown UUID not reported")
1508    logger.info("Use learned network configuration on ER")
1509    dev[0].request("WPS_ER_SET_CONFIG " + ap_uuid + " 0")
1510    if "OK" not in dev[0].request("WPS_ER_PBC " + enrollee):
1511        raise Exception("WPS_ER_PBC failed")
1512
1513    ev = dev[1].wait_event(["WPS-SUCCESS"], timeout=15)
1514    if ev is None:
1515        raise Exception("Enrollee did not report success")
1516    dev[1].wait_connected(timeout=15)
1517    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
1518    if ev is None:
1519        raise Exception("WPS ER did not report success")
1520    hapd.wait_sta(addr=dev[1].own_addr())
1521    hapd.wait_4way_hs()
1522    hwsim_utils.test_connectivity_sta(dev[0], dev[1])
1523
1524def test_ap_wps_er_pbc_overlap(dev, apdev):
1525    """WPS ER connected to AP and PBC session overlap"""
1526    try:
1527        _test_ap_wps_er_pbc_overlap(dev, apdev)
1528    finally:
1529        dev[0].request("WPS_ER_STOP")
1530
1531def _test_ap_wps_er_pbc_overlap(dev, apdev):
1532    ssid = "wps-er-add-enrollee-pbc"
1533    ap_pin = "12345670"
1534    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
1535    hostapd.add_ap(apdev[0],
1536                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1537                    "wpa_passphrase": "12345678", "wpa": "2",
1538                    "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
1539                    "device_name": "Wireless AP", "manufacturer": "Company",
1540                    "model_name": "WAP", "model_number": "123",
1541                    "serial_number": "12345", "device_type": "6-0050F204-1",
1542                    "os_version": "01020300",
1543                    "config_methods": "label push_button",
1544                    "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"})
1545    dev[0].flush_scan_cache()
1546    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
1547    dev[0].dump_monitor()
1548    dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
1549
1550    dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412")
1551    dev[2].scan_for_bss(apdev[0]['bssid'], freq="2412")
1552    # avoid leaving dev 1 or 2 as the last Probe Request to the AP
1553    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412, force_scan=True)
1554
1555    dev[0].dump_monitor()
1556    dev[0].request("WPS_ER_START ifname=lo")
1557
1558    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
1559    if ev is None:
1560        raise Exception("AP discovery timed out")
1561    if ap_uuid not in ev:
1562        raise Exception("Expected AP UUID not found")
1563
1564    # verify BSSID selection of the AP instead of UUID
1565    if "FAIL" in dev[0].request("WPS_ER_SET_CONFIG " + apdev[0]['bssid'] + " 0"):
1566        raise Exception("Could not select AP based on BSSID")
1567
1568    dev[0].dump_monitor()
1569    dev[1].request("WPS_PBC " + apdev[0]['bssid'])
1570    dev[2].request("WPS_PBC " + apdev[0]['bssid'])
1571    ev = dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
1572    if ev is None:
1573        raise Exception("PBC scan failed")
1574    ev = dev[2].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
1575    if ev is None:
1576        raise Exception("PBC scan failed")
1577    found1 = False
1578    found2 = False
1579    addr1 = dev[1].own_addr()
1580    addr2 = dev[2].own_addr()
1581    for i in range(3):
1582        ev = dev[0].wait_event(["WPS-ER-ENROLLEE-ADD"], timeout=15)
1583        if ev is None:
1584            raise Exception("Enrollee discovery timed out")
1585        if addr1 in ev:
1586            found1 = True
1587            if found2:
1588                break
1589        if addr2 in ev:
1590            found2 = True
1591            if found1:
1592                break
1593    if dev[0].request("WPS_ER_PBC " + ap_uuid) != "FAIL-PBC-OVERLAP\n":
1594        raise Exception("PBC overlap not reported")
1595    dev[1].request("WPS_CANCEL")
1596    dev[2].request("WPS_CANCEL")
1597    if dev[0].request("WPS_ER_PBC foo") != "FAIL\n":
1598        raise Exception("Invalid WPS_ER_PBC accepted")
1599
1600def test_ap_wps_er_v10_add_enrollee_pin(dev, apdev):
1601    """WPS v1.0 ER connected to AP and adding a new enrollee using PIN"""
1602    try:
1603        _test_ap_wps_er_v10_add_enrollee_pin(dev, apdev)
1604    finally:
1605        dev[0].request("WPS_ER_STOP")
1606
1607def _test_ap_wps_er_v10_add_enrollee_pin(dev, apdev):
1608    ssid = "wps-er-add-enrollee-pbc"
1609    ap_pin = "12345670"
1610    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
1611    hostapd.add_ap(apdev[0],
1612                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1613                    "wpa_passphrase": "12345678", "wpa": "2",
1614                    "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
1615                    "device_name": "Wireless AP", "manufacturer": "Company",
1616                    "model_name": "WAP", "model_number": "123",
1617                    "serial_number": "12345", "device_type": "6-0050F204-1",
1618                    "os_version": "01020300",
1619                    "config_methods": "label push_button",
1620                    "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"})
1621    logger.info("Learn AP configuration")
1622    dev[0].request("SET wps_version_number 0x10")
1623    dev[0].flush_scan_cache()
1624    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
1625    dev[0].dump_monitor()
1626    dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
1627    status = dev[0].get_status()
1628    if status['wpa_state'] != 'COMPLETED' or status['bssid'] != apdev[0]['bssid']:
1629        raise Exception("Not fully connected")
1630
1631    logger.info("Start ER")
1632    dev[0].request("WPS_ER_START ifname=lo")
1633    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
1634    if ev is None:
1635        raise Exception("AP discovery timed out")
1636    if ap_uuid not in ev:
1637        raise Exception("Expected AP UUID not found")
1638
1639    logger.info("Use learned network configuration on ER")
1640    dev[0].request("WPS_ER_SET_CONFIG " + ap_uuid + " 0")
1641
1642    logger.info("Add Enrollee using ER and PIN")
1643    enrollee = dev[1].p2p_interface_addr()
1644    pin = dev[1].wps_read_pin()
1645    dev[0].dump_monitor()
1646    dev[0].request("WPS_ER_PIN any " + pin + " " + enrollee)
1647    dev[1].scan_for_bss(apdev[0]['bssid'], freq=2412)
1648    dev[1].dump_monitor()
1649    dev[1].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
1650    dev[1].wait_connected(timeout=30)
1651    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
1652    if ev is None:
1653        raise Exception("WPS ER did not report success")
1654
1655@remote_compatible
1656def test_ap_wps_er_config_ap(dev, apdev):
1657    """WPS ER configuring AP over UPnP"""
1658    try:
1659        _test_ap_wps_er_config_ap(dev, apdev)
1660    finally:
1661        dev[0].request("WPS_ER_STOP")
1662
1663def _test_ap_wps_er_config_ap(dev, apdev):
1664    ssid = "wps-er-ap-config"
1665    ap_pin = "12345670"
1666    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
1667    hostapd.add_ap(apdev[0],
1668                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1669                    "wpa_passphrase": "12345678", "wpa": "2",
1670                    "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
1671                    "device_name": "Wireless AP", "manufacturer": "Company",
1672                    "model_name": "WAP", "model_number": "123",
1673                    "serial_number": "12345", "device_type": "6-0050F204-1",
1674                    "os_version": "01020300",
1675                    "config_methods": "label push_button",
1676                    "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"})
1677
1678    logger.info("Connect ER to the AP")
1679    dev[0].connect(ssid, psk="12345678", scan_freq="2412")
1680
1681    logger.info("WPS configuration step")
1682    dev[0].request("WPS_ER_START ifname=lo")
1683    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
1684    if ev is None:
1685        raise Exception("AP discovery timed out")
1686    if ap_uuid not in ev:
1687        raise Exception("Expected AP UUID not found")
1688    new_passphrase = "1234567890"
1689    dev[0].request("WPS_ER_CONFIG " + apdev[0]['bssid'] + " " + ap_pin + " " +
1690                   binascii.hexlify(ssid.encode()).decode() + " WPA2PSK CCMP " +
1691                   binascii.hexlify(new_passphrase.encode()).decode())
1692    ev = dev[0].wait_event(["WPS-SUCCESS"])
1693    if ev is None:
1694        raise Exception("WPS ER configuration operation timed out")
1695    dev[0].wait_disconnected(timeout=10)
1696    dev[0].connect(ssid, psk="1234567890", scan_freq="2412")
1697
1698    logger.info("WPS ER restart")
1699    dev[0].request("WPS_ER_START")
1700    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
1701    if ev is None:
1702        raise Exception("AP discovery timed out on ER restart")
1703    if ap_uuid not in ev:
1704        raise Exception("Expected AP UUID not found on ER restart")
1705    if "OK" not in dev[0].request("WPS_ER_STOP"):
1706        raise Exception("WPS_ER_STOP failed")
1707    if "OK" not in dev[0].request("WPS_ER_STOP"):
1708        raise Exception("WPS_ER_STOP failed")
1709
1710@remote_compatible
1711def test_ap_wps_er_cache_ap_settings(dev, apdev):
1712    """WPS ER caching AP settings"""
1713    try:
1714        _test_ap_wps_er_cache_ap_settings(dev, apdev)
1715    finally:
1716        dev[0].request("WPS_ER_STOP")
1717
1718def _test_ap_wps_er_cache_ap_settings(dev, apdev):
1719    ssid = "wps-er-add-enrollee"
1720    ap_pin = "12345670"
1721    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
1722    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1723              "wpa_passphrase": "12345678", "wpa": "2",
1724              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
1725              "device_name": "Wireless AP", "manufacturer": "Company",
1726              "model_name": "WAP", "model_number": "123",
1727              "serial_number": "12345", "device_type": "6-0050F204-1",
1728              "os_version": "01020300",
1729              "config_methods": "label push_button",
1730              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
1731    hapd = hostapd.add_ap(apdev[0], params)
1732    dev[0].flush_scan_cache()
1733    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
1734    dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
1735    id = int(dev[0].list_networks()[0]['id'])
1736    dev[0].set_network(id, "scan_freq", "2412")
1737
1738    dev[0].request("WPS_ER_START ifname=lo")
1739    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
1740    if ev is None:
1741        raise Exception("AP discovery timed out")
1742    if ap_uuid not in ev:
1743        raise Exception("Expected AP UUID not found")
1744
1745    dev[0].dump_monitor()
1746    dev[0].request("WPS_ER_LEARN " + ap_uuid + " " + ap_pin)
1747    ev = dev[0].wait_event(["WPS-ER-AP-SETTINGS"], timeout=15)
1748    if ev is None:
1749        raise Exception("AP learn timed out")
1750    ev = dev[0].wait_event(["WPS-FAIL"], timeout=15)
1751    if ev is None:
1752        raise Exception("WPS-FAIL after AP learn timed out")
1753    time.sleep(0.1)
1754
1755    hapd.disable()
1756
1757    for i in range(2):
1758        ev = dev[0].wait_event(["WPS-ER-AP-REMOVE", "CTRL-EVENT-DISCONNECTED"],
1759                               timeout=15)
1760        if ev is None:
1761            raise Exception("AP removal or disconnection timed out")
1762
1763    hapd = hostapd.add_ap(apdev[0], params)
1764    for i in range(2):
1765        ev = dev[0].wait_event(["WPS-ER-AP-ADD", "CTRL-EVENT-CONNECTED"],
1766                               timeout=15)
1767        if ev is None:
1768            raise Exception("AP discovery or connection timed out")
1769
1770    pin = dev[1].wps_read_pin()
1771    dev[0].dump_monitor()
1772    dev[0].request("WPS_ER_PIN any " + pin + " " + dev[1].p2p_interface_addr())
1773
1774    time.sleep(0.2)
1775
1776    dev[1].scan_for_bss(apdev[0]['bssid'], freq=2412)
1777    dev[1].dump_monitor()
1778    dev[1].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
1779    ev = dev[1].wait_event(["WPS-SUCCESS"], timeout=30)
1780    if ev is None:
1781        raise Exception("Enrollee did not report success")
1782    dev[1].wait_connected(timeout=15)
1783    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
1784    if ev is None:
1785        raise Exception("WPS ER did not report success")
1786
1787    dev[0].dump_monitor()
1788    dev[0].request("WPS_ER_STOP")
1789
1790def test_ap_wps_er_cache_ap_settings_oom(dev, apdev):
1791    """WPS ER caching AP settings (OOM)"""
1792    try:
1793        _test_ap_wps_er_cache_ap_settings_oom(dev, apdev)
1794    finally:
1795        dev[0].request("WPS_ER_STOP")
1796
1797def _test_ap_wps_er_cache_ap_settings_oom(dev, apdev):
1798    ssid = "wps-er-add-enrollee"
1799    ap_pin = "12345670"
1800    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
1801    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1802              "wpa_passphrase": "12345678", "wpa": "2",
1803              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
1804              "device_name": "Wireless AP", "manufacturer": "Company",
1805              "model_name": "WAP", "model_number": "123",
1806              "serial_number": "12345", "device_type": "6-0050F204-1",
1807              "os_version": "01020300",
1808              "config_methods": "label push_button",
1809              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
1810    hapd = hostapd.add_ap(apdev[0], params)
1811    dev[0].flush_scan_cache()
1812    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
1813    dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
1814    id = int(dev[0].list_networks()[0]['id'])
1815    dev[0].set_network(id, "scan_freq", "2412")
1816
1817    dev[0].request("WPS_ER_START ifname=lo")
1818    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
1819    if ev is None:
1820        raise Exception("AP discovery timed out")
1821    if ap_uuid not in ev:
1822        raise Exception("Expected AP UUID not found")
1823
1824    dev[0].dump_monitor()
1825    dev[0].request("WPS_ER_LEARN " + ap_uuid + " " + ap_pin)
1826    ev = dev[0].wait_event(["WPS-ER-AP-SETTINGS"], timeout=15)
1827    if ev is None:
1828        raise Exception("AP learn timed out")
1829    ev = dev[0].wait_event(["WPS-FAIL"], timeout=15)
1830    if ev is None:
1831        raise Exception("WPS-FAIL after AP learn timed out")
1832    time.sleep(0.1)
1833
1834    with alloc_fail(dev[0], 1, "=wps_er_ap_use_cached_settings"):
1835        hapd.disable()
1836
1837        for i in range(2):
1838            ev = dev[0].wait_event(["WPS-ER-AP-REMOVE",
1839                                    "CTRL-EVENT-DISCONNECTED"],
1840                                   timeout=15)
1841            if ev is None:
1842                raise Exception("AP removal or disconnection timed out")
1843
1844        hapd = hostapd.add_ap(apdev[0], params)
1845        for i in range(2):
1846            ev = dev[0].wait_event(["WPS-ER-AP-ADD", "CTRL-EVENT-CONNECTED"],
1847                                   timeout=15)
1848            if ev is None:
1849                raise Exception("AP discovery or connection timed out")
1850
1851    dev[0].request("WPS_ER_STOP")
1852
1853def test_ap_wps_er_cache_ap_settings_oom2(dev, apdev):
1854    """WPS ER caching AP settings (OOM 2)"""
1855    try:
1856        _test_ap_wps_er_cache_ap_settings_oom2(dev, apdev)
1857    finally:
1858        dev[0].request("WPS_ER_STOP")
1859
1860def _test_ap_wps_er_cache_ap_settings_oom2(dev, apdev):
1861    ssid = "wps-er-add-enrollee"
1862    ap_pin = "12345670"
1863    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
1864    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1865              "wpa_passphrase": "12345678", "wpa": "2",
1866              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
1867              "device_name": "Wireless AP", "manufacturer": "Company",
1868              "model_name": "WAP", "model_number": "123",
1869              "serial_number": "12345", "device_type": "6-0050F204-1",
1870              "os_version": "01020300",
1871              "config_methods": "label push_button",
1872              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
1873    hapd = hostapd.add_ap(apdev[0], params)
1874    dev[0].flush_scan_cache()
1875    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
1876    dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
1877    id = int(dev[0].list_networks()[0]['id'])
1878    dev[0].set_network(id, "scan_freq", "2412")
1879
1880    dev[0].request("WPS_ER_START ifname=lo")
1881    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
1882    if ev is None:
1883        raise Exception("AP discovery timed out")
1884    if ap_uuid not in ev:
1885        raise Exception("Expected AP UUID not found")
1886
1887    dev[0].dump_monitor()
1888    dev[0].request("WPS_ER_LEARN " + ap_uuid + " " + ap_pin)
1889    ev = dev[0].wait_event(["WPS-ER-AP-SETTINGS"], timeout=15)
1890    if ev is None:
1891        raise Exception("AP learn timed out")
1892    ev = dev[0].wait_event(["WPS-FAIL"], timeout=15)
1893    if ev is None:
1894        raise Exception("WPS-FAIL after AP learn timed out")
1895    time.sleep(0.1)
1896
1897    with alloc_fail(dev[0], 1, "=wps_er_ap_cache_settings"):
1898        hapd.disable()
1899
1900        for i in range(2):
1901            ev = dev[0].wait_event(["WPS-ER-AP-REMOVE",
1902                                    "CTRL-EVENT-DISCONNECTED"],
1903                                   timeout=15)
1904            if ev is None:
1905                raise Exception("AP removal or disconnection timed out")
1906
1907        hapd = hostapd.add_ap(apdev[0], params)
1908        for i in range(2):
1909            ev = dev[0].wait_event(["WPS-ER-AP-ADD", "CTRL-EVENT-CONNECTED"],
1910                                   timeout=15)
1911            if ev is None:
1912                raise Exception("AP discovery or connection timed out")
1913
1914    dev[0].request("WPS_ER_STOP")
1915
1916def test_ap_wps_er_subscribe_oom(dev, apdev):
1917    """WPS ER subscribe OOM"""
1918    try:
1919        _test_ap_wps_er_subscribe_oom(dev, apdev)
1920    finally:
1921        dev[0].request("WPS_ER_STOP")
1922
1923def _test_ap_wps_er_subscribe_oom(dev, apdev):
1924    ssid = "wps-er-add-enrollee"
1925    ap_pin = "12345670"
1926    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
1927    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1928              "wpa_passphrase": "12345678", "wpa": "2",
1929              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
1930              "device_name": "Wireless AP", "manufacturer": "Company",
1931              "model_name": "WAP", "model_number": "123",
1932              "serial_number": "12345", "device_type": "6-0050F204-1",
1933              "os_version": "01020300",
1934              "config_methods": "label push_button",
1935              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
1936    hapd = hostapd.add_ap(apdev[0], params)
1937    dev[0].flush_scan_cache()
1938    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
1939    dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
1940    id = int(dev[0].list_networks()[0]['id'])
1941    dev[0].set_network(id, "scan_freq", "2412")
1942
1943    with alloc_fail(dev[0], 1, "http_client_addr;wps_er_subscribe"):
1944        dev[0].request("WPS_ER_START ifname=lo")
1945        for i in range(50):
1946            res = dev[0].request("GET_ALLOC_FAIL")
1947            if res.startswith("0:"):
1948                break
1949            time.sleep(0.1)
1950        ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=0)
1951        if ev:
1952            raise Exception("Unexpected AP discovery during OOM")
1953
1954    dev[0].request("WPS_ER_STOP")
1955
1956def test_ap_wps_er_set_sel_reg_oom(dev, apdev):
1957    """WPS ER SetSelectedRegistrar OOM"""
1958    try:
1959        _test_ap_wps_er_set_sel_reg_oom(dev, apdev)
1960    finally:
1961        dev[0].request("WPS_ER_STOP")
1962
1963def _test_ap_wps_er_set_sel_reg_oom(dev, apdev):
1964    ssid = "wps-er-add-enrollee"
1965    ap_pin = "12345670"
1966    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
1967    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
1968              "wpa_passphrase": "12345678", "wpa": "2",
1969              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
1970              "device_name": "Wireless AP", "manufacturer": "Company",
1971              "model_name": "WAP", "model_number": "123",
1972              "serial_number": "12345", "device_type": "6-0050F204-1",
1973              "os_version": "01020300",
1974              "config_methods": "label push_button",
1975              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
1976    hapd = hostapd.add_ap(apdev[0], params)
1977    dev[0].flush_scan_cache()
1978    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
1979    dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
1980
1981    dev[0].request("WPS_ER_START ifname=lo")
1982    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=10)
1983    if ev is None:
1984        raise Exception("AP not discovered")
1985
1986    dev[0].request("WPS_ER_LEARN " + ap_uuid + " " + ap_pin)
1987    ev = dev[0].wait_event(["WPS-ER-AP-SETTINGS"], timeout=15)
1988    if ev is None:
1989        raise Exception("AP learn timed out")
1990    ev = dev[0].wait_event(["WPS-FAIL"], timeout=15)
1991    if ev is None:
1992        raise Exception("WPS-FAIL timed out")
1993    time.sleep(0.1)
1994
1995    for func in ["http_client_url_parse;wps_er_send_set_sel_reg",
1996                 "wps_er_soap_hdr;wps_er_send_set_sel_reg",
1997                 "http_client_addr;wps_er_send_set_sel_reg",
1998                 "wpabuf_alloc;wps_er_set_sel_reg"]:
1999        with alloc_fail(dev[0], 1, func):
2000            if "OK" not in dev[0].request("WPS_ER_PBC " + ap_uuid):
2001                raise Exception("WPS_ER_PBC failed")
2002            ev = dev[0].wait_event(["WPS-PBC-ACTIVE"], timeout=3)
2003            if ev is None:
2004                raise Exception("WPS-PBC-ACTIVE not seen")
2005
2006    dev[0].request("WPS_ER_STOP")
2007
2008@remote_compatible
2009def test_ap_wps_er_learn_oom(dev, apdev):
2010    """WPS ER learn OOM"""
2011    try:
2012        _test_ap_wps_er_learn_oom(dev, apdev)
2013    finally:
2014        dev[0].request("WPS_ER_STOP")
2015
2016def _test_ap_wps_er_learn_oom(dev, apdev):
2017    ssid = "wps-er-add-enrollee"
2018    ap_pin = "12345670"
2019    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
2020    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
2021              "wpa_passphrase": "12345678", "wpa": "2",
2022              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
2023              "device_name": "Wireless AP", "manufacturer": "Company",
2024              "model_name": "WAP", "model_number": "123",
2025              "serial_number": "12345", "device_type": "6-0050F204-1",
2026              "os_version": "01020300",
2027              "config_methods": "label push_button",
2028              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
2029    hapd = hostapd.add_ap(apdev[0], params)
2030    dev[0].flush_scan_cache()
2031    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
2032    dev[0].wps_reg(apdev[0]['bssid'], ap_pin)
2033
2034    dev[0].request("WPS_ER_START ifname=lo")
2035    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=10)
2036    if ev is None:
2037        raise Exception("AP not discovered")
2038
2039    for func in ["wps_er_http_put_message_cb",
2040                 "xml_get_base64_item;wps_er_http_put_message_cb",
2041                 "http_client_url_parse;wps_er_ap_put_message",
2042                 "wps_er_soap_hdr;wps_er_ap_put_message",
2043                 "http_client_addr;wps_er_ap_put_message"]:
2044        with alloc_fail(dev[0], 1, func):
2045            dev[0].request("WPS_ER_LEARN " + ap_uuid + " " + ap_pin)
2046            ev = dev[0].wait_event(["WPS-ER-AP-SETTINGS"], timeout=1)
2047            if ev is not None:
2048                raise Exception("AP learn succeeded during OOM")
2049
2050    dev[0].request("WPS_ER_LEARN " + ap_uuid + " " + ap_pin)
2051    ev = dev[0].wait_event(["WPS-ER-AP-SETTINGS"], timeout=10)
2052    if ev is None:
2053        raise Exception("AP learn did not succeed")
2054
2055    if "FAIL" not in dev[0].request("WPS_ER_LEARN 00000000-9e5c-4e73-bd82-f89cbcd10d7e " + ap_pin):
2056        raise Exception("WPS_ER_LEARN for unknown AP accepted")
2057
2058    dev[0].request("WPS_ER_STOP")
2059
2060def test_ap_wps_fragmentation(dev, apdev):
2061    """WPS with fragmentation in EAP-WSC and mixed mode WPA+WPA2"""
2062    skip_without_tkip(dev[0])
2063    ssid = "test-wps-fragmentation"
2064    appin = "12345670"
2065    hapd = hostapd.add_ap(apdev[0],
2066                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
2067                           "wpa_passphrase": "12345678", "wpa": "3",
2068                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
2069                           "wpa_pairwise": "TKIP", "ap_pin": appin,
2070                           "fragment_size": "50"})
2071    logger.info("WPS provisioning step (PBC)")
2072    hapd.request("WPS_PBC")
2073    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
2074    dev[0].dump_monitor()
2075    dev[0].request("SET wps_fragment_size 50")
2076    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
2077    dev[0].wait_connected(timeout=30)
2078    status = dev[0].get_status()
2079    if status['wpa_state'] != 'COMPLETED':
2080        raise Exception("Not fully connected")
2081    if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'TKIP':
2082        raise Exception("Unexpected encryption configuration")
2083    if status['key_mgmt'] != 'WPA2-PSK':
2084        raise Exception("Unexpected key_mgmt")
2085
2086    logger.info("WPS provisioning step (PIN)")
2087    pin = dev[1].wps_read_pin()
2088    hapd.request("WPS_PIN any " + pin)
2089    dev[1].scan_for_bss(apdev[0]['bssid'], freq=2412)
2090    dev[1].request("SET wps_fragment_size 50")
2091    dev[1].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
2092    dev[1].wait_connected(timeout=30)
2093    status = dev[1].get_status()
2094    if status['wpa_state'] != 'COMPLETED':
2095        raise Exception("Not fully connected")
2096    if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'TKIP':
2097        raise Exception("Unexpected encryption configuration")
2098    if status['key_mgmt'] != 'WPA2-PSK':
2099        raise Exception("Unexpected key_mgmt")
2100
2101    logger.info("WPS connection as registrar")
2102    dev[2].scan_for_bss(apdev[0]['bssid'], freq=2412)
2103    dev[2].request("SET wps_fragment_size 50")
2104    dev[2].wps_reg(apdev[0]['bssid'], appin)
2105    status = dev[2].get_status()
2106    if status['wpa_state'] != 'COMPLETED':
2107        raise Exception("Not fully connected")
2108    if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'TKIP':
2109        raise Exception("Unexpected encryption configuration")
2110    if status['key_mgmt'] != 'WPA2-PSK':
2111        raise Exception("Unexpected key_mgmt")
2112
2113@remote_compatible
2114def test_ap_wps_new_version_sta(dev, apdev):
2115    """WPS compatibility with new version number on the station"""
2116    ssid = "test-wps-ver"
2117    hapd = hostapd.add_ap(apdev[0],
2118                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
2119                           "wpa_passphrase": "12345678", "wpa": "2",
2120                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
2121    logger.info("WPS provisioning step")
2122    hapd.request("WPS_PBC")
2123    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
2124    dev[0].dump_monitor()
2125    dev[0].request("SET wps_version_number 0x43")
2126    dev[0].request("SET wps_vendor_ext_m1 000137100100020001")
2127    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
2128    dev[0].wait_connected(timeout=30)
2129
2130@remote_compatible
2131def test_ap_wps_new_version_ap(dev, apdev):
2132    """WPS compatibility with new version number on the AP"""
2133    ssid = "test-wps-ver"
2134    hapd = hostapd.add_ap(apdev[0],
2135                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
2136                           "wpa_passphrase": "12345678", "wpa": "2",
2137                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
2138    logger.info("WPS provisioning step")
2139    if "FAIL" in hapd.request("SET wps_version_number 0x43"):
2140        raise Exception("Failed to enable test functionality")
2141    hapd.request("WPS_PBC")
2142    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
2143    dev[0].dump_monitor()
2144    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
2145    dev[0].wait_connected(timeout=30)
2146    hapd.request("SET wps_version_number 0x20")
2147
2148@remote_compatible
2149def test_ap_wps_check_pin(dev, apdev):
2150    """Verify PIN checking through control interface"""
2151    hapd = hostapd.add_ap(apdev[0],
2152                          {"ssid": "wps", "eap_server": "1", "wps_state": "2",
2153                           "wpa_passphrase": "12345678", "wpa": "2",
2154                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
2155    for t in [("12345670", "12345670"),
2156              ("12345678", "FAIL-CHECKSUM"),
2157              ("12345", "FAIL"),
2158              ("123456789", "FAIL"),
2159              ("1234-5670", "12345670"),
2160              ("1234 5670", "12345670"),
2161              ("1-2.3:4 5670", "12345670")]:
2162        res = hapd.request("WPS_CHECK_PIN " + t[0]).rstrip('\n')
2163        res2 = dev[0].request("WPS_CHECK_PIN " + t[0]).rstrip('\n')
2164        if res != res2:
2165            raise Exception("Unexpected difference in WPS_CHECK_PIN responses")
2166        if res != t[1]:
2167            raise Exception("Incorrect WPS_CHECK_PIN response {} (expected {})".format(res, t[1]))
2168
2169    if "FAIL" not in hapd.request("WPS_CHECK_PIN 12345"):
2170        raise Exception("Unexpected WPS_CHECK_PIN success")
2171    if "FAIL" not in hapd.request("WPS_CHECK_PIN 123456789"):
2172        raise Exception("Unexpected WPS_CHECK_PIN success")
2173
2174    for i in range(0, 10):
2175        pin = dev[0].request("WPS_PIN get")
2176        rpin = dev[0].request("WPS_CHECK_PIN " + pin).rstrip('\n')
2177        if pin != rpin:
2178            raise Exception("Random PIN validation failed for " + pin)
2179
2180def test_ap_wps_pin_get_failure(dev, apdev):
2181    """PIN generation failure"""
2182    with fail_test(dev[0], 1,
2183                   "os_get_random;wpa_supplicant_ctrl_iface_wps_pin"):
2184        if "FAIL" not in dev[0].request("WPS_PIN get"):
2185            raise Exception("WPS_PIN did not report failure")
2186
2187def test_ap_wps_wep_config(dev, apdev):
2188    """WPS 2.0 AP rejecting WEP configuration"""
2189    ssid = "test-wps-config"
2190    appin = "12345670"
2191    hapd = hostapd.add_ap(apdev[0],
2192                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
2193                           "ap_pin": appin})
2194    dev[0].flush_scan_cache()
2195    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
2196    dev[0].wps_reg(apdev[0]['bssid'], appin, "wps-new-ssid-wep", "OPEN", "WEP",
2197                   "hello", no_wait=True)
2198    ev = hapd.wait_event(["WPS-FAIL"], timeout=15)
2199    if ev is None:
2200        raise Exception("WPS-FAIL timed out")
2201    if "reason=2" not in ev:
2202        raise Exception("Unexpected reason code in WPS-FAIL")
2203    status = hapd.request("WPS_GET_STATUS")
2204    if "Last WPS result: Failed" not in status:
2205        raise Exception("WPS failure result not shown correctly")
2206    if "Failure Reason: WEP Prohibited" not in status:
2207        raise Exception("Failure reason not reported correctly")
2208    if "Peer Address: " + dev[0].p2p_interface_addr() not in status:
2209        raise Exception("Peer address not shown correctly")
2210
2211def test_ap_wps_wep_enroll(dev, apdev):
2212    """WPS 2.0 STA rejecting WEP configuration"""
2213    ssid = "test-wps-wep"
2214    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
2215              "skip_cred_build": "1", "extra_cred": "wps-wep-cred"}
2216    hapd = hostapd.add_ap(apdev[0], params)
2217    hapd.request("WPS_PBC")
2218    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
2219    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
2220    ev = dev[0].wait_event(["WPS-FAIL"], timeout=15)
2221    if ev is None:
2222        raise Exception("WPS-FAIL event timed out")
2223    if "msg=12" not in ev or "reason=2 (WEP Prohibited)" not in ev:
2224        raise Exception("Unexpected WPS-FAIL event: " + ev)
2225
2226@remote_compatible
2227def test_ap_wps_ie_fragmentation(dev, apdev):
2228    """WPS AP using fragmented WPS IE"""
2229    ssid = "test-wps-ie-fragmentation"
2230    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
2231              "wpa_passphrase": "12345678", "wpa": "2",
2232              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
2233              "device_name": "1234567890abcdef1234567890abcdef",
2234              "manufacturer": "1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
2235              "model_name": "1234567890abcdef1234567890abcdef",
2236              "model_number": "1234567890abcdef1234567890abcdef",
2237              "serial_number": "1234567890abcdef1234567890abcdef"}
2238    hapd = hostapd.add_ap(apdev[0], params)
2239    hapd.request("WPS_PBC")
2240    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
2241    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
2242    dev[0].wait_connected(timeout=30)
2243    bss = dev[0].get_bss(apdev[0]['bssid'])
2244    if "wps_device_name" not in bss or bss['wps_device_name'] != "1234567890abcdef1234567890abcdef":
2245        logger.info("Device Name not received correctly")
2246        logger.info(bss)
2247        # This can fail if Probe Response frame is missed and Beacon frame was
2248        # used to fill in the BSS entry. This can happen, e.g., during heavy
2249        # load every now and then and is not really an error, so try to
2250        # workaround by runnign another scan.
2251        dev[0].scan(freq="2412", only_new=True)
2252        bss = dev[0].get_bss(apdev[0]['bssid'])
2253        if not bss or "wps_device_name" not in bss or bss['wps_device_name'] != "1234567890abcdef1234567890abcdef":
2254            logger.info(bss)
2255            raise Exception("Device Name not received correctly")
2256    if len(re.findall("dd..0050f204", bss['ie'])) != 2:
2257        raise Exception("Unexpected number of WPS IEs")
2258
2259def get_psk(pskfile):
2260    psks = {}
2261    with open(pskfile, "r") as f:
2262        lines = f.read().splitlines()
2263        for l in lines:
2264            if l == "# WPA PSKs":
2265                continue
2266            vals = l.split(' ')
2267            if len(vals) != 3 or vals[0] != "wps=1":
2268                continue
2269            addr = vals[1]
2270            psk = vals[2]
2271            psks[addr] = psk
2272    return psks
2273
2274def test_ap_wps_per_station_psk(dev, apdev):
2275    """WPS PBC provisioning with per-station PSK"""
2276    addr0 = dev[0].own_addr()
2277    addr1 = dev[1].own_addr()
2278    addr2 = dev[2].own_addr()
2279    ssid = "wps"
2280    appin = "12345670"
2281    pskfile = "/tmp/ap_wps_per_enrollee_psk.psk_file"
2282    try:
2283        os.remove(pskfile)
2284    except:
2285        pass
2286
2287    hapd = None
2288    try:
2289        with open(pskfile, "w") as f:
2290            f.write("# WPA PSKs\n")
2291
2292        params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
2293                  "wpa": "2", "wpa_key_mgmt": "WPA-PSK",
2294                  "rsn_pairwise": "CCMP", "ap_pin": appin,
2295                  "wpa_psk_file": pskfile}
2296        hapd = hostapd.add_ap(apdev[0], params)
2297
2298        logger.info("First enrollee")
2299        hapd.request("WPS_PBC")
2300        dev[0].flush_scan_cache()
2301        dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
2302        dev[0].request("WPS_PBC " + apdev[0]['bssid'])
2303        dev[0].wait_connected(timeout=30)
2304
2305        logger.info("Second enrollee")
2306        hapd.request("WPS_PBC")
2307        dev[1].scan_for_bss(apdev[0]['bssid'], freq=2412)
2308        dev[1].request("WPS_PBC " + apdev[0]['bssid'])
2309        dev[1].wait_connected(timeout=30)
2310
2311        logger.info("External registrar")
2312        dev[2].scan_for_bss(apdev[0]['bssid'], freq=2412)
2313        dev[2].wps_reg(apdev[0]['bssid'], appin)
2314
2315        logger.info("Verifying PSK results")
2316        psks = get_psk(pskfile)
2317        if addr0 not in psks:
2318            raise Exception("No PSK recorded for sta0")
2319        if addr1 not in psks:
2320            raise Exception("No PSK recorded for sta1")
2321        if addr2 not in psks:
2322            raise Exception("No PSK recorded for sta2")
2323        if psks[addr0] == psks[addr1]:
2324            raise Exception("Same PSK recorded for sta0 and sta1")
2325        if psks[addr0] == psks[addr2]:
2326            raise Exception("Same PSK recorded for sta0 and sta2")
2327        if psks[addr1] == psks[addr2]:
2328            raise Exception("Same PSK recorded for sta1 and sta2")
2329
2330        dev[0].request("REMOVE_NETWORK all")
2331        logger.info("Second external registrar")
2332        dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
2333        dev[0].wps_reg(apdev[0]['bssid'], appin)
2334        psks2 = get_psk(pskfile)
2335        if addr0 not in psks2:
2336            raise Exception("No PSK recorded for sta0(reg)")
2337        if psks[addr0] == psks2[addr0]:
2338            raise Exception("Same PSK recorded for sta0(enrollee) and sta0(reg)")
2339    finally:
2340        os.remove(pskfile)
2341        if hapd:
2342            dev[0].request("DISCONNECT")
2343            dev[1].request("DISCONNECT")
2344            dev[2].request("DISCONNECT")
2345            hapd.disable()
2346            dev[0].flush_scan_cache()
2347            dev[1].flush_scan_cache()
2348            dev[2].flush_scan_cache()
2349
2350def test_ap_wps_per_station_psk_preset(dev, apdev):
2351    """WPS PIN provisioning with per-station PSK preset"""
2352    addr0 = dev[0].own_addr()
2353    addr1 = dev[1].own_addr()
2354    addr2 = dev[2].own_addr()
2355    ssid = "wps"
2356    appin = "12345670"
2357    pskfile = "/tmp/ap_wps_per_enrollee_psk_preset.psk_file"
2358    try:
2359        os.remove(pskfile)
2360    except:
2361        pass
2362
2363    hapd = None
2364    try:
2365        with open(pskfile, "w") as f:
2366            f.write("# WPA PSKs\n")
2367            f.write("wps=1 " + addr0 + " preset-passphrase-0\n")
2368            f.write("wps=1 " + addr2 + " preset-passphrase-2\n")
2369
2370        params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
2371                  "wpa": "2", "wpa_key_mgmt": "WPA-PSK",
2372                  "rsn_pairwise": "CCMP", "ap_pin": appin,
2373                  "wpa_psk_file": pskfile}
2374        hapd = hostapd.add_ap(apdev[0], params)
2375        bssid = hapd.own_addr()
2376
2377        logger.info("First enrollee")
2378        pin = dev[0].wps_read_pin()
2379        hapd.request("WPS_PIN any " + pin)
2380        dev[0].scan_for_bss(bssid, freq=2412)
2381        dev[0].request("WPS_PIN %s %s" % (bssid, pin))
2382        dev[0].wait_connected(timeout=30)
2383
2384        logger.info("Second enrollee")
2385        pin = dev[1].wps_read_pin()
2386        hapd.request("WPS_PIN any " + pin)
2387        dev[1].scan_for_bss(bssid, freq=2412)
2388        dev[1].request("WPS_PIN %s %s" % (bssid, pin))
2389        dev[1].wait_connected(timeout=30)
2390
2391        logger.info("External registrar")
2392        dev[2].scan_for_bss(bssid, freq=2412)
2393        dev[2].wps_reg(bssid, appin)
2394
2395        logger.info("Verifying PSK results")
2396        psks = get_psk(pskfile)
2397        if addr0 not in psks:
2398            raise Exception("No PSK recorded for sta0")
2399        if addr1 not in psks:
2400            raise Exception("No PSK recorded for sta1")
2401        if addr2 not in psks:
2402            raise Exception("No PSK recorded for sta2")
2403        logger.info("PSK[0]: " + psks[addr0])
2404        logger.info("PSK[1]: " + psks[addr1])
2405        logger.info("PSK[2]: " + psks[addr2])
2406        if psks[addr0] == psks[addr1]:
2407            raise Exception("Same PSK recorded for sta0 and sta1")
2408        if psks[addr0] == psks[addr2]:
2409            raise Exception("Same PSK recorded for sta0 and sta2")
2410        if psks[addr1] == psks[addr2]:
2411            raise Exception("Same PSK recorded for sta1 and sta2")
2412        pmk0 = hapd.request("GET_PMK " + addr0)
2413        pmk1 = hapd.request("GET_PMK " + addr1)
2414        pmk2 = hapd.request("GET_PMK " + addr2)
2415        logger.info("PMK[0]: " + pmk0)
2416        logger.info("PMK[1]: " + pmk1)
2417        logger.info("PMK[2]: " + pmk2)
2418        if pmk0 != "565faec21ff04702d9d17c464e1301efd36c8a3ea46bb866b4bec7fed4384579":
2419            raise Exception("PSK[0] mismatch")
2420        if psks[addr1] != pmk1:
2421            raise Exception("PSK[1] mismatch")
2422        if psks[addr2] != pmk2:
2423            raise Exception("PSK[2] mismatch")
2424
2425        dev[0].request("REMOVE_NETWORK all")
2426        dev[0].wait_disconnected()
2427        dev[0].dump_monitor()
2428        logger.info("First enrollee again")
2429        pin = dev[0].wps_read_pin()
2430        hapd.request("WPS_PIN any " + pin)
2431        dev[0].scan_for_bss(bssid, freq=2412)
2432        dev[0].request("WPS_PIN %s %s" % (bssid, pin))
2433        dev[0].wait_connected(timeout=30)
2434        psks2 = get_psk(pskfile)
2435        if addr0 not in psks2:
2436            raise Exception("No PSK recorded for sta0 (2)")
2437        if psks[addr0] != psks2[addr0]:
2438            raise Exception("Different PSK recorded for sta0(enrollee) and sta0(enrollee 2)")
2439    finally:
2440        os.remove(pskfile)
2441
2442def test_ap_wps_per_station_psk_failure(dev, apdev):
2443    """WPS PBC provisioning with per-station PSK (file not writable)"""
2444    addr0 = dev[0].p2p_dev_addr()
2445    addr1 = dev[1].p2p_dev_addr()
2446    addr2 = dev[2].p2p_dev_addr()
2447    ssid = "wps"
2448    appin = "12345670"
2449    pskfile = "/tmp/ap_wps_per_enrollee_psk.psk_file"
2450    try:
2451        os.remove(pskfile)
2452    except:
2453        pass
2454
2455    hapd = None
2456    try:
2457        with open(pskfile, "w") as f:
2458            f.write("# WPA PSKs\n")
2459
2460        params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
2461                  "wpa": "2", "wpa_key_mgmt": "WPA-PSK",
2462                  "rsn_pairwise": "CCMP", "ap_pin": appin,
2463                  "wpa_psk_file": pskfile}
2464        hapd = hostapd.add_ap(apdev[0], params)
2465        if "FAIL" in hapd.request("SET wpa_psk_file /tmp/does/not/exists/ap_wps_per_enrollee_psk_failure.psk_file"):
2466            raise Exception("Failed to set wpa_psk_file")
2467
2468        logger.info("First enrollee")
2469        hapd.request("WPS_PBC")
2470        dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
2471        dev[0].request("WPS_PBC " + apdev[0]['bssid'])
2472        dev[0].wait_connected(timeout=30)
2473
2474        logger.info("Second enrollee")
2475        hapd.request("WPS_PBC")
2476        dev[1].scan_for_bss(apdev[0]['bssid'], freq=2412)
2477        dev[1].request("WPS_PBC " + apdev[0]['bssid'])
2478        dev[1].wait_connected(timeout=30)
2479
2480        logger.info("External registrar")
2481        dev[2].scan_for_bss(apdev[0]['bssid'], freq=2412)
2482        dev[2].wps_reg(apdev[0]['bssid'], appin)
2483
2484        logger.info("Verifying PSK results")
2485        psks = get_psk(pskfile)
2486        if len(psks) > 0:
2487            raise Exception("PSK recorded unexpectedly")
2488    finally:
2489        if hapd:
2490            for i in range(3):
2491                dev[i].request("DISCONNECT")
2492            hapd.disable()
2493            for i in range(3):
2494                dev[i].flush_scan_cache()
2495        os.remove(pskfile)
2496
2497def test_ap_wps_pin_request_file(dev, apdev):
2498    """WPS PIN provisioning with configured AP"""
2499    ssid = "wps"
2500    pinfile = "/tmp/ap_wps_pin_request_file.log"
2501    if os.path.exists(pinfile):
2502        os.remove(pinfile)
2503    hapd = hostapd.add_ap(apdev[0],
2504                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
2505                           "wps_pin_requests": pinfile,
2506                           "wpa_passphrase": "12345678", "wpa": "2",
2507                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
2508    uuid = dev[0].get_status_field("uuid")
2509    pin = dev[0].wps_read_pin()
2510    try:
2511        dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
2512        dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
2513        ev = hapd.wait_event(["WPS-PIN-NEEDED"], timeout=15)
2514        if ev is None:
2515            raise Exception("PIN needed event not shown")
2516        if uuid not in ev:
2517            raise Exception("UUID mismatch")
2518        dev[0].request("WPS_CANCEL")
2519        # hostapd reports WPS-PIN-NEEDED before writing the file, so wait a bit
2520        # for the file to avoid failures due to race condition.
2521        for i in range(10):
2522            if os.path.exists(pinfile):
2523                break
2524            time.sleep(0.1)
2525        success = False
2526        with open(pinfile, "r") as f:
2527            lines = f.readlines()
2528            for l in lines:
2529                if uuid in l:
2530                    success = True
2531                    break
2532        if not success:
2533            raise Exception("PIN request entry not in the log file")
2534    finally:
2535        try:
2536            os.remove(pinfile)
2537        except:
2538            pass
2539
2540def test_ap_wps_auto_setup_with_config_file(dev, apdev):
2541    """WPS auto-setup with configuration file"""
2542    skip_without_tkip(dev[0])
2543    conffile = "/tmp/ap_wps_auto_setup_with_config_file.conf"
2544    ifname = apdev[0]['ifname']
2545    try:
2546        with open(conffile, "w") as f:
2547            f.write("driver=nl80211\n")
2548            f.write("hw_mode=g\n")
2549            f.write("channel=1\n")
2550            f.write("ieee80211n=1\n")
2551            f.write("interface=%s\n" % ifname)
2552            f.write("ctrl_interface=/var/run/hostapd\n")
2553            f.write("ssid=wps\n")
2554            f.write("eap_server=1\n")
2555            f.write("wps_state=1\n")
2556        hapd = hostapd.add_bss(apdev[0], ifname, conffile)
2557        hapd.request("WPS_PBC")
2558        dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
2559        dev[0].request("WPS_PBC " + apdev[0]['bssid'])
2560        dev[0].wait_connected(timeout=30)
2561        with open(conffile, "r") as f:
2562            lines = f.read().splitlines()
2563            vals = dict()
2564            for l in lines:
2565                try:
2566                    [name, value] = l.split('=', 1)
2567                    vals[name] = value
2568                except ValueError as e:
2569                    if "# WPS configuration" in l:
2570                        pass
2571                    else:
2572                        raise Exception("Unexpected configuration line: " + l)
2573        if vals['ieee80211n'] != '1' or vals['wps_state'] != '2' or "WPA-PSK" not in vals['wpa_key_mgmt']:
2574            raise Exception("Incorrect configuration: " + str(vals))
2575    finally:
2576        try:
2577            os.remove(conffile)
2578        except:
2579            pass
2580
2581@long_duration_test
2582def test_ap_wps_pbc_timeout(dev, apdev):
2583    """wpa_supplicant PBC walk time and WPS ER SelReg timeout"""
2584    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
2585    hapd = add_ssdp_ap(apdev[0], ap_uuid)
2586
2587    location = ssdp_get_location(ap_uuid)
2588    urls = upnp_get_urls(location)
2589    eventurl = urlparse(urls['event_sub_url'])
2590    ctrlurl = urlparse(urls['control_url'])
2591
2592    url = urlparse(location)
2593    conn = HTTPConnection(url.netloc)
2594
2595    class WPSERHTTPServer(StreamRequestHandler):
2596        def handle(self):
2597            data = self.rfile.readline().strip()
2598            logger.debug(data)
2599            self.wfile.write(gen_wps_event())
2600
2601    server = MyTCPServer(("127.0.0.1", 12345), WPSERHTTPServer)
2602    server.timeout = 1
2603
2604    headers = {"callback": '<http://127.0.0.1:12345/event>',
2605               "NT": "upnp:event",
2606               "timeout": "Second-1234"}
2607    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
2608    resp = conn.getresponse()
2609    if resp.status != 200:
2610        raise Exception("Unexpected HTTP response: %d" % resp.status)
2611    sid = resp.getheader("sid")
2612    logger.debug("Subscription SID " + sid)
2613
2614    msg = '''<?xml version="1.0"?>
2615<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
2616<s:Body>
2617<u:SetSelectedRegistrar xmlns:u="urn:schemas-wifialliance-org:service:WFAWLANConfig:1">
2618<NewMessage>EEoAARAQQQABARASAAIAABBTAAIxSBBJAA4ANyoAASABBv///////xBIABA2LbR7pTpRkYj7
2619VFi5hrLk
2620</NewMessage>
2621</u:SetSelectedRegistrar>
2622</s:Body>
2623</s:Envelope>'''
2624    headers = {"Content-type": 'text/xml; charset="utf-8"'}
2625    headers["SOAPAction"] = '"urn:schemas-wifialliance-org:service:WFAWLANConfig:1#%s"' % "SetSelectedRegistrar"
2626    conn.request("POST", ctrlurl.path, msg, headers)
2627    resp = conn.getresponse()
2628    if resp.status != 200:
2629        raise Exception("Unexpected HTTP response: %d" % resp.status)
2630
2631    server.handle_request()
2632
2633    logger.info("Start WPS_PBC and wait for PBC walk time expiration")
2634    if "OK" not in dev[0].request("WPS_PBC"):
2635        raise Exception("WPS_PBC failed")
2636
2637    start = os.times()[4]
2638
2639    server.handle_request()
2640    dev[1].request("BSS_FLUSH 0")
2641    dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True,
2642                        only_new=True)
2643    bss = dev[1].get_bss(apdev[0]['bssid'])
2644    logger.debug("BSS: " + str(bss))
2645    if '[WPS-AUTH]' not in bss['flags']:
2646        raise Exception("WPS not indicated authorized")
2647
2648    server.handle_request()
2649
2650    wps_timeout_seen = False
2651
2652    while True:
2653        hapd.dump_monitor()
2654        dev[1].dump_monitor()
2655        if not wps_timeout_seen:
2656            ev = dev[0].wait_event(["WPS-TIMEOUT"], timeout=0)
2657            if ev is not None:
2658                logger.info("PBC timeout seen")
2659                wps_timeout_seen = True
2660        else:
2661            dev[0].dump_monitor()
2662        now = os.times()[4]
2663        if now - start > 130:
2664            raise Exception("Selected registration information not removed")
2665        dev[1].request("BSS_FLUSH 0")
2666        dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True,
2667                            only_new=True)
2668        bss = dev[1].get_bss(apdev[0]['bssid'])
2669        logger.debug("BSS: " + str(bss))
2670        if '[WPS-AUTH]' not in bss['flags']:
2671            break
2672        server.handle_request()
2673
2674    server.server_close()
2675
2676    if wps_timeout_seen:
2677        return
2678
2679    now = os.times()[4]
2680    if now < start + 150:
2681        dur = start + 150 - now
2682    else:
2683        dur = 1
2684    logger.info("Continue waiting for PBC timeout (%d sec)" % dur)
2685    ev = dev[0].wait_event(["WPS-TIMEOUT"], timeout=dur)
2686    if ev is None:
2687        raise Exception("WPS-TIMEOUT not reported")
2688
2689def add_ssdp_ap(ap, ap_uuid):
2690    ssid = "wps-ssdp"
2691    ap_pin = "12345670"
2692    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
2693              "wpa_passphrase": "12345678", "wpa": "2",
2694              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
2695              "device_name": "Wireless AP", "manufacturer": "Company",
2696              "model_name": "WAP", "model_number": "123",
2697              "serial_number": "12345", "device_type": "6-0050F204-1",
2698              "os_version": "01020300",
2699              "config_methods": "label push_button",
2700              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo",
2701              "friendly_name": "WPS Access Point",
2702              "manufacturer_url": "http://www.example.com/",
2703              "model_description": "Wireless Access Point",
2704              "model_url": "http://www.example.com/model/",
2705              "upc": "123456789012"}
2706    return hostapd.add_ap(ap, params)
2707
2708def ssdp_send(msg, no_recv=False):
2709    socket.setdefaulttimeout(1)
2710    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
2711    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
2712    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
2713    sock.bind(("127.0.0.1", 0))
2714    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2715    if no_recv:
2716        return None
2717    return sock.recv(1000).decode()
2718
2719def ssdp_send_msearch(st, no_recv=False):
2720    msg = '\r\n'.join([
2721            'M-SEARCH * HTTP/1.1',
2722            'HOST: 239.255.255.250:1900',
2723            'MX: 1',
2724            'MAN: "ssdp:discover"',
2725            'ST: ' + st,
2726            '', ''])
2727    return ssdp_send(msg, no_recv=no_recv)
2728
2729def test_ap_wps_ssdp_msearch(dev, apdev):
2730    """WPS AP and SSDP M-SEARCH messages"""
2731    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
2732    add_ssdp_ap(apdev[0], ap_uuid)
2733
2734    msg = '\r\n'.join([
2735            'M-SEARCH * HTTP/1.1',
2736            'Host: 239.255.255.250:1900',
2737            'Mx: 1',
2738            'Man: "ssdp:discover"',
2739            'St: urn:schemas-wifialliance-org:device:WFADevice:1',
2740            '', ''])
2741    ssdp_send(msg)
2742
2743    msg = '\r\n'.join([
2744            'M-SEARCH * HTTP/1.1',
2745            'host:\t239.255.255.250:1900\t\t\t\t \t\t',
2746            'mx: \t1\t\t   ',
2747            'man: \t \t "ssdp:discover"   ',
2748            'st: urn:schemas-wifialliance-org:device:WFADevice:1\t\t',
2749            '', ''])
2750    ssdp_send(msg)
2751
2752    ssdp_send_msearch("ssdp:all")
2753    ssdp_send_msearch("upnp:rootdevice")
2754    ssdp_send_msearch("uuid:" + ap_uuid)
2755    ssdp_send_msearch("urn:schemas-wifialliance-org:service:WFAWLANConfig:1")
2756    ssdp_send_msearch("urn:schemas-wifialliance-org:device:WFADevice:1")
2757
2758    msg = '\r\n'.join([
2759            'M-SEARCH * HTTP/1.1',
2760            'HOST:\t239.255.255.250:1900',
2761            'MAN: "ssdp:discover"',
2762            'MX: 130',
2763            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2764            '', ''])
2765    ssdp_send(msg, no_recv=True)
2766
2767def test_ap_wps_ssdp_invalid_msearch(dev, apdev):
2768    """WPS AP and invalid SSDP M-SEARCH messages"""
2769    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
2770    add_ssdp_ap(apdev[0], ap_uuid)
2771
2772    socket.setdefaulttimeout(1)
2773    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
2774    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
2775    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
2776    sock.bind(("127.0.0.1", 0))
2777
2778    logger.debug("Missing MX")
2779    msg = '\r\n'.join([
2780            'M-SEARCH * HTTP/1.1',
2781            'HOST: 239.255.255.250:1900',
2782            'MAN: "ssdp:discover"',
2783            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2784            '', ''])
2785    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2786
2787    logger.debug("Negative MX")
2788    msg = '\r\n'.join([
2789            'M-SEARCH * HTTP/1.1',
2790            'HOST: 239.255.255.250:1900',
2791            'MX: -1',
2792            'MAN: "ssdp:discover"',
2793            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2794            '', ''])
2795    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2796
2797    logger.debug("Invalid MX")
2798    msg = '\r\n'.join([
2799            'M-SEARCH * HTTP/1.1',
2800            'HOST: 239.255.255.250:1900',
2801            'MX; 1',
2802            'MAN: "ssdp:discover"',
2803            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2804            '', ''])
2805    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2806
2807    logger.debug("Missing MAN")
2808    msg = '\r\n'.join([
2809            'M-SEARCH * HTTP/1.1',
2810            'HOST: 239.255.255.250:1900',
2811            'MX: 1',
2812            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2813            '', ''])
2814    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2815
2816    logger.debug("Invalid MAN")
2817    msg = '\r\n'.join([
2818            'M-SEARCH * HTTP/1.1',
2819            'HOST: 239.255.255.250:1900',
2820            'MX: 1',
2821            'MAN: foo',
2822            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2823            '', ''])
2824    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2825    msg = '\r\n'.join([
2826            'M-SEARCH * HTTP/1.1',
2827            'HOST: 239.255.255.250:1900',
2828            'MX: 1',
2829            'MAN; "ssdp:discover"',
2830            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2831            '', ''])
2832    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2833
2834    logger.debug("Missing HOST")
2835    msg = '\r\n'.join([
2836            'M-SEARCH * HTTP/1.1',
2837            'MAN: "ssdp:discover"',
2838            'MX: 1',
2839            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2840            '', ''])
2841    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2842
2843    logger.debug("Missing ST")
2844    msg = '\r\n'.join([
2845            'M-SEARCH * HTTP/1.1',
2846            'HOST: 239.255.255.250:1900',
2847            'MAN: "ssdp:discover"',
2848            'MX: 1',
2849            '', ''])
2850    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2851
2852    logger.debug("Mismatching ST")
2853    msg = '\r\n'.join([
2854            'M-SEARCH * HTTP/1.1',
2855            'HOST: 239.255.255.250:1900',
2856            'MAN: "ssdp:discover"',
2857            'MX: 1',
2858            'ST: uuid:16d5f8a9-4ee4-4f5e-81f9-cc6e2f47f42d',
2859            '', ''])
2860    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2861    msg = '\r\n'.join([
2862            'M-SEARCH * HTTP/1.1',
2863            'HOST: 239.255.255.250:1900',
2864            'MAN: "ssdp:discover"',
2865            'MX: 1',
2866            'ST: foo:bar',
2867            '', ''])
2868    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2869    msg = '\r\n'.join([
2870            'M-SEARCH * HTTP/1.1',
2871            'HOST: 239.255.255.250:1900',
2872            'MAN: "ssdp:discover"',
2873            'MX: 1',
2874            'ST: foobar',
2875            '', ''])
2876    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2877
2878    logger.debug("Invalid ST")
2879    msg = '\r\n'.join([
2880            'M-SEARCH * HTTP/1.1',
2881            'HOST: 239.255.255.250:1900',
2882            'MAN: "ssdp:discover"',
2883            'MX: 1',
2884            'ST; urn:schemas-wifialliance-org:device:WFADevice:1',
2885            '', ''])
2886    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2887
2888    logger.debug("Invalid M-SEARCH")
2889    msg = '\r\n'.join([
2890            'M+SEARCH * HTTP/1.1',
2891            'HOST: 239.255.255.250:1900',
2892            'MAN: "ssdp:discover"',
2893            'MX: 1',
2894            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2895            '', ''])
2896    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2897    msg = '\r\n'.join([
2898            'M-SEARCH-* HTTP/1.1',
2899            'HOST: 239.255.255.250:1900',
2900            'MAN: "ssdp:discover"',
2901            'MX: 1',
2902            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2903            '', ''])
2904    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2905
2906    logger.debug("Invalid message format")
2907    sock.sendto(b"NOTIFY * HTTP/1.1", ("239.255.255.250", 1900))
2908    msg = '\r'.join([
2909            'M-SEARCH * HTTP/1.1',
2910            'HOST: 239.255.255.250:1900',
2911            'MAN: "ssdp:discover"',
2912            'MX: 1',
2913            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2914            '', ''])
2915    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2916
2917    try:
2918        r = sock.recv(1000)
2919        raise Exception("Unexpected M-SEARCH response: " + r)
2920    except socket.timeout:
2921        pass
2922
2923    logger.debug("Valid M-SEARCH")
2924    msg = '\r\n'.join([
2925            'M-SEARCH * HTTP/1.1',
2926            'HOST: 239.255.255.250:1900',
2927            'MAN: "ssdp:discover"',
2928            'MX: 1',
2929            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2930            '', ''])
2931    sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2932
2933    try:
2934        r = sock.recv(1000)
2935        pass
2936    except socket.timeout:
2937        raise Exception("No SSDP response")
2938
2939def test_ap_wps_ssdp_burst(dev, apdev):
2940    """WPS AP and SSDP burst"""
2941    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
2942    add_ssdp_ap(apdev[0], ap_uuid)
2943
2944    msg = '\r\n'.join([
2945            'M-SEARCH * HTTP/1.1',
2946            'HOST: 239.255.255.250:1900',
2947            'MAN: "ssdp:discover"',
2948            'MX: 1',
2949            'ST: urn:schemas-wifialliance-org:device:WFADevice:1',
2950            '', ''])
2951    socket.setdefaulttimeout(1)
2952    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
2953    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
2954    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
2955    sock.bind(("127.0.0.1", 0))
2956    for i in range(0, 25):
2957        sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2958    resp = 0
2959    while True:
2960        try:
2961            r = sock.recv(1000).decode()
2962            if not r.startswith("HTTP/1.1 200 OK\r\n"):
2963                raise Exception("Unexpected message: " + r)
2964            resp += 1
2965        except socket.timeout:
2966            break
2967    if resp < 20:
2968        raise Exception("Too few SSDP responses")
2969
2970    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
2971    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
2972    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 2)
2973    sock.bind(("127.0.0.1", 0))
2974    for i in range(0, 25):
2975        sock.sendto(msg.encode(), ("239.255.255.250", 1900))
2976    while True:
2977        try:
2978            r = sock.recv(1000).decode()
2979            if ap_uuid in r:
2980                break
2981        except socket.timeout:
2982            raise Exception("No SSDP response")
2983
2984def ssdp_get_location(uuid):
2985    res = ssdp_send_msearch("uuid:" + uuid)
2986    location = None
2987    for l in res.splitlines():
2988        if l.lower().startswith("location:"):
2989            location = l.split(':', 1)[1].strip()
2990            break
2991    if location is None:
2992        raise Exception("No UPnP location found")
2993    return location
2994
2995def upnp_get_urls(location):
2996    if sys.version_info[0] > 2:
2997        conn = urlopen(location)
2998    else:
2999        conn = urlopen(location, proxies={})
3000    tree = ET.parse(conn)
3001    root = tree.getroot()
3002    urn = '{urn:schemas-upnp-org:device-1-0}'
3003    service = root.find("./" + urn + "device/" + urn + "serviceList/" + urn + "service")
3004    res = {}
3005    res['scpd_url'] = urljoin(location, service.find(urn + 'SCPDURL').text)
3006    res['control_url'] = urljoin(location,
3007                                 service.find(urn + 'controlURL').text)
3008    res['event_sub_url'] = urljoin(location,
3009                                   service.find(urn + 'eventSubURL').text)
3010    return res
3011
3012def upnp_soap_action(conn, path, action, include_soap_action=True,
3013                     soap_action_override=None, newmsg=None, neweventtype=None,
3014                     neweventmac=None):
3015    soapns = 'http://schemas.xmlsoap.org/soap/envelope/'
3016    wpsns = 'urn:schemas-wifialliance-org:service:WFAWLANConfig:1'
3017    ET.register_namespace('soapenv', soapns)
3018    ET.register_namespace('wfa', wpsns)
3019    attrib = {}
3020    attrib['{%s}encodingStyle' % soapns] = 'http://schemas.xmlsoap.org/soap/encoding/'
3021    root = ET.Element("{%s}Envelope" % soapns, attrib=attrib)
3022    body = ET.SubElement(root, "{%s}Body" % soapns)
3023    act = ET.SubElement(body, "{%s}%s" % (wpsns, action))
3024    if newmsg:
3025        msg = ET.SubElement(act, "NewMessage")
3026        msg.text = base64.b64encode(newmsg.encode()).decode()
3027    if neweventtype:
3028        msg = ET.SubElement(act, "NewWLANEventType")
3029        msg.text = neweventtype
3030    if neweventmac:
3031        msg = ET.SubElement(act, "NewWLANEventMAC")
3032        msg.text = neweventmac
3033
3034    headers = {"Content-type": 'text/xml; charset="utf-8"'}
3035    if include_soap_action:
3036        headers["SOAPAction"] = '"urn:schemas-wifialliance-org:service:WFAWLANConfig:1#%s"' % action
3037    elif soap_action_override:
3038        headers["SOAPAction"] = soap_action_override
3039    decl = b'<?xml version=\'1.0\' encoding=\'utf8\'?>\n'
3040    conn.request("POST", path, decl + ET.tostring(root), headers)
3041    return conn.getresponse()
3042
3043def test_ap_wps_upnp(dev, apdev):
3044    """WPS AP and UPnP operations"""
3045    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
3046    add_ssdp_ap(apdev[0], ap_uuid)
3047
3048    location = ssdp_get_location(ap_uuid)
3049    urls = upnp_get_urls(location)
3050
3051    if sys.version_info[0] > 2:
3052        conn = urlopen(urls['scpd_url'])
3053    else:
3054        conn = urlopen(urls['scpd_url'], proxies={})
3055    scpd = conn.read()
3056
3057    if sys.version_info[0] > 2:
3058        try:
3059            conn = urlopen(urljoin(location, "unknown.html"))
3060            raise Exception("Unexpected HTTP response to GET unknown URL")
3061        except HTTPError as e:
3062            if e.code != 404:
3063                raise Exception("Unexpected HTTP response to GET unknown URL")
3064    else:
3065        conn = urlopen(urljoin(location, "unknown.html"), proxies={})
3066        if conn.getcode() != 404:
3067            raise Exception("Unexpected HTTP response to GET unknown URL")
3068
3069    url = urlparse(location)
3070    conn = HTTPConnection(url.netloc)
3071    #conn.set_debuglevel(1)
3072    headers = {"Content-type": 'text/xml; charset="utf-8"',
3073               "SOAPAction": '"urn:schemas-wifialliance-org:service:WFAWLANConfig:1#GetDeviceInfo"'}
3074    conn.request("POST", "hello", "\r\n\r\n", headers)
3075    resp = conn.getresponse()
3076    if resp.status != 404:
3077        raise Exception("Unexpected HTTP response: %d" % resp.status)
3078
3079    conn.request("UNKNOWN", "hello", "\r\n\r\n", headers)
3080    resp = conn.getresponse()
3081    if resp.status != 501:
3082        raise Exception("Unexpected HTTP response: %d" % resp.status)
3083
3084    headers = {"Content-type": 'text/xml; charset="utf-8"',
3085               "SOAPAction": '"urn:some-unknown-action#GetDeviceInfo"'}
3086    ctrlurl = urlparse(urls['control_url'])
3087    conn.request("POST", ctrlurl.path, "\r\n\r\n", headers)
3088    resp = conn.getresponse()
3089    if resp.status != 401:
3090        raise Exception("Unexpected HTTP response: %d" % resp.status)
3091
3092    logger.debug("GetDeviceInfo without SOAPAction header")
3093    resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo",
3094                            include_soap_action=False)
3095    if resp.status != 401:
3096        raise Exception("Unexpected HTTP response: %d" % resp.status)
3097
3098    logger.debug("GetDeviceInfo with invalid SOAPAction header")
3099    for act in ["foo",
3100                "urn:schemas-wifialliance-org:service:WFAWLANConfig:1#GetDeviceInfo",
3101                '"urn:schemas-wifialliance-org:service:WFAWLANConfig:1"',
3102                '"urn:schemas-wifialliance-org:service:WFAWLANConfig:123#GetDevice']:
3103        resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo",
3104                                include_soap_action=False,
3105                                soap_action_override=act)
3106        if resp.status != 401:
3107            raise Exception("Unexpected HTTP response: %d" % resp.status)
3108
3109    resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
3110    if resp.status != 200:
3111        raise Exception("Unexpected HTTP response: %d" % resp.status)
3112    dev = resp.read().decode()
3113    if "NewDeviceInfo" not in dev:
3114        raise Exception("Unexpected GetDeviceInfo response")
3115
3116    logger.debug("PutMessage without required parameters")
3117    resp = upnp_soap_action(conn, ctrlurl.path, "PutMessage")
3118    if resp.status != 600:
3119        raise Exception("Unexpected HTTP response: %d" % resp.status)
3120
3121    logger.debug("PutWLANResponse without required parameters")
3122    resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse")
3123    if resp.status != 600:
3124        raise Exception("Unexpected HTTP response: %d" % resp.status)
3125
3126    logger.debug("SetSelectedRegistrar from unregistered ER")
3127    resp = upnp_soap_action(conn, ctrlurl.path, "SetSelectedRegistrar")
3128    if resp.status != 501:
3129        raise Exception("Unexpected HTTP response: %d" % resp.status)
3130
3131    logger.debug("Unknown action")
3132    resp = upnp_soap_action(conn, ctrlurl.path, "Unknown")
3133    if resp.status != 401:
3134        raise Exception("Unexpected HTTP response: %d" % resp.status)
3135
3136def test_ap_wps_upnp_subscribe(dev, apdev):
3137    """WPS AP and UPnP event subscription"""
3138    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
3139    hapd = add_ssdp_ap(apdev[0], ap_uuid)
3140
3141    location = ssdp_get_location(ap_uuid)
3142    urls = upnp_get_urls(location)
3143    eventurl = urlparse(urls['event_sub_url'])
3144
3145    url = urlparse(location)
3146    conn = HTTPConnection(url.netloc)
3147    #conn.set_debuglevel(1)
3148    headers = {"callback": '<http://127.0.0.1:12345/event>',
3149               "timeout": "Second-1234"}
3150    conn.request("SUBSCRIBE", "hello", "\r\n\r\n", headers)
3151    resp = conn.getresponse()
3152    if resp.status != 412:
3153        raise Exception("Unexpected HTTP response: %d" % resp.status)
3154
3155    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3156    resp = conn.getresponse()
3157    if resp.status != 412:
3158        raise Exception("Unexpected HTTP response: %d" % resp.status)
3159
3160    headers = {"NT": "upnp:event",
3161               "timeout": "Second-1234"}
3162    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3163    resp = conn.getresponse()
3164    if resp.status != 412:
3165        raise Exception("Unexpected HTTP response: %d" % resp.status)
3166
3167    headers = {"callback": '<http://127.0.0.1:12345/event>',
3168               "NT": "upnp:foobar",
3169               "timeout": "Second-1234"}
3170    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3171    resp = conn.getresponse()
3172    if resp.status != 400:
3173        raise Exception("Unexpected HTTP response: %d" % resp.status)
3174
3175    logger.debug("Valid subscription")
3176    headers = {"callback": '<http://127.0.0.1:12345/event>',
3177               "NT": "upnp:event",
3178               "timeout": "Second-1234"}
3179    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3180    resp = conn.getresponse()
3181    if resp.status != 200:
3182        raise Exception("Unexpected HTTP response: %d" % resp.status)
3183    sid = resp.getheader("sid")
3184    logger.debug("Subscription SID " + sid)
3185
3186    logger.debug("Invalid re-subscription")
3187    headers = {"NT": "upnp:event",
3188               "sid": "123456734567854",
3189               "timeout": "Second-1234"}
3190    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3191    resp = conn.getresponse()
3192    if resp.status != 400:
3193        raise Exception("Unexpected HTTP response: %d" % resp.status)
3194
3195    logger.debug("Invalid re-subscription")
3196    headers = {"NT": "upnp:event",
3197               "sid": "uuid:123456734567854",
3198               "timeout": "Second-1234"}
3199    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3200    resp = conn.getresponse()
3201    if resp.status != 400:
3202        raise Exception("Unexpected HTTP response: %d" % resp.status)
3203
3204    logger.debug("Invalid re-subscription")
3205    headers = {"callback": '<http://127.0.0.1:12345/event>',
3206               "NT": "upnp:event",
3207               "sid": sid,
3208               "timeout": "Second-1234"}
3209    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3210    resp = conn.getresponse()
3211    if resp.status != 400:
3212        raise Exception("Unexpected HTTP response: %d" % resp.status)
3213
3214    logger.debug("SID mismatch in re-subscription")
3215    headers = {"NT": "upnp:event",
3216               "sid": "uuid:4c2bca79-1ff4-4e43-85d4-952a2b8a51fb",
3217               "timeout": "Second-1234"}
3218    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3219    resp = conn.getresponse()
3220    if resp.status != 412:
3221        raise Exception("Unexpected HTTP response: %d" % resp.status)
3222
3223    logger.debug("Valid re-subscription")
3224    headers = {"NT": "upnp:event",
3225               "sid": sid,
3226               "timeout": "Second-1234"}
3227    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3228    resp = conn.getresponse()
3229    if resp.status != 200:
3230        raise Exception("Unexpected HTTP response: %d" % resp.status)
3231    sid2 = resp.getheader("sid")
3232    logger.debug("Subscription SID " + sid2)
3233
3234    if sid != sid2:
3235        raise Exception("Unexpected SID change")
3236
3237    logger.debug("Valid re-subscription")
3238    headers = {"NT": "upnp:event",
3239               "sid": "uuid: \t \t" + sid.split(':')[1],
3240               "timeout": "Second-1234"}
3241    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3242    resp = conn.getresponse()
3243    if resp.status != 200:
3244        raise Exception("Unexpected HTTP response: %d" % resp.status)
3245
3246    logger.debug("Invalid unsubscription")
3247    headers = {"sid": sid}
3248    conn.request("UNSUBSCRIBE", "/hello", "\r\n\r\n", headers)
3249    resp = conn.getresponse()
3250    if resp.status != 412:
3251        raise Exception("Unexpected HTTP response: %d" % resp.status)
3252    headers = {"foo": "bar"}
3253    conn.request("UNSUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3254    resp = conn.getresponse()
3255    if resp.status != 412:
3256        raise Exception("Unexpected HTTP response: %d" % resp.status)
3257
3258    logger.debug("Valid unsubscription")
3259    headers = {"sid": sid}
3260    conn.request("UNSUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3261    resp = conn.getresponse()
3262    if resp.status != 200:
3263        raise Exception("Unexpected HTTP response: %d" % resp.status)
3264
3265    logger.debug("Unsubscription for not existing SID")
3266    headers = {"sid": sid}
3267    conn.request("UNSUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3268    resp = conn.getresponse()
3269    if resp.status != 412:
3270        raise Exception("Unexpected HTTP response: %d" % resp.status)
3271
3272    logger.debug("Invalid unsubscription")
3273    headers = {"sid": " \t \tfoo"}
3274    conn.request("UNSUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3275    resp = conn.getresponse()
3276    if resp.status != 400:
3277        raise Exception("Unexpected HTTP response: %d" % resp.status)
3278
3279    logger.debug("Invalid unsubscription")
3280    headers = {"sid": "uuid:\t \tfoo"}
3281    conn.request("UNSUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3282    resp = conn.getresponse()
3283    if resp.status != 400:
3284        raise Exception("Unexpected HTTP response: %d" % resp.status)
3285
3286    logger.debug("Invalid unsubscription")
3287    headers = {"NT": "upnp:event",
3288               "sid": sid}
3289    conn.request("UNSUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3290    resp = conn.getresponse()
3291    if resp.status != 400:
3292        raise Exception("Unexpected HTTP response: %d" % resp.status)
3293    headers = {"callback": '<http://127.0.0.1:12345/event>',
3294               "sid": sid}
3295    conn.request("UNSUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3296    resp = conn.getresponse()
3297    if resp.status != 400:
3298        raise Exception("Unexpected HTTP response: %d" % resp.status)
3299
3300    logger.debug("Valid subscription with multiple callbacks")
3301    headers = {"callback": '<http://127.0.0.1:12345/event> <http://127.0.0.1:12345/event>\t<http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event><http://127.0.0.1:12345/event>',
3302               "NT": "upnp:event",
3303               "timeout": "Second-1234"}
3304    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3305    resp = conn.getresponse()
3306    if resp.status != 200:
3307        raise Exception("Unexpected HTTP response: %d" % resp.status)
3308    sid = resp.getheader("sid")
3309    logger.debug("Subscription SID " + sid)
3310
3311    # Force subscription to be deleted due to errors
3312    dev[1].scan_for_bss(apdev[0]['bssid'], freq=2412)
3313    dev[2].scan_for_bss(apdev[0]['bssid'], freq=2412)
3314    with alloc_fail(hapd, 1, "event_build_message"):
3315        for i in range(10):
3316            dev[1].dump_monitor()
3317            dev[2].dump_monitor()
3318            dev[1].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
3319            dev[2].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
3320            dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
3321            dev[1].request("WPS_CANCEL")
3322            dev[2].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
3323            dev[2].request("WPS_CANCEL")
3324            if i % 4 == 1:
3325                time.sleep(1)
3326            else:
3327                time.sleep(0.1)
3328    time.sleep(0.2)
3329
3330    headers = {"sid": sid}
3331    conn.request("UNSUBSCRIBE", eventurl.path, "", headers)
3332    resp = conn.getresponse()
3333    if resp.status != 200 and resp.status != 412:
3334        raise Exception("Unexpected HTTP response for UNSUBSCRIBE: %d" % resp.status)
3335
3336    headers = {"callback": '<http://127.0.0.1:12345/event>',
3337               "NT": "upnp:event",
3338               "timeout": "Second-1234"}
3339    with alloc_fail(hapd, 1, "http_client_addr;event_send_start"):
3340        conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3341        resp = conn.getresponse()
3342        if resp.status != 200:
3343            raise Exception("Unexpected HTTP response for SUBSCRIBE: %d" % resp.status)
3344        sid = resp.getheader("sid")
3345        logger.debug("Subscription SID " + sid)
3346
3347    headers = {"sid": sid}
3348    conn.request("UNSUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3349    resp = conn.getresponse()
3350    if resp.status != 200:
3351        raise Exception("Unexpected HTTP response for UNSUBSCRIBE: %d" % resp.status)
3352
3353    headers = {"callback": '<http://127.0.0.1:12345/event>',
3354               "NT": "upnp:event",
3355               "timeout": "Second-1234"}
3356    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3357    resp = conn.getresponse()
3358    if resp.status != 200:
3359        raise Exception("Unexpected HTTP response: %d" % resp.status)
3360    sid = resp.getheader("sid")
3361    logger.debug("Subscription SID " + sid)
3362
3363    with alloc_fail(hapd, 1, "=wps_upnp_event_add"):
3364        for i in range(2):
3365            dev[1].dump_monitor()
3366            dev[2].dump_monitor()
3367            dev[1].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
3368            dev[2].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
3369            dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
3370            dev[1].request("WPS_CANCEL")
3371            dev[2].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
3372            dev[2].request("WPS_CANCEL")
3373            if i == 0:
3374                time.sleep(1)
3375            else:
3376                time.sleep(0.1)
3377
3378    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3379    resp = conn.getresponse()
3380    if resp.status != 200:
3381        raise Exception("Unexpected HTTP response: %d" % resp.status)
3382
3383    with alloc_fail(hapd, 1, "wpabuf_dup;wps_upnp_event_add"):
3384        dev[1].dump_monitor()
3385        dev[2].dump_monitor()
3386        dev[1].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
3387        dev[2].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
3388        dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
3389        dev[1].request("WPS_CANCEL")
3390        dev[2].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
3391        dev[2].request("WPS_CANCEL")
3392        time.sleep(0.1)
3393
3394    with fail_test(hapd, 1, "os_get_random;uuid_make;subscription_start"):
3395        conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3396        resp = conn.getresponse()
3397        if resp.status != 500:
3398            raise Exception("Unexpected HTTP response: %d" % resp.status)
3399
3400    with alloc_fail(hapd, 1, "=subscription_start"):
3401        conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3402        resp = conn.getresponse()
3403        if resp.status != 500:
3404            raise Exception("Unexpected HTTP response: %d" % resp.status)
3405
3406    headers = {"callback": '',
3407               "NT": "upnp:event",
3408               "timeout": "Second-1234"}
3409    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3410    resp = conn.getresponse()
3411    if resp.status != 500:
3412        raise Exception("Unexpected HTTP response: %d" % resp.status)
3413
3414    headers = {"callback": ' <',
3415               "NT": "upnp:event",
3416               "timeout": "Second-1234"}
3417    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3418    resp = conn.getresponse()
3419    if resp.status != 500:
3420        raise Exception("Unexpected HTTP response: %d" % resp.status)
3421
3422    headers = {"callback": '<http://127.0.0.1:12345/event>',
3423               "NT": "upnp:event",
3424               "timeout": "Second-1234"}
3425    with alloc_fail(hapd, 1, "wpabuf_alloc;subscription_first_event"):
3426        conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3427        resp = conn.getresponse()
3428        if resp.status != 500:
3429            raise Exception("Unexpected HTTP response: %d" % resp.status)
3430
3431    with alloc_fail(hapd, 1, "wps_upnp_event_add;subscription_first_event"):
3432        conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3433        resp = conn.getresponse()
3434        if resp.status != 500:
3435            raise Exception("Unexpected HTTP response: %d" % resp.status)
3436
3437    with alloc_fail(hapd, 1, "subscr_addr_add_url"):
3438        conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3439        resp = conn.getresponse()
3440        if resp.status != 500:
3441            raise Exception("Unexpected HTTP response: %d" % resp.status)
3442
3443    with alloc_fail(hapd, 2, "subscr_addr_add_url"):
3444        conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3445        resp = conn.getresponse()
3446        if resp.status != 500:
3447            raise Exception("Unexpected HTTP response: %d" % resp.status)
3448
3449    for i in range(6):
3450        headers = {"callback": '<http://127.0.0.1:%d/event>' % (12345 + i),
3451                   "NT": "upnp:event",
3452                   "timeout": "Second-1234"}
3453        conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3454        resp = conn.getresponse()
3455        if resp.status != 200:
3456            raise Exception("Unexpected HTTP response: %d" % resp.status)
3457
3458    with alloc_fail(hapd, 1, "=upnp_wps_device_send_wlan_event"):
3459        dev[1].dump_monitor()
3460        dev[1].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
3461        dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
3462        dev[1].request("WPS_CANCEL")
3463        time.sleep(0.1)
3464
3465    with alloc_fail(hapd, 1, "wpabuf_alloc;upnp_wps_device_send_event"):
3466        dev[1].dump_monitor()
3467        dev[1].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
3468        dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
3469        dev[1].request("WPS_CANCEL")
3470        time.sleep(0.1)
3471
3472    with alloc_fail(hapd, 1,
3473                    "base64_gen_encode;?base64_encode;upnp_wps_device_send_wlan_event"):
3474        dev[1].dump_monitor()
3475        dev[1].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
3476        dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
3477        dev[1].request("WPS_CANCEL")
3478        time.sleep(0.1)
3479
3480    hapd.disable()
3481    with alloc_fail(hapd, 1, "get_netif_info"):
3482        if "FAIL" not in hapd.request("ENABLE"):
3483            raise Exception("ENABLE succeeded during OOM")
3484
3485def test_ap_wps_upnp_subscribe_events(dev, apdev):
3486    """WPS AP and UPnP event subscription and many events"""
3487    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
3488    hapd = add_ssdp_ap(apdev[0], ap_uuid)
3489
3490    location = ssdp_get_location(ap_uuid)
3491    urls = upnp_get_urls(location)
3492    eventurl = urlparse(urls['event_sub_url'])
3493
3494    class WPSERHTTPServer(StreamRequestHandler):
3495        def handle(self):
3496            data = self.rfile.readline().strip()
3497            logger.debug(data)
3498            self.wfile.write(gen_wps_event())
3499
3500    server = MyTCPServer(("127.0.0.1", 12345), WPSERHTTPServer)
3501    server.timeout = 1
3502
3503    url = urlparse(location)
3504    conn = HTTPConnection(url.netloc)
3505
3506    headers = {"callback": '<http://127.0.0.1:12345/event>',
3507               "NT": "upnp:event",
3508               "timeout": "Second-1234"}
3509    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
3510    resp = conn.getresponse()
3511    if resp.status != 200:
3512        raise Exception("Unexpected HTTP response: %d" % resp.status)
3513    sid = resp.getheader("sid")
3514    logger.debug("Subscription SID " + sid)
3515
3516    # Fetch the first event message
3517    server.handle_request()
3518
3519    # Force subscription event queue to reach the maximum length by generating
3520    # new proxied events without the ER fetching any of the pending events.
3521    dev[1].scan_for_bss(apdev[0]['bssid'], freq=2412)
3522    dev[2].scan_for_bss(apdev[0]['bssid'], freq=2412)
3523    for i in range(16):
3524        dev[1].dump_monitor()
3525        dev[2].dump_monitor()
3526        dev[1].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
3527        dev[2].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
3528        dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
3529        dev[1].request("WPS_CANCEL")
3530        dev[2].wait_event(["CTRL-EVENT-SCAN-RESULTS"], 5)
3531        dev[2].request("WPS_CANCEL")
3532        if i % 4 == 1:
3533            time.sleep(1)
3534        else:
3535            time.sleep(0.1)
3536
3537    hapd.request("WPS_PIN any 12345670")
3538    dev[1].dump_monitor()
3539    dev[1].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
3540    ev = dev[1].wait_event(["WPS-SUCCESS"], timeout=10)
3541    if ev is None:
3542        raise Exception("WPS success not reported")
3543
3544    # Close the WPS ER HTTP server without fetching all the pending events.
3545    # This tests hostapd code path that clears subscription and the remaining
3546    # event queue when the interface is deinitialized.
3547    server.handle_request()
3548    server.server_close()
3549
3550    dev[1].wait_connected()
3551
3552def test_ap_wps_upnp_http_proto(dev, apdev):
3553    """WPS AP and UPnP/HTTP protocol testing"""
3554    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
3555    add_ssdp_ap(apdev[0], ap_uuid)
3556
3557    location = ssdp_get_location(ap_uuid)
3558
3559    url = urlparse(location)
3560    conn = HTTPConnection(url.netloc, timeout=0.2)
3561    #conn.set_debuglevel(1)
3562
3563    conn.request("HEAD", "hello")
3564    resp = conn.getresponse()
3565    if resp.status != 501:
3566        raise Exception("Unexpected response to HEAD: " + str(resp.status))
3567    conn.close()
3568
3569    for cmd in ["PUT", "DELETE", "TRACE", "CONNECT", "M-SEARCH", "M-POST"]:
3570        try:
3571            conn.request(cmd, "hello")
3572            resp = conn.getresponse()
3573        except Exception as e:
3574            pass
3575        conn.close()
3576
3577    headers = {"Content-Length": 'abc'}
3578    conn.request("HEAD", "hello", "\r\n\r\n", headers)
3579    try:
3580        resp = conn.getresponse()
3581    except Exception as e:
3582        pass
3583    conn.close()
3584
3585    headers = {"Content-Length": '-10'}
3586    conn.request("HEAD", "hello", "\r\n\r\n", headers)
3587    try:
3588        resp = conn.getresponse()
3589    except Exception as e:
3590        pass
3591    conn.close()
3592
3593    headers = {"Content-Length": '10000000000000'}
3594    conn.request("HEAD", "hello", "\r\n\r\nhello", headers)
3595    try:
3596        resp = conn.getresponse()
3597    except Exception as e:
3598        pass
3599    conn.close()
3600
3601    headers = {"Transfer-Encoding": 'abc'}
3602    conn.request("HEAD", "hello", "\r\n\r\n", headers)
3603    resp = conn.getresponse()
3604    if resp.status != 501:
3605        raise Exception("Unexpected response to HEAD: " + str(resp.status))
3606    conn.close()
3607
3608    headers = {"Transfer-Encoding": 'chunked'}
3609    conn.request("HEAD", "hello", "\r\n\r\n", headers)
3610    resp = conn.getresponse()
3611    if resp.status != 501:
3612        raise Exception("Unexpected response to HEAD: " + str(resp.status))
3613    conn.close()
3614
3615    # Too long a header
3616    conn.request("HEAD", 5000 * 'A')
3617    try:
3618        resp = conn.getresponse()
3619    except Exception as e:
3620        pass
3621    conn.close()
3622
3623    # Long URL but within header length limits
3624    conn.request("HEAD", 3000 * 'A')
3625    resp = conn.getresponse()
3626    if resp.status != 501:
3627        raise Exception("Unexpected response to HEAD: " + str(resp.status))
3628    conn.close()
3629
3630    headers = {"Content-Length": '20'}
3631    conn.request("POST", "hello", 10 * 'A' + "\r\n\r\n", headers)
3632    try:
3633        resp = conn.getresponse()
3634    except Exception as e:
3635        pass
3636    conn.close()
3637
3638    conn.request("POST", "hello", 5000 * 'A' + "\r\n\r\n")
3639    resp = conn.getresponse()
3640    if resp.status != 404:
3641        raise Exception("Unexpected HTTP response: %d" % resp.status)
3642    conn.close()
3643
3644    conn.request("POST", "hello", 60000 * 'A' + "\r\n\r\n")
3645    try:
3646        resp = conn.getresponse()
3647    except Exception as e:
3648        pass
3649    conn.close()
3650
3651def test_ap_wps_upnp_http_proto_chunked(dev, apdev):
3652    """WPS AP and UPnP/HTTP protocol testing for chunked encoding"""
3653    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
3654    add_ssdp_ap(apdev[0], ap_uuid)
3655
3656    location = ssdp_get_location(ap_uuid)
3657
3658    url = urlparse(location)
3659    conn = HTTPConnection(url.netloc)
3660    #conn.set_debuglevel(1)
3661
3662    headers = {"Transfer-Encoding": 'chunked'}
3663    conn.request("POST", "hello",
3664                 "a\r\nabcdefghij\r\n" + "2\r\nkl\r\n" + "0\r\n\r\n",
3665                 headers)
3666    resp = conn.getresponse()
3667    if resp.status != 404:
3668        raise Exception("Unexpected HTTP response: %d" % resp.status)
3669    conn.close()
3670
3671    conn.putrequest("POST", "hello")
3672    conn.putheader('Transfer-Encoding', 'chunked')
3673    conn.endheaders()
3674    conn.send(b"a\r\nabcdefghij\r\n")
3675    time.sleep(0.1)
3676    conn.send(b"2\r\nkl\r\n")
3677    conn.send(b"0\r\n\r\n")
3678    resp = conn.getresponse()
3679    if resp.status != 404:
3680        raise Exception("Unexpected HTTP response: %d" % resp.status)
3681    conn.close()
3682
3683    conn.putrequest("POST", "hello")
3684    conn.putheader('Transfer-Encoding', 'chunked')
3685    conn.endheaders()
3686    completed = False
3687    try:
3688        for i in range(20000):
3689            conn.send(b"1\r\nZ\r\n")
3690        conn.send(b"0\r\n\r\n")
3691        resp = conn.getresponse()
3692        completed = True
3693    except Exception as e:
3694        pass
3695    conn.close()
3696    if completed:
3697        raise Exception("Too long chunked request did not result in connection reset")
3698
3699    headers = {"Transfer-Encoding": 'chunked'}
3700    conn.request("POST", "hello", "80000000\r\na", headers)
3701    try:
3702        resp = conn.getresponse()
3703    except Exception as e:
3704        pass
3705    conn.close()
3706
3707    conn.request("POST", "hello", "10000000\r\na", headers)
3708    try:
3709        resp = conn.getresponse()
3710    except Exception as e:
3711        pass
3712    conn.close()
3713
3714@remote_compatible
3715def test_ap_wps_disabled(dev, apdev):
3716    """WPS operations while WPS is disabled"""
3717    ssid = "test-wps-disabled"
3718    hapd = hostapd.add_ap(apdev[0], {"ssid": ssid})
3719    if "FAIL" not in hapd.request("WPS_PBC"):
3720        raise Exception("WPS_PBC succeeded unexpectedly")
3721    if "FAIL" not in hapd.request("WPS_CANCEL"):
3722        raise Exception("WPS_CANCEL succeeded unexpectedly")
3723
3724def test_ap_wps_mixed_cred(dev, apdev):
3725    """WPS 2.0 STA merging mixed mode WPA/WPA2 credentials"""
3726    skip_without_tkip(dev[0])
3727    ssid = "test-wps-wep"
3728    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
3729              "skip_cred_build": "1", "extra_cred": "wps-mixed-cred"}
3730    hapd = hostapd.add_ap(apdev[0], params)
3731    hapd.request("WPS_PBC")
3732    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
3733    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
3734    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=30)
3735    if ev is None:
3736        raise Exception("WPS-SUCCESS event timed out")
3737    nets = dev[0].list_networks()
3738    if len(nets) != 1:
3739        raise Exception("Unexpected number of network blocks")
3740    id = nets[0]['id']
3741    proto = dev[0].get_network(id, "proto")
3742    if proto != "WPA RSN":
3743        raise Exception("Unexpected merged proto field value: " + proto)
3744    pairwise = dev[0].get_network(id, "pairwise")
3745    p = pairwise.split()
3746    if "CCMP" not in p or "TKIP" not in p:
3747        raise Exception("Unexpected merged pairwise field value: " + pairwise)
3748
3749@remote_compatible
3750def test_ap_wps_while_connected(dev, apdev):
3751    """WPS PBC provisioning while connected to another AP"""
3752    ssid = "test-wps-conf"
3753    hapd = hostapd.add_ap(apdev[0],
3754                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
3755                           "wpa_passphrase": "12345678", "wpa": "2",
3756                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
3757
3758    hostapd.add_ap(apdev[1], {"ssid": "open"})
3759    dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
3760
3761    logger.info("WPS provisioning step")
3762    hapd.request("WPS_PBC")
3763    dev[0].dump_monitor()
3764    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
3765    dev[0].wait_connected(timeout=30)
3766    status = dev[0].get_status()
3767    if status['bssid'] != apdev[0]['bssid']:
3768        raise Exception("Unexpected BSSID")
3769
3770@remote_compatible
3771def test_ap_wps_while_connected_no_autoconnect(dev, apdev):
3772    """WPS PBC provisioning while connected to another AP and STA_AUTOCONNECT disabled"""
3773    ssid = "test-wps-conf"
3774    hapd = hostapd.add_ap(apdev[0],
3775                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
3776                           "wpa_passphrase": "12345678", "wpa": "2",
3777                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
3778
3779    hostapd.add_ap(apdev[1], {"ssid": "open"})
3780
3781    try:
3782        dev[0].request("STA_AUTOCONNECT 0")
3783        dev[0].connect("open", key_mgmt="NONE", scan_freq="2412")
3784
3785        logger.info("WPS provisioning step")
3786        hapd.request("WPS_PBC")
3787        dev[0].dump_monitor()
3788        dev[0].request("WPS_PBC " + apdev[0]['bssid'])
3789        dev[0].wait_connected(timeout=30)
3790        status = dev[0].get_status()
3791        if status['bssid'] != apdev[0]['bssid']:
3792            raise Exception("Unexpected BSSID")
3793    finally:
3794        dev[0].request("STA_AUTOCONNECT 1")
3795
3796@remote_compatible
3797def test_ap_wps_from_event(dev, apdev):
3798    """WPS PBC event on AP to enable PBC"""
3799    ssid = "test-wps-conf"
3800    hapd = hostapd.add_ap(apdev[0],
3801                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
3802                           "wpa_passphrase": "12345678", "wpa": "2",
3803                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
3804    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
3805    dev[0].dump_monitor()
3806    hapd.dump_monitor()
3807    dev[0].request("WPS_PBC " + apdev[0]['bssid'])
3808
3809    ev = hapd.wait_event(['WPS-ENROLLEE-SEEN'], timeout=15)
3810    if ev is None:
3811        raise Exception("No WPS-ENROLLEE-SEEN event on AP")
3812    vals = ev.split(' ')
3813    if vals[1] != dev[0].p2p_interface_addr():
3814        raise Exception("Unexpected enrollee address: " + vals[1])
3815    if vals[5] != '4':
3816        raise Exception("Unexpected Device Password Id: " + vals[5])
3817    hapd.request("WPS_PBC")
3818    dev[0].wait_connected(timeout=30)
3819
3820def test_ap_wps_ap_scan_2(dev, apdev):
3821    """AP_SCAN 2 for WPS"""
3822    ssid = "test-wps-conf"
3823    hapd = hostapd.add_ap(apdev[0],
3824                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
3825                           "wpa_passphrase": "12345678", "wpa": "2",
3826                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
3827    hapd.request("WPS_PBC")
3828
3829    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
3830    wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
3831    wpas.dump_monitor()
3832
3833    if "OK" not in wpas.request("AP_SCAN 2"):
3834        raise Exception("Failed to set AP_SCAN 2")
3835
3836    wpas.flush_scan_cache()
3837    wpas.scan_for_bss(apdev[0]['bssid'], freq="2412")
3838    wpas.dump_monitor()
3839    wpas.request("WPS_PBC " + apdev[0]['bssid'])
3840    ev = wpas.wait_event(["WPS-SUCCESS"], timeout=15)
3841    if ev is None:
3842        raise Exception("WPS-SUCCESS event timed out")
3843    wpas.wait_connected(timeout=30)
3844    wpas.dump_monitor()
3845    wpas.request("DISCONNECT")
3846    wpas.wait_disconnected()
3847    id = wpas.list_networks()[0]['id']
3848    pairwise = wpas.get_network(id, "pairwise")
3849    if "CCMP" not in pairwise.split():
3850        raise Exception("Unexpected pairwise parameter value: " + pairwise)
3851    group = wpas.get_network(id, "group")
3852    if "CCMP" not in group.split():
3853        raise Exception("Unexpected group parameter value: " + group)
3854    # Need to select a single cipher for ap_scan=2 testing
3855    wpas.set_network(id, "pairwise", "CCMP")
3856    wpas.set_network(id, "group", "CCMP")
3857    wpas.request("BSS_FLUSH 0")
3858    wpas.dump_monitor()
3859    wpas.request("REASSOCIATE")
3860    wpas.wait_connected(timeout=30)
3861    wpas.dump_monitor()
3862    wpas.request("DISCONNECT")
3863    wpas.wait_disconnected()
3864    wpas.flush_scan_cache()
3865
3866@remote_compatible
3867def test_ap_wps_eapol_workaround(dev, apdev):
3868    """EAPOL workaround code path for 802.1X header length mismatch"""
3869    ssid = "test-wps"
3870    hapd = hostapd.add_ap(apdev[0],
3871                          {"ssid": ssid, "eap_server": "1", "wps_state": "1"})
3872    bssid = apdev[0]['bssid']
3873    hapd.request("SET ext_eapol_frame_io 1")
3874    dev[0].request("SET ext_eapol_frame_io 1")
3875    hapd.request("WPS_PBC")
3876    dev[0].request("WPS_PBC")
3877
3878    ev = hapd.wait_event(["EAPOL-TX"], timeout=15)
3879    if ev is None:
3880        raise Exception("Timeout on EAPOL-TX from hostapd")
3881
3882    res = dev[0].request("EAPOL_RX " + bssid + " 020000040193000501FFFF")
3883    if "OK" not in res:
3884        raise Exception("EAPOL_RX to wpa_supplicant failed")
3885
3886def test_ap_wps_iteration(dev, apdev):
3887    """WPS PIN and iterate through APs without selected registrar"""
3888    ssid = "test-wps-conf"
3889    hapd = hostapd.add_ap(apdev[0],
3890                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
3891                           "wpa_passphrase": "12345678", "wpa": "2",
3892                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
3893
3894    ssid2 = "test-wps-conf2"
3895    hapd2 = hostapd.add_ap(apdev[1],
3896                           {"ssid": ssid2, "eap_server": "1", "wps_state": "2",
3897                            "wpa_passphrase": "12345678", "wpa": "2",
3898                            "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
3899
3900    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
3901    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
3902    dev[0].dump_monitor()
3903    pin = dev[0].request("WPS_PIN any")
3904
3905    # Wait for iteration through all WPS APs to happen before enabling any
3906    # Registrar.
3907    for i in range(2):
3908        ev = dev[0].wait_event(["Associated with"], timeout=30)
3909        if ev is None:
3910            raise Exception("No association seen")
3911        ev = dev[0].wait_event(["WPS-M2D"], timeout=10)
3912        if ev is None:
3913            raise Exception("No M2D from AP")
3914        dev[0].wait_disconnected()
3915
3916    # Verify that each AP requested PIN
3917    ev = hapd.wait_event(["WPS-PIN-NEEDED"], timeout=1)
3918    if ev is None:
3919        raise Exception("No WPS-PIN-NEEDED event from AP")
3920    ev = hapd2.wait_event(["WPS-PIN-NEEDED"], timeout=1)
3921    if ev is None:
3922        raise Exception("No WPS-PIN-NEEDED event from AP2")
3923
3924    # Provide PIN to one of the APs and verify that connection gets formed
3925    hapd.request("WPS_PIN any " + pin)
3926    dev[0].wait_connected(timeout=30)
3927
3928def test_ap_wps_iteration_error(dev, apdev):
3929    """WPS AP iteration on no Selected Registrar and error case with an AP"""
3930    ssid = "test-wps-conf-pin"
3931    hapd = hostapd.add_ap(apdev[0],
3932                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
3933                           "wpa_passphrase": "12345678", "wpa": "2",
3934                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
3935                           "wps_independent": "1"})
3936    hapd.request("SET ext_eapol_frame_io 1")
3937    bssid = apdev[0]['bssid']
3938    pin = dev[0].wps_read_pin()
3939    dev[0].scan_for_bss(bssid, freq="2412")
3940    dev[0].dump_monitor()
3941    dev[0].request("WPS_PIN any " + pin)
3942
3943    ev = hapd.wait_event(["EAPOL-TX"], timeout=30)
3944    if ev is None:
3945        raise Exception("No EAPOL-TX (EAP-Request/Identity) from hostapd")
3946    dev[0].request("EAPOL_RX " + bssid + " " + ev.split(' ')[2])
3947
3948    ev = hapd.wait_event(["EAPOL-TX"], timeout=15)
3949    if ev is None:
3950        raise Exception("No EAPOL-TX (EAP-WSC/Start) from hostapd")
3951    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
3952    if ev is None:
3953        raise Exception("No CTRL-EVENT-EAP-STARTED")
3954
3955    # Do not forward any more EAPOL frames to test wpa_supplicant behavior for
3956    # a case with an incorrectly behaving WPS AP.
3957
3958    # Start the real target AP and activate registrar on it.
3959    hapd2 = hostapd.add_ap(apdev[1],
3960                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
3961                           "wpa_passphrase": "12345678", "wpa": "2",
3962                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
3963                           "wps_independent": "1"})
3964    hapd2.request("WPS_PIN any " + pin)
3965
3966    dev[0].wait_disconnected(timeout=15)
3967    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=15)
3968    if ev is None:
3969        raise Exception("No CTRL-EVENT-EAP-STARTED for the second AP")
3970    ev = dev[0].wait_event(["WPS-CRED-RECEIVED"], timeout=15)
3971    if ev is None:
3972        raise Exception("No WPS-CRED-RECEIVED for the second AP")
3973    dev[0].wait_connected(timeout=15)
3974
3975@remote_compatible
3976def test_ap_wps_priority(dev, apdev):
3977    """WPS PIN provisioning with configured AP and wps_priority"""
3978    ssid = "test-wps-conf-pin"
3979    hapd = hostapd.add_ap(apdev[0],
3980                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
3981                           "wpa_passphrase": "12345678", "wpa": "2",
3982                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
3983    logger.info("WPS provisioning step")
3984    pin = dev[0].wps_read_pin()
3985    hapd.request("WPS_PIN any " + pin)
3986    dev[0].flush_scan_cache()
3987    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
3988    dev[0].dump_monitor()
3989    try:
3990        dev[0].request("SET wps_priority 6")
3991        dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
3992        dev[0].wait_connected(timeout=30)
3993        netw = dev[0].list_networks()
3994        prio = dev[0].get_network(netw[0]['id'], 'priority')
3995        if prio != '6':
3996            raise Exception("Unexpected network priority: " + prio)
3997    finally:
3998        dev[0].request("SET wps_priority 0")
3999
4000@remote_compatible
4001def test_ap_wps_and_non_wps(dev, apdev):
4002    """WPS and non-WPS AP in single hostapd process"""
4003    params = {"ssid": "wps", "eap_server": "1", "wps_state": "1"}
4004    hapd = hostapd.add_ap(apdev[0], params)
4005
4006    params = {"ssid": "no wps"}
4007    hapd2 = hostapd.add_ap(apdev[1], params)
4008
4009    appin = hapd.request("WPS_AP_PIN random")
4010    if "FAIL" in appin:
4011        raise Exception("Could not generate random AP PIN")
4012    if appin not in hapd.request("WPS_AP_PIN get"):
4013        raise Exception("Could not fetch current AP PIN")
4014
4015    if "FAIL" in hapd.request("WPS_PBC"):
4016        raise Exception("WPS_PBC failed")
4017    if "FAIL" in hapd.request("WPS_CANCEL"):
4018        raise Exception("WPS_CANCEL failed")
4019
4020def test_ap_wps_init_oom(dev, apdev):
4021    """Initial AP configuration and OOM during PSK generation"""
4022    ssid = "test-wps"
4023    params = {"ssid": ssid, "eap_server": "1", "wps_state": "1"}
4024    hapd = hostapd.add_ap(apdev[0], params)
4025
4026    with alloc_fail(hapd, 1, "base64_gen_encode;?base64_encode;wps_build_cred"):
4027        pin = dev[0].wps_read_pin()
4028        hapd.request("WPS_PIN any " + pin)
4029        dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
4030        dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
4031        dev[0].wait_disconnected()
4032
4033    hapd.request("WPS_PIN any " + pin)
4034    dev[0].wait_connected(timeout=30)
4035
4036@remote_compatible
4037def test_ap_wps_er_oom(dev, apdev):
4038    """WPS ER OOM in XML processing"""
4039    try:
4040        _test_ap_wps_er_oom(dev, apdev)
4041    finally:
4042        dev[0].request("WPS_ER_STOP")
4043        dev[1].request("WPS_CANCEL")
4044        dev[0].request("DISCONNECT")
4045
4046def _test_ap_wps_er_oom(dev, apdev):
4047    ssid = "wps-er-ap-config"
4048    ap_pin = "12345670"
4049    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
4050    hostapd.add_ap(apdev[0],
4051                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
4052                    "wpa_passphrase": "12345678", "wpa": "2",
4053                    "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
4054                    "device_name": "Wireless AP", "manufacturer": "Company",
4055                    "model_name": "WAP", "model_number": "123",
4056                    "serial_number": "12345", "device_type": "6-0050F204-1",
4057                    "os_version": "01020300",
4058                    "config_methods": "label push_button",
4059                    "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"})
4060
4061    dev[0].connect(ssid, psk="12345678", scan_freq="2412")
4062
4063    with alloc_fail(dev[0], 1,
4064                    "base64_gen_decode;?base64_decode;xml_get_base64_item"):
4065        dev[0].request("WPS_ER_START ifname=lo")
4066        ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=3)
4067        if ev is not None:
4068            raise Exception("Unexpected AP discovery")
4069
4070    dev[0].request("WPS_ER_STOP")
4071    dev[0].request("WPS_ER_START ifname=lo")
4072    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=10)
4073    if ev is None:
4074        raise Exception("AP discovery timed out")
4075
4076    dev[1].scan_for_bss(apdev[0]['bssid'], freq=2412)
4077    with alloc_fail(dev[0], 1,
4078                    "base64_gen_decode;?base64_decode;xml_get_base64_item"):
4079        dev[1].request("WPS_PBC " + apdev[0]['bssid'])
4080        ev = dev[1].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
4081        if ev is None:
4082            raise Exception("PBC scan failed")
4083        ev = dev[0].wait_event(["WPS-ER-ENROLLEE-ADD"], timeout=15)
4084        if ev is None:
4085            raise Exception("Enrollee discovery timed out")
4086
4087@remote_compatible
4088def test_ap_wps_er_init_oom(dev, apdev):
4089    """WPS ER and OOM during init"""
4090    try:
4091        _test_ap_wps_er_init_oom(dev, apdev)
4092    finally:
4093        dev[0].request("WPS_ER_STOP")
4094
4095def _test_ap_wps_er_init_oom(dev, apdev):
4096    with alloc_fail(dev[0], 1, "wps_er_init"):
4097        if "FAIL" not in dev[0].request("WPS_ER_START ifname=lo"):
4098            raise Exception("WPS_ER_START succeeded during OOM")
4099    with alloc_fail(dev[0], 1, "http_server_init"):
4100        if "FAIL" not in dev[0].request("WPS_ER_START ifname=lo"):
4101            raise Exception("WPS_ER_START succeeded during OOM")
4102    with alloc_fail(dev[0], 2, "http_server_init"):
4103        if "FAIL" not in dev[0].request("WPS_ER_START ifname=lo"):
4104            raise Exception("WPS_ER_START succeeded during OOM")
4105    with alloc_fail(dev[0], 1, "eloop_sock_table_add_sock;?eloop_register_sock;wps_er_ssdp_init"):
4106        if "FAIL" not in dev[0].request("WPS_ER_START ifname=lo"):
4107            raise Exception("WPS_ER_START succeeded during OOM")
4108    with fail_test(dev[0], 1, "os_get_random;wps_er_init"):
4109        if "FAIL" not in dev[0].request("WPS_ER_START ifname=lo"):
4110            raise Exception("WPS_ER_START succeeded during os_get_random failure")
4111
4112@remote_compatible
4113def test_ap_wps_er_init_fail(dev, apdev):
4114    """WPS ER init failure"""
4115    if "FAIL" not in dev[0].request("WPS_ER_START ifname=does-not-exist"):
4116        dev[0].request("WPS_ER_STOP")
4117        raise Exception("WPS_ER_START with non-existing ifname succeeded")
4118
4119def test_ap_wps_wpa_cli_action(dev, apdev, test_params):
4120    """WPS events and wpa_cli action script"""
4121    logdir = os.path.abspath(test_params['logdir'])
4122    pidfile = os.path.join(logdir, 'ap_wps_wpa_cli_action.wpa_cli.pid')
4123    logfile = os.path.join(logdir, 'ap_wps_wpa_cli_action.wpa_cli.res')
4124    actionfile = os.path.join(logdir, 'ap_wps_wpa_cli_action.wpa_cli.action.sh')
4125
4126    with open(actionfile, 'w') as f:
4127        f.write('#!/bin/sh\n')
4128        f.write('echo $* >> %s\n' % logfile)
4129        # Kill the process and wait some time before returning to allow all the
4130        # pending events to be processed with some of this happening after the
4131        # eloop SIGALRM signal has been scheduled.
4132        f.write('if [ $2 = "WPS-SUCCESS" -a -r %s ]; then kill `cat %s`; sleep 1; fi\n' % (pidfile, pidfile))
4133
4134    os.chmod(actionfile, stat.S_IREAD | stat.S_IWRITE | stat.S_IEXEC |
4135             stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
4136
4137    ssid = "test-wps-conf"
4138    hapd = hostapd.add_ap(apdev[0],
4139                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
4140                           "wpa_passphrase": "12345678", "wpa": "2",
4141                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
4142
4143    prg = os.path.join(test_params['logdir'],
4144                       'alt-wpa_supplicant/wpa_supplicant/wpa_cli')
4145    if not os.path.exists(prg):
4146        prg = '../../wpa_supplicant/wpa_cli'
4147    arg = [prg, '-P', pidfile, '-B', '-i', dev[0].ifname, '-a', actionfile]
4148    subprocess.call(arg)
4149
4150    arg = ['ps', 'ax']
4151    cmd = subprocess.Popen(arg, stdout=subprocess.PIPE)
4152    out = cmd.communicate()[0].decode()
4153    cmd.wait()
4154    logger.debug("Processes:\n" + out)
4155    if "wpa_cli -P %s -B -i %s" % (pidfile, dev[0].ifname) not in out:
4156        raise Exception("Did not see wpa_cli running")
4157
4158    hapd.request("WPS_PIN any 12345670")
4159    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
4160    dev[0].dump_monitor()
4161    dev[0].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
4162    dev[0].wait_connected(timeout=30)
4163
4164    for i in range(30):
4165        if not os.path.exists(pidfile):
4166            break
4167        time.sleep(0.1)
4168
4169    if not os.path.exists(logfile):
4170        raise Exception("wpa_cli action results file not found")
4171    with open(logfile, 'r') as f:
4172        res = f.read()
4173    if "WPS-SUCCESS" not in res:
4174        raise Exception("WPS-SUCCESS event not seen in action file")
4175
4176    arg = ['ps', 'ax']
4177    cmd = subprocess.Popen(arg, stdout=subprocess.PIPE)
4178    out = cmd.communicate()[0].decode()
4179    cmd.wait()
4180    logger.debug("Remaining processes:\n" + out)
4181    if "wpa_cli -P %s -B -i %s" % (pidfile, dev[0].ifname) in out:
4182        raise Exception("wpa_cli still running")
4183
4184    if os.path.exists(pidfile):
4185        raise Exception("PID file not removed")
4186
4187def test_ap_wps_er_ssdp_proto(dev, apdev):
4188    """WPS ER SSDP protocol testing"""
4189    try:
4190        _test_ap_wps_er_ssdp_proto(dev, apdev)
4191    finally:
4192        dev[0].request("WPS_ER_STOP")
4193
4194def _test_ap_wps_er_ssdp_proto(dev, apdev):
4195    socket.setdefaulttimeout(1)
4196    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
4197    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
4198    sock.bind(("239.255.255.250", 1900))
4199    if "FAIL" not in dev[0].request("WPS_ER_START ifname=lo foo"):
4200        raise Exception("Invalid filter accepted")
4201    if "OK" not in dev[0].request("WPS_ER_START ifname=lo 1.2.3.4"):
4202        raise Exception("WPS_ER_START with filter failed")
4203    (msg, addr) = sock.recvfrom(1000)
4204    msg = msg.decode()
4205    logger.debug("Received SSDP message from %s: %s" % (str(addr), msg))
4206    if "M-SEARCH" not in msg:
4207        raise Exception("Not an M-SEARCH")
4208    sock.sendto(b"FOO", addr)
4209    time.sleep(0.1)
4210    dev[0].request("WPS_ER_STOP")
4211
4212    dev[0].request("WPS_ER_START ifname=lo")
4213    (msg, addr) = sock.recvfrom(1000)
4214    msg = msg.decode()
4215    logger.debug("Received SSDP message from %s: %s" % (str(addr), msg))
4216    if "M-SEARCH" not in msg:
4217        raise Exception("Not an M-SEARCH")
4218    sock.sendto(b"FOO", addr)
4219    sock.sendto(b"HTTP/1.1 200 OK\r\nFOO\r\n\r\n", addr)
4220    sock.sendto(b"HTTP/1.1 200 OK\r\nNTS:foo\r\n\r\n", addr)
4221    sock.sendto(b"HTTP/1.1 200 OK\r\nNTS:ssdp:byebye\r\n\r\n", addr)
4222    sock.sendto(b"HTTP/1.1 200 OK\r\ncache-control:   foo=1\r\n\r\n", addr)
4223    sock.sendto(b"HTTP/1.1 200 OK\r\ncache-control:   max-age=1\r\n\r\n", addr)
4224    sock.sendto(b"HTTP/1.1 200 OK\r\nusn:\r\n\r\n", addr)
4225    sock.sendto(b"HTTP/1.1 200 OK\r\nusn:foo\r\n\r\n", addr)
4226    sock.sendto(b"HTTP/1.1 200 OK\r\nusn:   uuid:\r\n\r\n", addr)
4227    sock.sendto(b"HTTP/1.1 200 OK\r\nusn:   uuid:     \r\n\r\n", addr)
4228    sock.sendto(b"HTTP/1.1 200 OK\r\nusn:   uuid:     foo\r\n\r\n", addr)
4229    sock.sendto(b"HTTP/1.1 200 OK\r\nST: urn:schemas-wifialliance-org:device:WFADevice:1\r\n\r\n", addr)
4230    sock.sendto(b"HTTP/1.1 200 OK\r\nST: urn:schemas-wifialliance-org:device:WFADevice:1\r\nNTS:ssdp:byebye\r\n\r\n", addr)
4231    sock.sendto(b"HTTP/1.1 200 OK\r\nST: urn:schemas-wifialliance-org:device:WFADevice:1\r\nlocation:foo\r\n\r\n", addr)
4232    with alloc_fail(dev[0], 1, "wps_er_ap_add"):
4233        sock.sendto(b"HTTP/1.1 200 OK\r\nST: urn:schemas-wifialliance-org:device:WFADevice:1\r\nlocation:foo\r\ncache-control:max-age=1\r\n\r\n", addr)
4234        time.sleep(0.1)
4235    with alloc_fail(dev[0], 2, "wps_er_ap_add"):
4236        sock.sendto(b"HTTP/1.1 200 OK\r\nST: urn:schemas-wifialliance-org:device:WFADevice:1\r\nlocation:foo\r\ncache-control:max-age=1\r\n\r\n", addr)
4237        time.sleep(0.1)
4238
4239    # Add an AP with bogus URL
4240    sock.sendto(b"HTTP/1.1 200 OK\r\nST: urn:schemas-wifialliance-org:device:WFADevice:1\r\nlocation:foo\r\ncache-control:max-age=1\r\n\r\n", addr)
4241    # Update timeout on AP without updating URL
4242    sock.sendto(b"HTTP/1.1 200 OK\r\nST: urn:schemas-wifialliance-org:device:WFADevice:1\r\nlocation:http://127.0.0.1:12345/foo.xml\r\ncache-control:max-age=1\r\n\r\n", addr)
4243    ev = dev[0].wait_event(["WPS-ER-AP-REMOVE"], timeout=5)
4244    if ev is None:
4245        raise Exception("No WPS-ER-AP-REMOVE event on max-age timeout")
4246
4247    # Add an AP with a valid URL (but no server listing to it)
4248    sock.sendto(b"HTTP/1.1 200 OK\r\nST: urn:schemas-wifialliance-org:device:WFADevice:1\r\nlocation:http://127.0.0.1:12345/foo.xml\r\ncache-control:max-age=1\r\n\r\n", addr)
4249    ev = dev[0].wait_event(["WPS-ER-AP-REMOVE"], timeout=5)
4250    if ev is None:
4251        raise Exception("No WPS-ER-AP-REMOVE event on max-age timeout")
4252
4253    sock.close()
4254
4255wps_event_url = None
4256
4257def gen_upnp_info(eventSubURL='wps_event', controlURL='wps_control',
4258                  udn='uuid:27ea801a-9e5c-4e73-bd82-f89cbcd10d7e'):
4259    payload = '''<?xml version="1.0"?>
4260<root xmlns="urn:schemas-upnp-org:device-1-0">
4261<specVersion>
4262<major>1</major>
4263<minor>0</minor>
4264</specVersion>
4265<device>
4266<deviceType>urn:schemas-wifialliance-org:device:WFADevice:1</deviceType>
4267<friendlyName>WPS Access Point</friendlyName>
4268<manufacturer>Company</manufacturer>
4269<modelName>WAP</modelName>
4270<modelNumber>123</modelNumber>
4271<serialNumber>12345</serialNumber>
4272'''
4273    if udn:
4274        payload += '<UDN>' + udn + '</UDN>'
4275    payload += '''<serviceList>
4276<service>
4277<serviceType>urn:schemas-wifialliance-org:service:WFAWLANConfig:1</serviceType>
4278<serviceId>urn:wifialliance-org:serviceId:WFAWLANConfig1</serviceId>
4279<SCPDURL>wps_scpd.xml</SCPDURL>
4280'''
4281    if controlURL:
4282        payload += '<controlURL>' + controlURL + '</controlURL>\n'
4283    if eventSubURL:
4284        payload += '<eventSubURL>' + eventSubURL + '</eventSubURL>\n'
4285    payload += '''</service>
4286</serviceList>
4287</device>
4288</root>
4289'''
4290    hdr = 'HTTP/1.1 200 OK\r\n' + \
4291          'Content-Type: text/xml; charset="utf-8"\r\n' + \
4292          'Server: Unspecified, UPnP/1.0, Unspecified\r\n' + \
4293          'Connection: close\r\n' + \
4294          'Content-Length: ' + str(len(payload)) + '\r\n' + \
4295          'Date: Sat, 15 Aug 2015 18:55:08 GMT\r\n\r\n'
4296    return (hdr + payload).encode()
4297
4298def gen_wps_control(payload_override=None):
4299    payload = '''<?xml version="1.0"?>
4300<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
4301<s:Body>
4302<u:GetDeviceInfoResponse xmlns:u="urn:schemas-wifialliance-org:service:WFAWLANConfig:1">
4303<NewDeviceInfo>EEoAARAQIgABBBBHABAn6oAanlxOc72C+Jy80Q1+ECAABgIAAAADABAaABCJZ7DPtbU3Ust9
4304Z3wJF07WEDIAwH45D3i1OqB7eJGwTzqeapS71h3KyXncK2xJZ+xqScrlorNEg6LijBJzG2Ca
4305+FZli0iliDJd397yAx/jk4nFXco3q5ylBSvSw9dhJ5u1xBKSnTilKGlUHPhLP75PUqM3fot9
43067zwtFZ4bx6x1sBA6oEe2d0aUJmLumQGCiKEIWlnxs44zego/2tAe81bDzdPBM7o5HH/FUhD+
4307KoGzFXp51atP+1n9Vta6AkI0Vye99JKLcC6Md9dMJltSVBgd4Xc4lRAEAAIAIxAQAAIADRAN
4308AAEBEAgAAgAEEEQAAQIQIQAHQ29tcGFueRAjAANXQVAQJAADMTIzEEIABTEyMzQ1EFQACAAG
4309AFDyBAABEBEAC1dpcmVsZXNzIEFQEDwAAQEQAgACAAAQEgACAAAQCQACAAAQLQAEgQIDABBJ
4310AAYANyoAASA=
4311</NewDeviceInfo>
4312</u:GetDeviceInfoResponse>
4313</s:Body>
4314</s:Envelope>
4315'''
4316    if payload_override:
4317        payload = payload_override
4318    hdr = 'HTTP/1.1 200 OK\r\n' + \
4319          'Content-Type: text/xml; charset="utf-8"\r\n' + \
4320          'Server: Unspecified, UPnP/1.0, Unspecified\r\n' + \
4321          'Connection: close\r\n' + \
4322          'Content-Length: ' + str(len(payload)) + '\r\n' + \
4323          'Date: Sat, 15 Aug 2015 18:55:08 GMT\r\n\r\n'
4324    return (hdr + payload).encode()
4325
4326def gen_wps_event(sid='uuid:7eb3342a-8a5f-47fe-a585-0785bfec6d8a'):
4327    payload = ""
4328    hdr = 'HTTP/1.1 200 OK\r\n' + \
4329          'Content-Type: text/xml; charset="utf-8"\r\n' + \
4330          'Server: Unspecified, UPnP/1.0, Unspecified\r\n' + \
4331          'Connection: close\r\n' + \
4332          'Content-Length: ' + str(len(payload)) + '\r\n'
4333    if sid:
4334        hdr += 'SID: ' + sid + '\r\n'
4335    hdr += 'Timeout: Second-1801\r\n' + \
4336          'Date: Sat, 15 Aug 2015 18:55:08 GMT\r\n\r\n'
4337    return (hdr + payload).encode()
4338
4339class WPSAPHTTPServer(StreamRequestHandler):
4340    def handle(self):
4341        data = self.rfile.readline().decode().strip()
4342        logger.info("HTTP server received: " + data)
4343        while True:
4344            hdr = self.rfile.readline().decode().strip()
4345            if len(hdr) == 0:
4346                break
4347            logger.info("HTTP header: " + hdr)
4348            if "CALLBACK:" in hdr:
4349                global wps_event_url
4350                wps_event_url = hdr.split(' ')[1].strip('<>')
4351
4352        if "GET /foo.xml" in data:
4353            self.handle_upnp_info()
4354        elif "POST /wps_control" in data:
4355            self.handle_wps_control()
4356        elif "SUBSCRIBE /wps_event" in data:
4357            self.handle_wps_event()
4358        else:
4359            self.handle_others(data)
4360
4361    def handle_upnp_info(self):
4362        self.wfile.write(gen_upnp_info())
4363
4364    def handle_wps_control(self):
4365        self.wfile.write(gen_wps_control())
4366
4367    def handle_wps_event(self):
4368        self.wfile.write(gen_wps_event())
4369
4370    def handle_others(self, data):
4371        logger.info("Ignore HTTP request: " + data)
4372
4373class MyTCPServer(TCPServer):
4374    def __init__(self, addr, handler):
4375        self.allow_reuse_address = True
4376        TCPServer.__init__(self, addr, handler)
4377
4378def wps_er_start(dev, http_server, max_age=1, wait_m_search=False,
4379                 location_url=None):
4380    socket.setdefaulttimeout(1)
4381    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
4382    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
4383    sock.bind(("239.255.255.250", 1900))
4384    dev.request("WPS_ER_START ifname=lo")
4385    for i in range(100):
4386        (msg, addr) = sock.recvfrom(1000)
4387        msg = msg.decode()
4388        logger.debug("Received SSDP message from %s: %s" % (str(addr), msg))
4389        if "M-SEARCH" in msg:
4390            break
4391        if not wait_m_search:
4392            raise Exception("Not an M-SEARCH")
4393        if i == 99:
4394            raise Exception("No M-SEARCH seen")
4395
4396    # Add an AP with a valid URL and server listing to it
4397    server = MyTCPServer(("127.0.0.1", 12345), http_server)
4398    if not location_url:
4399        location_url = 'http://127.0.0.1:12345/foo.xml'
4400    sock.sendto(("HTTP/1.1 200 OK\r\nST: urn:schemas-wifialliance-org:device:WFADevice:1\r\nlocation:%s\r\ncache-control:max-age=%d\r\n\r\n" % (location_url, max_age)).encode(), addr)
4401    server.timeout = 1
4402    return server, sock
4403
4404def wps_er_stop(dev, sock, server, on_alloc_fail=False):
4405    sock.close()
4406    server.server_close()
4407
4408    if on_alloc_fail:
4409        done = False
4410        for i in range(50):
4411            res = dev.request("GET_ALLOC_FAIL")
4412            if res.startswith("0:"):
4413                done = True
4414                break
4415            time.sleep(0.1)
4416        if not done:
4417            raise Exception("No allocation failure reported")
4418    else:
4419        ev = dev.wait_event(["WPS-ER-AP-REMOVE"], timeout=5)
4420        if ev is None:
4421            raise Exception("No WPS-ER-AP-REMOVE event on max-age timeout")
4422    dev.request("WPS_ER_STOP")
4423
4424def run_wps_er_proto_test(dev, handler, no_event_url=False, location_url=None,
4425                          max_age=1):
4426    try:
4427        uuid = '27ea801a-9e5c-4e73-bd82-f89cbcd10d7e'
4428        server, sock = wps_er_start(dev, handler, location_url=location_url,
4429                                    max_age=max_age)
4430        global wps_event_url
4431        wps_event_url = None
4432        server.handle_request()
4433        server.handle_request()
4434        server.handle_request()
4435        server.server_close()
4436        if no_event_url:
4437            if wps_event_url:
4438                raise Exception("Received event URL unexpectedly")
4439            return
4440        if wps_event_url is None:
4441            raise Exception("Did not get event URL")
4442        logger.info("Event URL: " + wps_event_url)
4443    finally:
4444            dev.request("WPS_ER_STOP")
4445
4446def send_wlanevent(url, uuid, data, no_response=False):
4447    conn = HTTPConnection(url.netloc)
4448    payload = '''<?xml version="1.0" encoding="utf-8"?>
4449<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
4450<e:property><STAStatus>1</STAStatus></e:property>
4451<e:property><APStatus>1</APStatus></e:property>
4452<e:property><WLANEvent>'''
4453    payload += base64.b64encode(data).decode()
4454    payload += '</WLANEvent></e:property></e:propertyset>'
4455    headers = {"Content-type": 'text/xml; charset="utf-8"',
4456               "Server": "Unspecified, UPnP/1.0, Unspecified",
4457               "HOST": url.netloc,
4458               "NT": "upnp:event",
4459               "SID": "uuid:" + uuid,
4460               "SEQ": "0",
4461               "Content-Length": str(len(payload))}
4462    conn.request("NOTIFY", url.path, payload, headers)
4463    if no_response:
4464        try:
4465            conn.getresponse()
4466        except Exception as e:
4467            pass
4468        return
4469    resp = conn.getresponse()
4470    if resp.status != 200:
4471        raise Exception("Unexpected HTTP response: %d" % resp.status)
4472
4473def test_ap_wps_er_http_proto(dev, apdev):
4474    """WPS ER HTTP protocol testing"""
4475    try:
4476        _test_ap_wps_er_http_proto(dev, apdev)
4477    finally:
4478        dev[0].request("WPS_ER_STOP")
4479
4480def _test_ap_wps_er_http_proto(dev, apdev):
4481    uuid = '27ea801a-9e5c-4e73-bd82-f89cbcd10d7e'
4482    server, sock = wps_er_start(dev[0], WPSAPHTTPServer, max_age=15)
4483    global wps_event_url
4484    wps_event_url = None
4485    server.handle_request()
4486    server.handle_request()
4487    server.handle_request()
4488    server.server_close()
4489    if wps_event_url is None:
4490        raise Exception("Did not get event URL")
4491    logger.info("Event URL: " + wps_event_url)
4492
4493    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=10)
4494    if ev is None:
4495        raise Exception("No WPS-ER-AP-ADD event")
4496    if uuid not in ev:
4497        raise Exception("UUID mismatch")
4498
4499    sock.close()
4500
4501    logger.info("Valid Probe Request notification")
4502    url = urlparse(wps_event_url)
4503    conn = HTTPConnection(url.netloc)
4504    payload = '''<?xml version="1.0" encoding="utf-8"?>
4505<e:propertyset xmlns:e="urn:schemas-upnp-org:event-1-0">
4506<e:property><STAStatus>1</STAStatus></e:property>
4507<e:property><APStatus>1</APStatus></e:property>
4508<e:property><WLANEvent>ATAyOjAwOjAwOjAwOjAwOjAwEEoAARAQOgABAhAIAAIxSBBHABA2LbR7pTpRkYj7VFi5hrLk
4509EFQACAAAAAAAAAAAEDwAAQMQAgACAAAQCQACAAAQEgACAAAQIQABIBAjAAEgECQAASAQEQAI
4510RGV2aWNlIEEQSQAGADcqAAEg
4511</WLANEvent></e:property>
4512</e:propertyset>
4513'''
4514    headers = {"Content-type": 'text/xml; charset="utf-8"',
4515               "Server": "Unspecified, UPnP/1.0, Unspecified",
4516               "HOST": url.netloc,
4517               "NT": "upnp:event",
4518               "SID": "uuid:" + uuid,
4519               "SEQ": "0",
4520               "Content-Length": str(len(payload))}
4521    conn.request("NOTIFY", url.path, payload, headers)
4522    resp = conn.getresponse()
4523    if resp.status != 200:
4524        raise Exception("Unexpected HTTP response: %d" % resp.status)
4525
4526    ev = dev[0].wait_event(["WPS-ER-ENROLLEE-ADD"], timeout=5)
4527    if ev is None:
4528        raise Exception("No WPS-ER-ENROLLEE-ADD event")
4529    if "362db47b-a53a-5191-88fb-5458b986b2e4" not in ev:
4530        raise Exception("No Enrollee UUID match")
4531
4532    logger.info("Incorrect event URL AP id")
4533    conn = HTTPConnection(url.netloc)
4534    conn.request("NOTIFY", url.path + '123', payload, headers)
4535    resp = conn.getresponse()
4536    if resp.status != 404:
4537        raise Exception("Unexpected HTTP response: %d" % resp.status)
4538
4539    logger.info("Missing AP id")
4540    conn = HTTPConnection(url.netloc)
4541    conn.request("NOTIFY", '/event/' + url.path.split('/')[2],
4542                 payload, headers)
4543    time.sleep(0.1)
4544
4545    logger.info("Incorrect event URL event id")
4546    conn = HTTPConnection(url.netloc)
4547    conn.request("NOTIFY", '/event/123456789/123', payload, headers)
4548    time.sleep(0.1)
4549
4550    logger.info("Incorrect event URL prefix")
4551    conn = HTTPConnection(url.netloc)
4552    conn.request("NOTIFY", '/foobar/123456789/123', payload, headers)
4553    resp = conn.getresponse()
4554    if resp.status != 404:
4555        raise Exception("Unexpected HTTP response: %d" % resp.status)
4556
4557    logger.info("Unsupported request")
4558    conn = HTTPConnection(url.netloc)
4559    conn.request("FOOBAR", '/foobar/123456789/123', payload, headers)
4560    resp = conn.getresponse()
4561    if resp.status != 501:
4562        raise Exception("Unexpected HTTP response: %d" % resp.status)
4563
4564    logger.info("Unsupported request and OOM")
4565    with alloc_fail(dev[0], 1, "wps_er_http_req"):
4566        conn = HTTPConnection(url.netloc)
4567        conn.request("FOOBAR", '/foobar/123456789/123', payload, headers)
4568        time.sleep(0.5)
4569
4570    logger.info("Too short WLANEvent")
4571    data = b'\x00'
4572    send_wlanevent(url, uuid, data)
4573
4574    logger.info("Invalid WLANEventMAC")
4575    data = b'\x00qwertyuiopasdfghjklzxcvbnm'
4576    send_wlanevent(url, uuid, data)
4577
4578    logger.info("Unknown WLANEventType")
4579    data = b'\xff02:00:00:00:00:00'
4580    send_wlanevent(url, uuid, data)
4581
4582    logger.info("Probe Request notification without any attributes")
4583    data = b'\x0102:00:00:00:00:00'
4584    send_wlanevent(url, uuid, data)
4585
4586    logger.info("Probe Request notification with invalid attribute")
4587    data = b'\x0102:00:00:00:00:00\xff'
4588    send_wlanevent(url, uuid, data)
4589
4590    logger.info("EAP message without any attributes")
4591    data = b'\x0202:00:00:00:00:00'
4592    send_wlanevent(url, uuid, data)
4593
4594    logger.info("EAP message with invalid attribute")
4595    data = b'\x0202:00:00:00:00:00\xff'
4596    send_wlanevent(url, uuid, data)
4597
4598    logger.info("EAP message from new STA and not M1")
4599    data = b'\x0202:ff:ff:ff:ff:ff' + b'\x10\x22\x00\x01\x05'
4600    send_wlanevent(url, uuid, data)
4601
4602    logger.info("EAP message: M1")
4603    data = b'\x0202:00:00:00:00:00'
4604    data += b'\x10\x22\x00\x01\x04'
4605    data += b'\x10\x47\x00\x10' + 16 * b'\x00'
4606    data += b'\x10\x20\x00\x06\x02\x00\x00\x00\x00\x00'
4607    data += b'\x10\x1a\x00\x10' + 16 * b'\x00'
4608    data += b'\x10\x32\x00\xc0' + 192 * b'\x00'
4609    data += b'\x10\x04\x00\x02\x00\x00'
4610    data += b'\x10\x10\x00\x02\x00\x00'
4611    data += b'\x10\x0d\x00\x01\x00'
4612    data += b'\x10\x08\x00\x02\x00\x00'
4613    data += b'\x10\x44\x00\x01\x00'
4614    data += b'\x10\x21\x00\x00'
4615    data += b'\x10\x23\x00\x00'
4616    data += b'\x10\x24\x00\x00'
4617    data += b'\x10\x42\x00\x00'
4618    data += b'\x10\x54\x00\x08' + 8 * b'\x00'
4619    data += b'\x10\x11\x00\x00'
4620    data += b'\x10\x3c\x00\x01\x00'
4621    data += b'\x10\x02\x00\x02\x00\x00'
4622    data += b'\x10\x12\x00\x02\x00\x00'
4623    data += b'\x10\x09\x00\x02\x00\x00'
4624    data += b'\x10\x2d\x00\x04\x00\x00\x00\x00'
4625    m1 = data
4626    send_wlanevent(url, uuid, data)
4627
4628    logger.info("EAP message: WSC_ACK")
4629    data = b'\x0202:00:00:00:00:00' + b'\x10\x22\x00\x01\x0d'
4630    send_wlanevent(url, uuid, data)
4631
4632    logger.info("EAP message: M1")
4633    send_wlanevent(url, uuid, m1)
4634
4635    logger.info("EAP message: WSC_NACK")
4636    data = b'\x0202:00:00:00:00:00' + b'\x10\x22\x00\x01\x0e'
4637    send_wlanevent(url, uuid, data)
4638
4639    logger.info("EAP message: M1 - Too long attribute values")
4640    data = b'\x0202:00:00:00:00:00'
4641    data += b'\x10\x11\x00\x21' + 33 * b'\x00'
4642    data += b'\x10\x45\x00\x21' + 33 * b'\x00'
4643    data += b'\x10\x42\x00\x21' + 33 * b'\x00'
4644    data += b'\x10\x24\x00\x21' + 33 * b'\x00'
4645    data += b'\x10\x23\x00\x21' + 33 * b'\x00'
4646    data += b'\x10\x21\x00\x41' + 65 * b'\x00'
4647    data += b'\x10\x49\x00\x09\x00\x37\x2a\x05\x02\x00\x00\x05\x00'
4648    send_wlanevent(url, uuid, data)
4649
4650    logger.info("EAP message: M1 missing UUID-E")
4651    data = b'\x0202:00:00:00:00:00'
4652    data += b'\x10\x22\x00\x01\x04'
4653    send_wlanevent(url, uuid, data)
4654
4655    logger.info("EAP message: M1 missing MAC Address")
4656    data += b'\x10\x47\x00\x10' + 16 * b'\x00'
4657    send_wlanevent(url, uuid, data)
4658
4659    logger.info("EAP message: M1 missing Enrollee Nonce")
4660    data += b'\x10\x20\x00\x06\x02\x00\x00\x00\x00\x00'
4661    send_wlanevent(url, uuid, data)
4662
4663    logger.info("EAP message: M1 missing Public Key")
4664    data += b'\x10\x1a\x00\x10' + 16 * b'\x00'
4665    send_wlanevent(url, uuid, data)
4666
4667    logger.info("EAP message: M1 missing Authentication Type flags")
4668    data += b'\x10\x32\x00\xc0' + 192 * b'\x00'
4669    send_wlanevent(url, uuid, data)
4670
4671    logger.info("EAP message: M1 missing Encryption Type Flags")
4672    data += b'\x10\x04\x00\x02\x00\x00'
4673    send_wlanevent(url, uuid, data)
4674
4675    logger.info("EAP message: M1 missing Connection Type flags")
4676    data += b'\x10\x10\x00\x02\x00\x00'
4677    send_wlanevent(url, uuid, data)
4678
4679    logger.info("EAP message: M1 missing Config Methods")
4680    data += b'\x10\x0d\x00\x01\x00'
4681    send_wlanevent(url, uuid, data)
4682
4683    logger.info("EAP message: M1 missing Wi-Fi Protected Setup State")
4684    data += b'\x10\x08\x00\x02\x00\x00'
4685    send_wlanevent(url, uuid, data)
4686
4687    logger.info("EAP message: M1 missing Manufacturer")
4688    data += b'\x10\x44\x00\x01\x00'
4689    send_wlanevent(url, uuid, data)
4690
4691    logger.info("EAP message: M1 missing Model Name")
4692    data += b'\x10\x21\x00\x00'
4693    send_wlanevent(url, uuid, data)
4694
4695    logger.info("EAP message: M1 missing Model Number")
4696    data += b'\x10\x23\x00\x00'
4697    send_wlanevent(url, uuid, data)
4698
4699    logger.info("EAP message: M1 missing Serial Number")
4700    data += b'\x10\x24\x00\x00'
4701    send_wlanevent(url, uuid, data)
4702
4703    logger.info("EAP message: M1 missing Primary Device Type")
4704    data += b'\x10\x42\x00\x00'
4705    send_wlanevent(url, uuid, data)
4706
4707    logger.info("EAP message: M1 missing Device Name")
4708    data += b'\x10\x54\x00\x08' + 8 * b'\x00'
4709    send_wlanevent(url, uuid, data)
4710
4711    logger.info("EAP message: M1 missing RF Bands")
4712    data += b'\x10\x11\x00\x00'
4713    send_wlanevent(url, uuid, data)
4714
4715    logger.info("EAP message: M1 missing Association State")
4716    data += b'\x10\x3c\x00\x01\x00'
4717    send_wlanevent(url, uuid, data)
4718
4719    logger.info("EAP message: M1 missing Device Password ID")
4720    data += b'\x10\x02\x00\x02\x00\x00'
4721    send_wlanevent(url, uuid, data)
4722
4723    logger.info("EAP message: M1 missing Configuration Error")
4724    data += b'\x10\x12\x00\x02\x00\x00'
4725    send_wlanevent(url, uuid, data)
4726
4727    logger.info("EAP message: M1 missing OS Version")
4728    data += b'\x10\x09\x00\x02\x00\x00'
4729    send_wlanevent(url, uuid, data)
4730
4731    logger.info("Check max concurrent requests")
4732    addr = (url.hostname, url.port)
4733    socks = {}
4734    for i in range(20):
4735        socks[i] = socket.socket(socket.AF_INET, socket.SOCK_STREAM,
4736                                 socket.IPPROTO_TCP)
4737        socks[i].settimeout(10)
4738        socks[i].connect(addr)
4739    for i in range(20):
4740        socks[i].send(b"GET / HTTP/1.1\r\n\r\n")
4741    count = 0
4742    for i in range(20):
4743        try:
4744            res = socks[i].recv(100).decode()
4745            if "HTTP/1" in res:
4746                count += 1
4747            else:
4748                logger.info("recv[%d]: len=%d" % (i, len(res)))
4749        except:
4750            pass
4751        socks[i].close()
4752    logger.info("%d concurrent HTTP GET operations returned response" % count)
4753    if count < 8:
4754        raise Exception("Too few concurrent HTTP connections accepted")
4755
4756    logger.info("OOM in HTTP server")
4757    for func in ["http_request_init", "httpread_create",
4758                 "eloop_register_timeout;httpread_create",
4759                 "eloop_sock_table_add_sock;?eloop_register_sock;httpread_create",
4760                 "httpread_hdr_analyze"]:
4761        with alloc_fail(dev[0], 1, func):
4762            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM,
4763                                 socket.IPPROTO_TCP)
4764            sock.connect(addr)
4765            sock.send(b"GET / HTTP/1.1\r\n\r\n")
4766            try:
4767                sock.recv(100)
4768            except:
4769                pass
4770            sock.close()
4771
4772    logger.info("Invalid HTTP header")
4773    for req in [" GET / HTTP/1.1\r\n\r\n",
4774                "HTTP/1.1 200 OK\r\n\r\n",
4775                "HTTP/\r\n\r\n",
4776                "GET %%a%aa% HTTP/1.1\r\n\r\n",
4777                "GET / HTTP/1.1\r\n FOO\r\n\r\n",
4778                "NOTIFY / HTTP/1.1\r\n" + 4097*'a' + '\r\n\r\n',
4779                "NOTIFY / HTTP/1.1\r\n\r\n" + 8193*'a',
4780                "POST / HTTP/1.1\r\nTransfer-Encoding: CHUNKED\r\n\r\n foo\r\n",
4781                "POST / HTTP/1.1\r\nTransfer-Encoding: CHUNKED\r\n\r\n1\r\nfoo\r\n",
4782                "POST / HTTP/1.1\r\nTransfer-Encoding: CHUNKED\r\n\r\n0\r\n",
4783                "POST / HTTP/1.1\r\nTransfer-Encoding: CHUNKED\r\n\r\n0\r\naa\ra\r\n\ra"]:
4784        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM,
4785                             socket.IPPROTO_TCP)
4786        sock.settimeout(0.1)
4787        sock.connect(addr)
4788        sock.send(req.encode())
4789        try:
4790            sock.recv(100)
4791        except:
4792            pass
4793        sock.close()
4794
4795    with alloc_fail(dev[0], 2, "httpread_read_handler"):
4796        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM,
4797                             socket.IPPROTO_TCP)
4798        sock.connect(addr)
4799        sock.send(b"NOTIFY / HTTP/1.1\r\n\r\n" + 4500 * b'a')
4800        try:
4801            sock.recv(100)
4802        except:
4803            pass
4804        sock.close()
4805
4806    conn = HTTPConnection(url.netloc)
4807    payload = '<foo'
4808    headers = {"Content-type": 'text/xml; charset="utf-8"',
4809               "Server": "Unspecified, UPnP/1.0, Unspecified",
4810               "HOST": url.netloc,
4811               "NT": "upnp:event",
4812               "SID": "uuid:" + uuid,
4813               "SEQ": "0",
4814               "Content-Length": str(len(payload))}
4815    conn.request("NOTIFY", url.path, payload, headers)
4816    resp = conn.getresponse()
4817    if resp.status != 200:
4818        raise Exception("Unexpected HTTP response: %d" % resp.status)
4819
4820    conn = HTTPConnection(url.netloc)
4821    payload = '<WLANEvent foo></WLANEvent>'
4822    headers = {"Content-type": 'text/xml; charset="utf-8"',
4823               "Server": "Unspecified, UPnP/1.0, Unspecified",
4824               "HOST": url.netloc,
4825               "NT": "upnp:event",
4826               "SID": "uuid:" + uuid,
4827               "SEQ": "0",
4828               "Content-Length": str(len(payload))}
4829    conn.request("NOTIFY", url.path, payload, headers)
4830    resp = conn.getresponse()
4831    if resp.status != 200:
4832        raise Exception("Unexpected HTTP response: %d" % resp.status)
4833
4834    with alloc_fail(dev[0], 1, "xml_get_first_item"):
4835        send_wlanevent(url, uuid, b'')
4836
4837    with alloc_fail(dev[0], 1, "wpabuf_alloc_ext_data;xml_get_base64_item"):
4838        send_wlanevent(url, uuid, b'foo')
4839
4840    for func in ["wps_init",
4841                 "wps_process_manufacturer",
4842                 "wps_process_model_name",
4843                 "wps_process_model_number",
4844                 "wps_process_serial_number",
4845                 "wps_process_dev_name"]:
4846        with alloc_fail(dev[0], 1, func):
4847            send_wlanevent(url, uuid, m1)
4848
4849    with alloc_fail(dev[0], 1, "wps_er_http_resp_ok"):
4850        send_wlanevent(url, uuid, m1, no_response=True)
4851
4852    with alloc_fail(dev[0], 1, "wps_er_http_resp_not_found"):
4853        url2 = urlparse(wps_event_url.replace('/event/', '/notfound/'))
4854        send_wlanevent(url2, uuid, m1, no_response=True)
4855
4856    logger.info("EAP message: M1")
4857    data = b'\x0202:11:22:00:00:00'
4858    data += b'\x10\x22\x00\x01\x04'
4859    data += b'\x10\x47\x00\x10' + 16 * b'\x00'
4860    data += b'\x10\x20\x00\x06\x02\x00\x00\x00\x00\x00'
4861    data += b'\x10\x1a\x00\x10' + 16 * b'\x00'
4862    data += b'\x10\x32\x00\xc0' + 192 * b'\x00'
4863    data += b'\x10\x04\x00\x02\x00\x00'
4864    data += b'\x10\x10\x00\x02\x00\x00'
4865    data += b'\x10\x0d\x00\x01\x00'
4866    data += b'\x10\x08\x00\x02\x00\x00'
4867    data += b'\x10\x44\x00\x01\x00'
4868    data += b'\x10\x21\x00\x00'
4869    data += b'\x10\x23\x00\x00'
4870    data += b'\x10\x24\x00\x00'
4871    data += b'\x10\x42\x00\x00'
4872    data += b'\x10\x54\x00\x08' + 8 * b'\x00'
4873    data += b'\x10\x11\x00\x00'
4874    data += b'\x10\x3c\x00\x01\x00'
4875    data += b'\x10\x02\x00\x02\x00\x00'
4876    data += b'\x10\x12\x00\x02\x00\x00'
4877    data += b'\x10\x09\x00\x02\x00\x00'
4878    data += b'\x10\x2d\x00\x04\x00\x00\x00\x00'
4879    dev[0].dump_monitor()
4880    with alloc_fail(dev[0], 1, "wps_er_add_sta_data"):
4881        send_wlanevent(url, uuid, data)
4882        ev = dev[0].wait_event(["WPS-ER-ENROLLEE-ADD"], timeout=0.1)
4883        if ev is not None:
4884            raise Exception("Unexpected enrollee add event")
4885    send_wlanevent(url, uuid, data)
4886    ev = dev[0].wait_event(["WPS-ER-ENROLLEE-ADD"], timeout=2)
4887    if ev is None:
4888        raise Exception("Enrollee add event not seen")
4889
4890    with alloc_fail(dev[0], 1,
4891                    "base64_gen_encode;?base64_encode;wps_er_soap_hdr"):
4892        send_wlanevent(url, uuid, data)
4893
4894    with alloc_fail(dev[0], 1, "wpabuf_alloc;wps_er_soap_hdr"):
4895        send_wlanevent(url, uuid, data)
4896
4897    with alloc_fail(dev[0], 1, "http_client_url_parse;wps_er_sta_send_msg"):
4898        send_wlanevent(url, uuid, data)
4899
4900    with alloc_fail(dev[0], 1, "http_client_addr;wps_er_sta_send_msg"):
4901        send_wlanevent(url, uuid, data)
4902
4903def test_ap_wps_er_http_proto_no_event_sub_url(dev, apdev):
4904    """WPS ER HTTP protocol testing - no eventSubURL"""
4905    class WPSAPHTTPServer_no_event_sub_url(WPSAPHTTPServer):
4906        def handle_upnp_info(self):
4907            self.wfile.write(gen_upnp_info(eventSubURL=None))
4908    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_no_event_sub_url,
4909                          no_event_url=True)
4910
4911def test_ap_wps_er_http_proto_event_sub_url_dns(dev, apdev):
4912    """WPS ER HTTP protocol testing - DNS name in eventSubURL"""
4913    class WPSAPHTTPServer_event_sub_url_dns(WPSAPHTTPServer):
4914        def handle_upnp_info(self):
4915            self.wfile.write(gen_upnp_info(eventSubURL='http://example.com/wps_event'))
4916    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_event_sub_url_dns,
4917                          no_event_url=True)
4918
4919def test_ap_wps_er_http_proto_subscribe_oom(dev, apdev):
4920    """WPS ER HTTP protocol testing - subscribe OOM"""
4921    try:
4922        _test_ap_wps_er_http_proto_subscribe_oom(dev, apdev)
4923    finally:
4924        dev[0].request("WPS_ER_STOP")
4925
4926def _test_ap_wps_er_http_proto_subscribe_oom(dev, apdev):
4927    tests = [(1, "http_client_url_parse"),
4928             (1, "wpabuf_alloc;wps_er_subscribe"),
4929             (1, "http_client_addr"),
4930             (1, "eloop_sock_table_add_sock;?eloop_register_sock;http_client_addr"),
4931             (1, "eloop_register_timeout;http_client_addr")]
4932    for count, func in tests:
4933        with alloc_fail(dev[0], count, func):
4934            server, sock = wps_er_start(dev[0], WPSAPHTTPServer)
4935            server.handle_request()
4936            server.handle_request()
4937            wps_er_stop(dev[0], sock, server, on_alloc_fail=True)
4938
4939def test_ap_wps_er_http_proto_no_sid(dev, apdev):
4940    """WPS ER HTTP protocol testing - no SID"""
4941    class WPSAPHTTPServer_no_sid(WPSAPHTTPServer):
4942        def handle_wps_event(self):
4943            self.wfile.write(gen_wps_event(sid=None))
4944    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_no_sid)
4945
4946def test_ap_wps_er_http_proto_invalid_sid_no_uuid(dev, apdev):
4947    """WPS ER HTTP protocol testing - invalid SID - no UUID"""
4948    class WPSAPHTTPServer_invalid_sid_no_uuid(WPSAPHTTPServer):
4949        def handle_wps_event(self):
4950            self.wfile.write(gen_wps_event(sid='FOO'))
4951    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_invalid_sid_no_uuid)
4952
4953def test_ap_wps_er_http_proto_invalid_sid_uuid(dev, apdev):
4954    """WPS ER HTTP protocol testing - invalid SID UUID"""
4955    class WPSAPHTTPServer_invalid_sid_uuid(WPSAPHTTPServer):
4956        def handle_wps_event(self):
4957            self.wfile.write(gen_wps_event(sid='uuid:FOO'))
4958    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_invalid_sid_uuid)
4959
4960def test_ap_wps_er_http_proto_subscribe_failing(dev, apdev):
4961    """WPS ER HTTP protocol testing - SUBSCRIBE failing"""
4962    class WPSAPHTTPServer_fail_subscribe(WPSAPHTTPServer):
4963        def handle_wps_event(self):
4964            payload = ""
4965            hdr = 'HTTP/1.1 404 Not Found\r\n' + \
4966                  'Content-Type: text/xml; charset="utf-8"\r\n' + \
4967                  'Server: Unspecified, UPnP/1.0, Unspecified\r\n' + \
4968                  'Connection: close\r\n' + \
4969                  'Content-Length: ' + str(len(payload)) + '\r\n' + \
4970                  'Timeout: Second-1801\r\n' + \
4971                  'Date: Sat, 15 Aug 2015 18:55:08 GMT\r\n\r\n'
4972            self.wfile.write((hdr + payload).encode())
4973    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_fail_subscribe)
4974
4975def test_ap_wps_er_http_proto_subscribe_invalid_response(dev, apdev):
4976    """WPS ER HTTP protocol testing - SUBSCRIBE and invalid response"""
4977    class WPSAPHTTPServer_subscribe_invalid_response(WPSAPHTTPServer):
4978        def handle_wps_event(self):
4979            payload = ""
4980            hdr = 'HTTP/1.1 FOO\r\n' + \
4981                  'Content-Type: text/xml; charset="utf-8"\r\n' + \
4982                  'Server: Unspecified, UPnP/1.0, Unspecified\r\n' + \
4983                  'Connection: close\r\n' + \
4984                  'Content-Length: ' + str(len(payload)) + '\r\n' + \
4985                  'Timeout: Second-1801\r\n' + \
4986                  'Date: Sat, 15 Aug 2015 18:55:08 GMT\r\n\r\n'
4987            self.wfile.write((hdr + payload).encode())
4988    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_subscribe_invalid_response)
4989
4990def test_ap_wps_er_http_proto_subscribe_invalid_response(dev, apdev):
4991    """WPS ER HTTP protocol testing - SUBSCRIBE and invalid response"""
4992    class WPSAPHTTPServer_invalid_m1(WPSAPHTTPServer):
4993        def handle_wps_control(self):
4994            payload = '''<?xml version="1.0"?>
4995<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
4996<s:Body>
4997<u:GetDeviceInfoResponse xmlns:u="urn:schemas-wifialliance-org:service:WFAWLANConfig:1">
4998<NewDeviceInfo>Rk9P</NewDeviceInfo>
4999</u:GetDeviceInfoResponse>
5000</s:Body>
5001</s:Envelope>
5002'''
5003            self.wfile.write(gen_wps_control(payload_override=payload))
5004    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_invalid_m1, no_event_url=True)
5005
5006def test_ap_wps_er_http_proto_upnp_info_no_device(dev, apdev):
5007    """WPS ER HTTP protocol testing - No device in UPnP info"""
5008    class WPSAPHTTPServer_no_device(WPSAPHTTPServer):
5009        def handle_upnp_info(self):
5010            payload = '''<?xml version="1.0"?>
5011<root xmlns="urn:schemas-upnp-org:device-1-0">
5012<specVersion>
5013<major>1</major>
5014<minor>0</minor>
5015</specVersion>
5016</root>
5017'''
5018            hdr = 'HTTP/1.1 200 OK\r\n' + \
5019                  'Content-Type: text/xml; charset="utf-8"\r\n' + \
5020                  'Server: Unspecified, UPnP/1.0, Unspecified\r\n' + \
5021                  'Connection: close\r\n' + \
5022                  'Content-Length: ' + str(len(payload)) + '\r\n' + \
5023                  'Date: Sat, 15 Aug 2015 18:55:08 GMT\r\n\r\n'
5024            self.wfile.write((hdr + payload).encode())
5025    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_no_device, no_event_url=True)
5026
5027def test_ap_wps_er_http_proto_upnp_info_no_device_type(dev, apdev):
5028    """WPS ER HTTP protocol testing - No deviceType in UPnP info"""
5029    class WPSAPHTTPServer_no_device(WPSAPHTTPServer):
5030        def handle_upnp_info(self):
5031            payload = '''<?xml version="1.0"?>
5032<root xmlns="urn:schemas-upnp-org:device-1-0">
5033<specVersion>
5034<major>1</major>
5035<minor>0</minor>
5036</specVersion>
5037<device>
5038</device>
5039</root>
5040'''
5041            hdr = 'HTTP/1.1 200 OK\r\n' + \
5042                  'Content-Type: text/xml; charset="utf-8"\r\n' + \
5043                  'Server: Unspecified, UPnP/1.0, Unspecified\r\n' + \
5044                  'Connection: close\r\n' + \
5045                  'Content-Length: ' + str(len(payload)) + '\r\n' + \
5046                  'Date: Sat, 15 Aug 2015 18:55:08 GMT\r\n\r\n'
5047            self.wfile.write((hdr + payload).encode())
5048    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_no_device, no_event_url=True)
5049
5050def test_ap_wps_er_http_proto_upnp_info_invalid_udn_uuid(dev, apdev):
5051    """WPS ER HTTP protocol testing - Invalid UDN UUID"""
5052    class WPSAPHTTPServer_invalid_udn_uuid(WPSAPHTTPServer):
5053        def handle_upnp_info(self):
5054            self.wfile.write(gen_upnp_info(udn='uuid:foo'))
5055    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_invalid_udn_uuid)
5056
5057def test_ap_wps_er_http_proto_no_control_url(dev, apdev):
5058    """WPS ER HTTP protocol testing - no controlURL"""
5059    class WPSAPHTTPServer_no_control_url(WPSAPHTTPServer):
5060        def handle_upnp_info(self):
5061            self.wfile.write(gen_upnp_info(controlURL=None))
5062    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_no_control_url,
5063                          no_event_url=True)
5064
5065def test_ap_wps_er_http_proto_control_url_dns(dev, apdev):
5066    """WPS ER HTTP protocol testing - DNS name in controlURL"""
5067    class WPSAPHTTPServer_control_url_dns(WPSAPHTTPServer):
5068        def handle_upnp_info(self):
5069            self.wfile.write(gen_upnp_info(controlURL='http://example.com/wps_control'))
5070    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_control_url_dns,
5071                          no_event_url=True)
5072
5073def test_ap_wps_http_timeout(dev, apdev):
5074    """WPS AP/ER and HTTP timeout"""
5075    try:
5076        _test_ap_wps_http_timeout(dev, apdev)
5077    finally:
5078        dev[0].request("WPS_ER_STOP")
5079
5080def _test_ap_wps_http_timeout(dev, apdev):
5081    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
5082    add_ssdp_ap(apdev[0], ap_uuid)
5083
5084    location = ssdp_get_location(ap_uuid)
5085    url = urlparse(location)
5086    addr = (url.hostname, url.port)
5087    logger.debug("Open HTTP connection to hostapd, but do not complete request")
5088    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM,
5089                         socket.IPPROTO_TCP)
5090    sock.connect(addr)
5091    sock.send(b"G")
5092
5093    class StubServer(StreamRequestHandler):
5094        def handle(self):
5095            logger.debug("StubServer - start 31 sec wait")
5096            time.sleep(31)
5097            logger.debug("StubServer - wait done")
5098
5099    logger.debug("Start WPS ER")
5100    server, sock2 = wps_er_start(dev[0], StubServer, max_age=40,
5101                                 wait_m_search=True)
5102
5103    logger.debug("Start server to accept, but not complete, HTTP connection from WPS ER")
5104    # This will wait for 31 seconds..
5105    server.handle_request()
5106
5107    logger.debug("Complete HTTP connection with hostapd (that should have already closed the connection)")
5108    try:
5109        sock.send("ET / HTTP/1.1\r\n\r\n")
5110        res = sock.recv(100)
5111        sock.close()
5112    except:
5113        pass
5114
5115def test_ap_wps_er_url_parse(dev, apdev):
5116    """WPS ER and URL parsing special cases"""
5117    try:
5118        _test_ap_wps_er_url_parse(dev, apdev)
5119    finally:
5120        dev[0].request("WPS_ER_STOP")
5121
5122def _test_ap_wps_er_url_parse(dev, apdev):
5123    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
5124    sock.settimeout(1)
5125    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
5126    sock.bind(("239.255.255.250", 1900))
5127    dev[0].request("WPS_ER_START ifname=lo")
5128    (msg, addr) = sock.recvfrom(1000)
5129    msg = msg.decode()
5130    logger.debug("Received SSDP message from %s: %s" % (str(addr), msg))
5131    if "M-SEARCH" not in msg:
5132        raise Exception("Not an M-SEARCH")
5133    sock.sendto(b"HTTP/1.1 200 OK\r\nST: urn:schemas-wifialliance-org:device:WFADevice:1\r\nlocation:http://127.0.0.1\r\ncache-control:max-age=1\r\n\r\n", addr)
5134    ev = dev[0].wait_event(["WPS-ER-AP-REMOVE"], timeout=2)
5135    sock.sendto(b"HTTP/1.1 200 OK\r\nST: urn:schemas-wifialliance-org:device:WFADevice:1\r\nlocation:http://127.0.0.1/:foo\r\ncache-control:max-age=1\r\n\r\n", addr)
5136    ev = dev[0].wait_event(["WPS-ER-AP-REMOVE"], timeout=2)
5137    sock.sendto(b"HTTP/1.1 200 OK\r\nST: urn:schemas-wifialliance-org:device:WFADevice:1\r\nlocation:http://255.255.255.255:0/foo.xml\r\ncache-control:max-age=1\r\n\r\n", addr)
5138    ev = dev[0].wait_event(["WPS-ER-AP-REMOVE"], timeout=2)
5139
5140    sock.close()
5141
5142def test_ap_wps_er_link_update(dev, apdev):
5143    """WPS ER and link update special cases"""
5144    class WPSAPHTTPServer_link_update(WPSAPHTTPServer):
5145        def handle_upnp_info(self):
5146            self.wfile.write(gen_upnp_info(controlURL='/wps_control'))
5147    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_link_update)
5148
5149    class WPSAPHTTPServer_link_update2(WPSAPHTTPServer):
5150        def handle_others(self, data):
5151            if "GET / " in data:
5152                self.wfile.write(gen_upnp_info(controlURL='/wps_control'))
5153    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_link_update2,
5154                          location_url='http://127.0.0.1:12345')
5155
5156def test_ap_wps_er_http_client(dev, apdev):
5157    """WPS ER and HTTP client special cases"""
5158    with alloc_fail(dev[0], 1, "http_link_update"):
5159        run_wps_er_proto_test(dev[0], WPSAPHTTPServer)
5160
5161    with alloc_fail(dev[0], 1, "wpabuf_alloc;http_client_url"):
5162        run_wps_er_proto_test(dev[0], WPSAPHTTPServer, no_event_url=True)
5163
5164    with alloc_fail(dev[0], 1, "httpread_create;http_client_tx_ready"):
5165        run_wps_er_proto_test(dev[0], WPSAPHTTPServer, no_event_url=True)
5166
5167    class WPSAPHTTPServer_req_as_resp(WPSAPHTTPServer):
5168        def handle_upnp_info(self):
5169            self.wfile.write(b"GET / HTTP/1.1\r\n\r\n")
5170    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_req_as_resp,
5171                          no_event_url=True)
5172
5173def test_ap_wps_er_http_client_timeout(dev, apdev):
5174    """WPS ER and HTTP client timeout"""
5175    class WPSAPHTTPServer_timeout(WPSAPHTTPServer):
5176        def handle_upnp_info(self):
5177            time.sleep(31)
5178            self.wfile.write(b"GET / HTTP/1.1\r\n\r\n")
5179    run_wps_er_proto_test(dev[0], WPSAPHTTPServer_timeout,
5180                          no_event_url=True, max_age=60)
5181
5182def test_ap_wps_init_oom(dev, apdev):
5183    """wps_init OOM cases"""
5184    ssid = "test-wps"
5185    appin = "12345670"
5186    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
5187              "ap_pin": appin}
5188    hapd = hostapd.add_ap(apdev[0], params)
5189    pin = dev[0].wps_read_pin()
5190
5191    with alloc_fail(hapd, 1, "wps_init"):
5192        hapd.request("WPS_PIN any " + pin)
5193        dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5194        dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
5195        ev = hapd.wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
5196        if ev is None:
5197            raise Exception("No EAP failure reported")
5198        dev[0].request("WPS_CANCEL")
5199
5200    with alloc_fail(dev[0], 2, "wps_init"):
5201        hapd.request("WPS_PIN any " + pin)
5202        dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5203        dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
5204        ev = hapd.wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
5205        if ev is None:
5206            raise Exception("No EAP failure reported")
5207        dev[0].request("WPS_CANCEL")
5208
5209    with alloc_fail(dev[0], 2, "wps_init"):
5210        hapd.request("WPS_PBC")
5211        dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5212        dev[0].request("WPS_PBC %s" % (apdev[0]['bssid']))
5213        ev = hapd.wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
5214        if ev is None:
5215            raise Exception("No EAP failure reported")
5216        dev[0].request("WPS_CANCEL")
5217
5218    dev[0].dump_monitor()
5219    new_ssid = "wps-new-ssid"
5220    new_passphrase = "1234567890"
5221    with alloc_fail(dev[0], 3, "wps_init"):
5222        dev[0].wps_reg(apdev[0]['bssid'], appin, new_ssid, "WPA2PSK", "CCMP",
5223                       new_passphrase, no_wait=True)
5224        ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
5225        if ev is None:
5226            raise Exception("No EAP failure reported")
5227
5228    dev[0].flush_scan_cache()
5229
5230@remote_compatible
5231def test_ap_wps_invalid_assoc_req_elem(dev, apdev):
5232    """WPS and invalid IE in Association Request frame"""
5233    ssid = "test-wps"
5234    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2"}
5235    hapd = hostapd.add_ap(apdev[0], params)
5236    pin = "12345670"
5237    hapd.request("WPS_PIN any " + pin)
5238    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5239    try:
5240        dev[0].request("VENDOR_ELEM_ADD 13 dd050050f20410")
5241        dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
5242        for i in range(5):
5243            ev = hapd.wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=10)
5244            if ev and "vendor=14122" in ev:
5245                break
5246        if ev is None or "vendor=14122" not in ev:
5247            raise Exception("EAP-WSC not started")
5248        dev[0].request("WPS_CANCEL")
5249    finally:
5250        dev[0].request("VENDOR_ELEM_REMOVE 13 *")
5251
5252def test_ap_wps_pbc_pin_mismatch(dev, apdev):
5253    """WPS PBC/PIN mismatch"""
5254    ssid = "test-wps"
5255    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2"}
5256    hapd = hostapd.add_ap(apdev[0], params)
5257    hapd.request("SET wps_version_number 0x10")
5258    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5259    hapd.request("WPS_PBC")
5260    pin = dev[0].wps_read_pin()
5261    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
5262    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
5263    if ev is None:
5264        raise Exception("Scan did not complete")
5265    dev[0].request("WPS_CANCEL")
5266
5267    hapd.request("WPS_CANCEL")
5268    dev[0].flush_scan_cache()
5269
5270@remote_compatible
5271def test_ap_wps_ie_invalid(dev, apdev):
5272    """WPS PIN attempt with AP that has invalid WSC IE"""
5273    ssid = "test-wps"
5274    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
5275              "vendor_elements": "dd050050f20410"}
5276    hapd = hostapd.add_ap(apdev[0], params)
5277    params = {'ssid': "another", "vendor_elements": "dd050050f20410"}
5278    hostapd.add_ap(apdev[1], params)
5279    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5280    pin = dev[0].wps_read_pin()
5281    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
5282    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
5283    if ev is None:
5284        raise Exception("Scan did not complete")
5285    dev[0].request("WPS_CANCEL")
5286
5287@remote_compatible
5288def test_ap_wps_scan_prio_order(dev, apdev):
5289    """WPS scan priority ordering"""
5290    ssid = "test-wps"
5291    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2"}
5292    hapd = hostapd.add_ap(apdev[0], params)
5293    params = {'ssid': "another", "vendor_elements": "dd050050f20410"}
5294    hostapd.add_ap(apdev[1], params)
5295    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5296    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
5297    pin = dev[0].wps_read_pin()
5298    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
5299    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"])
5300    if ev is None:
5301        raise Exception("Scan did not complete")
5302    dev[0].request("WPS_CANCEL")
5303
5304def test_ap_wps_probe_req_ie_oom(dev, apdev):
5305    """WPS ProbeReq IE OOM"""
5306    ssid = "test-wps"
5307    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2"}
5308    hapd = hostapd.add_ap(apdev[0], params)
5309    pin = dev[0].wps_read_pin()
5310    hapd.request("WPS_PIN any " + pin)
5311    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5312    with alloc_fail(dev[0], 1, "wps_build_probe_req_ie"):
5313        dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
5314        ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=10)
5315        if ev is None:
5316            raise Exception("Association not seen")
5317    dev[0].request("WPS_CANCEL")
5318    dev[0].wait_disconnected()
5319
5320    with alloc_fail(dev[0], 1, "wps_ie_encapsulate"):
5321        dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
5322        ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=10)
5323        if ev is None:
5324            raise Exception("Association not seen")
5325    dev[0].request("WPS_CANCEL")
5326    hapd.disable()
5327    dev[0].request("REMOVE_NETWORK all")
5328    dev[0].wait_disconnected()
5329    time.sleep(0.2)
5330    dev[0].flush_scan_cache()
5331
5332def test_ap_wps_assoc_req_ie_oom(dev, apdev):
5333    """WPS AssocReq IE OOM"""
5334    ssid = "test-wps"
5335    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2"}
5336    hapd = hostapd.add_ap(apdev[0], params)
5337    pin = dev[0].wps_read_pin()
5338    hapd.request("WPS_PIN any " + pin)
5339    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5340    with alloc_fail(dev[0], 1, "wps_build_assoc_req_ie"):
5341        dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
5342        ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=10)
5343        if ev is None:
5344            raise Exception("Association not seen")
5345    dev[0].request("WPS_CANCEL")
5346
5347def test_ap_wps_assoc_resp_ie_oom(dev, apdev):
5348    """WPS AssocResp IE OOM"""
5349    ssid = "test-wps"
5350    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2"}
5351    hapd = hostapd.add_ap(apdev[0], params)
5352    pin = dev[0].wps_read_pin()
5353    hapd.request("WPS_PIN any " + pin)
5354    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5355    with alloc_fail(hapd, 1, "wps_build_assoc_resp_ie"):
5356        dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
5357        ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=10)
5358        if ev is None:
5359            raise Exception("Association not seen")
5360    dev[0].request("WPS_CANCEL")
5361
5362@remote_compatible
5363def test_ap_wps_bss_info_errors(dev, apdev):
5364    """WPS BSS info errors"""
5365    params = {"ssid": "1",
5366              "vendor_elements": "dd0e0050f20410440001ff101100010a"}
5367    hostapd.add_ap(apdev[0], params)
5368    params = {'ssid': "2", "vendor_elements": "dd050050f20410"}
5369    hostapd.add_ap(apdev[1], params)
5370    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5371    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
5372    bss = dev[0].get_bss(apdev[0]['bssid'])
5373    logger.info("BSS: " + str(bss))
5374    if "wps_state" in bss:
5375        raise Exception("Unexpected wps_state in BSS info")
5376    if 'wps_device_name' not in bss:
5377        raise Exception("No wps_device_name in BSS info")
5378    if bss['wps_device_name'] != '_':
5379        raise Exception("Unexpected wps_device_name value")
5380    bss = dev[0].get_bss(apdev[1]['bssid'])
5381    logger.info("BSS: " + str(bss))
5382
5383    with alloc_fail(dev[0], 1, "=wps_attr_text"):
5384        bss = dev[0].get_bss(apdev[0]['bssid'])
5385        logger.info("BSS(OOM): " + str(bss))
5386
5387def wps_run_pbc_fail_ap(apdev, dev, hapd):
5388    hapd.request("WPS_PBC")
5389    dev.scan_for_bss(apdev['bssid'], freq="2412")
5390    dev.request("WPS_PBC " + apdev['bssid'])
5391    ev = dev.wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
5392    if ev is None:
5393        raise Exception("No EAP failure reported")
5394    dev.request("WPS_CANCEL")
5395    dev.wait_disconnected()
5396    for i in range(5):
5397        try:
5398            dev.flush_scan_cache()
5399            break
5400        except Exception as e:
5401            if str(e).startswith("Failed to trigger scan"):
5402                # Try again
5403                time.sleep(1)
5404            else:
5405                raise
5406
5407def wps_run_pbc_fail(apdev, dev):
5408    hapd = wps_start_ap(apdev)
5409    wps_run_pbc_fail_ap(apdev, dev, hapd)
5410
5411@remote_compatible
5412def test_ap_wps_pk_oom(dev, apdev):
5413    """WPS and public key OOM"""
5414    with alloc_fail(dev[0], 1, "wps_build_public_key"):
5415        wps_run_pbc_fail(apdev[0], dev[0])
5416
5417@remote_compatible
5418def test_ap_wps_pk_oom_ap(dev, apdev):
5419    """WPS and public key OOM on AP"""
5420    hapd = wps_start_ap(apdev[0])
5421    with alloc_fail(hapd, 1, "wps_build_public_key"):
5422        wps_run_pbc_fail_ap(apdev[0], dev[0], hapd)
5423
5424@remote_compatible
5425def test_ap_wps_encr_oom_ap(dev, apdev):
5426    """WPS and encrypted settings decryption OOM on AP"""
5427    hapd = wps_start_ap(apdev[0])
5428    pin = dev[0].wps_read_pin()
5429    hapd.request("WPS_PIN any " + pin)
5430    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5431    with alloc_fail(hapd, 1, "wps_decrypt_encr_settings"):
5432        dev[0].request("WPS_PIN " + apdev[0]['bssid'] + " " + pin)
5433        ev = hapd.wait_event(["WPS-FAIL"], timeout=10)
5434        if ev is None:
5435            raise Exception("No WPS-FAIL reported")
5436        dev[0].request("WPS_CANCEL")
5437    dev[0].wait_disconnected()
5438
5439@remote_compatible
5440def test_ap_wps_encr_no_random_ap(dev, apdev):
5441    """WPS and no random data available for encryption on AP"""
5442    hapd = wps_start_ap(apdev[0])
5443    with fail_test(hapd, 1, "os_get_random;wps_build_encr_settings"):
5444        wps_run_pbc_fail_ap(apdev[0], dev[0], hapd)
5445
5446@remote_compatible
5447def test_ap_wps_e_hash_no_random_sta(dev, apdev):
5448    """WPS and no random data available for e-hash on STA"""
5449    with fail_test(dev[0], 1, "os_get_random;wps_build_e_hash"):
5450        wps_run_pbc_fail(apdev[0], dev[0])
5451
5452@remote_compatible
5453def test_ap_wps_m1_no_random(dev, apdev):
5454    """WPS and no random for M1 on STA"""
5455    with fail_test(dev[0], 1, "os_get_random;wps_build_m1"):
5456        wps_run_pbc_fail(apdev[0], dev[0])
5457
5458@remote_compatible
5459def test_ap_wps_m1_oom(dev, apdev):
5460    """WPS and OOM for M1 on STA"""
5461    with alloc_fail(dev[0], 1, "wps_build_m1"):
5462        wps_run_pbc_fail(apdev[0], dev[0])
5463
5464@remote_compatible
5465def test_ap_wps_m3_oom(dev, apdev):
5466    """WPS and OOM for M3 on STA"""
5467    with alloc_fail(dev[0], 1, "wps_build_m3"):
5468        wps_run_pbc_fail(apdev[0], dev[0])
5469
5470@remote_compatible
5471def test_ap_wps_m5_oom(dev, apdev):
5472    """WPS and OOM for M5 on STA"""
5473    hapd = wps_start_ap(apdev[0])
5474    hapd.request("WPS_PBC")
5475    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5476    for i in range(1, 3):
5477        with alloc_fail(dev[0], i, "wps_build_m5"):
5478            dev[0].request("WPS_PBC " + apdev[0]['bssid'])
5479            ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
5480            if ev is None:
5481                raise Exception("No EAP failure reported")
5482            dev[0].request("WPS_CANCEL")
5483            dev[0].wait_disconnected()
5484    dev[0].flush_scan_cache()
5485
5486@remote_compatible
5487def test_ap_wps_m5_no_random(dev, apdev):
5488    """WPS and no random for M5 on STA"""
5489    with fail_test(dev[0], 1,
5490                   "os_get_random;wps_build_encr_settings;wps_build_m5"):
5491        wps_run_pbc_fail(apdev[0], dev[0])
5492
5493@remote_compatible
5494def test_ap_wps_m7_oom(dev, apdev):
5495    """WPS and OOM for M7 on STA"""
5496    hapd = wps_start_ap(apdev[0])
5497    hapd.request("WPS_PBC")
5498    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5499    for i in range(1, 3):
5500        with alloc_fail(dev[0], i, "wps_build_m7"):
5501            dev[0].request("WPS_PBC " + apdev[0]['bssid'])
5502            ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
5503            if ev is None:
5504                raise Exception("No EAP failure reported")
5505            dev[0].request("WPS_CANCEL")
5506            dev[0].wait_disconnected()
5507    dev[0].flush_scan_cache()
5508
5509@remote_compatible
5510def test_ap_wps_m7_no_random(dev, apdev):
5511    """WPS and no random for M7 on STA"""
5512    with fail_test(dev[0], 1,
5513                   "os_get_random;wps_build_encr_settings;wps_build_m7"):
5514        wps_run_pbc_fail(apdev[0], dev[0])
5515
5516@remote_compatible
5517def test_ap_wps_wsc_done_oom(dev, apdev):
5518    """WPS and OOM for WSC_Done on STA"""
5519    with alloc_fail(dev[0], 1, "wps_build_wsc_done"):
5520        wps_run_pbc_fail(apdev[0], dev[0])
5521
5522def test_ap_wps_random_psk_fail(dev, apdev):
5523    """WPS and no random for PSK on AP"""
5524    ssid = "test-wps"
5525    pskfile = "/tmp/ap_wps_per_enrollee_psk.psk_file"
5526    appin = "12345670"
5527    try:
5528        os.remove(pskfile)
5529    except:
5530        pass
5531
5532    try:
5533        with open(pskfile, "w") as f:
5534            f.write("# WPA PSKs\n")
5535
5536        params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
5537                  "wpa": "2", "wpa_key_mgmt": "WPA-PSK",
5538                  "rsn_pairwise": "CCMP", "ap_pin": appin,
5539                  "wpa_psk_file": pskfile}
5540        hapd = hostapd.add_ap(apdev[0], params)
5541
5542        dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
5543        with fail_test(hapd, 1, "os_get_random;wps_build_cred_network_key"):
5544            dev[0].request("WPS_REG " + apdev[0]['bssid'] + " " + appin)
5545            ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=10)
5546            if ev is None:
5547                raise Exception("No EAP failure reported")
5548            dev[0].request("WPS_CANCEL")
5549        dev[0].wait_disconnected()
5550
5551        with fail_test(hapd, 1, "os_get_random;wps_build_cred"):
5552            wps_run_pbc_fail_ap(apdev[0], dev[0], hapd)
5553
5554        with alloc_fail(hapd, 1, "wps_build_cred"):
5555            wps_run_pbc_fail_ap(apdev[0], dev[0], hapd)
5556
5557        with alloc_fail(hapd, 2, "wps_build_cred"):
5558            wps_run_pbc_fail_ap(apdev[0], dev[0], hapd)
5559    finally:
5560        os.remove(pskfile)
5561
5562def wps_ext_eap_identity_req(dev, hapd, bssid):
5563    logger.debug("EAP-Identity/Request")
5564    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5565    if ev is None:
5566        raise Exception("Timeout on EAPOL-TX from hostapd")
5567    res = dev.request("EAPOL_RX " + bssid + " " + ev.split(' ')[2])
5568    if "OK" not in res:
5569        raise Exception("EAPOL_RX to wpa_supplicant failed")
5570
5571def wps_ext_eap_identity_resp(hapd, dev, addr):
5572    ev = dev.wait_event(["EAPOL-TX"], timeout=10)
5573    if ev is None:
5574        raise Exception("Timeout on EAPOL-TX from wpa_supplicant")
5575    res = hapd.request("EAPOL_RX " + addr + " " + ev.split(' ')[2])
5576    if "OK" not in res:
5577        raise Exception("EAPOL_RX to hostapd failed")
5578
5579def wps_ext_eap_wsc(dst, src, src_addr, msg):
5580    logger.debug(msg)
5581    ev = src.wait_event(["EAPOL-TX"], timeout=10)
5582    if ev is None:
5583        raise Exception("Timeout on EAPOL-TX")
5584    res = dst.request("EAPOL_RX " + src_addr + " " + ev.split(' ')[2])
5585    if "OK" not in res:
5586        raise Exception("EAPOL_RX failed")
5587
5588def wps_start_ext(apdev, dev, pbc=False, pin=None):
5589    dev.flush_scan_cache()
5590
5591    addr = dev.own_addr()
5592    bssid = apdev['bssid']
5593    ssid = "test-wps-conf"
5594    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
5595              "wpa_passphrase": "12345678", "wpa": "2",
5596              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
5597    hapd = hostapd.add_ap(apdev, params)
5598
5599    if pbc:
5600        hapd.request("WPS_PBC")
5601    else:
5602        if pin is None:
5603            pin = dev.wps_read_pin()
5604        hapd.request("WPS_PIN any " + pin)
5605    dev.scan_for_bss(bssid, freq="2412")
5606    hapd.request("SET ext_eapol_frame_io 1")
5607    dev.request("SET ext_eapol_frame_io 1")
5608
5609    if pbc:
5610        dev.request("WPS_PBC " + bssid)
5611    else:
5612        dev.request("WPS_PIN " + bssid + " " + pin)
5613    return addr, bssid, hapd
5614
5615def wps_auth_corrupt(dst, src, addr):
5616    ev = src.wait_event(["EAPOL-TX"], timeout=10)
5617    if ev is None:
5618        raise Exception("Timeout on EAPOL-TX")
5619    src.request("SET ext_eapol_frame_io 0")
5620    dst.request("SET ext_eapol_frame_io 0")
5621    msg = ev.split(' ')[2]
5622    if msg[-24:-16] != '10050008':
5623        raise Exception("Could not find Authenticator attribute")
5624    # Corrupt Authenticator value
5625    msg = msg[:-1] + '%x' % ((int(msg[-1], 16) + 1) % 16)
5626    res = dst.request("EAPOL_RX " + addr + " " + msg)
5627    if "OK" not in res:
5628        raise Exception("EAPOL_RX failed")
5629
5630def wps_fail_finish(hapd, dev, fail_str):
5631    ev = hapd.wait_event(["WPS-FAIL"], timeout=5)
5632    if ev is None:
5633        raise Exception("WPS-FAIL not indicated")
5634    if fail_str not in ev:
5635        raise Exception("Unexpected WPS-FAIL value: " + ev)
5636    dev.request("WPS_CANCEL")
5637    dev.wait_disconnected()
5638
5639def wps_auth_corrupt_from_ap(dev, hapd, bssid, fail_str):
5640    wps_auth_corrupt(dev, hapd, bssid)
5641    wps_fail_finish(hapd, dev, fail_str)
5642
5643def wps_auth_corrupt_to_ap(dev, hapd, addr, fail_str):
5644    wps_auth_corrupt(hapd, dev, addr)
5645    wps_fail_finish(hapd, dev, fail_str)
5646
5647def test_ap_wps_authenticator_mismatch_m2(dev, apdev):
5648    """WPS and Authenticator attribute mismatch in M2"""
5649    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5650    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5651    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5652    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5653    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5654    logger.debug("M2")
5655    wps_auth_corrupt_from_ap(dev[0], hapd, bssid, "msg=5")
5656
5657def test_ap_wps_authenticator_mismatch_m3(dev, apdev):
5658    """WPS and Authenticator attribute mismatch in M3"""
5659    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5660    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5661    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5662    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5663    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5664    wps_ext_eap_wsc(dev[0], hapd, bssid, "M2")
5665    logger.debug("M3")
5666    wps_auth_corrupt_to_ap(dev[0], hapd, addr, "msg=7")
5667
5668def test_ap_wps_authenticator_mismatch_m4(dev, apdev):
5669    """WPS and Authenticator attribute mismatch in M4"""
5670    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5671    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5672    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5673    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5674    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5675    wps_ext_eap_wsc(dev[0], hapd, bssid, "M2")
5676    wps_ext_eap_wsc(hapd, dev[0], addr, "M3")
5677    logger.debug("M4")
5678    wps_auth_corrupt_from_ap(dev[0], hapd, bssid, "msg=8")
5679
5680def test_ap_wps_authenticator_mismatch_m5(dev, apdev):
5681    """WPS and Authenticator attribute mismatch in M5"""
5682    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5683    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5684    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5685    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5686    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5687    wps_ext_eap_wsc(dev[0], hapd, bssid, "M2")
5688    wps_ext_eap_wsc(hapd, dev[0], addr, "M3")
5689    wps_ext_eap_wsc(dev[0], hapd, bssid, "M4")
5690    logger.debug("M5")
5691    wps_auth_corrupt_to_ap(dev[0], hapd, addr, "msg=9")
5692
5693def test_ap_wps_authenticator_mismatch_m6(dev, apdev):
5694    """WPS and Authenticator attribute mismatch in M6"""
5695    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5696    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5697    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5698    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5699    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5700    wps_ext_eap_wsc(dev[0], hapd, bssid, "M2")
5701    wps_ext_eap_wsc(hapd, dev[0], addr, "M3")
5702    wps_ext_eap_wsc(dev[0], hapd, bssid, "M4")
5703    wps_ext_eap_wsc(hapd, dev[0], addr, "M5")
5704    logger.debug("M6")
5705    wps_auth_corrupt_from_ap(dev[0], hapd, bssid, "msg=10")
5706
5707def test_ap_wps_authenticator_mismatch_m7(dev, apdev):
5708    """WPS and Authenticator attribute mismatch in M7"""
5709    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5710    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5711    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5712    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5713    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5714    wps_ext_eap_wsc(dev[0], hapd, bssid, "M2")
5715    wps_ext_eap_wsc(hapd, dev[0], addr, "M3")
5716    wps_ext_eap_wsc(dev[0], hapd, bssid, "M4")
5717    wps_ext_eap_wsc(hapd, dev[0], addr, "M5")
5718    wps_ext_eap_wsc(dev[0], hapd, bssid, "M6")
5719    logger.debug("M7")
5720    wps_auth_corrupt_to_ap(dev[0], hapd, addr, "msg=11")
5721
5722def test_ap_wps_authenticator_mismatch_m8(dev, apdev):
5723    """WPS and Authenticator attribute mismatch in M8"""
5724    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5725    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5726    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5727    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5728    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5729    wps_ext_eap_wsc(dev[0], hapd, bssid, "M2")
5730    wps_ext_eap_wsc(hapd, dev[0], addr, "M3")
5731    wps_ext_eap_wsc(dev[0], hapd, bssid, "M4")
5732    wps_ext_eap_wsc(hapd, dev[0], addr, "M5")
5733    wps_ext_eap_wsc(dev[0], hapd, bssid, "M6")
5734    wps_ext_eap_wsc(hapd, dev[0], addr, "M7")
5735    logger.debug("M8")
5736    wps_auth_corrupt_from_ap(dev[0], hapd, bssid, "msg=12")
5737
5738def test_ap_wps_authenticator_missing_m2(dev, apdev):
5739    """WPS and Authenticator attribute missing from M2"""
5740    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5741    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5742    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5743    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5744    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5745    logger.debug("M2")
5746    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5747    if ev is None:
5748        raise Exception("Timeout on EAPOL-TX")
5749    hapd.request("SET ext_eapol_frame_io 0")
5750    dev[0].request("SET ext_eapol_frame_io 0")
5751    msg = ev.split(' ')[2]
5752    if msg[-24:-16] != '10050008':
5753        raise Exception("Could not find Authenticator attribute")
5754    # Remove Authenticator value
5755    msg = msg[:-24]
5756    mlen = "%04x" % (int(msg[4:8], 16) - 12)
5757    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:]
5758    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5759    if "OK" not in res:
5760        raise Exception("EAPOL_RX failed")
5761    wps_fail_finish(hapd, dev[0], "msg=5")
5762
5763def test_ap_wps_m2_dev_passwd_id_p2p(dev, apdev):
5764    """WPS and M2 with different Device Password ID (P2P)"""
5765    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5766    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5767    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5768    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5769    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5770    logger.debug("M2")
5771    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5772    if ev is None:
5773        raise Exception("Timeout on EAPOL-TX")
5774    hapd.request("SET ext_eapol_frame_io 0")
5775    dev[0].request("SET ext_eapol_frame_io 0")
5776    msg = ev.split(' ')[2]
5777    if msg[722:730] != '10120002':
5778        raise Exception("Could not find Device Password ID attribute")
5779    # Replace Device Password ID value. This will fail Authenticator check, but
5780    # allows the code path in wps_process_dev_pw_id() to be checked from debug
5781    # log.
5782    msg = msg[0:730] + "0005" + msg[734:]
5783    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5784    if "OK" not in res:
5785        raise Exception("EAPOL_RX failed")
5786    wps_fail_finish(hapd, dev[0], "msg=5")
5787
5788def test_ap_wps_m2_dev_passwd_id_change_pin_to_pbc(dev, apdev):
5789    """WPS and M2 with different Device Password ID (PIN to PBC)"""
5790    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5791    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5792    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5793    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5794    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5795    logger.debug("M2")
5796    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5797    if ev is None:
5798        raise Exception("Timeout on EAPOL-TX")
5799    hapd.request("SET ext_eapol_frame_io 0")
5800    dev[0].request("SET ext_eapol_frame_io 0")
5801    msg = ev.split(' ')[2]
5802    if msg[722:730] != '10120002':
5803        raise Exception("Could not find Device Password ID attribute")
5804    # Replace Device Password ID value (PIN --> PBC). This will be rejected.
5805    msg = msg[0:730] + "0004" + msg[734:]
5806    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5807    if "OK" not in res:
5808        raise Exception("EAPOL_RX failed")
5809    wps_fail_finish(hapd, dev[0], "msg=5")
5810
5811def test_ap_wps_m2_dev_passwd_id_change_pbc_to_pin(dev, apdev):
5812    """WPS and M2 with different Device Password ID (PBC to PIN)"""
5813    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
5814    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5815    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5816    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5817    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5818    logger.debug("M2")
5819    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5820    if ev is None:
5821        raise Exception("Timeout on EAPOL-TX")
5822    hapd.request("SET ext_eapol_frame_io 0")
5823    dev[0].request("SET ext_eapol_frame_io 0")
5824    msg = ev.split(' ')[2]
5825    if msg[722:730] != '10120002':
5826        raise Exception("Could not find Device Password ID attribute")
5827    # Replace Device Password ID value. This will fail Authenticator check, but
5828    # allows the code path in wps_process_dev_pw_id() to be checked from debug
5829    # log.
5830    msg = msg[0:730] + "0000" + msg[734:]
5831    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5832    if "OK" not in res:
5833        raise Exception("EAPOL_RX failed")
5834    wps_fail_finish(hapd, dev[0], "msg=5")
5835    dev[0].flush_scan_cache()
5836
5837def test_ap_wps_m2_missing_dev_passwd_id(dev, apdev):
5838    """WPS and M2 without Device Password ID"""
5839    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5840    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5841    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5842    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5843    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5844    logger.debug("M2")
5845    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5846    if ev is None:
5847        raise Exception("Timeout on EAPOL-TX")
5848    hapd.request("SET ext_eapol_frame_io 0")
5849    dev[0].request("SET ext_eapol_frame_io 0")
5850    msg = ev.split(' ')[2]
5851    if msg[722:730] != '10120002':
5852        raise Exception("Could not find Device Password ID attribute")
5853    # Remove Device Password ID value. This will fail Authenticator check, but
5854    # allows the code path in wps_process_dev_pw_id() to be checked from debug
5855    # log.
5856    mlen = "%04x" % (int(msg[4:8], 16) - 6)
5857    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:722] + msg[734:]
5858    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5859    if "OK" not in res:
5860        raise Exception("EAPOL_RX failed")
5861    wps_fail_finish(hapd, dev[0], "msg=5")
5862
5863def test_ap_wps_m2_missing_registrar_nonce(dev, apdev):
5864    """WPS and M2 without Registrar Nonce"""
5865    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
5866    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5867    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5868    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5869    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5870    logger.debug("M2")
5871    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5872    if ev is None:
5873        raise Exception("Timeout on EAPOL-TX")
5874    hapd.request("SET ext_eapol_frame_io 0")
5875    dev[0].request("SET ext_eapol_frame_io 0")
5876    msg = ev.split(' ')[2]
5877    if msg[96:104] != '10390010':
5878        raise Exception("Could not find Registrar Nonce attribute")
5879    # Remove Registrar Nonce. This will fail Authenticator check, but
5880    # allows the code path in wps_process_registrar_nonce() to be checked from
5881    # the debug log.
5882    mlen = "%04x" % (int(msg[4:8], 16) - 20)
5883    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:96] + msg[136:]
5884    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5885    if "OK" not in res:
5886        raise Exception("EAPOL_RX failed")
5887    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECT"], timeout=5)
5888    if ev is None:
5889        raise Exception("Disconnect event not seen")
5890    dev[0].request("WPS_CANCEL")
5891    dev[0].flush_scan_cache()
5892
5893def test_ap_wps_m2_missing_enrollee_nonce(dev, apdev):
5894    """WPS and M2 without Enrollee Nonce"""
5895    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
5896    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5897    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5898    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5899    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5900    logger.debug("M2")
5901    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5902    if ev is None:
5903        raise Exception("Timeout on EAPOL-TX")
5904    hapd.request("SET ext_eapol_frame_io 0")
5905    dev[0].request("SET ext_eapol_frame_io 0")
5906    msg = ev.split(' ')[2]
5907    if msg[56:64] != '101a0010':
5908        raise Exception("Could not find enrollee Nonce attribute")
5909    # Remove Enrollee Nonce. This will fail Authenticator check, but
5910    # allows the code path in wps_process_enrollee_nonce() to be checked from
5911    # the debug log.
5912    mlen = "%04x" % (int(msg[4:8], 16) - 20)
5913    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:56] + msg[96:]
5914    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5915    if "OK" not in res:
5916        raise Exception("EAPOL_RX failed")
5917    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECT"], timeout=5)
5918    if ev is None:
5919        raise Exception("Disconnect event not seen")
5920    dev[0].request("WPS_CANCEL")
5921    dev[0].flush_scan_cache()
5922
5923def test_ap_wps_m2_missing_uuid_r(dev, apdev):
5924    """WPS and M2 without UUID-R"""
5925    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
5926    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5927    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5928    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5929    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5930    logger.debug("M2")
5931    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5932    if ev is None:
5933        raise Exception("Timeout on EAPOL-TX")
5934    hapd.request("SET ext_eapol_frame_io 0")
5935    dev[0].request("SET ext_eapol_frame_io 0")
5936    msg = ev.split(' ')[2]
5937    if msg[136:144] != '10480010':
5938        raise Exception("Could not find enrollee Nonce attribute")
5939    # Remove UUID-R. This will fail Authenticator check, but allows the code
5940    # path in wps_process_uuid_r() to be checked from the debug log.
5941    mlen = "%04x" % (int(msg[4:8], 16) - 20)
5942    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:136] + msg[176:]
5943    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5944    if "OK" not in res:
5945        raise Exception("EAPOL_RX failed")
5946    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECT"], timeout=5)
5947    if ev is None:
5948        raise Exception("Disconnect event not seen")
5949    dev[0].request("WPS_CANCEL")
5950    dev[0].flush_scan_cache()
5951
5952def test_ap_wps_m2_invalid(dev, apdev):
5953    """WPS and M2 parsing failure"""
5954    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
5955    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5956    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5957    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5958    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5959    logger.debug("M2")
5960    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5961    if ev is None:
5962        raise Exception("Timeout on EAPOL-TX")
5963    hapd.request("SET ext_eapol_frame_io 0")
5964    dev[0].request("SET ext_eapol_frame_io 0")
5965    msg = ev.split(' ')[2]
5966    if msg[136:144] != '10480010':
5967        raise Exception("Could not find enrollee Nonce attribute")
5968    # Remove UUID-R. This will fail Authenticator check, but allows the code
5969    # path in wps_process_uuid_r() to be checked from the debug log.
5970    mlen = "%04x" % (int(msg[4:8], 16) - 1)
5971    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:-2]
5972    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5973    if "OK" not in res:
5974        raise Exception("EAPOL_RX failed")
5975    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECT"], timeout=5)
5976    if ev is None:
5977        raise Exception("Disconnect event not seen")
5978    dev[0].request("WPS_CANCEL")
5979    dev[0].flush_scan_cache()
5980
5981def test_ap_wps_m2_missing_msg_type(dev, apdev):
5982    """WPS and M2 without Message Type"""
5983    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
5984    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5985    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5986    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5987    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5988    logger.debug("M2")
5989    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5990    if ev is None:
5991        raise Exception("Timeout on EAPOL-TX")
5992    hapd.request("SET ext_eapol_frame_io 0")
5993    dev[0].request("SET ext_eapol_frame_io 0")
5994    msg = ev.split(' ')[2]
5995    if msg[46:54] != '10220001':
5996        raise Exception("Could not find Message Type attribute")
5997    # Remove Message Type. This will fail Authenticator check, but allows the
5998    # code path in wps_process_wsc_msg() to be checked from the debug log.
5999    mlen = "%04x" % (int(msg[4:8], 16) - 5)
6000    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:46] + msg[56:]
6001    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
6002    if "OK" not in res:
6003        raise Exception("EAPOL_RX failed")
6004    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECT"], timeout=5)
6005    if ev is None:
6006        raise Exception("Disconnect event not seen")
6007    dev[0].request("WPS_CANCEL")
6008    dev[0].flush_scan_cache()
6009
6010def test_ap_wps_m2_unknown_msg_type(dev, apdev):
6011    """WPS and M2 but unknown Message Type"""
6012    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
6013    wps_ext_eap_identity_req(dev[0], hapd, bssid)
6014    wps_ext_eap_identity_resp(hapd, dev[0], addr)
6015    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
6016    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
6017    logger.debug("M2")
6018    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
6019    if ev is None:
6020        raise Exception("Timeout on EAPOL-TX")
6021    hapd.request("SET ext_eapol_frame_io 0")
6022    dev[0].request("SET ext_eapol_frame_io 0")
6023    msg = ev.split(' ')[2]
6024    if msg[46:54] != '10220001':
6025        raise Exception("Could not find Message Type attribute")
6026    # Replace Message Type value. This will be rejected.
6027    msg = msg[0:54] + "00" + msg[56:]
6028    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
6029    if "OK" not in res:
6030        raise Exception("EAPOL_RX failed")
6031    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECT"], timeout=5)
6032    if ev is None:
6033        raise Exception("Disconnect event not seen")
6034    dev[0].request("WPS_CANCEL")
6035    dev[0].flush_scan_cache()
6036
6037def test_ap_wps_m2_unknown_opcode(dev, apdev):
6038    """WPS and M2 but unknown opcode"""
6039    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
6040    wps_ext_eap_identity_req(dev[0], hapd, bssid)
6041    wps_ext_eap_identity_resp(hapd, dev[0], addr)
6042    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
6043    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
6044    logger.debug("M2")
6045    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
6046    if ev is None:
6047        raise Exception("Timeout on EAPOL-TX")
6048    hapd.request("SET ext_eapol_frame_io 0")
6049    dev[0].request("SET ext_eapol_frame_io 0")
6050    msg = ev.split(' ')[2]
6051    # Replace opcode. This will be discarded in EAP-WSC processing.
6052    msg = msg[0:32] + "00" + msg[34:]
6053    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
6054    if "OK" not in res:
6055        raise Exception("EAPOL_RX failed")
6056    dev[0].request("WPS_CANCEL")
6057    dev[0].wait_disconnected()
6058    dev[0].flush_scan_cache()
6059
6060def test_ap_wps_m2_unknown_opcode2(dev, apdev):
6061    """WPS and M2 but unknown opcode (WSC_Start)"""
6062    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
6063    wps_ext_eap_identity_req(dev[0], hapd, bssid)
6064    wps_ext_eap_identity_resp(hapd, dev[0], addr)
6065    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
6066    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
6067    logger.debug("M2")
6068    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
6069    if ev is None:
6070        raise Exception("Timeout on EAPOL-TX")
6071    hapd.request("SET ext_eapol_frame_io 0")
6072    dev[0].request("SET ext_eapol_frame_io 0")
6073    msg = ev.split(' ')[2]
6074    # Replace opcode. This will be discarded in EAP-WSC processing.
6075    msg = msg[0:32] + "01" + msg[34:]
6076    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
6077    if "OK" not in res:
6078        raise Exception("EAPOL_RX failed")
6079    dev[0].request("WPS_CANCEL")
6080    dev[0].wait_disconnected()
6081    dev[0].flush_scan_cache()
6082
6083def test_ap_wps_m2_unknown_opcode3(dev, apdev):
6084    """WPS and M2 but unknown opcode (WSC_Done)"""
6085    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
6086    wps_ext_eap_identity_req(dev[0], hapd, bssid)
6087    wps_ext_eap_identity_resp(hapd, dev[0], addr)
6088    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
6089    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
6090    logger.debug("M2")
6091    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
6092    if ev is None:
6093        raise Exception("Timeout on EAPOL-TX")
6094    hapd.request("SET ext_eapol_frame_io 0")
6095    dev[0].request("SET ext_eapol_frame_io 0")
6096    msg = ev.split(' ')[2]
6097    # Replace opcode. This will be discarded in WPS Enrollee processing.
6098    msg = msg[0:32] + "05" + msg[34:]
6099    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
6100    if "OK" not in res:
6101        raise Exception("EAPOL_RX failed")
6102    dev[0].request("WPS_CANCEL")
6103    dev[0].wait_disconnected()
6104    dev[0].flush_scan_cache()
6105
6106def wps_m2_but_other(dev, apdev, title, msgtype):
6107    addr, bssid, hapd = wps_start_ext(apdev, dev)
6108    wps_ext_eap_identity_req(dev, hapd, bssid)
6109    wps_ext_eap_identity_resp(hapd, dev, addr)
6110    wps_ext_eap_wsc(dev, hapd, bssid, "EAP-WSC/Start")
6111    wps_ext_eap_wsc(hapd, dev, addr, "M1")
6112    logger.debug(title)
6113    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
6114    if ev is None:
6115        raise Exception("Timeout on EAPOL-TX")
6116    hapd.request("SET ext_eapol_frame_io 0")
6117    dev.request("SET ext_eapol_frame_io 0")
6118    msg = ev.split(' ')[2]
6119    if msg[46:54] != '10220001':
6120        raise Exception("Could not find Message Type attribute")
6121    # Replace Message Type value. This will be rejected.
6122    msg = msg[0:54] + msgtype + msg[56:]
6123    res = dev.request("EAPOL_RX " + bssid + " " + msg)
6124    if "OK" not in res:
6125        raise Exception("EAPOL_RX failed")
6126    ev = dev.wait_event(["WPS-FAIL"], timeout=5)
6127    if ev is None:
6128        raise Exception("WPS-FAIL event not seen")
6129    dev.request("WPS_CANCEL")
6130    dev.wait_disconnected()
6131
6132def wps_m4_but_other(dev, apdev, title, msgtype):
6133    addr, bssid, hapd = wps_start_ext(apdev, dev)
6134    wps_ext_eap_identity_req(dev, hapd, bssid)
6135    wps_ext_eap_identity_resp(hapd, dev, addr)
6136    wps_ext_eap_wsc(dev, hapd, bssid, "EAP-WSC/Start")
6137    wps_ext_eap_wsc(hapd, dev, addr, "M1")
6138    wps_ext_eap_wsc(dev, hapd, bssid, "M2")
6139    wps_ext_eap_wsc(hapd, dev, addr, "M3")
6140    logger.debug(title)
6141    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
6142    if ev is None:
6143        raise Exception("Timeout on EAPOL-TX")
6144    hapd.request("SET ext_eapol_frame_io 0")
6145    dev.request("SET ext_eapol_frame_io 0")
6146    msg = ev.split(' ')[2]
6147    if msg[46:54] != '10220001':
6148        raise Exception("Could not find Message Type attribute")
6149    # Replace Message Type value. This will be rejected.
6150    msg = msg[0:54] + msgtype + msg[56:]
6151    res = dev.request("EAPOL_RX " + bssid + " " + msg)
6152    if "OK" not in res:
6153        raise Exception("EAPOL_RX failed")
6154    ev = hapd.wait_event(["WPS-FAIL"], timeout=5)
6155    if ev is None:
6156        raise Exception("WPS-FAIL event not seen")
6157    dev.request("WPS_CANCEL")
6158    dev.wait_disconnected()
6159
6160def test_ap_wps_m2_msg_type_m4(dev, apdev):
6161    """WPS and M2 but Message Type M4"""
6162    wps_m2_but_other(dev[0], apdev[0], "M2/M4", "08")
6163
6164def test_ap_wps_m2_msg_type_m6(dev, apdev):
6165    """WPS and M2 but Message Type M6"""
6166    wps_m2_but_other(dev[0], apdev[0], "M2/M6", "0a")
6167
6168def test_ap_wps_m2_msg_type_m8(dev, apdev):
6169    """WPS and M2 but Message Type M8"""
6170    wps_m2_but_other(dev[0], apdev[0], "M2/M8", "0c")
6171
6172def test_ap_wps_m4_msg_type_m2(dev, apdev):
6173    """WPS and M4 but Message Type M2"""
6174    wps_m4_but_other(dev[0], apdev[0], "M4/M2", "05")
6175
6176def test_ap_wps_m4_msg_type_m2d(dev, apdev):
6177    """WPS and M4 but Message Type M2D"""
6178    wps_m4_but_other(dev[0], apdev[0], "M4/M2D", "06")
6179
6180@remote_compatible
6181def test_ap_wps_config_methods(dev, apdev):
6182    """WPS configuration method parsing"""
6183    ssid = "test-wps-conf"
6184    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
6185              "wpa_passphrase": "12345678", "wpa": "2",
6186              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
6187              "config_methods": "ethernet display ext_nfc_token int_nfc_token physical_display physical_push_button"}
6188    hapd = hostapd.add_ap(apdev[0], params)
6189    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
6190              "wpa_passphrase": "12345678", "wpa": "2",
6191              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
6192              "config_methods": "display push_button"}
6193    hapd2 = hostapd.add_ap(apdev[1], params)
6194
6195def test_ap_wps_set_selected_registrar_proto(dev, apdev):
6196    """WPS UPnP SetSelectedRegistrar protocol testing"""
6197    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
6198    hapd = add_ssdp_ap(apdev[0], ap_uuid)
6199
6200    location = ssdp_get_location(ap_uuid)
6201    urls = upnp_get_urls(location)
6202    eventurl = urlparse(urls['event_sub_url'])
6203    ctrlurl = urlparse(urls['control_url'])
6204    url = urlparse(location)
6205    conn = HTTPConnection(url.netloc)
6206
6207    class WPSERHTTPServer(StreamRequestHandler):
6208        def handle(self):
6209            data = self.rfile.readline().strip()
6210            logger.debug(data)
6211            self.wfile.write(gen_wps_event())
6212
6213    server = MyTCPServer(("127.0.0.1", 12345), WPSERHTTPServer)
6214    server.timeout = 1
6215
6216    headers = {"callback": '<http://127.0.0.1:12345/event>',
6217               "NT": "upnp:event",
6218               "timeout": "Second-1234"}
6219    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
6220    resp = conn.getresponse()
6221    if resp.status != 200:
6222        raise Exception("Unexpected HTTP response: %d" % resp.status)
6223    sid = resp.getheader("sid")
6224    logger.debug("Subscription SID " + sid)
6225    server.handle_request()
6226
6227    tests = [(500, "10"),
6228             (200, "104a000110" + "1041000101" + "101200020000" +
6229              "105300023148" +
6230              "1049002c00372a0001200124111111111111222222222222333333333333444444444444555555555555666666666666" +
6231              "10480010362db47ba53a519188fb5458b986b2e4"),
6232             (200, "104a000110" + "1041000100" + "101200020000" +
6233              "105300020000"),
6234             (200, "104a000110" + "1041000100"),
6235             (200, "104a000110")]
6236    for status, test in tests:
6237        tlvs = binascii.unhexlify(test)
6238        newmsg = base64.b64encode(tlvs).decode()
6239        msg = '<?xml version="1.0"?>\n'
6240        msg += '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">'
6241        msg += '<s:Body>'
6242        msg += '<u:SetSelectedRegistrar xmlns:u="urn:schemas-wifialliance-org:service:WFAWLANConfig:1">'
6243        msg += '<NewMessage>'
6244        msg += newmsg
6245        msg += "</NewMessage></u:SetSelectedRegistrar></s:Body></s:Envelope>"
6246        headers = {"Content-type": 'text/xml; charset="utf-8"'}
6247        headers["SOAPAction"] = '"urn:schemas-wifialliance-org:service:WFAWLANConfig:1#%s"' % "SetSelectedRegistrar"
6248        conn.request("POST", ctrlurl.path, msg, headers)
6249        resp = conn.getresponse()
6250        if resp.status != status:
6251            raise Exception("Unexpected HTTP response: %d (expected %d)" % (resp.status, status))
6252
6253def test_ap_wps_adv_oom(dev, apdev):
6254    """WPS AP and advertisement OOM"""
6255    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
6256    hapd = add_ssdp_ap(apdev[0], ap_uuid)
6257
6258    with alloc_fail(hapd, 1, "=msearchreply_state_machine_start"):
6259        ssdp_send_msearch("urn:schemas-wifialliance-org:service:WFAWLANConfig:1",
6260                          no_recv=True)
6261        time.sleep(0.2)
6262
6263    with alloc_fail(hapd, 1, "eloop_register_timeout;msearchreply_state_machine_start"):
6264        ssdp_send_msearch("urn:schemas-wifialliance-org:service:WFAWLANConfig:1",
6265                          no_recv=True)
6266        time.sleep(0.2)
6267
6268    with alloc_fail(hapd, 1,
6269                    "next_advertisement;advertisement_state_machine_stop"):
6270        hapd.disable()
6271
6272    with alloc_fail(hapd, 1, "ssdp_listener_start"):
6273        if "FAIL" not in hapd.request("ENABLE"):
6274            raise Exception("ENABLE succeeded during OOM")
6275
6276def test_wps_config_methods(dev):
6277    """WPS config method update"""
6278    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
6279    wpas.interface_add("wlan5")
6280    if "OK" not in wpas.request("SET config_methods display label"):
6281        raise Exception("Failed to set config_methods")
6282    if wpas.request("GET config_methods").strip() != "display label":
6283        raise Exception("config_methods were not updated")
6284    if "OK" not in wpas.request("SET config_methods "):
6285        raise Exception("Failed to clear config_methods")
6286    if wpas.request("GET config_methods").strip() != "":
6287        raise Exception("config_methods were not cleared")
6288
6289WPS_VENDOR_ID_WFA = 14122
6290WPS_VENDOR_TYPE = 1
6291
6292# EAP-WSC Op-Code values
6293WSC_Start = 0x01
6294WSC_ACK = 0x02
6295WSC_NACK = 0x03
6296WSC_MSG = 0x04
6297WSC_Done = 0x05
6298WSC_FRAG_ACK = 0x06
6299
6300ATTR_AP_CHANNEL = 0x1001
6301ATTR_ASSOC_STATE = 0x1002
6302ATTR_AUTH_TYPE = 0x1003
6303ATTR_AUTH_TYPE_FLAGS = 0x1004
6304ATTR_AUTHENTICATOR = 0x1005
6305ATTR_CONFIG_METHODS = 0x1008
6306ATTR_CONFIG_ERROR = 0x1009
6307ATTR_CONFIRM_URL4 = 0x100a
6308ATTR_CONFIRM_URL6 = 0x100b
6309ATTR_CONN_TYPE = 0x100c
6310ATTR_CONN_TYPE_FLAGS = 0x100d
6311ATTR_CRED = 0x100e
6312ATTR_ENCR_TYPE = 0x100f
6313ATTR_ENCR_TYPE_FLAGS = 0x1010
6314ATTR_DEV_NAME = 0x1011
6315ATTR_DEV_PASSWORD_ID = 0x1012
6316ATTR_E_HASH1 = 0x1014
6317ATTR_E_HASH2 = 0x1015
6318ATTR_E_SNONCE1 = 0x1016
6319ATTR_E_SNONCE2 = 0x1017
6320ATTR_ENCR_SETTINGS = 0x1018
6321ATTR_ENROLLEE_NONCE = 0x101a
6322ATTR_FEATURE_ID = 0x101b
6323ATTR_IDENTITY = 0x101c
6324ATTR_IDENTITY_PROOF = 0x101d
6325ATTR_KEY_WRAP_AUTH = 0x101e
6326ATTR_KEY_ID = 0x101f
6327ATTR_MAC_ADDR = 0x1020
6328ATTR_MANUFACTURER = 0x1021
6329ATTR_MSG_TYPE = 0x1022
6330ATTR_MODEL_NAME = 0x1023
6331ATTR_MODEL_NUMBER = 0x1024
6332ATTR_NETWORK_INDEX = 0x1026
6333ATTR_NETWORK_KEY = 0x1027
6334ATTR_NETWORK_KEY_INDEX = 0x1028
6335ATTR_NEW_DEVICE_NAME = 0x1029
6336ATTR_NEW_PASSWORD = 0x102a
6337ATTR_OOB_DEVICE_PASSWORD = 0x102c
6338ATTR_OS_VERSION = 0x102d
6339ATTR_POWER_LEVEL = 0x102f
6340ATTR_PSK_CURRENT = 0x1030
6341ATTR_PSK_MAX = 0x1031
6342ATTR_PUBLIC_KEY = 0x1032
6343ATTR_RADIO_ENABLE = 0x1033
6344ATTR_REBOOT = 0x1034
6345ATTR_REGISTRAR_CURRENT = 0x1035
6346ATTR_REGISTRAR_ESTABLISHED = 0x1036
6347ATTR_REGISTRAR_LIST = 0x1037
6348ATTR_REGISTRAR_MAX = 0x1038
6349ATTR_REGISTRAR_NONCE = 0x1039
6350ATTR_REQUEST_TYPE = 0x103a
6351ATTR_RESPONSE_TYPE = 0x103b
6352ATTR_RF_BANDS = 0x103c
6353ATTR_R_HASH1 = 0x103d
6354ATTR_R_HASH2 = 0x103e
6355ATTR_R_SNONCE1 = 0x103f
6356ATTR_R_SNONCE2 = 0x1040
6357ATTR_SELECTED_REGISTRAR = 0x1041
6358ATTR_SERIAL_NUMBER = 0x1042
6359ATTR_WPS_STATE = 0x1044
6360ATTR_SSID = 0x1045
6361ATTR_TOTAL_NETWORKS = 0x1046
6362ATTR_UUID_E = 0x1047
6363ATTR_UUID_R = 0x1048
6364ATTR_VENDOR_EXT = 0x1049
6365ATTR_VERSION = 0x104a
6366ATTR_X509_CERT_REQ = 0x104b
6367ATTR_X509_CERT = 0x104c
6368ATTR_EAP_IDENTITY = 0x104d
6369ATTR_MSG_COUNTER = 0x104e
6370ATTR_PUBKEY_HASH = 0x104f
6371ATTR_REKEY_KEY = 0x1050
6372ATTR_KEY_LIFETIME = 0x1051
6373ATTR_PERMITTED_CFG_METHODS = 0x1052
6374ATTR_SELECTED_REGISTRAR_CONFIG_METHODS = 0x1053
6375ATTR_PRIMARY_DEV_TYPE = 0x1054
6376ATTR_SECONDARY_DEV_TYPE_LIST = 0x1055
6377ATTR_PORTABLE_DEV = 0x1056
6378ATTR_AP_SETUP_LOCKED = 0x1057
6379ATTR_APPLICATION_EXT = 0x1058
6380ATTR_EAP_TYPE = 0x1059
6381ATTR_IV = 0x1060
6382ATTR_KEY_PROVIDED_AUTO = 0x1061
6383ATTR_802_1X_ENABLED = 0x1062
6384ATTR_APPSESSIONKEY = 0x1063
6385ATTR_WEPTRANSMITKEY = 0x1064
6386ATTR_REQUESTED_DEV_TYPE = 0x106a
6387
6388# Message Type
6389WPS_Beacon = 0x01
6390WPS_ProbeRequest = 0x02
6391WPS_ProbeResponse = 0x03
6392WPS_M1 = 0x04
6393WPS_M2 = 0x05
6394WPS_M2D = 0x06
6395WPS_M3 = 0x07
6396WPS_M4 = 0x08
6397WPS_M5 = 0x09
6398WPS_M6 = 0x0a
6399WPS_M7 = 0x0b
6400WPS_M8 = 0x0c
6401WPS_WSC_ACK = 0x0d
6402WPS_WSC_NACK = 0x0e
6403WPS_WSC_DONE = 0x0f
6404
6405def get_wsc_msg(dev):
6406    ev = dev.wait_event(["EAPOL-TX"], timeout=10)
6407    if ev is None:
6408        raise Exception("Timeout on EAPOL-TX")
6409    data = binascii.unhexlify(ev.split(' ')[2])
6410    msg = {}
6411
6412    # Parse EAPOL header
6413    if len(data) < 4:
6414        raise Exception("No room for EAPOL header")
6415    version, type, length = struct.unpack('>BBH', data[0:4])
6416    msg['eapol_version'] = version
6417    msg['eapol_type'] = type
6418    msg['eapol_length'] = length
6419    data = data[4:]
6420    if length != len(data):
6421        raise Exception("EAPOL header length mismatch (%d != %d)" % (length, len(data)))
6422    if type != 0:
6423        raise Exception("Unexpected EAPOL header type: %d" % type)
6424
6425    # Parse EAP header
6426    if len(data) < 4:
6427        raise Exception("No room for EAP header")
6428    code, identifier, length = struct.unpack('>BBH', data[0:4])
6429    msg['eap_code'] = code
6430    msg['eap_identifier'] = identifier
6431    msg['eap_length'] = length
6432    data = data[4:]
6433    if msg['eapol_length'] != msg['eap_length']:
6434        raise Exception("EAP header length mismatch (%d != %d)" % (msg['eapol_length'], length))
6435
6436    # Parse EAP expanded header
6437    if len(data) < 1:
6438        raise Exception("No EAP type included")
6439    msg['eap_type'], = struct.unpack('B', data[0:1])
6440    data = data[1:]
6441
6442    if msg['eap_type'] == 254:
6443        if len(data) < 3 + 4:
6444            raise Exception("Truncated EAP expanded header")
6445        msg['eap_vendor_id'], msg['eap_vendor_type'] = struct.unpack('>LL', b'\x00' + data[0:7])
6446        data = data[7:]
6447    else:
6448        raise Exception("Unexpected EAP type")
6449
6450    if msg['eap_vendor_id'] != WPS_VENDOR_ID_WFA:
6451        raise Exception("Unexpected Vendor-Id")
6452    if msg['eap_vendor_type'] != WPS_VENDOR_TYPE:
6453        raise Exception("Unexpected Vendor-Type")
6454
6455    # Parse EAP-WSC header
6456    if len(data) < 2:
6457        raise Exception("Truncated EAP-WSC header")
6458    msg['wsc_opcode'], msg['wsc_flags'] = struct.unpack('BB', data[0:2])
6459    data = data[2:]
6460
6461    # Parse WSC attributes
6462    msg['raw_attrs'] = data
6463    attrs = {}
6464    while len(data) > 0:
6465        if len(data) < 4:
6466            raise Exception("Truncated attribute header")
6467        attr, length = struct.unpack('>HH', data[0:4])
6468        data = data[4:]
6469        if length > len(data):
6470            raise Exception("Truncated attribute 0x%04x" % attr)
6471        attrs[attr] = data[0:length]
6472        data = data[length:]
6473    msg['wsc_attrs'] = attrs
6474
6475    if ATTR_MSG_TYPE in attrs:
6476        msg['wsc_msg_type'], = struct.unpack('B', attrs[ATTR_MSG_TYPE])
6477
6478    return msg
6479
6480def recv_wsc_msg(dev, opcode, msg_type):
6481    msg = get_wsc_msg(dev)
6482    if msg['wsc_opcode'] != opcode or msg['wsc_msg_type'] != msg_type:
6483        raise Exception("Unexpected Op-Code/MsgType")
6484    return msg, msg['wsc_attrs'], msg['raw_attrs']
6485
6486def build_wsc_attr(attr, payload):
6487    _payload = payload if type(payload) == bytes else payload.encode()
6488    return struct.pack('>HH', attr, len(_payload)) + _payload
6489
6490def build_attr_msg_type(msg_type):
6491    return build_wsc_attr(ATTR_MSG_TYPE, struct.pack('B', msg_type))
6492
6493def build_eap_wsc(eap_code, eap_id, payload, opcode=WSC_MSG):
6494    length = 4 + 8 + 2 + len(payload)
6495    # EAPOL header
6496    msg = struct.pack('>BBH', 2, 0, length)
6497    # EAP header
6498    msg += struct.pack('>BBH', eap_code, eap_id, length)
6499    # EAP expanded header for EAP-WSC
6500    msg += struct.pack('B', 254)
6501    msg += struct.pack('>L', WPS_VENDOR_ID_WFA)[1:4]
6502    msg += struct.pack('>L', WPS_VENDOR_TYPE)
6503    # EAP-WSC header
6504    msg += struct.pack('BB', opcode, 0)
6505    # WSC attributes
6506    msg += payload
6507    return msg
6508
6509def build_eap_success(eap_id):
6510    length = 4
6511    # EAPOL header
6512    msg = struct.pack('>BBH', 2, 0, length)
6513    # EAP header
6514    msg += struct.pack('>BBH', 3, eap_id, length)
6515    return msg
6516
6517def build_eap_failure(eap_id):
6518    length = 4
6519    # EAPOL header
6520    msg = struct.pack('>BBH', 2, 0, length)
6521    # EAP header
6522    msg += struct.pack('>BBH', 4, eap_id, length)
6523    return msg
6524
6525def send_wsc_msg(dev, src, msg):
6526    res = dev.request("EAPOL_RX " + src + " " + binascii.hexlify(msg).decode())
6527    if "OK" not in res:
6528        raise Exception("EAPOL_RX failed")
6529
6530group_5_prime = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF
6531group_5_generator = 2
6532
6533def wsc_kdf(key, label, bits):
6534    result = b''
6535    i = 1
6536    while len(result) * 8 < bits:
6537        data = struct.pack('>L', i) + label.encode() + struct.pack('>L', bits)
6538        m = hmac.new(key, data, hashlib.sha256)
6539        result += m.digest()
6540        i += 1
6541    return result[0:bits // 8]
6542
6543def wsc_keys(kdk):
6544    keys = wsc_kdf(kdk, "Wi-Fi Easy and Secure Key Derivation", 640)
6545    authkey = keys[0:32]
6546    keywrapkey = keys[32:48]
6547    emsk = keys[48:80]
6548    return authkey, keywrapkey, emsk
6549
6550def wsc_dev_pw_half_psk(authkey, dev_pw):
6551    m = hmac.new(authkey, dev_pw.encode(), hashlib.sha256)
6552    return m.digest()[0:16]
6553
6554def wsc_dev_pw_psk(authkey, dev_pw):
6555    dev_pw_1 = dev_pw[0:len(dev_pw) // 2]
6556    dev_pw_2 = dev_pw[len(dev_pw) // 2:]
6557    psk1 = wsc_dev_pw_half_psk(authkey, dev_pw_1)
6558    psk2 = wsc_dev_pw_half_psk(authkey, dev_pw_2)
6559    return psk1, psk2
6560
6561def build_attr_authenticator(authkey, prev_msg, curr_msg):
6562    m = hmac.new(authkey, prev_msg + curr_msg, hashlib.sha256)
6563    auth = m.digest()[0:8]
6564    return build_wsc_attr(ATTR_AUTHENTICATOR, auth)
6565
6566def build_attr_encr_settings(authkey, keywrapkey, data):
6567    m = hmac.new(authkey, data, hashlib.sha256)
6568    kwa = m.digest()[0:8]
6569    data += build_wsc_attr(ATTR_KEY_WRAP_AUTH, kwa)
6570    iv = 16*b'\x99'
6571    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
6572    pad_len = 16 - len(data) % 16
6573    ps = pad_len * struct.pack('B', pad_len)
6574    data += ps
6575    wrapped = aes.encrypt(data)
6576    return build_wsc_attr(ATTR_ENCR_SETTINGS, iv + wrapped)
6577
6578def decrypt_attr_encr_settings(authkey, keywrapkey, data):
6579    if len(data) < 32 or len(data) % 16 != 0:
6580        raise Exception("Unexpected Encrypted Settings length: %d" % len(data))
6581    iv = data[0:16]
6582    encr = data[16:]
6583    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
6584    decrypted = aes.decrypt(encr)
6585    pad_len, = struct.unpack('B', decrypted[-1:])
6586    if pad_len > len(decrypted):
6587        raise Exception("Invalid padding in Encrypted Settings")
6588    for i in range(-pad_len, -1):
6589        if decrypted[i] != decrypted[-1]:
6590            raise Exception("Invalid PS value in Encrypted Settings")
6591
6592    decrypted = decrypted[0:len(decrypted) - pad_len]
6593    if len(decrypted) < 12:
6594        raise Exception("Truncated Encrypted Settings plaintext")
6595    kwa = decrypted[-12:]
6596    attr, length = struct.unpack(">HH", kwa[0:4])
6597    if attr != ATTR_KEY_WRAP_AUTH or length != 8:
6598        raise Exception("Invalid KWA header")
6599    kwa = kwa[4:]
6600    decrypted = decrypted[0:len(decrypted) - 12]
6601
6602    m = hmac.new(authkey, decrypted, hashlib.sha256)
6603    calc_kwa = m.digest()[0:8]
6604    if kwa != calc_kwa:
6605        raise Exception("KWA mismatch")
6606
6607    return decrypted
6608
6609def zeropad_str(val, pad_len):
6610    while len(val) < pad_len * 2:
6611        val = '0' + val
6612    return val
6613
6614def wsc_dh_init():
6615    # For now, use a hardcoded private key. In theory, this is supposed to be
6616    # randomly selected.
6617    own_private = 0x123456789
6618    own_public = pow(group_5_generator, own_private, group_5_prime)
6619    pk = binascii.unhexlify(zeropad_str(format(own_public, '02x'), 192))
6620    return own_private, pk
6621
6622def wsc_dh_kdf(peer_pk, own_private, mac_addr, e_nonce, r_nonce):
6623    peer_public = int(binascii.hexlify(peer_pk), 16)
6624    if peer_public < 2 or peer_public >= group_5_prime:
6625        raise Exception("Invalid peer public key")
6626    if pow(peer_public, (group_5_prime - 1) // 2, group_5_prime) != 1:
6627        raise Exception("Unexpected Legendre symbol for peer public key")
6628
6629    shared_secret = pow(peer_public, own_private, group_5_prime)
6630    ss = zeropad_str(format(shared_secret, "02x"), 192)
6631    logger.debug("DH shared secret: " + ss)
6632
6633    dhkey = hashlib.sha256(binascii.unhexlify(ss)).digest()
6634    logger.debug("DHKey: " + binascii.hexlify(dhkey).decode())
6635
6636    m = hmac.new(dhkey, e_nonce + mac_addr + r_nonce, hashlib.sha256)
6637    kdk = m.digest()
6638    logger.debug("KDK: " + binascii.hexlify(kdk).decode())
6639    authkey, keywrapkey, emsk = wsc_keys(kdk)
6640    logger.debug("AuthKey: " + binascii.hexlify(authkey).decode())
6641    logger.debug("KeyWrapKey: " + binascii.hexlify(keywrapkey).decode())
6642    logger.debug("EMSK: " + binascii.hexlify(emsk).decode())
6643    return authkey, keywrapkey
6644
6645def wsc_dev_pw_hash(authkey, dev_pw, e_pk, r_pk):
6646    psk1, psk2 = wsc_dev_pw_psk(authkey, dev_pw)
6647    logger.debug("PSK1: " + binascii.hexlify(psk1).decode())
6648    logger.debug("PSK2: " + binascii.hexlify(psk2).decode())
6649
6650    # Note: Secret values are supposed to be random, but hardcoded values are
6651    # fine for testing.
6652    s1 = 16*b'\x77'
6653    m = hmac.new(authkey, s1 + psk1 + e_pk + r_pk, hashlib.sha256)
6654    hash1 = m.digest()
6655    logger.debug("Hash1: " + binascii.hexlify(hash1).decode())
6656
6657    s2 = 16*b'\x88'
6658    m = hmac.new(authkey, s2 + psk2 + e_pk + r_pk, hashlib.sha256)
6659    hash2 = m.digest()
6660    logger.debug("Hash2: " + binascii.hexlify(hash2).decode())
6661    return s1, s2, hash1, hash2
6662
6663def build_m1(eap_id, uuid_e, mac_addr, e_nonce, e_pk,
6664             manufacturer='', model_name='', config_methods='\x00\x00'):
6665    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6666    attrs += build_attr_msg_type(WPS_M1)
6667    attrs += build_wsc_attr(ATTR_UUID_E, uuid_e)
6668    attrs += build_wsc_attr(ATTR_MAC_ADDR, mac_addr)
6669    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
6670    attrs += build_wsc_attr(ATTR_PUBLIC_KEY, e_pk)
6671    attrs += build_wsc_attr(ATTR_AUTH_TYPE_FLAGS, '\x00\x00')
6672    attrs += build_wsc_attr(ATTR_ENCR_TYPE_FLAGS, '\x00\x00')
6673    attrs += build_wsc_attr(ATTR_CONN_TYPE_FLAGS, '\x00')
6674    attrs += build_wsc_attr(ATTR_CONFIG_METHODS, config_methods)
6675    attrs += build_wsc_attr(ATTR_WPS_STATE, '\x00')
6676    attrs += build_wsc_attr(ATTR_MANUFACTURER, manufacturer)
6677    attrs += build_wsc_attr(ATTR_MODEL_NAME, model_name)
6678    attrs += build_wsc_attr(ATTR_MODEL_NUMBER, '')
6679    attrs += build_wsc_attr(ATTR_SERIAL_NUMBER, '')
6680    attrs += build_wsc_attr(ATTR_PRIMARY_DEV_TYPE, 8*'\x00')
6681    attrs += build_wsc_attr(ATTR_DEV_NAME, '')
6682    attrs += build_wsc_attr(ATTR_RF_BANDS, '\x00')
6683    attrs += build_wsc_attr(ATTR_ASSOC_STATE, '\x00\x00')
6684    attrs += build_wsc_attr(ATTR_DEV_PASSWORD_ID, '\x00\x00')
6685    attrs += build_wsc_attr(ATTR_CONFIG_ERROR, '\x00\x00')
6686    attrs += build_wsc_attr(ATTR_OS_VERSION, '\x00\x00\x00\x00')
6687    m1 = build_eap_wsc(2, eap_id, attrs)
6688    return m1, attrs
6689
6690def build_m2(authkey, m1, eap_id, e_nonce, r_nonce, uuid_r, r_pk,
6691             dev_pw_id='\x00\x00', eap_code=1):
6692    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6693    attrs += build_attr_msg_type(WPS_M2)
6694    if e_nonce:
6695        attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
6696    if r_nonce:
6697        attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
6698    attrs += build_wsc_attr(ATTR_UUID_R, uuid_r)
6699    if r_pk:
6700        attrs += build_wsc_attr(ATTR_PUBLIC_KEY, r_pk)
6701    attrs += build_wsc_attr(ATTR_AUTH_TYPE_FLAGS, '\x00\x00')
6702    attrs += build_wsc_attr(ATTR_ENCR_TYPE_FLAGS, '\x00\x00')
6703    attrs += build_wsc_attr(ATTR_CONN_TYPE_FLAGS, '\x00')
6704    attrs += build_wsc_attr(ATTR_CONFIG_METHODS, '\x00\x00')
6705    attrs += build_wsc_attr(ATTR_MANUFACTURER, '')
6706    attrs += build_wsc_attr(ATTR_MODEL_NAME, '')
6707    attrs += build_wsc_attr(ATTR_MODEL_NUMBER, '')
6708    attrs += build_wsc_attr(ATTR_SERIAL_NUMBER, '')
6709    attrs += build_wsc_attr(ATTR_PRIMARY_DEV_TYPE, 8*'\x00')
6710    attrs += build_wsc_attr(ATTR_DEV_NAME, '')
6711    attrs += build_wsc_attr(ATTR_RF_BANDS, '\x00')
6712    attrs += build_wsc_attr(ATTR_ASSOC_STATE, '\x00\x00')
6713    attrs += build_wsc_attr(ATTR_CONFIG_ERROR, '\x00\x00')
6714    attrs += build_wsc_attr(ATTR_DEV_PASSWORD_ID, dev_pw_id)
6715    attrs += build_wsc_attr(ATTR_OS_VERSION, '\x00\x00\x00\x00')
6716    attrs += build_attr_authenticator(authkey, m1, attrs)
6717    m2 = build_eap_wsc(eap_code, eap_id, attrs)
6718    return m2, attrs
6719
6720def build_m2d(m1, eap_id, e_nonce, r_nonce, uuid_r, dev_pw_id=None, eap_code=1):
6721    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6722    attrs += build_attr_msg_type(WPS_M2D)
6723    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
6724    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
6725    attrs += build_wsc_attr(ATTR_UUID_R, uuid_r)
6726    attrs += build_wsc_attr(ATTR_AUTH_TYPE_FLAGS, '\x00\x00')
6727    attrs += build_wsc_attr(ATTR_ENCR_TYPE_FLAGS, '\x00\x00')
6728    attrs += build_wsc_attr(ATTR_CONN_TYPE_FLAGS, '\x00')
6729    attrs += build_wsc_attr(ATTR_CONFIG_METHODS, '\x00\x00')
6730    attrs += build_wsc_attr(ATTR_MANUFACTURER, '')
6731    attrs += build_wsc_attr(ATTR_MODEL_NAME, '')
6732    #attrs += build_wsc_attr(ATTR_MODEL_NUMBER, '')
6733    attrs += build_wsc_attr(ATTR_SERIAL_NUMBER, '')
6734    attrs += build_wsc_attr(ATTR_PRIMARY_DEV_TYPE, 8*'\x00')
6735    attrs += build_wsc_attr(ATTR_DEV_NAME, '')
6736    attrs += build_wsc_attr(ATTR_RF_BANDS, '\x00')
6737    attrs += build_wsc_attr(ATTR_ASSOC_STATE, '\x00\x00')
6738    attrs += build_wsc_attr(ATTR_CONFIG_ERROR, '\x00\x00')
6739    attrs += build_wsc_attr(ATTR_OS_VERSION, '\x00\x00\x00\x00')
6740    if dev_pw_id:
6741        attrs += build_wsc_attr(ATTR_DEV_PASSWORD_ID, dev_pw_id)
6742    m2d = build_eap_wsc(eap_code, eap_id, attrs)
6743    return m2d, attrs
6744
6745def build_ack(eap_id, e_nonce, r_nonce, msg_type=WPS_WSC_ACK, eap_code=1):
6746    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6747    if msg_type is not None:
6748        attrs += build_attr_msg_type(msg_type)
6749    if e_nonce:
6750        attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
6751    if r_nonce:
6752        attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
6753    msg = build_eap_wsc(eap_code, eap_id, attrs, opcode=WSC_ACK)
6754    return msg, attrs
6755
6756def build_nack(eap_id, e_nonce, r_nonce, config_error='\x00\x00',
6757               msg_type=WPS_WSC_NACK, eap_code=1):
6758    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6759    if msg_type is not None:
6760        attrs += build_attr_msg_type(msg_type)
6761    if e_nonce:
6762        attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
6763    if r_nonce:
6764        attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
6765    if config_error:
6766        attrs += build_wsc_attr(ATTR_CONFIG_ERROR, config_error)
6767    msg = build_eap_wsc(eap_code, eap_id, attrs, opcode=WSC_NACK)
6768    return msg, attrs
6769
6770def test_wps_ext(dev, apdev):
6771    """WPS against external implementation"""
6772    pin = "12345670"
6773    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
6774    wps_ext_eap_identity_req(dev[0], hapd, bssid)
6775    wps_ext_eap_identity_resp(hapd, dev[0], addr)
6776
6777    logger.debug("Receive WSC/Start from AP")
6778    msg = get_wsc_msg(hapd)
6779    if msg['wsc_opcode'] != WSC_Start:
6780        raise Exception("Unexpected Op-Code for WSC/Start")
6781    wsc_start_id = msg['eap_identifier']
6782
6783    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
6784    uuid_e = 16*b'\x11'
6785    e_nonce = 16*b'\x22'
6786    own_private, e_pk = wsc_dh_init()
6787
6788    logger.debug("Send M1 to AP")
6789    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
6790                                e_nonce, e_pk)
6791    send_wsc_msg(hapd, addr, m1)
6792
6793    logger.debug("Receive M2 from AP")
6794    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
6795
6796    authkey, keywrapkey = wsc_dh_kdf(m2_attrs[ATTR_PUBLIC_KEY], own_private,
6797                                     mac_addr, e_nonce,
6798                                     m2_attrs[ATTR_REGISTRAR_NONCE])
6799    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk,
6800                                                   m2_attrs[ATTR_PUBLIC_KEY])
6801
6802    logger.debug("Send M3 to AP")
6803    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6804    attrs += build_attr_msg_type(WPS_M3)
6805    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE,
6806                            m2_attrs[ATTR_REGISTRAR_NONCE])
6807    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
6808    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
6809    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
6810    raw_m3_attrs = attrs
6811    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
6812    send_wsc_msg(hapd, addr, m3)
6813
6814    logger.debug("Receive M4 from AP")
6815    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
6816
6817    logger.debug("Send M5 to AP")
6818    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6819    attrs += build_attr_msg_type(WPS_M5)
6820    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE,
6821                            m2_attrs[ATTR_REGISTRAR_NONCE])
6822    data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
6823    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
6824    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
6825    raw_m5_attrs = attrs
6826    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
6827    send_wsc_msg(hapd, addr, m5)
6828
6829    logger.debug("Receive M6 from AP")
6830    msg, m6_attrs, raw_m6_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M6)
6831
6832    logger.debug("Send M7 to AP")
6833    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6834    attrs += build_attr_msg_type(WPS_M7)
6835    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE,
6836                            m2_attrs[ATTR_REGISTRAR_NONCE])
6837    data = build_wsc_attr(ATTR_E_SNONCE2, e_s2)
6838    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
6839    attrs += build_attr_authenticator(authkey, raw_m6_attrs, attrs)
6840    m7 = build_eap_wsc(2, msg['eap_identifier'], attrs)
6841    raw_m7_attrs = attrs
6842    send_wsc_msg(hapd, addr, m7)
6843
6844    logger.debug("Receive M8 from AP")
6845    msg, m8_attrs, raw_m8_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M8)
6846    m8_cred = decrypt_attr_encr_settings(authkey, keywrapkey,
6847                                         m8_attrs[ATTR_ENCR_SETTINGS])
6848    logger.debug("M8 Credential: " + binascii.hexlify(m8_cred).decode())
6849
6850    logger.debug("Prepare WSC_Done")
6851    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6852    attrs += build_attr_msg_type(WPS_WSC_DONE)
6853    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
6854    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE,
6855                            m2_attrs[ATTR_REGISTRAR_NONCE])
6856    wsc_done = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
6857    # Do not send WSC_Done yet to allow exchangw with STA complete before the
6858    # AP disconnects.
6859
6860    uuid_r = 16*b'\x33'
6861    r_nonce = 16*b'\x44'
6862
6863    eap_id = wsc_start_id
6864    logger.debug("Send WSC/Start to STA")
6865    wsc_start = build_eap_wsc(1, eap_id, b'', opcode=WSC_Start)
6866    send_wsc_msg(dev[0], bssid, wsc_start)
6867    eap_id = (eap_id + 1) % 256
6868
6869    logger.debug("Receive M1 from STA")
6870    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
6871
6872    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
6873                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
6874                                     r_nonce)
6875    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
6876                                                   m1_attrs[ATTR_PUBLIC_KEY],
6877                                                   e_pk)
6878
6879    logger.debug("Send M2 to STA")
6880    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
6881                                m1_attrs[ATTR_ENROLLEE_NONCE],
6882                                r_nonce, uuid_r, e_pk)
6883    send_wsc_msg(dev[0], bssid, m2)
6884    eap_id = (eap_id + 1) % 256
6885
6886    logger.debug("Receive M3 from STA")
6887    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
6888
6889    logger.debug("Send M4 to STA")
6890    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6891    attrs += build_attr_msg_type(WPS_M4)
6892    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, m1_attrs[ATTR_ENROLLEE_NONCE])
6893    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
6894    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
6895    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
6896    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
6897    attrs += build_attr_authenticator(authkey, raw_m3_attrs, attrs)
6898    raw_m4_attrs = attrs
6899    m4 = build_eap_wsc(1, eap_id, attrs)
6900    send_wsc_msg(dev[0], bssid, m4)
6901    eap_id = (eap_id + 1) % 256
6902
6903    logger.debug("Receive M5 from STA")
6904    msg, m5_attrs, raw_m5_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M5)
6905
6906    logger.debug("Send M6 to STA")
6907    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6908    attrs += build_attr_msg_type(WPS_M6)
6909    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE,
6910                            m1_attrs[ATTR_ENROLLEE_NONCE])
6911    data = build_wsc_attr(ATTR_R_SNONCE2, r_s2)
6912    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
6913    attrs += build_attr_authenticator(authkey, raw_m5_attrs, attrs)
6914    raw_m6_attrs = attrs
6915    m6 = build_eap_wsc(1, eap_id, attrs)
6916    send_wsc_msg(dev[0], bssid, m6)
6917    eap_id = (eap_id + 1) % 256
6918
6919    logger.debug("Receive M7 from STA")
6920    msg, m7_attrs, raw_m7_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M7)
6921
6922    logger.debug("Send M8 to STA")
6923    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6924    attrs += build_attr_msg_type(WPS_M8)
6925    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE,
6926                            m1_attrs[ATTR_ENROLLEE_NONCE])
6927    attrs += build_attr_encr_settings(authkey, keywrapkey, m8_cred)
6928    attrs += build_attr_authenticator(authkey, raw_m7_attrs, attrs)
6929    raw_m8_attrs = attrs
6930    m8 = build_eap_wsc(1, eap_id, attrs)
6931    send_wsc_msg(dev[0], bssid, m8)
6932    eap_id = (eap_id + 1) % 256
6933
6934    ev = dev[0].wait_event(["WPS-CRED-RECEIVED"], timeout=5)
6935    if ev is None:
6936        raise Exception("wpa_supplicant did not report credential")
6937
6938    logger.debug("Receive WSC_Done from STA")
6939    msg = get_wsc_msg(dev[0])
6940    if msg['wsc_opcode'] != WSC_Done or msg['wsc_msg_type'] != WPS_WSC_DONE:
6941        raise Exception("Unexpected Op-Code/MsgType for WSC_Done")
6942
6943    logger.debug("Send WSC_Done to AP")
6944    hapd.request("SET ext_eapol_frame_io 0")
6945    dev[0].request("SET ext_eapol_frame_io 0")
6946    send_wsc_msg(hapd, addr, wsc_done)
6947
6948    ev = hapd.wait_event(["WPS-REG-SUCCESS"], timeout=5)
6949    if ev is None:
6950        raise Exception("hostapd did not report WPS success")
6951
6952    dev[0].wait_connected()
6953
6954def wps_start_kwa(dev, apdev):
6955    pin = "12345670"
6956    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
6957    wps_ext_eap_identity_req(dev[0], hapd, bssid)
6958    wps_ext_eap_identity_resp(hapd, dev[0], addr)
6959    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
6960
6961    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
6962    uuid_r = 16*b'\x33'
6963    r_nonce = 16*b'\x44'
6964    own_private, e_pk = wsc_dh_init()
6965
6966    logger.debug("Receive M1 from STA")
6967    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
6968    eap_id = (msg['eap_identifier'] + 1) % 256
6969
6970    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
6971                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
6972                                     r_nonce)
6973    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
6974                                                   m1_attrs[ATTR_PUBLIC_KEY],
6975                                                   e_pk)
6976
6977    logger.debug("Send M2 to STA")
6978    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
6979                                m1_attrs[ATTR_ENROLLEE_NONCE],
6980                                r_nonce, uuid_r, e_pk)
6981    send_wsc_msg(dev[0], bssid, m2)
6982    eap_id = (eap_id + 1) % 256
6983
6984    logger.debug("Receive M3 from STA")
6985    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
6986
6987    logger.debug("Send M4 to STA")
6988    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6989    attrs += build_attr_msg_type(WPS_M4)
6990    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, m1_attrs[ATTR_ENROLLEE_NONCE])
6991    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
6992    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
6993
6994    return r_s1, keywrapkey, authkey, raw_m3_attrs, eap_id, bssid, attrs
6995
6996def wps_stop_kwa(dev, bssid, attrs, authkey, raw_m3_attrs, eap_id):
6997    attrs += build_attr_authenticator(authkey, raw_m3_attrs, attrs)
6998    m4 = build_eap_wsc(1, eap_id, attrs)
6999    send_wsc_msg(dev[0], bssid, m4)
7000    eap_id = (eap_id + 1) % 256
7001
7002    logger.debug("Receive M5 from STA")
7003    msg = get_wsc_msg(dev[0])
7004    if msg['wsc_opcode'] != WSC_NACK:
7005        raise Exception("Unexpected message - expected WSC_Nack")
7006
7007    dev[0].request("WPS_CANCEL")
7008    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7009    dev[0].wait_disconnected()
7010
7011def test_wps_ext_kwa_proto_no_kwa(dev, apdev):
7012    """WPS and KWA error: No KWA attribute"""
7013    r_s1, keywrapkey, authkey, raw_m3_attrs, eap_id, bssid, attrs = wps_start_kwa(dev, apdev)
7014    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7015    # Encrypted Settings without KWA
7016    iv = 16*b'\x99'
7017    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
7018    pad_len = 16 - len(data) % 16
7019    ps = pad_len * struct.pack('B', pad_len)
7020    data += ps
7021    wrapped = aes.encrypt(data)
7022    attrs += build_wsc_attr(ATTR_ENCR_SETTINGS, iv + wrapped)
7023    wps_stop_kwa(dev, bssid, attrs, authkey, raw_m3_attrs, eap_id)
7024
7025def test_wps_ext_kwa_proto_data_after_kwa(dev, apdev):
7026    """WPS and KWA error: Data after KWA"""
7027    r_s1, keywrapkey, authkey, raw_m3_attrs, eap_id, bssid, attrs = wps_start_kwa(dev, apdev)
7028    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7029    # Encrypted Settings and data after KWA
7030    m = hmac.new(authkey, data, hashlib.sha256)
7031    kwa = m.digest()[0:8]
7032    data += build_wsc_attr(ATTR_KEY_WRAP_AUTH, kwa)
7033    data += build_wsc_attr(ATTR_VENDOR_EXT, "1234567890")
7034    iv = 16*b'\x99'
7035    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
7036    pad_len = 16 - len(data) % 16
7037    ps = pad_len * struct.pack('B', pad_len)
7038    data += ps
7039    wrapped = aes.encrypt(data)
7040    attrs += build_wsc_attr(ATTR_ENCR_SETTINGS, iv + wrapped)
7041    wps_stop_kwa(dev, bssid, attrs, authkey, raw_m3_attrs, eap_id)
7042
7043def test_wps_ext_kwa_proto_kwa_mismatch(dev, apdev):
7044    """WPS and KWA error: KWA mismatch"""
7045    r_s1, keywrapkey, authkey, raw_m3_attrs, eap_id, bssid, attrs = wps_start_kwa(dev, apdev)
7046    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7047    # Encrypted Settings and KWA with incorrect value
7048    data += build_wsc_attr(ATTR_KEY_WRAP_AUTH, 8*'\x00')
7049    iv = 16*b'\x99'
7050    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
7051    pad_len = 16 - len(data) % 16
7052    ps = pad_len * struct.pack('B', pad_len)
7053    data += ps
7054    wrapped = aes.encrypt(data)
7055    attrs += build_wsc_attr(ATTR_ENCR_SETTINGS, iv + wrapped)
7056    wps_stop_kwa(dev, bssid, attrs, authkey, raw_m3_attrs, eap_id)
7057
7058def wps_run_cred_proto(dev, apdev, m8_cred, connect=False, no_connect=False):
7059    pin = "12345670"
7060    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7061    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7062    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7063    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7064
7065    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7066    uuid_r = 16*b'\x33'
7067    r_nonce = 16*b'\x44'
7068    own_private, e_pk = wsc_dh_init()
7069
7070    logger.debug("Receive M1 from STA")
7071    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7072    eap_id = (msg['eap_identifier'] + 1) % 256
7073
7074    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7075                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7076                                     r_nonce)
7077    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7078                                                   m1_attrs[ATTR_PUBLIC_KEY],
7079                                                   e_pk)
7080
7081    logger.debug("Send M2 to STA")
7082    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7083                                m1_attrs[ATTR_ENROLLEE_NONCE],
7084                                r_nonce, uuid_r, e_pk)
7085    send_wsc_msg(dev[0], bssid, m2)
7086    eap_id = (eap_id + 1) % 256
7087
7088    logger.debug("Receive M3 from STA")
7089    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
7090
7091    logger.debug("Send M4 to STA")
7092    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7093    attrs += build_attr_msg_type(WPS_M4)
7094    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, m1_attrs[ATTR_ENROLLEE_NONCE])
7095    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7096    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7097    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7098    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7099    attrs += build_attr_authenticator(authkey, raw_m3_attrs, attrs)
7100    raw_m4_attrs = attrs
7101    m4 = build_eap_wsc(1, eap_id, attrs)
7102    send_wsc_msg(dev[0], bssid, m4)
7103    eap_id = (eap_id + 1) % 256
7104
7105    logger.debug("Receive M5 from STA")
7106    msg, m5_attrs, raw_m5_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M5)
7107
7108    logger.debug("Send M6 to STA")
7109    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7110    attrs += build_attr_msg_type(WPS_M6)
7111    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE,
7112                            m1_attrs[ATTR_ENROLLEE_NONCE])
7113    data = build_wsc_attr(ATTR_R_SNONCE2, r_s2)
7114    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7115    attrs += build_attr_authenticator(authkey, raw_m5_attrs, attrs)
7116    raw_m6_attrs = attrs
7117    m6 = build_eap_wsc(1, eap_id, attrs)
7118    send_wsc_msg(dev[0], bssid, m6)
7119    eap_id = (eap_id + 1) % 256
7120
7121    logger.debug("Receive M7 from STA")
7122    msg, m7_attrs, raw_m7_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M7)
7123
7124    logger.debug("Send M8 to STA")
7125    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7126    attrs += build_attr_msg_type(WPS_M8)
7127    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE,
7128                            m1_attrs[ATTR_ENROLLEE_NONCE])
7129    attrs += build_attr_encr_settings(authkey, keywrapkey, m8_cred)
7130    attrs += build_attr_authenticator(authkey, raw_m7_attrs, attrs)
7131    raw_m8_attrs = attrs
7132    m8 = build_eap_wsc(1, eap_id, attrs)
7133    send_wsc_msg(dev[0], bssid, m8)
7134    eap_id = (eap_id + 1) % 256
7135
7136    if no_connect:
7137        logger.debug("Receive WSC_Done from STA")
7138        msg = get_wsc_msg(dev[0])
7139        if msg['wsc_opcode'] != WSC_Done or msg['wsc_msg_type'] != WPS_WSC_DONE:
7140            raise Exception("Unexpected Op-Code/MsgType for WSC_Done")
7141
7142        hapd.request("SET ext_eapol_frame_io 0")
7143        dev[0].request("SET ext_eapol_frame_io 0")
7144
7145        send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7146
7147        dev[0].wait_disconnected()
7148        dev[0].request("REMOVE_NETWORK all")
7149    elif connect:
7150        logger.debug("Receive WSC_Done from STA")
7151        msg = get_wsc_msg(dev[0])
7152        if msg['wsc_opcode'] != WSC_Done or msg['wsc_msg_type'] != WPS_WSC_DONE:
7153            raise Exception("Unexpected Op-Code/MsgType for WSC_Done")
7154
7155        hapd.request("SET ext_eapol_frame_io 0")
7156        dev[0].request("SET ext_eapol_frame_io 0")
7157
7158        send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7159
7160        dev[0].wait_connected()
7161    else:
7162        # Verify STA NACK's the credential
7163        msg = get_wsc_msg(dev[0])
7164        if msg['wsc_opcode'] != WSC_NACK:
7165            raise Exception("Unexpected message - expected WSC_Nack")
7166        dev[0].request("WPS_CANCEL")
7167        send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7168        dev[0].wait_disconnected()
7169
7170def build_cred(nw_idx='\x01', ssid='test-wps-conf', auth_type='\x00\x20',
7171               encr_type='\x00\x08', nw_key="12345678",
7172               mac_addr='\x00\x00\x00\x00\x00\x00'):
7173    attrs = b''
7174    if nw_idx is not None:
7175        attrs += build_wsc_attr(ATTR_NETWORK_INDEX, nw_idx)
7176    if ssid is not None:
7177        attrs += build_wsc_attr(ATTR_SSID, ssid)
7178    if auth_type is not None:
7179        attrs += build_wsc_attr(ATTR_AUTH_TYPE, auth_type)
7180    if encr_type is not None:
7181        attrs += build_wsc_attr(ATTR_ENCR_TYPE, encr_type)
7182    if nw_key is not None:
7183        attrs += build_wsc_attr(ATTR_NETWORK_KEY, nw_key)
7184    if mac_addr is not None:
7185        attrs += build_wsc_attr(ATTR_MAC_ADDR, mac_addr)
7186    return build_wsc_attr(ATTR_CRED, attrs)
7187
7188def test_wps_ext_cred_proto_success(dev, apdev):
7189    """WPS and Credential: success"""
7190    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7191    m8_cred = build_cred(mac_addr=mac_addr)
7192    wps_run_cred_proto(dev, apdev, m8_cred, connect=True)
7193
7194def test_wps_ext_cred_proto_mac_addr_mismatch(dev, apdev):
7195    """WPS and Credential: MAC Address mismatch"""
7196    m8_cred = build_cred()
7197    wps_run_cred_proto(dev, apdev, m8_cred, connect=True)
7198
7199def test_wps_ext_cred_proto_zero_padding(dev, apdev):
7200    """WPS and Credential: zeropadded attributes"""
7201    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7202    m8_cred = build_cred(mac_addr=mac_addr, ssid='test-wps-conf\x00',
7203                         nw_key="12345678\x00")
7204    wps_run_cred_proto(dev, apdev, m8_cred, connect=True)
7205
7206def test_wps_ext_cred_proto_ssid_missing(dev, apdev):
7207    """WPS and Credential: SSID missing"""
7208    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7209    m8_cred = build_cred(mac_addr=mac_addr, ssid=None)
7210    wps_run_cred_proto(dev, apdev, m8_cred)
7211
7212def test_wps_ext_cred_proto_ssid_zero_len(dev, apdev):
7213    """WPS and Credential: Zero-length SSID"""
7214    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7215    m8_cred = build_cred(mac_addr=mac_addr, ssid="")
7216    wps_run_cred_proto(dev, apdev, m8_cred, no_connect=True)
7217
7218def test_wps_ext_cred_proto_auth_type_missing(dev, apdev):
7219    """WPS and Credential: Auth Type missing"""
7220    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7221    m8_cred = build_cred(mac_addr=mac_addr, auth_type=None)
7222    wps_run_cred_proto(dev, apdev, m8_cred)
7223
7224def test_wps_ext_cred_proto_encr_type_missing(dev, apdev):
7225    """WPS and Credential: Encr Type missing"""
7226    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7227    m8_cred = build_cred(mac_addr=mac_addr, encr_type=None)
7228    wps_run_cred_proto(dev, apdev, m8_cred)
7229
7230def test_wps_ext_cred_proto_network_key_missing(dev, apdev):
7231    """WPS and Credential: Network Key missing"""
7232    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7233    m8_cred = build_cred(mac_addr=mac_addr, nw_key=None)
7234    wps_run_cred_proto(dev, apdev, m8_cred)
7235
7236def test_wps_ext_cred_proto_network_key_missing_open(dev, apdev):
7237    """WPS and Credential: Network Key missing (open)"""
7238    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7239    m8_cred = build_cred(mac_addr=mac_addr, auth_type='\x00\x01',
7240                         encr_type='\x00\x01', nw_key=None, ssid="foo")
7241    wps_run_cred_proto(dev, apdev, m8_cred, no_connect=True)
7242
7243def test_wps_ext_cred_proto_mac_addr_missing(dev, apdev):
7244    """WPS and Credential: MAC Address missing"""
7245    m8_cred = build_cred(mac_addr=None)
7246    wps_run_cred_proto(dev, apdev, m8_cred)
7247
7248def test_wps_ext_cred_proto_invalid_encr_type(dev, apdev):
7249    """WPS and Credential: Invalid Encr Type"""
7250    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7251    m8_cred = build_cred(mac_addr=mac_addr, encr_type='\x00\x00')
7252    wps_run_cred_proto(dev, apdev, m8_cred)
7253
7254def test_wps_ext_cred_proto_missing_cred(dev, apdev):
7255    """WPS and Credential: Missing Credential"""
7256    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7257    m8_cred = b''
7258    wps_run_cred_proto(dev, apdev, m8_cred)
7259
7260def test_wps_ext_proto_m2_no_public_key(dev, apdev):
7261    """WPS and no Public Key in M2"""
7262    pin = "12345670"
7263    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7264    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7265    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7266    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7267
7268    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7269    uuid_r = 16*b'\x33'
7270    r_nonce = 16*b'\x44'
7271    own_private, e_pk = wsc_dh_init()
7272
7273    logger.debug("Receive M1 from STA")
7274    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7275    eap_id = (msg['eap_identifier'] + 1) % 256
7276
7277    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7278                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7279                                     r_nonce)
7280    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7281                                                   m1_attrs[ATTR_PUBLIC_KEY],
7282                                                   e_pk)
7283
7284    logger.debug("Send M2 to STA")
7285    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7286                                m1_attrs[ATTR_ENROLLEE_NONCE],
7287                                r_nonce, uuid_r, None)
7288    send_wsc_msg(dev[0], bssid, m2)
7289    eap_id = (eap_id + 1) % 256
7290
7291    # Verify STA NACK's the credential
7292    msg = get_wsc_msg(dev[0])
7293    if msg['wsc_opcode'] != WSC_NACK:
7294        raise Exception("Unexpected message - expected WSC_Nack")
7295    dev[0].request("WPS_CANCEL")
7296    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7297    dev[0].wait_disconnected()
7298
7299def test_wps_ext_proto_m2_invalid_public_key(dev, apdev):
7300    """WPS and invalid Public Key in M2"""
7301    pin = "12345670"
7302    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7303    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7304    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7305    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7306
7307    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7308    uuid_r = 16*b'\x33'
7309    r_nonce = 16*b'\x44'
7310    own_private, e_pk = wsc_dh_init()
7311
7312    logger.debug("Receive M1 from STA")
7313    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7314    eap_id = (msg['eap_identifier'] + 1) % 256
7315
7316    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7317                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7318                                     r_nonce)
7319    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7320                                                   m1_attrs[ATTR_PUBLIC_KEY],
7321                                                   e_pk)
7322
7323    logger.debug("Send M2 to STA")
7324    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7325                                m1_attrs[ATTR_ENROLLEE_NONCE],
7326                                r_nonce, uuid_r, 192*b'\xff')
7327    send_wsc_msg(dev[0], bssid, m2)
7328    eap_id = (eap_id + 1) % 256
7329
7330    # Verify STA NACK's the credential
7331    msg = get_wsc_msg(dev[0])
7332    if msg['wsc_opcode'] != WSC_NACK:
7333        raise Exception("Unexpected message - expected WSC_Nack")
7334    dev[0].request("WPS_CANCEL")
7335    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7336    dev[0].wait_disconnected()
7337
7338def test_wps_ext_proto_m2_public_key_oom(dev, apdev):
7339    """WPS and Public Key OOM in M2"""
7340    pin = "12345670"
7341    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7342    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7343    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7344    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7345
7346    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7347    uuid_r = 16*b'\x33'
7348    r_nonce = 16*b'\x44'
7349    own_private, e_pk = wsc_dh_init()
7350
7351    logger.debug("Receive M1 from STA")
7352    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7353    eap_id = (msg['eap_identifier'] + 1) % 256
7354
7355    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7356                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7357                                     r_nonce)
7358    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7359                                                   m1_attrs[ATTR_PUBLIC_KEY],
7360                                                   e_pk)
7361
7362    logger.debug("Send M2 to STA")
7363    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7364                                m1_attrs[ATTR_ENROLLEE_NONCE],
7365                                r_nonce, uuid_r, e_pk)
7366    with alloc_fail(dev[0], 1, "wpabuf_alloc_copy;wps_process_pubkey"):
7367        send_wsc_msg(dev[0], bssid, m2)
7368        eap_id = (eap_id + 1) % 256
7369
7370        # Verify STA NACK's the credential
7371        msg = get_wsc_msg(dev[0])
7372        if msg['wsc_opcode'] != WSC_NACK:
7373            raise Exception("Unexpected message - expected WSC_Nack")
7374        dev[0].request("WPS_CANCEL")
7375        send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7376        dev[0].wait_disconnected()
7377
7378def test_wps_ext_proto_nack_m3(dev, apdev):
7379    """WPS and NACK M3"""
7380    pin = "12345670"
7381    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7382    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7383    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7384    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7385
7386    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7387    uuid_r = 16*b'\x33'
7388    r_nonce = 16*b'\x44'
7389    own_private, e_pk = wsc_dh_init()
7390
7391    logger.debug("Receive M1 from STA")
7392    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7393    eap_id = (msg['eap_identifier'] + 1) % 256
7394
7395    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7396                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7397                                     r_nonce)
7398    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7399                                                   m1_attrs[ATTR_PUBLIC_KEY],
7400                                                   e_pk)
7401
7402    logger.debug("Send M2 to STA")
7403    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7404                                m1_attrs[ATTR_ENROLLEE_NONCE],
7405                                r_nonce, uuid_r, e_pk)
7406    send_wsc_msg(dev[0], bssid, m2)
7407    eap_id = (eap_id + 1) % 256
7408
7409    logger.debug("Receive M3 from STA")
7410    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
7411
7412    logger.debug("Send NACK to STA")
7413    msg, attrs = build_nack(eap_id, m1_attrs[ATTR_ENROLLEE_NONCE],
7414                            r_nonce, config_error='\x01\x23')
7415    send_wsc_msg(dev[0], bssid, msg)
7416    ev = dev[0].wait_event(["WPS-FAIL"], timeout=5)
7417    if ev is None:
7418        raise Exception("Failure not reported")
7419    if "msg=7 config_error=291" not in ev:
7420        raise Exception("Unexpected failure reason: " + ev)
7421
7422def test_wps_ext_proto_nack_m5(dev, apdev):
7423    """WPS and NACK M5"""
7424    pin = "12345670"
7425    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7426    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7427    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7428    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7429
7430    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7431    uuid_r = 16*b'\x33'
7432    r_nonce = 16*b'\x44'
7433    own_private, e_pk = wsc_dh_init()
7434
7435    logger.debug("Receive M1 from STA")
7436    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7437    eap_id = (msg['eap_identifier'] + 1) % 256
7438
7439    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7440                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7441                                     r_nonce)
7442    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7443                                                   m1_attrs[ATTR_PUBLIC_KEY],
7444                                                   e_pk)
7445
7446    logger.debug("Send M2 to STA")
7447    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7448                                m1_attrs[ATTR_ENROLLEE_NONCE],
7449                                r_nonce, uuid_r, e_pk)
7450    send_wsc_msg(dev[0], bssid, m2)
7451    eap_id = (eap_id + 1) % 256
7452
7453    logger.debug("Receive M3 from STA")
7454    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
7455
7456    logger.debug("Send M4 to STA")
7457    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7458    attrs += build_attr_msg_type(WPS_M4)
7459    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, m1_attrs[ATTR_ENROLLEE_NONCE])
7460    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7461    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7462    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7463    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7464    attrs += build_attr_authenticator(authkey, raw_m3_attrs, attrs)
7465    raw_m4_attrs = attrs
7466    m4 = build_eap_wsc(1, eap_id, attrs)
7467    send_wsc_msg(dev[0], bssid, m4)
7468    eap_id = (eap_id + 1) % 256
7469
7470    logger.debug("Receive M5 from STA")
7471    msg, m5_attrs, raw_m5_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M5)
7472
7473    logger.debug("Send NACK to STA")
7474    msg, attrs = build_nack(eap_id, m1_attrs[ATTR_ENROLLEE_NONCE],
7475                            r_nonce, config_error='\x01\x24')
7476    send_wsc_msg(dev[0], bssid, msg)
7477    ev = dev[0].wait_event(["WPS-FAIL"], timeout=5)
7478    if ev is None:
7479        raise Exception("Failure not reported")
7480    if "msg=9 config_error=292" not in ev:
7481        raise Exception("Unexpected failure reason: " + ev)
7482
7483def wps_nack_m3(dev, apdev):
7484    pin = "00000000"
7485    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
7486    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7487    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7488    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7489
7490    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7491    uuid_r = 16*b'\x33'
7492    r_nonce = 16*b'\x44'
7493    own_private, e_pk = wsc_dh_init()
7494
7495    logger.debug("Receive M1 from STA")
7496    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7497    eap_id = (msg['eap_identifier'] + 1) % 256
7498
7499    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7500                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7501                                     r_nonce)
7502    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7503                                                   m1_attrs[ATTR_PUBLIC_KEY],
7504                                                   e_pk)
7505
7506    logger.debug("Send M2 to STA")
7507    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7508                                m1_attrs[ATTR_ENROLLEE_NONCE],
7509                                r_nonce, uuid_r, e_pk, dev_pw_id='\x00\x04')
7510    send_wsc_msg(dev[0], bssid, m2)
7511    eap_id = (eap_id + 1) % 256
7512
7513    logger.debug("Receive M3 from STA")
7514    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
7515    return eap_id, m1_attrs[ATTR_ENROLLEE_NONCE], r_nonce, bssid
7516
7517def test_wps_ext_proto_nack_m3_no_config_error(dev, apdev):
7518    """WPS and NACK M3 missing Config Error"""
7519    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7520    logger.debug("Send NACK to STA")
7521    msg, attrs = build_nack(eap_id, e_nonce, r_nonce, config_error=None)
7522    send_wsc_msg(dev[0], bssid, msg)
7523    dev[0].request("WPS_CANCEL")
7524    dev[0].wait_disconnected()
7525    dev[0].flush_scan_cache()
7526
7527def test_wps_ext_proto_nack_m3_no_e_nonce(dev, apdev):
7528    """WPS and NACK M3 missing E-Nonce"""
7529    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7530    logger.debug("Send NACK to STA")
7531    msg, attrs = build_nack(eap_id, None, r_nonce)
7532    send_wsc_msg(dev[0], bssid, msg)
7533    dev[0].request("WPS_CANCEL")
7534    dev[0].wait_disconnected()
7535    dev[0].flush_scan_cache()
7536
7537def test_wps_ext_proto_nack_m3_e_nonce_mismatch(dev, apdev):
7538    """WPS and NACK M3 E-Nonce mismatch"""
7539    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7540    logger.debug("Send NACK to STA")
7541    msg, attrs = build_nack(eap_id, 16*'\x00', r_nonce)
7542    send_wsc_msg(dev[0], bssid, msg)
7543    dev[0].request("WPS_CANCEL")
7544    dev[0].wait_disconnected()
7545    dev[0].flush_scan_cache()
7546
7547def test_wps_ext_proto_nack_m3_no_r_nonce(dev, apdev):
7548    """WPS and NACK M3 missing R-Nonce"""
7549    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7550    logger.debug("Send NACK to STA")
7551    msg, attrs = build_nack(eap_id, e_nonce, None)
7552    send_wsc_msg(dev[0], bssid, msg)
7553    dev[0].request("WPS_CANCEL")
7554    dev[0].wait_disconnected()
7555    dev[0].flush_scan_cache()
7556
7557def test_wps_ext_proto_nack_m3_r_nonce_mismatch(dev, apdev):
7558    """WPS and NACK M3 R-Nonce mismatch"""
7559    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7560    logger.debug("Send NACK to STA")
7561    msg, attrs = build_nack(eap_id, e_nonce, 16*'\x00')
7562    send_wsc_msg(dev[0], bssid, msg)
7563    dev[0].request("WPS_CANCEL")
7564    dev[0].wait_disconnected()
7565    dev[0].flush_scan_cache()
7566
7567def test_wps_ext_proto_nack_m3_no_msg_type(dev, apdev):
7568    """WPS and NACK M3 no Message Type"""
7569    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7570    logger.debug("Send NACK to STA")
7571    msg, attrs = build_nack(eap_id, e_nonce, r_nonce, msg_type=None)
7572    send_wsc_msg(dev[0], bssid, msg)
7573    dev[0].request("WPS_CANCEL")
7574    dev[0].wait_disconnected()
7575    dev[0].flush_scan_cache()
7576
7577def test_wps_ext_proto_nack_m3_invalid_msg_type(dev, apdev):
7578    """WPS and NACK M3 invalid Message Type"""
7579    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7580    logger.debug("Send NACK to STA")
7581    msg, attrs = build_nack(eap_id, e_nonce, r_nonce, msg_type=123)
7582    send_wsc_msg(dev[0], bssid, msg)
7583    dev[0].request("WPS_CANCEL")
7584    dev[0].wait_disconnected()
7585    dev[0].flush_scan_cache()
7586
7587def test_wps_ext_proto_nack_m3_invalid_attr(dev, apdev):
7588    """WPS and NACK M3 invalid attribute"""
7589    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7590    logger.debug("Send NACK to STA")
7591    attrs = b'\x10\x10\x00'
7592    msg = build_eap_wsc(1, eap_id, attrs, opcode=WSC_NACK)
7593    send_wsc_msg(dev[0], bssid, msg)
7594    dev[0].request("WPS_CANCEL")
7595    dev[0].wait_disconnected()
7596    dev[0].flush_scan_cache()
7597
7598def test_wps_ext_proto_ack_m3_no_e_nonce(dev, apdev):
7599    """WPS and ACK M3 missing E-Nonce"""
7600    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7601    logger.debug("Send NACK to STA")
7602    msg, attrs = build_ack(eap_id, None, r_nonce)
7603    send_wsc_msg(dev[0], bssid, msg)
7604    dev[0].request("WPS_CANCEL")
7605    dev[0].wait_disconnected()
7606    dev[0].flush_scan_cache()
7607
7608def test_wps_ext_proto_ack_m3_e_nonce_mismatch(dev, apdev):
7609    """WPS and ACK M3 E-Nonce mismatch"""
7610    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7611    logger.debug("Send NACK to STA")
7612    msg, attrs = build_ack(eap_id, 16*'\x00', r_nonce)
7613    send_wsc_msg(dev[0], bssid, msg)
7614    dev[0].request("WPS_CANCEL")
7615    dev[0].wait_disconnected()
7616    dev[0].flush_scan_cache()
7617
7618def test_wps_ext_proto_ack_m3_no_r_nonce(dev, apdev):
7619    """WPS and ACK M3 missing R-Nonce"""
7620    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7621    logger.debug("Send NACK to STA")
7622    msg, attrs = build_ack(eap_id, e_nonce, None)
7623    send_wsc_msg(dev[0], bssid, msg)
7624    dev[0].request("WPS_CANCEL")
7625    dev[0].wait_disconnected()
7626    dev[0].flush_scan_cache()
7627
7628def test_wps_ext_proto_ack_m3_r_nonce_mismatch(dev, apdev):
7629    """WPS and ACK M3 R-Nonce mismatch"""
7630    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7631    logger.debug("Send NACK to STA")
7632    msg, attrs = build_ack(eap_id, e_nonce, 16*'\x00')
7633    send_wsc_msg(dev[0], bssid, msg)
7634    dev[0].request("WPS_CANCEL")
7635    dev[0].wait_disconnected()
7636    dev[0].flush_scan_cache()
7637
7638def test_wps_ext_proto_ack_m3_no_msg_type(dev, apdev):
7639    """WPS and ACK M3 no Message Type"""
7640    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7641    logger.debug("Send NACK to STA")
7642    msg, attrs = build_ack(eap_id, e_nonce, r_nonce, msg_type=None)
7643    send_wsc_msg(dev[0], bssid, msg)
7644    dev[0].request("WPS_CANCEL")
7645    dev[0].wait_disconnected()
7646    dev[0].flush_scan_cache()
7647
7648def test_wps_ext_proto_ack_m3_invalid_msg_type(dev, apdev):
7649    """WPS and ACK M3 invalid Message Type"""
7650    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7651    logger.debug("Send NACK to STA")
7652    msg, attrs = build_ack(eap_id, e_nonce, r_nonce, msg_type=123)
7653    send_wsc_msg(dev[0], bssid, msg)
7654    dev[0].request("WPS_CANCEL")
7655    dev[0].wait_disconnected()
7656    dev[0].flush_scan_cache()
7657
7658def test_wps_ext_proto_ack_m3_invalid_attr(dev, apdev):
7659    """WPS and ACK M3 invalid attribute"""
7660    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7661    logger.debug("Send ACK to STA")
7662    attrs = b'\x10\x10\x00'
7663    msg = build_eap_wsc(1, eap_id, attrs, opcode=WSC_ACK)
7664    send_wsc_msg(dev[0], bssid, msg)
7665    dev[0].request("WPS_CANCEL")
7666    dev[0].wait_disconnected()
7667    dev[0].flush_scan_cache()
7668
7669def test_wps_ext_proto_ack_m3(dev, apdev):
7670    """WPS and ACK M3"""
7671    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7672    logger.debug("Send ACK to STA")
7673    msg, attrs = build_ack(eap_id, e_nonce, r_nonce)
7674    send_wsc_msg(dev[0], bssid, msg)
7675    dev[0].request("WPS_CANCEL")
7676    dev[0].wait_disconnected()
7677    dev[0].flush_scan_cache()
7678
7679def wps_to_m3_helper(dev, apdev):
7680    pin = "12345670"
7681    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7682    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7683    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7684    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7685
7686    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7687    uuid_r = 16*b'\x33'
7688    r_nonce = 16*b'\x44'
7689    own_private, e_pk = wsc_dh_init()
7690
7691    logger.debug("Receive M1 from STA")
7692    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7693    eap_id = (msg['eap_identifier'] + 1) % 256
7694
7695    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7696                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7697                                     r_nonce)
7698    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7699                                                   m1_attrs[ATTR_PUBLIC_KEY],
7700                                                   e_pk)
7701
7702    logger.debug("Send M2 to STA")
7703    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7704                                m1_attrs[ATTR_ENROLLEE_NONCE],
7705                                r_nonce, uuid_r, e_pk)
7706    send_wsc_msg(dev[0], bssid, m2)
7707    eap_id = (eap_id + 1) % 256
7708
7709    logger.debug("Receive M3 from STA")
7710    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
7711    return eap_id, m1_attrs, r_nonce, bssid, r_hash1, r_hash2, r_s1, r_s2, raw_m3_attrs, authkey, keywrapkey
7712
7713def wps_to_m3(dev, apdev):
7714    eap_id, m1_attrs, r_nonce, bssid, r_hash1, r_hash2, r_s1, r_s2, raw_m3_attrs, authkey, keywrapkey = wps_to_m3_helper(dev, apdev)
7715    return eap_id, m1_attrs[ATTR_ENROLLEE_NONCE], r_nonce, bssid, r_hash1, r_hash2, r_s1, raw_m3_attrs, authkey, keywrapkey
7716
7717def wps_to_m5(dev, apdev):
7718    eap_id, m1_attrs, r_nonce, bssid, r_hash1, r_hash2, r_s1, r_s2, raw_m3_attrs, authkey, keywrapkey = wps_to_m3_helper(dev, apdev)
7719
7720    logger.debug("Send M4 to STA")
7721    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7722    attrs += build_attr_msg_type(WPS_M4)
7723    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, m1_attrs[ATTR_ENROLLEE_NONCE])
7724    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7725    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7726    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7727    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7728    attrs += build_attr_authenticator(authkey, raw_m3_attrs, attrs)
7729    raw_m4_attrs = attrs
7730    m4 = build_eap_wsc(1, eap_id, attrs)
7731    send_wsc_msg(dev[0], bssid, m4)
7732    eap_id = (eap_id + 1) % 256
7733
7734    logger.debug("Receive M5 from STA")
7735    msg, m5_attrs, raw_m5_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M5)
7736
7737    return eap_id, m1_attrs[ATTR_ENROLLEE_NONCE], r_nonce, bssid, r_hash1, r_hash2, r_s2, raw_m5_attrs, authkey, keywrapkey
7738
7739def test_wps_ext_proto_m4_missing_r_hash1(dev, apdev):
7740    """WPS and no R-Hash1 in M4"""
7741    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s1, m3, authkey, keywrapkey = wps_to_m3(dev, apdev)
7742
7743    logger.debug("Send M4 to STA")
7744    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7745    attrs += build_attr_msg_type(WPS_M4)
7746    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7747    #attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7748    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7749    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7750    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7751    attrs += build_attr_authenticator(authkey, m3, attrs)
7752    m4 = build_eap_wsc(1, eap_id, attrs)
7753    send_wsc_msg(dev[0], bssid, m4)
7754    eap_id = (eap_id + 1) % 256
7755
7756    logger.debug("Receive M5 (NACK) from STA")
7757    msg = get_wsc_msg(dev[0])
7758    if msg['wsc_opcode'] != WSC_NACK:
7759        raise Exception("Unexpected message - expected WSC_Nack")
7760
7761    dev[0].request("WPS_CANCEL")
7762    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7763    dev[0].wait_disconnected()
7764
7765def test_wps_ext_proto_m4_missing_r_hash2(dev, apdev):
7766    """WPS and no R-Hash2 in M4"""
7767    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s1, m3, authkey, keywrapkey = wps_to_m3(dev, apdev)
7768
7769    logger.debug("Send M4 to STA")
7770    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7771    attrs += build_attr_msg_type(WPS_M4)
7772    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7773    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7774    #attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7775    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7776    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7777    attrs += build_attr_authenticator(authkey, m3, attrs)
7778    m4 = build_eap_wsc(1, eap_id, attrs)
7779    send_wsc_msg(dev[0], bssid, m4)
7780    eap_id = (eap_id + 1) % 256
7781
7782    logger.debug("Receive M5 (NACK) from STA")
7783    msg = get_wsc_msg(dev[0])
7784    if msg['wsc_opcode'] != WSC_NACK:
7785        raise Exception("Unexpected message - expected WSC_Nack")
7786
7787    dev[0].request("WPS_CANCEL")
7788    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7789    dev[0].wait_disconnected()
7790
7791def test_wps_ext_proto_m4_missing_r_snonce1(dev, apdev):
7792    """WPS and no R-SNonce1 in M4"""
7793    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s1, m3, authkey, keywrapkey = wps_to_m3(dev, apdev)
7794
7795    logger.debug("Send M4 to STA")
7796    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7797    attrs += build_attr_msg_type(WPS_M4)
7798    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7799    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7800    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7801    #data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7802    data = b''
7803    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7804    attrs += build_attr_authenticator(authkey, m3, attrs)
7805    m4 = build_eap_wsc(1, eap_id, attrs)
7806    send_wsc_msg(dev[0], bssid, m4)
7807    eap_id = (eap_id + 1) % 256
7808
7809    logger.debug("Receive M5 (NACK) from STA")
7810    msg = get_wsc_msg(dev[0])
7811    if msg['wsc_opcode'] != WSC_NACK:
7812        raise Exception("Unexpected message - expected WSC_Nack")
7813
7814    dev[0].request("WPS_CANCEL")
7815    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7816    dev[0].wait_disconnected()
7817
7818def test_wps_ext_proto_m4_invalid_pad_string(dev, apdev):
7819    """WPS and invalid pad string in M4"""
7820    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s1, m3, authkey, keywrapkey = wps_to_m3(dev, apdev)
7821
7822    logger.debug("Send M4 to STA")
7823    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7824    attrs += build_attr_msg_type(WPS_M4)
7825    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7826    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7827    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7828    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7829
7830    m = hmac.new(authkey, data, hashlib.sha256)
7831    kwa = m.digest()[0:8]
7832    data += build_wsc_attr(ATTR_KEY_WRAP_AUTH, kwa)
7833    iv = 16*b'\x99'
7834    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
7835    pad_len = 16 - len(data) % 16
7836    ps = (pad_len - 1) * struct.pack('B', pad_len) + struct.pack('B', pad_len - 1)
7837    data += ps
7838    wrapped = aes.encrypt(data)
7839    attrs += build_wsc_attr(ATTR_ENCR_SETTINGS, iv + wrapped)
7840
7841    attrs += build_attr_authenticator(authkey, m3, attrs)
7842    m4 = build_eap_wsc(1, eap_id, attrs)
7843    send_wsc_msg(dev[0], bssid, m4)
7844    eap_id = (eap_id + 1) % 256
7845
7846    logger.debug("Receive M5 (NACK) from STA")
7847    msg = get_wsc_msg(dev[0])
7848    if msg['wsc_opcode'] != WSC_NACK:
7849        raise Exception("Unexpected message - expected WSC_Nack")
7850
7851    dev[0].request("WPS_CANCEL")
7852    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7853    dev[0].wait_disconnected()
7854
7855def test_wps_ext_proto_m4_invalid_pad_value(dev, apdev):
7856    """WPS and invalid pad value in M4"""
7857    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s1, m3, authkey, keywrapkey = wps_to_m3(dev, apdev)
7858
7859    logger.debug("Send M4 to STA")
7860    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7861    attrs += build_attr_msg_type(WPS_M4)
7862    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7863    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7864    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7865    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7866
7867    m = hmac.new(authkey, data, hashlib.sha256)
7868    kwa = m.digest()[0:8]
7869    data += build_wsc_attr(ATTR_KEY_WRAP_AUTH, kwa)
7870    iv = 16*b'\x99'
7871    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
7872    pad_len = 16 - len(data) % 16
7873    ps = (pad_len - 1) * struct.pack('B', pad_len) + struct.pack('B', 255)
7874    data += ps
7875    wrapped = aes.encrypt(data)
7876    attrs += build_wsc_attr(ATTR_ENCR_SETTINGS, iv + wrapped)
7877
7878    attrs += build_attr_authenticator(authkey, m3, attrs)
7879    m4 = build_eap_wsc(1, eap_id, attrs)
7880    send_wsc_msg(dev[0], bssid, m4)
7881    eap_id = (eap_id + 1) % 256
7882
7883    logger.debug("Receive M5 (NACK) from STA")
7884    msg = get_wsc_msg(dev[0])
7885    if msg['wsc_opcode'] != WSC_NACK:
7886        raise Exception("Unexpected message - expected WSC_Nack")
7887
7888    dev[0].request("WPS_CANCEL")
7889    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7890    dev[0].wait_disconnected()
7891
7892def test_wps_ext_proto_m4_no_encr_settings(dev, apdev):
7893    """WPS and no Encr Settings in M4"""
7894    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s1, m3, authkey, keywrapkey = wps_to_m3(dev, apdev)
7895
7896    logger.debug("Send M4 to STA")
7897    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7898    attrs += build_attr_msg_type(WPS_M4)
7899    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7900    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7901    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7902    attrs += build_attr_authenticator(authkey, m3, attrs)
7903    m4 = build_eap_wsc(1, eap_id, attrs)
7904    send_wsc_msg(dev[0], bssid, m4)
7905    eap_id = (eap_id + 1) % 256
7906
7907    logger.debug("Receive M5 (NACK) from STA")
7908    msg = get_wsc_msg(dev[0])
7909    if msg['wsc_opcode'] != WSC_NACK:
7910        raise Exception("Unexpected message - expected WSC_Nack")
7911
7912    dev[0].request("WPS_CANCEL")
7913    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7914    dev[0].wait_disconnected()
7915
7916def test_wps_ext_proto_m6_missing_r_snonce2(dev, apdev):
7917    """WPS and no R-SNonce2 in M6"""
7918    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s2, m5, authkey, keywrapkey = wps_to_m5(dev, apdev)
7919
7920    logger.debug("Send M6 to STA")
7921    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7922    attrs += build_attr_msg_type(WPS_M6)
7923    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7924    #data = build_wsc_attr(ATTR_R_SNONCE2, r_s2)
7925    data = b''
7926    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7927    attrs += build_attr_authenticator(authkey, m5, attrs)
7928    m6 = build_eap_wsc(1, eap_id, attrs)
7929    send_wsc_msg(dev[0], bssid, m6)
7930    eap_id = (eap_id + 1) % 256
7931
7932    logger.debug("Receive M7 (NACK) from STA")
7933    msg = get_wsc_msg(dev[0])
7934    if msg['wsc_opcode'] != WSC_NACK:
7935        raise Exception("Unexpected message - expected WSC_Nack")
7936
7937    dev[0].request("WPS_CANCEL")
7938    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7939    dev[0].wait_disconnected()
7940
7941def test_wps_ext_proto_m6_no_encr_settings(dev, apdev):
7942    """WPS and no Encr Settings in M6"""
7943    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s2, m5, authkey, keywrapkey = wps_to_m5(dev, apdev)
7944
7945    logger.debug("Send M6 to STA")
7946    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7947    attrs += build_attr_msg_type(WPS_M6)
7948    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7949    data = build_wsc_attr(ATTR_R_SNONCE2, r_s2)
7950    #attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7951    attrs += build_attr_authenticator(authkey, m5, attrs)
7952    m6 = build_eap_wsc(1, eap_id, attrs)
7953    send_wsc_msg(dev[0], bssid, m6)
7954    eap_id = (eap_id + 1) % 256
7955
7956    logger.debug("Receive M7 (NACK) from STA")
7957    msg = get_wsc_msg(dev[0])
7958    if msg['wsc_opcode'] != WSC_NACK:
7959        raise Exception("Unexpected message - expected WSC_Nack")
7960
7961    dev[0].request("WPS_CANCEL")
7962    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7963    dev[0].wait_disconnected()
7964
7965def test_wps_ext_proto_m8_no_encr_settings(dev, apdev):
7966    """WPS and no Encr Settings in M6"""
7967    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s2, m5, authkey, keywrapkey = wps_to_m5(dev, apdev)
7968
7969    logger.debug("Send M6 to STA")
7970    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7971    attrs += build_attr_msg_type(WPS_M6)
7972    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7973    data = build_wsc_attr(ATTR_R_SNONCE2, r_s2)
7974    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7975    attrs += build_attr_authenticator(authkey, m5, attrs)
7976    raw_m6_attrs = attrs
7977    m6 = build_eap_wsc(1, eap_id, attrs)
7978    send_wsc_msg(dev[0], bssid, m6)
7979    eap_id = (eap_id + 1) % 256
7980
7981    logger.debug("Receive M7 from STA")
7982    msg, m7_attrs, raw_m7_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M7)
7983
7984    logger.debug("Send M8 to STA")
7985    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7986    attrs += build_attr_msg_type(WPS_M8)
7987    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7988    #attrs += build_attr_encr_settings(authkey, keywrapkey, m8_cred)
7989    attrs += build_attr_authenticator(authkey, raw_m7_attrs, attrs)
7990    raw_m8_attrs = attrs
7991    m8 = build_eap_wsc(1, eap_id, attrs)
7992    send_wsc_msg(dev[0], bssid, m8)
7993
7994    logger.debug("Receive WSC_Done (NACK) from STA")
7995    msg = get_wsc_msg(dev[0])
7996    if msg['wsc_opcode'] != WSC_NACK:
7997        raise Exception("Unexpected message - expected WSC_Nack")
7998
7999    dev[0].request("WPS_CANCEL")
8000    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
8001    dev[0].wait_disconnected()
8002
8003def wps_start_ext_reg(apdev, dev):
8004    addr = dev.own_addr()
8005    bssid = apdev['bssid']
8006    ssid = "test-wps-conf"
8007    appin = "12345670"
8008    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
8009              "wpa_passphrase": "12345678", "wpa": "2",
8010              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
8011              "ap_pin": appin}
8012    hapd = hostapd.add_ap(apdev, params)
8013
8014    dev.scan_for_bss(bssid, freq="2412")
8015    hapd.request("SET ext_eapol_frame_io 1")
8016    dev.request("SET ext_eapol_frame_io 1")
8017
8018    dev.request("WPS_REG " + bssid + " " + appin)
8019
8020    return addr, bssid, hapd
8021
8022def wps_run_ap_settings_proto(dev, apdev, ap_settings, success):
8023    addr, bssid, hapd = wps_start_ext_reg(apdev[0], dev[0])
8024    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8025    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8026
8027    logger.debug("Receive M1 from AP")
8028    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M1)
8029    mac_addr = m1_attrs[ATTR_MAC_ADDR]
8030    e_nonce = m1_attrs[ATTR_ENROLLEE_NONCE]
8031    e_pk = m1_attrs[ATTR_PUBLIC_KEY]
8032
8033    appin = '12345670'
8034    uuid_r = 16*b'\x33'
8035    r_nonce = 16*b'\x44'
8036    own_private, r_pk = wsc_dh_init()
8037    authkey, keywrapkey = wsc_dh_kdf(e_pk, own_private, mac_addr, e_nonce,
8038                                     r_nonce)
8039    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, appin, e_pk, r_pk)
8040
8041    logger.debug("Send M2 to AP")
8042    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, msg['eap_identifier'],
8043                                e_nonce, r_nonce, uuid_r, r_pk, eap_code=2)
8044    send_wsc_msg(hapd, addr, m2)
8045
8046    logger.debug("Receive M3 from AP")
8047    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M3)
8048
8049    logger.debug("Send M4 to AP")
8050    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8051    attrs += build_attr_msg_type(WPS_M4)
8052    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
8053    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
8054    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
8055    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
8056    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8057    attrs += build_attr_authenticator(authkey, raw_m3_attrs, attrs)
8058    raw_m4_attrs = attrs
8059    m4 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8060    send_wsc_msg(hapd, addr, m4)
8061
8062    logger.debug("Receive M5 from AP")
8063    msg, m5_attrs, raw_m5_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M5)
8064
8065    logger.debug("Send M6 to STA")
8066    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8067    attrs += build_attr_msg_type(WPS_M6)
8068    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
8069    data = build_wsc_attr(ATTR_R_SNONCE2, r_s2)
8070    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8071    attrs += build_attr_authenticator(authkey, raw_m5_attrs, attrs)
8072    raw_m6_attrs = attrs
8073    m6 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8074    send_wsc_msg(hapd, addr, m6)
8075
8076    logger.debug("Receive M7 from AP")
8077    msg, m7_attrs, raw_m7_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M7)
8078
8079    logger.debug("Send M8 to STA")
8080    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8081    attrs += build_attr_msg_type(WPS_M8)
8082    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
8083    if ap_settings:
8084        attrs += build_attr_encr_settings(authkey, keywrapkey, ap_settings)
8085    attrs += build_attr_authenticator(authkey, raw_m7_attrs, attrs)
8086    raw_m8_attrs = attrs
8087    m8 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8088    send_wsc_msg(hapd, addr, m8)
8089
8090    if success:
8091        ev = hapd.wait_event(["WPS-NEW-AP-SETTINGS"], timeout=5)
8092        if ev is None:
8093            raise Exception("New AP settings not reported")
8094        logger.debug("Receive WSC_Done from AP")
8095        msg = get_wsc_msg(hapd)
8096        if msg['wsc_opcode'] != WSC_Done:
8097            raise Exception("Unexpected message - expected WSC_Done")
8098
8099        logger.debug("Send WSC_ACK to AP")
8100        ack, attrs = build_ack(msg['eap_identifier'], e_nonce, r_nonce,
8101                               eap_code=2)
8102        send_wsc_msg(hapd, addr, ack)
8103        dev[0].wait_disconnected()
8104    else:
8105        ev = hapd.wait_event(["WPS-FAIL"], timeout=5)
8106        if ev is None:
8107            raise Exception("WPS failure not reported")
8108        logger.debug("Receive WSC_NACK from AP")
8109        msg = get_wsc_msg(hapd)
8110        if msg['wsc_opcode'] != WSC_NACK:
8111            raise Exception("Unexpected message - expected WSC_NACK")
8112
8113        logger.debug("Send WSC_NACK to AP")
8114        nack, attrs = build_nack(msg['eap_identifier'], e_nonce, r_nonce,
8115                                 eap_code=2)
8116        send_wsc_msg(hapd, addr, nack)
8117        dev[0].wait_disconnected()
8118
8119def test_wps_ext_ap_settings_success(dev, apdev):
8120    """WPS and AP Settings: success"""
8121    ap_settings = build_wsc_attr(ATTR_NETWORK_INDEX, '\x01')
8122    ap_settings += build_wsc_attr(ATTR_SSID, "test")
8123    ap_settings += build_wsc_attr(ATTR_AUTH_TYPE, '\x00\x01')
8124    ap_settings += build_wsc_attr(ATTR_ENCR_TYPE, '\x00\x01')
8125    ap_settings += build_wsc_attr(ATTR_NETWORK_KEY, '')
8126    ap_settings += build_wsc_attr(ATTR_MAC_ADDR, binascii.unhexlify(apdev[0]['bssid'].replace(':', '')))
8127    wps_run_ap_settings_proto(dev, apdev, ap_settings, True)
8128
8129@remote_compatible
8130def test_wps_ext_ap_settings_missing(dev, apdev):
8131    """WPS and AP Settings: missing"""
8132    wps_run_ap_settings_proto(dev, apdev, None, False)
8133
8134@remote_compatible
8135def test_wps_ext_ap_settings_mac_addr_mismatch(dev, apdev):
8136    """WPS and AP Settings: MAC Address mismatch"""
8137    ap_settings = build_wsc_attr(ATTR_NETWORK_INDEX, '\x01')
8138    ap_settings += build_wsc_attr(ATTR_SSID, "test")
8139    ap_settings += build_wsc_attr(ATTR_AUTH_TYPE, '\x00\x01')
8140    ap_settings += build_wsc_attr(ATTR_ENCR_TYPE, '\x00\x01')
8141    ap_settings += build_wsc_attr(ATTR_NETWORK_KEY, '')
8142    ap_settings += build_wsc_attr(ATTR_MAC_ADDR, '\x00\x00\x00\x00\x00\x00')
8143    wps_run_ap_settings_proto(dev, apdev, ap_settings, True)
8144
8145@remote_compatible
8146def test_wps_ext_ap_settings_mac_addr_missing(dev, apdev):
8147    """WPS and AP Settings: missing MAC Address"""
8148    ap_settings = build_wsc_attr(ATTR_NETWORK_INDEX, '\x01')
8149    ap_settings += build_wsc_attr(ATTR_SSID, "test")
8150    ap_settings += build_wsc_attr(ATTR_AUTH_TYPE, '\x00\x01')
8151    ap_settings += build_wsc_attr(ATTR_ENCR_TYPE, '\x00\x01')
8152    ap_settings += build_wsc_attr(ATTR_NETWORK_KEY, '')
8153    wps_run_ap_settings_proto(dev, apdev, ap_settings, False)
8154
8155@remote_compatible
8156def test_wps_ext_ap_settings_reject_encr_type(dev, apdev):
8157    """WPS and AP Settings: reject Encr Type"""
8158    ap_settings = build_wsc_attr(ATTR_NETWORK_INDEX, '\x01')
8159    ap_settings += build_wsc_attr(ATTR_SSID, "test")
8160    ap_settings += build_wsc_attr(ATTR_AUTH_TYPE, '\x00\x01')
8161    ap_settings += build_wsc_attr(ATTR_ENCR_TYPE, '\x00\x00')
8162    ap_settings += build_wsc_attr(ATTR_NETWORK_KEY, '')
8163    ap_settings += build_wsc_attr(ATTR_MAC_ADDR, binascii.unhexlify(apdev[0]['bssid'].replace(':', '')))
8164    wps_run_ap_settings_proto(dev, apdev, ap_settings, False)
8165
8166@remote_compatible
8167def test_wps_ext_ap_settings_m2d(dev, apdev):
8168    """WPS and AP Settings: M2D"""
8169    addr, bssid, hapd = wps_start_ext_reg(apdev[0], dev[0])
8170    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8171    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8172
8173    logger.debug("Receive M1 from AP")
8174    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M1)
8175    e_nonce = m1_attrs[ATTR_ENROLLEE_NONCE]
8176
8177    r_nonce = 16*'\x44'
8178    uuid_r = 16*'\x33'
8179
8180    logger.debug("Send M2D to AP")
8181    m2d, raw_m2d_attrs = build_m2d(raw_m1_attrs, msg['eap_identifier'],
8182                                   e_nonce, r_nonce, uuid_r,
8183                                   dev_pw_id='\x00\x00', eap_code=2)
8184    send_wsc_msg(hapd, addr, m2d)
8185
8186    ev = hapd.wait_event(["WPS-M2D"], timeout=5)
8187    if ev is None:
8188        raise Exception("M2D not reported")
8189
8190    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8191
8192def wps_wait_ap_nack(hapd, dev, e_nonce, r_nonce):
8193    logger.debug("Receive WSC_NACK from AP")
8194    msg = get_wsc_msg(hapd)
8195    if msg['wsc_opcode'] != WSC_NACK:
8196        raise Exception("Unexpected message - expected WSC_NACK")
8197
8198    logger.debug("Send WSC_NACK to AP")
8199    nack, attrs = build_nack(msg['eap_identifier'], e_nonce, r_nonce,
8200                             eap_code=2)
8201    send_wsc_msg(hapd, dev.own_addr(), nack)
8202    dev.wait_disconnected()
8203
8204@remote_compatible
8205def test_wps_ext_m3_missing_e_hash1(dev, apdev):
8206    """WPS proto: M3 missing E-Hash1"""
8207    pin = "12345670"
8208    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8209    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8210    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8211
8212    logger.debug("Receive WSC/Start from AP")
8213    msg = get_wsc_msg(hapd)
8214    if msg['wsc_opcode'] != WSC_Start:
8215        raise Exception("Unexpected Op-Code for WSC/Start")
8216
8217    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8218    uuid_e = 16*b'\x11'
8219    e_nonce = 16*b'\x22'
8220    own_private, e_pk = wsc_dh_init()
8221
8222    logger.debug("Send M1 to AP")
8223    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8224                                e_nonce, e_pk)
8225    send_wsc_msg(hapd, addr, m1)
8226
8227    logger.debug("Receive M2 from AP")
8228    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8229    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8230    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8231
8232    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8233                                     r_nonce)
8234    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8235
8236    logger.debug("Send M3 to AP")
8237    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8238    attrs += build_attr_msg_type(WPS_M3)
8239    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8240    #attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8241    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8242    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8243    raw_m3_attrs = attrs
8244    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8245    send_wsc_msg(hapd, addr, m3)
8246
8247    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8248
8249@remote_compatible
8250def test_wps_ext_m3_missing_e_hash2(dev, apdev):
8251    """WPS proto: M3 missing E-Hash2"""
8252    pin = "12345670"
8253    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8254    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8255    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8256
8257    logger.debug("Receive WSC/Start from AP")
8258    msg = get_wsc_msg(hapd)
8259    if msg['wsc_opcode'] != WSC_Start:
8260        raise Exception("Unexpected Op-Code for WSC/Start")
8261
8262    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8263    uuid_e = 16*b'\x11'
8264    e_nonce = 16*b'\x22'
8265    own_private, e_pk = wsc_dh_init()
8266
8267    logger.debug("Send M1 to AP")
8268    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8269                                e_nonce, e_pk)
8270    send_wsc_msg(hapd, addr, m1)
8271
8272    logger.debug("Receive M2 from AP")
8273    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8274    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8275    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8276
8277    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8278                                     r_nonce)
8279    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8280
8281    logger.debug("Send M3 to AP")
8282    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8283    attrs += build_attr_msg_type(WPS_M3)
8284    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8285    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8286    #attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8287    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8288    raw_m3_attrs = attrs
8289    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8290    send_wsc_msg(hapd, addr, m3)
8291
8292    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8293
8294@remote_compatible
8295def test_wps_ext_m5_missing_e_snonce1(dev, apdev):
8296    """WPS proto: M5 missing E-SNonce1"""
8297    pin = "12345670"
8298    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8299    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8300    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8301
8302    logger.debug("Receive WSC/Start from AP")
8303    msg = get_wsc_msg(hapd)
8304    if msg['wsc_opcode'] != WSC_Start:
8305        raise Exception("Unexpected Op-Code for WSC/Start")
8306
8307    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8308    uuid_e = 16*b'\x11'
8309    e_nonce = 16*b'\x22'
8310    own_private, e_pk = wsc_dh_init()
8311
8312    logger.debug("Send M1 to AP")
8313    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8314                                e_nonce, e_pk)
8315    send_wsc_msg(hapd, addr, m1)
8316
8317    logger.debug("Receive M2 from AP")
8318    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8319    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8320    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8321
8322    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8323                                     r_nonce)
8324    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8325
8326    logger.debug("Send M3 to AP")
8327    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8328    attrs += build_attr_msg_type(WPS_M3)
8329    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8330    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8331    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8332    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8333    raw_m3_attrs = attrs
8334    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8335    send_wsc_msg(hapd, addr, m3)
8336
8337    logger.debug("Receive M4 from AP")
8338    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
8339
8340    logger.debug("Send M5 to AP")
8341    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8342    attrs += build_attr_msg_type(WPS_M5)
8343    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8344    #data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
8345    data = b''
8346    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8347    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
8348    raw_m5_attrs = attrs
8349    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8350    send_wsc_msg(hapd, addr, m5)
8351
8352    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8353
8354@remote_compatible
8355def test_wps_ext_m5_e_snonce1_mismatch(dev, apdev):
8356    """WPS proto: M5 E-SNonce1 mismatch"""
8357    pin = "12345670"
8358    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8359    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8360    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8361
8362    logger.debug("Receive WSC/Start from AP")
8363    msg = get_wsc_msg(hapd)
8364    if msg['wsc_opcode'] != WSC_Start:
8365        raise Exception("Unexpected Op-Code for WSC/Start")
8366
8367    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8368    uuid_e = 16*b'\x11'
8369    e_nonce = 16*b'\x22'
8370    own_private, e_pk = wsc_dh_init()
8371
8372    logger.debug("Send M1 to AP")
8373    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8374                                e_nonce, e_pk)
8375    send_wsc_msg(hapd, addr, m1)
8376
8377    logger.debug("Receive M2 from AP")
8378    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8379    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8380    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8381
8382    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8383                                     r_nonce)
8384    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8385
8386    logger.debug("Send M3 to AP")
8387    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8388    attrs += build_attr_msg_type(WPS_M3)
8389    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8390    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8391    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8392    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8393    raw_m3_attrs = attrs
8394    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8395    send_wsc_msg(hapd, addr, m3)
8396
8397    logger.debug("Receive M4 from AP")
8398    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
8399
8400    logger.debug("Send M5 to AP")
8401    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8402    attrs += build_attr_msg_type(WPS_M5)
8403    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8404    data = build_wsc_attr(ATTR_E_SNONCE1, 16*'\x00')
8405    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8406    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
8407    raw_m5_attrs = attrs
8408    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8409    send_wsc_msg(hapd, addr, m5)
8410
8411    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8412
8413def test_wps_ext_m7_missing_e_snonce2(dev, apdev):
8414    """WPS proto: M7 missing E-SNonce2"""
8415    pin = "12345670"
8416    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8417    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8418    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8419
8420    logger.debug("Receive WSC/Start from AP")
8421    msg = get_wsc_msg(hapd)
8422    if msg['wsc_opcode'] != WSC_Start:
8423        raise Exception("Unexpected Op-Code for WSC/Start")
8424
8425    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8426    uuid_e = 16*b'\x11'
8427    e_nonce = 16*b'\x22'
8428    own_private, e_pk = wsc_dh_init()
8429
8430    logger.debug("Send M1 to AP")
8431    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8432                                e_nonce, e_pk)
8433    send_wsc_msg(hapd, addr, m1)
8434
8435    logger.debug("Receive M2 from AP")
8436    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8437    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8438    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8439
8440    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8441                                     r_nonce)
8442    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8443
8444    logger.debug("Send M3 to AP")
8445    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8446    attrs += build_attr_msg_type(WPS_M3)
8447    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8448    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8449    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8450    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8451    raw_m3_attrs = attrs
8452    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8453    send_wsc_msg(hapd, addr, m3)
8454
8455    logger.debug("Receive M4 from AP")
8456    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
8457
8458    logger.debug("Send M5 to AP")
8459    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8460    attrs += build_attr_msg_type(WPS_M5)
8461    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8462    data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
8463    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8464    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
8465    raw_m5_attrs = attrs
8466    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8467    send_wsc_msg(hapd, addr, m5)
8468
8469    logger.debug("Receive M6 from AP")
8470    msg, m6_attrs, raw_m6_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M6)
8471
8472    logger.debug("Send M7 to AP")
8473    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8474    attrs += build_attr_msg_type(WPS_M7)
8475    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8476    #data = build_wsc_attr(ATTR_E_SNONCE2, e_s2)
8477    data = b''
8478    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8479    attrs += build_attr_authenticator(authkey, raw_m6_attrs, attrs)
8480    m7 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8481    raw_m7_attrs = attrs
8482    send_wsc_msg(hapd, addr, m7)
8483
8484    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8485
8486@remote_compatible
8487def test_wps_ext_m7_e_snonce2_mismatch(dev, apdev):
8488    """WPS proto: M7 E-SNonce2 mismatch"""
8489    pin = "12345670"
8490    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8491    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8492    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8493
8494    logger.debug("Receive WSC/Start from AP")
8495    msg = get_wsc_msg(hapd)
8496    if msg['wsc_opcode'] != WSC_Start:
8497        raise Exception("Unexpected Op-Code for WSC/Start")
8498
8499    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8500    uuid_e = 16*b'\x11'
8501    e_nonce = 16*b'\x22'
8502    own_private, e_pk = wsc_dh_init()
8503
8504    logger.debug("Send M1 to AP")
8505    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8506                                e_nonce, e_pk)
8507    send_wsc_msg(hapd, addr, m1)
8508
8509    logger.debug("Receive M2 from AP")
8510    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8511    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8512    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8513
8514    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8515                                     r_nonce)
8516    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8517
8518    logger.debug("Send M3 to AP")
8519    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8520    attrs += build_attr_msg_type(WPS_M3)
8521    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8522    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8523    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8524    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8525    raw_m3_attrs = attrs
8526    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8527    send_wsc_msg(hapd, addr, m3)
8528
8529    logger.debug("Receive M4 from AP")
8530    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
8531
8532    logger.debug("Send M5 to AP")
8533    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8534    attrs += build_attr_msg_type(WPS_M5)
8535    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8536    data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
8537    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8538    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
8539    raw_m5_attrs = attrs
8540    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8541    send_wsc_msg(hapd, addr, m5)
8542
8543    logger.debug("Receive M6 from AP")
8544    msg, m6_attrs, raw_m6_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M6)
8545
8546    logger.debug("Send M7 to AP")
8547    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8548    attrs += build_attr_msg_type(WPS_M7)
8549    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8550    data = build_wsc_attr(ATTR_E_SNONCE2, 16*'\x00')
8551    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8552    attrs += build_attr_authenticator(authkey, raw_m6_attrs, attrs)
8553    m7 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8554    raw_m7_attrs = attrs
8555    send_wsc_msg(hapd, addr, m7)
8556
8557    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8558
8559@remote_compatible
8560def test_wps_ext_m1_pubkey_oom(dev, apdev):
8561    """WPS proto: M1 PubKey OOM"""
8562    pin = "12345670"
8563    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8564    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8565    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8566
8567    logger.debug("Receive WSC/Start from AP")
8568    msg = get_wsc_msg(hapd)
8569    if msg['wsc_opcode'] != WSC_Start:
8570        raise Exception("Unexpected Op-Code for WSC/Start")
8571
8572    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8573    uuid_e = 16*'\x11'
8574    e_nonce = 16*'\x22'
8575    own_private, e_pk = wsc_dh_init()
8576
8577    logger.debug("Send M1 to AP")
8578    with alloc_fail(hapd, 1, "wpabuf_alloc_copy;wps_process_pubkey"):
8579        m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8580                                    e_nonce, e_pk)
8581        send_wsc_msg(hapd, addr, m1)
8582        wps_wait_eap_failure(hapd, dev[0])
8583
8584def wps_wait_eap_failure(hapd, dev):
8585    ev = hapd.wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
8586    if ev is None:
8587        raise Exception("EAP-Failure not reported")
8588    dev.wait_disconnected()
8589
8590@remote_compatible
8591def test_wps_ext_m3_m1(dev, apdev):
8592    """WPS proto: M3 replaced with M1"""
8593    pin = "12345670"
8594    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8595    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8596    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8597
8598    logger.debug("Receive WSC/Start from AP")
8599    msg = get_wsc_msg(hapd)
8600    if msg['wsc_opcode'] != WSC_Start:
8601        raise Exception("Unexpected Op-Code for WSC/Start")
8602
8603    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8604    uuid_e = 16*b'\x11'
8605    e_nonce = 16*b'\x22'
8606    own_private, e_pk = wsc_dh_init()
8607
8608    logger.debug("Send M1 to AP")
8609    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8610                                e_nonce, e_pk)
8611    send_wsc_msg(hapd, addr, m1)
8612
8613    logger.debug("Receive M2 from AP")
8614    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8615    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8616    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8617
8618    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8619                                     r_nonce)
8620    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8621
8622    logger.debug("Send M3(M1) to AP")
8623    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8624    attrs += build_attr_msg_type(WPS_M1)
8625    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8626    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8627    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8628    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8629    raw_m3_attrs = attrs
8630    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8631    send_wsc_msg(hapd, addr, m3)
8632
8633    wps_wait_eap_failure(hapd, dev[0])
8634
8635@remote_compatible
8636def test_wps_ext_m5_m3(dev, apdev):
8637    """WPS proto: M5 replaced with M3"""
8638    pin = "12345670"
8639    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8640    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8641    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8642
8643    logger.debug("Receive WSC/Start from AP")
8644    msg = get_wsc_msg(hapd)
8645    if msg['wsc_opcode'] != WSC_Start:
8646        raise Exception("Unexpected Op-Code for WSC/Start")
8647
8648    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8649    uuid_e = 16*b'\x11'
8650    e_nonce = 16*b'\x22'
8651    own_private, e_pk = wsc_dh_init()
8652
8653    logger.debug("Send M1 to AP")
8654    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8655                                e_nonce, e_pk)
8656    send_wsc_msg(hapd, addr, m1)
8657
8658    logger.debug("Receive M2 from AP")
8659    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8660    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8661    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8662
8663    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8664                                     r_nonce)
8665    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8666
8667    logger.debug("Send M3 to AP")
8668    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8669    attrs += build_attr_msg_type(WPS_M3)
8670    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8671    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8672    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8673    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8674    raw_m3_attrs = attrs
8675    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8676    send_wsc_msg(hapd, addr, m3)
8677
8678    logger.debug("Receive M4 from AP")
8679    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
8680
8681    logger.debug("Send M5(M3) to AP")
8682    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8683    attrs += build_attr_msg_type(WPS_M3)
8684    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8685    data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
8686    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8687    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
8688    raw_m5_attrs = attrs
8689    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8690    send_wsc_msg(hapd, addr, m5)
8691
8692    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8693
8694@remote_compatible
8695def test_wps_ext_m3_m2(dev, apdev):
8696    """WPS proto: M3 replaced with M2"""
8697    pin = "12345670"
8698    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8699    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8700    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8701
8702    logger.debug("Receive WSC/Start from AP")
8703    msg = get_wsc_msg(hapd)
8704    if msg['wsc_opcode'] != WSC_Start:
8705        raise Exception("Unexpected Op-Code for WSC/Start")
8706
8707    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8708    uuid_e = 16*b'\x11'
8709    e_nonce = 16*b'\x22'
8710    own_private, e_pk = wsc_dh_init()
8711
8712    logger.debug("Send M1 to AP")
8713    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8714                                e_nonce, e_pk)
8715    send_wsc_msg(hapd, addr, m1)
8716
8717    logger.debug("Receive M2 from AP")
8718    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8719    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8720    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8721
8722    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8723                                     r_nonce)
8724    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8725
8726    logger.debug("Send M3(M2) to AP")
8727    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8728    attrs += build_attr_msg_type(WPS_M2)
8729    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8730    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8731    raw_m3_attrs = attrs
8732    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8733    send_wsc_msg(hapd, addr, m3)
8734
8735    wps_wait_eap_failure(hapd, dev[0])
8736
8737@remote_compatible
8738def test_wps_ext_m3_m5(dev, apdev):
8739    """WPS proto: M3 replaced with M5"""
8740    pin = "12345670"
8741    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8742    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8743    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8744
8745    logger.debug("Receive WSC/Start from AP")
8746    msg = get_wsc_msg(hapd)
8747    if msg['wsc_opcode'] != WSC_Start:
8748        raise Exception("Unexpected Op-Code for WSC/Start")
8749
8750    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8751    uuid_e = 16*b'\x11'
8752    e_nonce = 16*b'\x22'
8753    own_private, e_pk = wsc_dh_init()
8754
8755    logger.debug("Send M1 to AP")
8756    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8757                                e_nonce, e_pk)
8758    send_wsc_msg(hapd, addr, m1)
8759
8760    logger.debug("Receive M2 from AP")
8761    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8762    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8763    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8764
8765    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8766                                     r_nonce)
8767    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8768
8769    logger.debug("Send M3(M5) to AP")
8770    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8771    attrs += build_attr_msg_type(WPS_M5)
8772    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8773    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8774    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8775    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8776    raw_m3_attrs = attrs
8777    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8778    send_wsc_msg(hapd, addr, m3)
8779
8780    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8781
8782@remote_compatible
8783def test_wps_ext_m3_m7(dev, apdev):
8784    """WPS proto: M3 replaced with M7"""
8785    pin = "12345670"
8786    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8787    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8788    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8789
8790    logger.debug("Receive WSC/Start from AP")
8791    msg = get_wsc_msg(hapd)
8792    if msg['wsc_opcode'] != WSC_Start:
8793        raise Exception("Unexpected Op-Code for WSC/Start")
8794
8795    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8796    uuid_e = 16*b'\x11'
8797    e_nonce = 16*b'\x22'
8798    own_private, e_pk = wsc_dh_init()
8799
8800    logger.debug("Send M1 to AP")
8801    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8802                                e_nonce, e_pk)
8803    send_wsc_msg(hapd, addr, m1)
8804
8805    logger.debug("Receive M2 from AP")
8806    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8807    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8808    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8809
8810    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8811                                     r_nonce)
8812    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8813
8814    logger.debug("Send M3(M7) to AP")
8815    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8816    attrs += build_attr_msg_type(WPS_M7)
8817    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8818    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8819    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8820    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8821    raw_m3_attrs = attrs
8822    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8823    send_wsc_msg(hapd, addr, m3)
8824
8825    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8826
8827@remote_compatible
8828def test_wps_ext_m3_done(dev, apdev):
8829    """WPS proto: M3 replaced with WSC_Done"""
8830    pin = "12345670"
8831    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8832    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8833    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8834
8835    logger.debug("Receive WSC/Start from AP")
8836    msg = get_wsc_msg(hapd)
8837    if msg['wsc_opcode'] != WSC_Start:
8838        raise Exception("Unexpected Op-Code for WSC/Start")
8839
8840    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8841    uuid_e = 16*b'\x11'
8842    e_nonce = 16*b'\x22'
8843    own_private, e_pk = wsc_dh_init()
8844
8845    logger.debug("Send M1 to AP")
8846    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8847                                e_nonce, e_pk)
8848    send_wsc_msg(hapd, addr, m1)
8849
8850    logger.debug("Receive M2 from AP")
8851    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8852    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8853    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8854
8855    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8856                                     r_nonce)
8857    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8858
8859    logger.debug("Send M3(WSC_Done) to AP")
8860    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8861    attrs += build_attr_msg_type(WPS_WSC_DONE)
8862    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8863    raw_m3_attrs = attrs
8864    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
8865    send_wsc_msg(hapd, addr, m3)
8866
8867    wps_wait_eap_failure(hapd, dev[0])
8868
8869@remote_compatible
8870def test_wps_ext_m2_nack_invalid(dev, apdev):
8871    """WPS proto: M2 followed by invalid NACK"""
8872    pin = "12345670"
8873    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8874    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8875    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8876
8877    logger.debug("Receive WSC/Start from AP")
8878    msg = get_wsc_msg(hapd)
8879    if msg['wsc_opcode'] != WSC_Start:
8880        raise Exception("Unexpected Op-Code for WSC/Start")
8881
8882    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8883    uuid_e = 16*b'\x11'
8884    e_nonce = 16*b'\x22'
8885    own_private, e_pk = wsc_dh_init()
8886
8887    logger.debug("Send M1 to AP")
8888    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8889                                e_nonce, e_pk)
8890    send_wsc_msg(hapd, addr, m1)
8891
8892    logger.debug("Receive M2 from AP")
8893    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8894    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8895    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8896
8897    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8898                                     r_nonce)
8899    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8900
8901    logger.debug("Send WSC_NACK to AP")
8902    attrs = b'\x10\x00\x00'
8903    nack = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_NACK)
8904    send_wsc_msg(hapd, addr, nack)
8905
8906    wps_wait_eap_failure(hapd, dev[0])
8907
8908@remote_compatible
8909def test_wps_ext_m2_nack_no_msg_type(dev, apdev):
8910    """WPS proto: M2 followed by NACK without Msg Type"""
8911    pin = "12345670"
8912    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8913    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8914    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8915
8916    logger.debug("Receive WSC/Start from AP")
8917    msg = get_wsc_msg(hapd)
8918    if msg['wsc_opcode'] != WSC_Start:
8919        raise Exception("Unexpected Op-Code for WSC/Start")
8920
8921    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8922    uuid_e = 16*b'\x11'
8923    e_nonce = 16*b'\x22'
8924    own_private, e_pk = wsc_dh_init()
8925
8926    logger.debug("Send M1 to AP")
8927    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8928                                e_nonce, e_pk)
8929    send_wsc_msg(hapd, addr, m1)
8930
8931    logger.debug("Receive M2 from AP")
8932    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8933    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8934    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8935
8936    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8937                                     r_nonce)
8938    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8939
8940    logger.debug("Send WSC_NACK to AP")
8941    nack, attrs = build_nack(msg['eap_identifier'], e_nonce, r_nonce,
8942                             msg_type=None, eap_code=2)
8943    send_wsc_msg(hapd, addr, nack)
8944
8945    wps_wait_eap_failure(hapd, dev[0])
8946
8947@remote_compatible
8948def test_wps_ext_m2_nack_invalid_msg_type(dev, apdev):
8949    """WPS proto: M2 followed by NACK with invalid Msg Type"""
8950    pin = "12345670"
8951    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8952    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8953    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8954
8955    logger.debug("Receive WSC/Start from AP")
8956    msg = get_wsc_msg(hapd)
8957    if msg['wsc_opcode'] != WSC_Start:
8958        raise Exception("Unexpected Op-Code for WSC/Start")
8959
8960    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8961    uuid_e = 16*b'\x11'
8962    e_nonce = 16*b'\x22'
8963    own_private, e_pk = wsc_dh_init()
8964
8965    logger.debug("Send M1 to AP")
8966    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8967                                e_nonce, e_pk)
8968    send_wsc_msg(hapd, addr, m1)
8969
8970    logger.debug("Receive M2 from AP")
8971    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8972    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8973    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8974
8975    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8976                                     r_nonce)
8977    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8978
8979    logger.debug("Send WSC_NACK to AP")
8980    nack, attrs = build_nack(msg['eap_identifier'], e_nonce, r_nonce,
8981                             msg_type=WPS_WSC_ACK, eap_code=2)
8982    send_wsc_msg(hapd, addr, nack)
8983
8984    wps_wait_eap_failure(hapd, dev[0])
8985
8986@remote_compatible
8987def test_wps_ext_m2_nack_e_nonce_mismatch(dev, apdev):
8988    """WPS proto: M2 followed by NACK with e-nonce mismatch"""
8989    pin = "12345670"
8990    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8991    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8992    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8993
8994    logger.debug("Receive WSC/Start from AP")
8995    msg = get_wsc_msg(hapd)
8996    if msg['wsc_opcode'] != WSC_Start:
8997        raise Exception("Unexpected Op-Code for WSC/Start")
8998
8999    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9000    uuid_e = 16*b'\x11'
9001    e_nonce = 16*b'\x22'
9002    own_private, e_pk = wsc_dh_init()
9003
9004    logger.debug("Send M1 to AP")
9005    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9006                                e_nonce, e_pk)
9007    send_wsc_msg(hapd, addr, m1)
9008
9009    logger.debug("Receive M2 from AP")
9010    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9011    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9012    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9013
9014    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9015                                     r_nonce)
9016    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9017
9018    logger.debug("Send WSC_NACK to AP")
9019    nack, attrs = build_nack(msg['eap_identifier'], 16*b'\x00', r_nonce,
9020                             eap_code=2)
9021    send_wsc_msg(hapd, addr, nack)
9022
9023    wps_wait_eap_failure(hapd, dev[0])
9024
9025@remote_compatible
9026def test_wps_ext_m2_nack_no_config_error(dev, apdev):
9027    """WPS proto: M2 followed by NACK without Config Error"""
9028    pin = "12345670"
9029    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9030    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9031    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9032
9033    logger.debug("Receive WSC/Start from AP")
9034    msg = get_wsc_msg(hapd)
9035    if msg['wsc_opcode'] != WSC_Start:
9036        raise Exception("Unexpected Op-Code for WSC/Start")
9037
9038    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9039    uuid_e = 16*b'\x11'
9040    e_nonce = 16*b'\x22'
9041    own_private, e_pk = wsc_dh_init()
9042
9043    logger.debug("Send M1 to AP")
9044    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9045                                e_nonce, e_pk)
9046    send_wsc_msg(hapd, addr, m1)
9047
9048    logger.debug("Receive M2 from AP")
9049    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9050    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9051    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9052
9053    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9054                                     r_nonce)
9055    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9056
9057    logger.debug("Send WSC_NACK to AP")
9058    nack, attrs = build_nack(msg['eap_identifier'], e_nonce, r_nonce,
9059                             config_error=None, eap_code=2)
9060    send_wsc_msg(hapd, addr, nack)
9061
9062    wps_wait_eap_failure(hapd, dev[0])
9063
9064@remote_compatible
9065def test_wps_ext_m2_ack_invalid(dev, apdev):
9066    """WPS proto: M2 followed by invalid ACK"""
9067    pin = "12345670"
9068    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9069    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9070    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9071
9072    logger.debug("Receive WSC/Start from AP")
9073    msg = get_wsc_msg(hapd)
9074    if msg['wsc_opcode'] != WSC_Start:
9075        raise Exception("Unexpected Op-Code for WSC/Start")
9076
9077    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9078    uuid_e = 16*b'\x11'
9079    e_nonce = 16*b'\x22'
9080    own_private, e_pk = wsc_dh_init()
9081
9082    logger.debug("Send M1 to AP")
9083    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9084                                e_nonce, e_pk)
9085    send_wsc_msg(hapd, addr, m1)
9086
9087    logger.debug("Receive M2 from AP")
9088    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9089    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9090    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9091
9092    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9093                                     r_nonce)
9094    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9095
9096    logger.debug("Send WSC_ACK to AP")
9097    attrs = b'\x10\x00\x00'
9098    ack = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_ACK)
9099    send_wsc_msg(hapd, addr, ack)
9100
9101    wps_wait_eap_failure(hapd, dev[0])
9102
9103@remote_compatible
9104def test_wps_ext_m2_ack(dev, apdev):
9105    """WPS proto: M2 followed by ACK"""
9106    pin = "12345670"
9107    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9108    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9109    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9110
9111    logger.debug("Receive WSC/Start from AP")
9112    msg = get_wsc_msg(hapd)
9113    if msg['wsc_opcode'] != WSC_Start:
9114        raise Exception("Unexpected Op-Code for WSC/Start")
9115
9116    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9117    uuid_e = 16*b'\x11'
9118    e_nonce = 16*b'\x22'
9119    own_private, e_pk = wsc_dh_init()
9120
9121    logger.debug("Send M1 to AP")
9122    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9123                                e_nonce, e_pk)
9124    send_wsc_msg(hapd, addr, m1)
9125
9126    logger.debug("Receive M2 from AP")
9127    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9128    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9129    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9130
9131    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9132                                     r_nonce)
9133    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9134
9135    logger.debug("Send WSC_ACK to AP")
9136    ack, attrs = build_ack(msg['eap_identifier'], e_nonce, r_nonce, eap_code=2)
9137    send_wsc_msg(hapd, addr, ack)
9138
9139    wps_wait_eap_failure(hapd, dev[0])
9140
9141@remote_compatible
9142def test_wps_ext_m2_ack_no_msg_type(dev, apdev):
9143    """WPS proto: M2 followed by ACK missing Msg Type"""
9144    pin = "12345670"
9145    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9146    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9147    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9148
9149    logger.debug("Receive WSC/Start from AP")
9150    msg = get_wsc_msg(hapd)
9151    if msg['wsc_opcode'] != WSC_Start:
9152        raise Exception("Unexpected Op-Code for WSC/Start")
9153
9154    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9155    uuid_e = 16*b'\x11'
9156    e_nonce = 16*b'\x22'
9157    own_private, e_pk = wsc_dh_init()
9158
9159    logger.debug("Send M1 to AP")
9160    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9161                                e_nonce, e_pk)
9162    send_wsc_msg(hapd, addr, m1)
9163
9164    logger.debug("Receive M2 from AP")
9165    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9166    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9167    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9168
9169    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9170                                     r_nonce)
9171    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9172
9173    logger.debug("Send WSC_ACK to AP")
9174    ack, attrs = build_ack(msg['eap_identifier'], e_nonce, r_nonce,
9175                           msg_type=None, eap_code=2)
9176    send_wsc_msg(hapd, addr, ack)
9177
9178    wps_wait_eap_failure(hapd, dev[0])
9179
9180@remote_compatible
9181def test_wps_ext_m2_ack_invalid_msg_type(dev, apdev):
9182    """WPS proto: M2 followed by ACK with invalid Msg Type"""
9183    pin = "12345670"
9184    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9185    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9186    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9187
9188    logger.debug("Receive WSC/Start from AP")
9189    msg = get_wsc_msg(hapd)
9190    if msg['wsc_opcode'] != WSC_Start:
9191        raise Exception("Unexpected Op-Code for WSC/Start")
9192
9193    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9194    uuid_e = 16*b'\x11'
9195    e_nonce = 16*b'\x22'
9196    own_private, e_pk = wsc_dh_init()
9197
9198    logger.debug("Send M1 to AP")
9199    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9200                                e_nonce, e_pk)
9201    send_wsc_msg(hapd, addr, m1)
9202
9203    logger.debug("Receive M2 from AP")
9204    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9205    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9206    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9207
9208    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9209                                     r_nonce)
9210    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9211
9212    logger.debug("Send WSC_ACK to AP")
9213    ack, attrs = build_ack(msg['eap_identifier'], e_nonce, r_nonce,
9214                          msg_type=WPS_WSC_NACK, eap_code=2)
9215    send_wsc_msg(hapd, addr, ack)
9216
9217    wps_wait_eap_failure(hapd, dev[0])
9218
9219@remote_compatible
9220def test_wps_ext_m2_ack_e_nonce_mismatch(dev, apdev):
9221    """WPS proto: M2 followed by ACK with e-nonce mismatch"""
9222    pin = "12345670"
9223    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9224    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9225    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9226
9227    logger.debug("Receive WSC/Start from AP")
9228    msg = get_wsc_msg(hapd)
9229    if msg['wsc_opcode'] != WSC_Start:
9230        raise Exception("Unexpected Op-Code for WSC/Start")
9231
9232    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9233    uuid_e = 16*b'\x11'
9234    e_nonce = 16*b'\x22'
9235    own_private, e_pk = wsc_dh_init()
9236
9237    logger.debug("Send M1 to AP")
9238    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9239                                e_nonce, e_pk)
9240    send_wsc_msg(hapd, addr, m1)
9241
9242    logger.debug("Receive M2 from AP")
9243    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9244    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9245    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9246
9247    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9248                                     r_nonce)
9249    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9250
9251    logger.debug("Send WSC_ACK to AP")
9252    ack, attrs = build_ack(msg['eap_identifier'], 16*b'\x00', r_nonce,
9253                           eap_code=2)
9254    send_wsc_msg(hapd, addr, ack)
9255
9256    wps_wait_eap_failure(hapd, dev[0])
9257
9258@remote_compatible
9259def test_wps_ext_m1_invalid(dev, apdev):
9260    """WPS proto: M1 failing parsing"""
9261    pin = "12345670"
9262    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9263    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9264    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9265
9266    logger.debug("Receive WSC/Start from AP")
9267    msg = get_wsc_msg(hapd)
9268    if msg['wsc_opcode'] != WSC_Start:
9269        raise Exception("Unexpected Op-Code for WSC/Start")
9270
9271    logger.debug("Send M1 to AP")
9272    attrs = b'\x10\x00\x00'
9273    m1 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9274    send_wsc_msg(hapd, addr, m1)
9275
9276    wps_wait_eap_failure(hapd, dev[0])
9277
9278def test_wps_ext_m1_missing_msg_type(dev, apdev):
9279    """WPS proto: M1 missing Msg Type"""
9280    pin = "12345670"
9281    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9282    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9283    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9284
9285    logger.debug("Receive WSC/Start from AP")
9286    msg = get_wsc_msg(hapd)
9287    if msg['wsc_opcode'] != WSC_Start:
9288        raise Exception("Unexpected Op-Code for WSC/Start")
9289
9290    logger.debug("Send M1 to AP")
9291    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9292    m1 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9293    send_wsc_msg(hapd, addr, m1)
9294
9295    wps_wait_ap_nack(hapd, dev[0], 16*b'\x00', 16*b'\x00')
9296
9297def wps_ext_wsc_done(dev, apdev):
9298    pin = "12345670"
9299    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9300    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9301    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9302
9303    logger.debug("Receive WSC/Start from AP")
9304    msg = get_wsc_msg(hapd)
9305    if msg['wsc_opcode'] != WSC_Start:
9306        raise Exception("Unexpected Op-Code for WSC/Start")
9307
9308    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9309    uuid_e = 16*b'\x11'
9310    e_nonce = 16*b'\x22'
9311    own_private, e_pk = wsc_dh_init()
9312
9313    logger.debug("Send M1 to AP")
9314    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9315                                e_nonce, e_pk)
9316    send_wsc_msg(hapd, addr, m1)
9317
9318    logger.debug("Receive M2 from AP")
9319    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9320    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9321    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9322
9323    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9324                                     r_nonce)
9325    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9326
9327    logger.debug("Send M3 to AP")
9328    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9329    attrs += build_attr_msg_type(WPS_M3)
9330    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9331    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
9332    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
9333    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
9334    raw_m3_attrs = attrs
9335    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9336    send_wsc_msg(hapd, addr, m3)
9337
9338    logger.debug("Receive M4 from AP")
9339    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
9340
9341    logger.debug("Send M5 to AP")
9342    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9343    attrs += build_attr_msg_type(WPS_M5)
9344    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9345    data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
9346    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
9347    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
9348    raw_m5_attrs = attrs
9349    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9350    send_wsc_msg(hapd, addr, m5)
9351
9352    logger.debug("Receive M6 from AP")
9353    msg, m6_attrs, raw_m6_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M6)
9354
9355    logger.debug("Send M7 to AP")
9356    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9357    attrs += build_attr_msg_type(WPS_M7)
9358    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9359    data = build_wsc_attr(ATTR_E_SNONCE2, e_s2)
9360    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
9361    attrs += build_attr_authenticator(authkey, raw_m6_attrs, attrs)
9362    m7 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9363    raw_m7_attrs = attrs
9364    send_wsc_msg(hapd, addr, m7)
9365
9366    logger.debug("Receive M8 from AP")
9367    msg, m8_attrs, raw_m8_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M8)
9368    return hapd, msg, e_nonce, r_nonce
9369
9370@remote_compatible
9371def test_wps_ext_wsc_done_invalid(dev, apdev):
9372    """WPS proto: invalid WSC_Done"""
9373    hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
9374
9375    logger.debug("Send WSC_Done to AP")
9376    attrs = b'\x10\x00\x00'
9377    wsc_done = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
9378    send_wsc_msg(hapd, dev[0].own_addr(), wsc_done)
9379
9380    wps_wait_eap_failure(hapd, dev[0])
9381
9382@remote_compatible
9383def test_wps_ext_wsc_done_no_msg_type(dev, apdev):
9384    """WPS proto: invalid WSC_Done"""
9385    hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
9386
9387    logger.debug("Send WSC_Done to AP")
9388    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9389    #attrs += build_attr_msg_type(WPS_WSC_DONE)
9390    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
9391    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9392    wsc_done = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
9393    send_wsc_msg(hapd, dev[0].own_addr(), wsc_done)
9394
9395    wps_wait_eap_failure(hapd, dev[0])
9396
9397@remote_compatible
9398def test_wps_ext_wsc_done_wrong_msg_type(dev, apdev):
9399    """WPS proto: WSC_Done with wrong Msg Type"""
9400    hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
9401
9402    logger.debug("Send WSC_Done to AP")
9403    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9404    attrs += build_attr_msg_type(WPS_WSC_ACK)
9405    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
9406    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9407    wsc_done = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
9408    send_wsc_msg(hapd, dev[0].own_addr(), wsc_done)
9409
9410    wps_wait_eap_failure(hapd, dev[0])
9411
9412@remote_compatible
9413def test_wps_ext_wsc_done_no_e_nonce(dev, apdev):
9414    """WPS proto: WSC_Done without e_nonce"""
9415    hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
9416
9417    logger.debug("Send WSC_Done to AP")
9418    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9419    attrs += build_attr_msg_type(WPS_WSC_DONE)
9420    #attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
9421    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9422    wsc_done = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
9423    send_wsc_msg(hapd, dev[0].own_addr(), wsc_done)
9424
9425    wps_wait_eap_failure(hapd, dev[0])
9426
9427def test_wps_ext_wsc_done_no_r_nonce(dev, apdev):
9428    """WPS proto: WSC_Done without r_nonce"""
9429    hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
9430
9431    logger.debug("Send WSC_Done to AP")
9432    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9433    attrs += build_attr_msg_type(WPS_WSC_DONE)
9434    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
9435    #attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9436    wsc_done = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
9437    send_wsc_msg(hapd, dev[0].own_addr(), wsc_done)
9438
9439    wps_wait_eap_failure(hapd, dev[0])
9440
9441@remote_compatible
9442def test_wps_ext_m7_no_encr_settings(dev, apdev):
9443    """WPS proto: M7 without Encr Settings"""
9444    pin = "12345670"
9445    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9446    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9447    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9448
9449    logger.debug("Receive WSC/Start from AP")
9450    msg = get_wsc_msg(hapd)
9451    if msg['wsc_opcode'] != WSC_Start:
9452        raise Exception("Unexpected Op-Code for WSC/Start")
9453
9454    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9455    uuid_e = 16*b'\x11'
9456    e_nonce = 16*b'\x22'
9457    own_private, e_pk = wsc_dh_init()
9458
9459    logger.debug("Send M1 to AP")
9460    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9461                                e_nonce, e_pk)
9462    send_wsc_msg(hapd, addr, m1)
9463
9464    logger.debug("Receive M2 from AP")
9465    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9466    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9467    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9468
9469    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9470                                     r_nonce)
9471    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9472
9473    logger.debug("Send M3 to AP")
9474    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9475    attrs += build_attr_msg_type(WPS_M3)
9476    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9477    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
9478    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
9479    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
9480    raw_m3_attrs = attrs
9481    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9482    send_wsc_msg(hapd, addr, m3)
9483
9484    logger.debug("Receive M4 from AP")
9485    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
9486
9487    logger.debug("Send M5 to AP")
9488    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9489    attrs += build_attr_msg_type(WPS_M5)
9490    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9491    data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
9492    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
9493    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
9494    raw_m5_attrs = attrs
9495    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9496    send_wsc_msg(hapd, addr, m5)
9497
9498    logger.debug("Receive M6 from AP")
9499    msg, m6_attrs, raw_m6_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M6)
9500
9501    logger.debug("Send M7 to AP")
9502    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9503    attrs += build_attr_msg_type(WPS_M7)
9504    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9505    #data = build_wsc_attr(ATTR_E_SNONCE2, e_s2)
9506    #attrs += build_attr_encr_settings(authkey, keywrapkey, data)
9507    attrs += build_attr_authenticator(authkey, raw_m6_attrs, attrs)
9508    m7 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9509    raw_m7_attrs = attrs
9510    send_wsc_msg(hapd, addr, m7)
9511
9512    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
9513
9514@remote_compatible
9515def test_wps_ext_m1_workaround(dev, apdev):
9516    """WPS proto: M1 Manufacturer/Model workaround"""
9517    pin = "12345670"
9518    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9519    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9520    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9521
9522    logger.debug("Receive WSC/Start from AP")
9523    msg = get_wsc_msg(hapd)
9524    if msg['wsc_opcode'] != WSC_Start:
9525        raise Exception("Unexpected Op-Code for WSC/Start")
9526
9527    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9528    uuid_e = 16*b'\x11'
9529    e_nonce = 16*b'\x22'
9530    own_private, e_pk = wsc_dh_init()
9531
9532    logger.debug("Send M1 to AP")
9533    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9534                                e_nonce, e_pk, manufacturer='Apple TEST',
9535                                model_name='AirPort', config_methods=b'\xff\xff')
9536    send_wsc_msg(hapd, addr, m1)
9537
9538    logger.debug("Receive M2 from AP")
9539    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9540
9541@remote_compatible
9542def test_ap_wps_disable_enable(dev, apdev):
9543    """WPS and DISABLE/ENABLE AP"""
9544    hapd = wps_start_ap(apdev[0])
9545    hapd.disable()
9546    hapd.enable()
9547    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
9548
9549def test_ap_wps_upnp_web_oom(dev, apdev, params):
9550    """hostapd WPS UPnP web OOM"""
9551    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
9552    hapd = add_ssdp_ap(apdev[0], ap_uuid)
9553
9554    location = ssdp_get_location(ap_uuid)
9555    url = urlparse(location)
9556    urls = upnp_get_urls(location)
9557    eventurl = urlparse(urls['event_sub_url'])
9558    ctrlurl = urlparse(urls['control_url'])
9559
9560    conn = HTTPConnection(url.netloc)
9561    with alloc_fail(hapd, 1, "web_connection_parse_get"):
9562        conn.request("GET", "/wps_device.xml")
9563        try:
9564            resp = conn.getresponse()
9565        except:
9566            pass
9567
9568    conn = HTTPConnection(url.netloc)
9569    conn.request("GET", "/unknown")
9570    resp = conn.getresponse()
9571    if resp.status != 404:
9572        raise Exception("Unexpected HTTP result for unknown URL: %d" + resp.status)
9573
9574    with alloc_fail(hapd, 1, "web_connection_parse_get"):
9575        conn.request("GET", "/unknown")
9576        try:
9577            resp = conn.getresponse()
9578            print(resp.status)
9579        except:
9580            pass
9581
9582    conn = HTTPConnection(url.netloc)
9583    conn.request("GET", "/wps_device.xml")
9584    resp = conn.getresponse()
9585    if resp.status != 200:
9586        raise Exception("GET /wps_device.xml failed")
9587
9588    conn = HTTPConnection(url.netloc)
9589    resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
9590    if resp.status != 200:
9591        raise Exception("GetDeviceInfo failed")
9592
9593    with alloc_fail(hapd, 1, "web_process_get_device_info"):
9594        conn = HTTPConnection(url.netloc)
9595        resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
9596        if resp.status != 500:
9597            raise Exception("Internal error not reported from GetDeviceInfo OOM")
9598
9599    with alloc_fail(hapd, 1, "wps_build_m1;web_process_get_device_info"):
9600        conn = HTTPConnection(url.netloc)
9601        resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
9602        if resp.status != 500:
9603            raise Exception("Internal error not reported from GetDeviceInfo OOM")
9604
9605    with alloc_fail(hapd, 1, "wpabuf_alloc;web_connection_send_reply"):
9606        conn = HTTPConnection(url.netloc)
9607        try:
9608            resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
9609        except:
9610            pass
9611
9612    conn = HTTPConnection(url.netloc)
9613    resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
9614    if resp.status != 200:
9615        raise Exception("GetDeviceInfo failed")
9616
9617    # No NewWLANEventType in PutWLANResponse NewMessage
9618    conn = HTTPConnection(url.netloc)
9619    resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse", newmsg="foo")
9620    if resp.status != 600:
9621        raise Exception("Unexpected HTTP response: %d" % resp.status)
9622
9623    # No NewWLANEventMAC in PutWLANResponse NewMessage
9624    conn = HTTPConnection(url.netloc)
9625    resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse",
9626                            newmsg="foo", neweventtype="1")
9627    if resp.status != 600:
9628        raise Exception("Unexpected HTTP response: %d" % resp.status)
9629
9630    # Invalid NewWLANEventMAC in PutWLANResponse NewMessage
9631    conn = HTTPConnection(url.netloc)
9632    resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse",
9633                            newmsg="foo", neweventtype="1",
9634                            neweventmac="foo")
9635    if resp.status != 600:
9636        raise Exception("Unexpected HTTP response: %d" % resp.status)
9637
9638    # Workaround for NewWLANEventMAC in PutWLANResponse NewMessage
9639    # Ignored unexpected PutWLANResponse WLANEventType 1
9640    conn = HTTPConnection(url.netloc)
9641    resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse",
9642                            newmsg="foo", neweventtype="1",
9643                            neweventmac="00.11.22.33.44.55")
9644    if resp.status != 500:
9645        raise Exception("Unexpected HTTP response: %d" % resp.status)
9646
9647    # PutWLANResponse NewMessage with invalid EAP message
9648    conn = HTTPConnection(url.netloc)
9649    resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse",
9650                            newmsg="foo", neweventtype="2",
9651                            neweventmac="00:11:22:33:44:55")
9652    if resp.status != 200:
9653        raise Exception("Unexpected HTTP response: %d" % resp.status)
9654
9655    with alloc_fail(hapd, 1, "web_connection_parse_subscribe"):
9656        conn = HTTPConnection(url.netloc)
9657        headers = {"callback": '<http://127.0.0.1:12345/event>',
9658                   "NT": "upnp:event",
9659                   "timeout": "Second-1234"}
9660        conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
9661        try:
9662            resp = conn.getresponse()
9663        except:
9664            pass
9665
9666    with alloc_fail(hapd, 1, "dup_binstr;web_connection_parse_subscribe"):
9667        conn = HTTPConnection(url.netloc)
9668        headers = {"callback": '<http://127.0.0.1:12345/event>',
9669                   "NT": "upnp:event",
9670                   "timeout": "Second-1234"}
9671        conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
9672        resp = conn.getresponse()
9673        if resp.status != 500:
9674            raise Exception("Unexpected HTTP response: %d" % resp.status)
9675
9676    with alloc_fail(hapd, 1, "wpabuf_alloc;web_connection_parse_unsubscribe"):
9677        conn = HTTPConnection(url.netloc)
9678        headers = {"callback": '<http://127.0.0.1:12345/event>',
9679                   "NT": "upnp:event",
9680                   "timeout": "Second-1234"}
9681        conn.request("UNSUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
9682        try:
9683            resp = conn.getresponse()
9684        except:
9685            pass
9686
9687    with alloc_fail(hapd, 1, "web_connection_unimplemented"):
9688        conn = HTTPConnection(url.netloc)
9689        conn.request("HEAD", "/wps_device.xml")
9690        try:
9691            resp = conn.getresponse()
9692        except:
9693            pass
9694
9695def test_ap_wps_frag_ack_oom(dev, apdev):
9696    """WPS and fragment ack OOM"""
9697    dev[0].request("SET wps_fragment_size 50")
9698    hapd = wps_start_ap(apdev[0])
9699    with alloc_fail(hapd, 1, "eap_wsc_build_frag_ack"):
9700        wps_run_pbc_fail_ap(apdev[0], dev[0], hapd)
9701
9702def wait_scan_stopped(dev):
9703    dev.request("ABORT_SCAN")
9704    for i in range(50):
9705        res = dev.get_driver_status_field("scan_state")
9706        if "SCAN_STARTED" not in res and "SCAN_REQUESTED" not in res:
9707            break
9708        logger.debug("Waiting for scan to complete")
9709        time.sleep(0.1)
9710
9711@remote_compatible
9712def test_ap_wps_eap_wsc_errors(dev, apdev):
9713    """WPS and EAP-WSC error cases"""
9714    ssid = "test-wps-conf-pin"
9715    appin = "12345670"
9716    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
9717              "wpa_passphrase": "12345678", "wpa": "2",
9718              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
9719              "fragment_size": "300", "ap_pin": appin}
9720    hapd = hostapd.add_ap(apdev[0], params)
9721    bssid = apdev[0]['bssid']
9722
9723    pin = dev[0].wps_read_pin()
9724    hapd.request("WPS_PIN any " + pin)
9725    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
9726    dev[0].dump_monitor()
9727
9728    dev[0].wps_reg(bssid, appin + " new_ssid=a", "new ssid", "WPA2PSK", "CCMP",
9729                   "new passphrase", no_wait=True)
9730    ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
9731    if ev is None:
9732        raise Exception("WPS-FAIL not reported")
9733    dev[0].request("WPS_CANCEL")
9734    dev[0].wait_disconnected()
9735    wait_scan_stopped(dev[0])
9736    dev[0].dump_monitor()
9737
9738    dev[0].wps_reg(bssid, appin, "new ssid", "FOO", "CCMP",
9739                   "new passphrase", no_wait=True)
9740    ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
9741    if ev is None:
9742        raise Exception("WPS-FAIL not reported")
9743    dev[0].request("WPS_CANCEL")
9744    dev[0].wait_disconnected()
9745    wait_scan_stopped(dev[0])
9746    dev[0].dump_monitor()
9747
9748    dev[0].wps_reg(bssid, appin, "new ssid", "WPA2PSK", "FOO",
9749                   "new passphrase", no_wait=True)
9750    ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
9751    if ev is None:
9752        raise Exception("WPS-FAIL not reported")
9753    dev[0].request("WPS_CANCEL")
9754    dev[0].wait_disconnected()
9755    wait_scan_stopped(dev[0])
9756    dev[0].dump_monitor()
9757
9758    dev[0].wps_reg(bssid, appin + "new_key=a", "new ssid", "WPA2PSK", "CCMP",
9759                   "new passphrase", no_wait=True)
9760    ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
9761    if ev is None:
9762        raise Exception("WPS-FAIL not reported")
9763    dev[0].request("WPS_CANCEL")
9764    dev[0].wait_disconnected()
9765    wait_scan_stopped(dev[0])
9766    dev[0].dump_monitor()
9767
9768    tests = ["eap_wsc_init",
9769             "eap_msg_alloc;eap_wsc_build_msg",
9770             "wpabuf_alloc;eap_wsc_process_fragment"]
9771    for func in tests:
9772        with alloc_fail(dev[0], 1, func):
9773            dev[0].request("WPS_PIN %s %s" % (bssid, pin))
9774            wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
9775            dev[0].request("WPS_CANCEL")
9776            dev[0].wait_disconnected()
9777            wait_scan_stopped(dev[0])
9778            dev[0].dump_monitor()
9779
9780    tests = [(1, "wps_decrypt_encr_settings"),
9781             (2, "hmac_sha256;wps_derive_psk")]
9782    for count, func in tests:
9783        hapd.request("WPS_PIN any " + pin)
9784        with fail_test(dev[0], count, func):
9785            dev[0].request("WPS_PIN %s %s" % (bssid, pin))
9786            wait_fail_trigger(dev[0], "GET_FAIL")
9787            dev[0].request("WPS_CANCEL")
9788            dev[0].wait_disconnected()
9789            wait_scan_stopped(dev[0])
9790            dev[0].dump_monitor()
9791
9792    with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_sm_build_expanded_nak"):
9793        dev[0].wps_reg(bssid, appin + " new_ssid=a", "new ssid", "WPA2PSK",
9794                       "CCMP", "new passphrase", no_wait=True)
9795        wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
9796        dev[0].request("WPS_CANCEL")
9797        dev[0].wait_disconnected()
9798        wait_scan_stopped(dev[0])
9799        dev[0].dump_monitor()
9800
9801def test_ap_wps_eap_wsc(dev, apdev):
9802    """WPS and EAP-WSC in network profile"""
9803    params = int_eap_server_params()
9804    params["wps_state"] = "2"
9805    hapd = hostapd.add_ap(apdev[0], params)
9806    bssid = apdev[0]['bssid']
9807
9808    logger.info("Unexpected identity")
9809    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9810                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-unexpected",
9811                   wait_connect=False)
9812    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9813    if ev is None:
9814        raise Exception("No EAP-Failure seen")
9815    dev[0].request("REMOVE_NETWORK all")
9816    dev[0].wait_disconnected()
9817
9818    logger.info("No phase1 parameter")
9819    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9820                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9821                   wait_connect=False)
9822    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9823    if ev is None:
9824        raise Exception("Timeout on EAP method start")
9825    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9826    if ev is None:
9827        raise Exception("No EAP-Failure seen")
9828    dev[0].request("REMOVE_NETWORK all")
9829    dev[0].wait_disconnected()
9830
9831    logger.info("No PIN/PBC in phase1")
9832    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9833                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9834                   phase1="foo", wait_connect=False)
9835    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9836    if ev is None:
9837        raise Exception("Timeout on EAP method start")
9838    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9839    if ev is None:
9840        raise Exception("No EAP-Failure seen")
9841    dev[0].request("REMOVE_NETWORK all")
9842    dev[0].wait_disconnected()
9843
9844    logger.info("Invalid pkhash in phase1")
9845    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9846                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9847                   phase1="foo pkhash=q pbc=1", wait_connect=False)
9848    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9849    if ev is None:
9850        raise Exception("Timeout on EAP method start")
9851    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9852    if ev is None:
9853        raise Exception("No EAP-Failure seen")
9854    dev[0].request("REMOVE_NETWORK all")
9855    dev[0].wait_disconnected()
9856
9857    logger.info("Zero fragment_size")
9858    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9859                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9860                   fragment_size="0", phase1="pin=12345670", wait_connect=False)
9861    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9862    if ev is None:
9863        raise Exception("Timeout on EAP method start")
9864    ev = dev[0].wait_event(["WPS-M2D"], timeout=5)
9865    if ev is None:
9866        raise Exception("No M2D seen")
9867    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9868    if ev is None:
9869        raise Exception("No EAP-Failure seen")
9870    dev[0].request("REMOVE_NETWORK all")
9871    dev[0].wait_disconnected()
9872
9873    logger.info("Missing new_auth")
9874    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9875                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9876                   phase1="pin=12345670 new_ssid=aa", wait_connect=False)
9877    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9878    if ev is None:
9879        raise Exception("Timeout on EAP method start")
9880    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9881    if ev is None:
9882        raise Exception("No EAP-Failure seen")
9883    dev[0].request("REMOVE_NETWORK all")
9884    dev[0].wait_disconnected()
9885
9886    logger.info("Missing new_encr")
9887    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9888                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9889                   phase1="pin=12345670 new_auth=WPA2PSK new_ssid=aa", wait_connect=False)
9890    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9891    if ev is None:
9892        raise Exception("Timeout on EAP method start")
9893    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9894    if ev is None:
9895        raise Exception("No EAP-Failure seen")
9896    dev[0].request("REMOVE_NETWORK all")
9897    dev[0].wait_disconnected()
9898
9899    logger.info("Missing new_key")
9900    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9901                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9902                   phase1="pin=12345670 new_auth=WPA2PSK new_ssid=aa new_encr=CCMP",
9903                   wait_connect=False)
9904    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9905    if ev is None:
9906        raise Exception("Timeout on EAP method start")
9907    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9908    if ev is None:
9909        raise Exception("No EAP-Failure seen")
9910    dev[0].request("REMOVE_NETWORK all")
9911    dev[0].wait_disconnected()
9912
9913def test_ap_wps_and_bss_limit(dev, apdev):
9914    """WPS and wpa_supplicant BSS entry limit"""
9915    try:
9916        _test_ap_wps_and_bss_limit(dev, apdev)
9917    finally:
9918        dev[0].request("SET bss_max_count 200")
9919        pass
9920
9921def _test_ap_wps_and_bss_limit(dev, apdev):
9922    params = {"ssid": "test-wps", "eap_server": "1", "wps_state": "2",
9923              "wpa_passphrase": "12345678", "wpa": "2",
9924              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
9925    hapd = hostapd.add_ap(apdev[0], params)
9926
9927    params = {"ssid": "test-wps-2", "eap_server": "1", "wps_state": "2",
9928              "wpa_passphrase": "1234567890", "wpa": "2",
9929              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
9930    hapd2 = hostapd.add_ap(apdev[1], params)
9931
9932    id = dev[1].add_network()
9933    dev[1].set_network(id, "mode", "2")
9934    dev[1].set_network_quoted(id, "ssid", "wpas-ap-no-wps")
9935    dev[1].set_network_quoted(id, "psk", "12345678")
9936    dev[1].set_network(id, "frequency", "2462")
9937    dev[1].set_network(id, "scan_freq", "2462")
9938    dev[1].set_network(id, "wps_disabled", "1")
9939    dev[1].select_network(id)
9940
9941    id = dev[2].add_network()
9942    dev[2].set_network(id, "mode", "2")
9943    dev[2].set_network_quoted(id, "ssid", "wpas-ap")
9944    dev[2].set_network_quoted(id, "psk", "12345678")
9945    dev[2].set_network(id, "frequency", "2437")
9946    dev[2].set_network(id, "scan_freq", "2437")
9947    dev[2].select_network(id)
9948
9949    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
9950    wpas.interface_add("wlan5")
9951    id = wpas.add_network()
9952    wpas.set_network(id, "mode", "2")
9953    wpas.set_network_quoted(id, "ssid", "wpas-ap")
9954    wpas.set_network_quoted(id, "psk", "12345678")
9955    wpas.set_network(id, "frequency", "2437")
9956    wpas.set_network(id, "scan_freq", "2437")
9957    wpas.select_network(id)
9958
9959    dev[1].wait_connected()
9960    dev[2].wait_connected()
9961    wpas.wait_connected()
9962    wpas.request("WPS_PIN any 12345670")
9963
9964    hapd.request("WPS_PBC")
9965    hapd2.request("WPS_PBC")
9966
9967    dev[0].request("SET bss_max_count 1")
9968
9969    id = dev[0].add_network()
9970    dev[0].set_network_quoted(id, "ssid", "testing")
9971
9972    id = dev[0].add_network()
9973    dev[0].set_network_quoted(id, "ssid", "testing")
9974    dev[0].set_network(id, "key_mgmt", "WPS")
9975
9976    dev[0].request("WPS_PBC")
9977    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
9978    dev[0].request("WPS_CANCEL")
9979
9980    id = dev[0].add_network()
9981    dev[0].set_network_quoted(id, "ssid", "testing")
9982    dev[0].set_network(id, "key_mgmt", "WPS")
9983
9984    dev[0].scan(freq="2412")
9985
9986def test_ap_wps_pbc_2ap(dev, apdev):
9987    """WPS PBC with two APs advertising same SSID"""
9988    params = {"ssid": "wps", "eap_server": "1", "wps_state": "2",
9989              "wpa_passphrase": "12345678", "wpa": "2",
9990              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
9991              "wps_independent": "1"}
9992    hapd = hostapd.add_ap(apdev[0], params)
9993    params = {"ssid": "wps", "eap_server": "1", "wps_state": "2",
9994              "wpa_passphrase": "123456789", "wpa": "2",
9995              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
9996              "wps_independent": "1"}
9997    hapd2 = hostapd.add_ap(apdev[1], params)
9998    hapd.request("WPS_PBC")
9999
10000    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
10001    wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
10002    wpas.dump_monitor()
10003    wpas.flush_scan_cache()
10004
10005    wpas.scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
10006    wpas.scan_for_bss(apdev[1]['bssid'], freq="2412")
10007    wpas.request("WPS_PBC")
10008    wpas.wait_connected()
10009    wpas.request("DISCONNECT")
10010    hapd.request("DISABLE")
10011    hapd2.request("DISABLE")
10012    wpas.flush_scan_cache()
10013
10014def test_ap_wps_er_enrollee_to_conf_ap(dev, apdev):
10015    """WPS ER enrolling a new device to a configured AP"""
10016    try:
10017        _test_ap_wps_er_enrollee_to_conf_ap(dev, apdev)
10018    finally:
10019        dev[0].request("WPS_ER_STOP")
10020
10021def _test_ap_wps_er_enrollee_to_conf_ap(dev, apdev):
10022    ssid = "wps-er-enrollee-to-conf-ap"
10023    ap_pin = "12345670"
10024    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
10025    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10026              "wpa_passphrase": "12345678", "wpa": "2",
10027              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
10028              "device_name": "Wireless AP", "manufacturer": "Company",
10029              "model_name": "WAP", "model_number": "123",
10030              "serial_number": "12345", "device_type": "6-0050F204-1",
10031              "os_version": "01020300",
10032              "config_methods": "label push_button",
10033              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
10034    hapd = hostapd.add_ap(apdev[0], params)
10035    bssid = hapd.own_addr()
10036
10037    id = dev[0].connect(ssid, psk="12345678", scan_freq="2412")
10038    dev[0].dump_monitor()
10039
10040    dev[0].request("WPS_ER_START ifname=lo")
10041    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
10042    if ev is None:
10043        raise Exception("AP discovery timed out")
10044    if ap_uuid not in ev:
10045        raise Exception("Expected AP UUID not found")
10046
10047    pin = dev[2].wps_read_pin()
10048    addr2 = dev[2].own_addr()
10049    dev[0].dump_monitor()
10050    dev[2].scan_for_bss(bssid, freq=2412)
10051    dev[2].dump_monitor()
10052    dev[2].request("WPS_PIN %s %s" % (bssid, pin))
10053
10054    for i in range(3):
10055        ev = dev[0].wait_event(["WPS-ER-ENROLLEE-ADD"], timeout=10)
10056        if ev is None:
10057            raise Exception("Enrollee not seen")
10058        if addr2 in ev:
10059            break
10060    if addr2 not in ev:
10061        raise Exception("Unexpected Enrollee MAC address")
10062    dev[0].dump_monitor()
10063
10064    dev[0].request("WPS_ER_SET_CONFIG " + ap_uuid + " " + str(id))
10065    dev[0].request("WPS_ER_PIN " + addr2 + " " + pin + " " + addr2)
10066    dev[2].wait_connected(timeout=30)
10067    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
10068    if ev is None:
10069        raise Exception("WPS ER did not report success")
10070
10071def test_ap_wps_er_enrollee_to_conf_ap2(dev, apdev):
10072    """WPS ER enrolling a new device to a configured AP (2)"""
10073    try:
10074        _test_ap_wps_er_enrollee_to_conf_ap2(dev, apdev)
10075    finally:
10076        dev[0].request("WPS_ER_STOP")
10077
10078def _test_ap_wps_er_enrollee_to_conf_ap2(dev, apdev):
10079    ssid = "wps-er-enrollee-to-conf-ap"
10080    ap_pin = "12345670"
10081    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
10082    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10083              "wpa_passphrase": "12345678", "wpa": "2",
10084              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
10085              "device_name": "Wireless AP", "manufacturer": "Company",
10086              "model_name": "WAP", "model_number": "123",
10087              "serial_number": "12345", "device_type": "6-0050F204-1",
10088              "os_version": "01020300",
10089              "config_methods": "label push_button",
10090              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
10091    hapd = hostapd.add_ap(apdev[0], params)
10092    bssid = hapd.own_addr()
10093
10094    id = dev[0].connect(ssid, psk="12345678", scan_freq="2412")
10095    dev[0].dump_monitor()
10096
10097    dev[0].request("WPS_ER_START ifname=lo")
10098    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
10099    if ev is None:
10100        raise Exception("AP discovery timed out")
10101    if ap_uuid not in ev:
10102        raise Exception("Expected AP UUID not found")
10103
10104    dev[0].request("WPS_ER_LEARN " + ap_uuid + " " + ap_pin)
10105    ev = dev[0].wait_event(["WPS-ER-AP-SETTINGS"], timeout=15)
10106    if ev is None:
10107        raise Exception("AP learn timed out")
10108    if ap_uuid not in ev:
10109        raise Exception("Expected AP UUID not in settings")
10110    ev = dev[0].wait_event(["WPS-FAIL"], timeout=15)
10111    if ev is None:
10112        raise Exception("WPS-FAIL after AP learn timed out")
10113    time.sleep(0.1)
10114
10115    pin = dev[1].wps_read_pin()
10116    addr1 = dev[1].own_addr()
10117    dev[0].dump_monitor()
10118    dev[0].request("WPS_ER_PIN any " + pin)
10119    time.sleep(0.1)
10120    dev[1].scan_for_bss(bssid, freq=2412)
10121    dev[1].request("WPS_PIN any %s" % pin)
10122    ev = dev[1].wait_event(["WPS-SUCCESS"], timeout=30)
10123    if ev is None:
10124        raise Exception("Enrollee did not report success")
10125    dev[1].wait_connected(timeout=15)
10126    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
10127    if ev is None:
10128        raise Exception("WPS ER did not report success")
10129
10130def test_ap_wps_ignore_broadcast_ssid(dev, apdev):
10131    """WPS AP trying to ignore broadcast SSID"""
10132    ssid = "test-wps"
10133    hapd = hostapd.add_ap(apdev[0],
10134                          {"ssid": ssid, "eap_server": "1", "wps_state": "1",
10135                           "ignore_broadcast_ssid": "1"})
10136    if "FAIL" not in hapd.request("WPS_PBC"):
10137        raise Exception("WPS unexpectedly enabled")
10138
10139def test_ap_wps_wep(dev, apdev):
10140    """WPS AP trying to enable WEP"""
10141    check_wep_capa(dev[0])
10142    ssid = "test-wps"
10143    hapd = hostapd.add_ap(apdev[0],
10144                          {"ssid": ssid, "eap_server": "1", "wps_state": "1",
10145                           "ieee80211n": "0", "wep_key0": '"hello"'})
10146    if "FAIL" not in hapd.request("WPS_PBC"):
10147        raise Exception("WPS unexpectedly enabled")
10148
10149def test_ap_wps_tkip(dev, apdev):
10150    """WPS AP trying to enable TKIP"""
10151    ssid = "test-wps"
10152    hapd = hostapd.add_ap(apdev[0],
10153                          {"ssid": ssid, "eap_server": "1", "wps_state": "1",
10154                           "ieee80211n": "0", "wpa": '1',
10155                           "wpa_key_mgmt": "WPA-PSK",
10156                           "wpa_passphrase": "12345678"})
10157    if "FAIL" not in hapd.request("WPS_PBC"):
10158        raise Exception("WPS unexpectedly enabled")
10159
10160def test_ap_wps_conf_stub_cred(dev, apdev):
10161    """WPS PIN provisioning with configured AP using stub cred"""
10162    ssid = "test-wps-conf"
10163    hapd = hostapd.add_ap(apdev[0],
10164                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10165                           "wpa_passphrase": "12345678", "wpa": "2",
10166                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
10167    hapd.request("WPS_PIN any 12345670")
10168    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
10169    dev[0].dump_monitor()
10170    try:
10171        hapd.set("wps_testing_stub_cred", "1")
10172        dev[0].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
10173        for i in range(1, 3):
10174            ev = dev[0].wait_event(["WPS-CRED-RECEIVED"], timeout=15)
10175            if ev is None:
10176                raise Exception("WPS credential %d not received" % i)
10177        dev[0].wait_connected(timeout=30)
10178    finally:
10179        hapd.set("wps_testing_stub_cred", "0")
10180
10181def test_ap_wps_rf_bands(dev, apdev):
10182    """WPS and wps_rf_bands configuration"""
10183    ssid = "test-wps-conf"
10184    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10185              "wpa_passphrase": "12345678", "wpa": "2",
10186              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
10187              "wps_rf_bands": "ag"}
10188
10189    hapd = hostapd.add_ap(apdev[0], params)
10190    bssid = hapd.own_addr()
10191    hapd.request("WPS_PBC")
10192    dev[0].scan_for_bss(bssid, freq="2412")
10193    dev[0].dump_monitor()
10194    dev[0].request("WPS_PBC " + bssid)
10195    dev[0].wait_connected(timeout=30)
10196    bss = dev[0].get_bss(bssid)
10197    logger.info("BSS: " + str(bss))
10198    if "103c000103" not in bss['ie']:
10199        raise Exception("RF Bands attribute with expected values not found")
10200    dev[0].request("DISCONNECT")
10201    dev[0].wait_disconnected()
10202    hapd.set("wps_rf_bands", "ad")
10203    hapd.set("wps_rf_bands", "a")
10204    hapd.set("wps_rf_bands", "g")
10205    hapd.set("wps_rf_bands", "b")
10206    hapd.set("wps_rf_bands", "ga")
10207    hapd.disable()
10208    dev[0].dump_monitor()
10209    dev[0].flush_scan_cache()
10210
10211def test_ap_wps_pbc_in_m1(dev, apdev):
10212    """WPS and pbc_in_m1"""
10213    ssid = "test-wps-conf"
10214    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10215              "wpa_passphrase": "12345678", "wpa": "2",
10216              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
10217              "config_methods": "virtual_push_button virtual_display",
10218              "pbc_in_m1": "1"}
10219
10220    hapd = hostapd.add_ap(apdev[0], params)
10221    bssid = hapd.own_addr()
10222    hapd.request("WPS_PBC")
10223    dev[0].scan_for_bss(bssid, freq="2412")
10224    dev[0].dump_monitor()
10225    dev[0].request("WPS_PBC " + bssid)
10226    dev[0].wait_connected(timeout=30)
10227    dev[0].request("DISCONNECT")
10228    dev[0].wait_disconnected()
10229    hapd.disable()
10230    dev[0].dump_monitor()
10231    dev[0].flush_scan_cache()
10232
10233def test_ap_wps_pbc_mac_addr_change(dev, apdev, params):
10234    """WPS M1 with MAC address change"""
10235    skip_without_tkip(dev[0])
10236    ssid = "test-wps-mac-addr-change"
10237    hapd = hostapd.add_ap(apdev[0],
10238                          {"ssid": ssid, "eap_server": "1", "wps_state": "1"})
10239    hapd.request("WPS_PBC")
10240    if "PBC Status: Active" not in hapd.request("WPS_GET_STATUS"):
10241        raise Exception("PBC status not shown correctly")
10242    dev[0].flush_scan_cache()
10243
10244    test_addr = '02:11:22:33:44:55'
10245    addr = dev[0].get_status_field("address")
10246    if addr == test_addr:
10247        raise Exception("Unexpected initial MAC address")
10248
10249    try:
10250        subprocess.call(['ip', 'link', 'set', 'dev', dev[0].ifname, 'down'])
10251        subprocess.call(['ip', 'link', 'set', 'dev', dev[0].ifname, 'address',
10252                         test_addr])
10253        subprocess.call(['ip', 'link', 'set', 'dev', dev[0].ifname, 'up'])
10254        addr1 = dev[0].get_status_field("address")
10255        if addr1 != test_addr:
10256            raise Exception("Failed to change MAC address")
10257
10258        dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
10259        dev[0].request("WPS_PBC " + apdev[0]['bssid'])
10260        dev[0].wait_connected(timeout=30)
10261        status = dev[0].get_status()
10262        if status['wpa_state'] != 'COMPLETED' or \
10263           status['bssid'] != apdev[0]['bssid']:
10264            raise Exception("Not fully connected")
10265
10266        out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
10267                         "wps.message_type == 0x04",
10268                         display=["wps.mac_address"])
10269        res = out.splitlines()
10270
10271        if len(res) < 1:
10272            raise Exception("No M1 message with MAC address found")
10273        if res[0] != addr1:
10274            raise Exception("Wrong M1 MAC address")
10275        dev[0].request("DISCONNECT")
10276        dev[0].wait_disconnected()
10277        hapd.disable()
10278        dev[0].dump_monitor()
10279        dev[0].flush_scan_cache()
10280    finally:
10281        # Restore MAC address
10282        subprocess.call(['ip', 'link', 'set', 'dev', dev[0].ifname, 'down'])
10283        subprocess.call(['ip', 'link', 'set', 'dev', dev[0].ifname, 'address',
10284                         addr])
10285        subprocess.call(['ip', 'link', 'set', 'dev', dev[0].ifname, 'up'])
10286
10287def test_ap_wps_pin_start_failure(dev, apdev):
10288    """WPS_PIN start failure"""
10289    with alloc_fail(dev[0], 1, "wpas_wps_start_dev_pw"):
10290        if "FAIL" not in dev[0].request("WPS_PIN any 12345670"):
10291            raise Exception("WPS_PIN not rejected during OOM")
10292    with alloc_fail(dev[0], 1, "wpas_wps_start_dev_pw"):
10293        if "FAIL" not in dev[0].request("WPS_PIN any"):
10294            raise Exception("WPS_PIN not rejected during OOM")
10295
10296def test_ap_wps_ap_pin_failure(dev, apdev):
10297    """WPS_AP_PIN failure"""
10298    id = dev[0].add_network()
10299    dev[0].set_network(id, "mode", "2")
10300    dev[0].set_network_quoted(id, "ssid", "wpas-ap-wps")
10301    dev[0].set_network_quoted(id, "psk", "1234567890")
10302    dev[0].set_network(id, "frequency", "2412")
10303    dev[0].set_network(id, "scan_freq", "2412")
10304    dev[0].select_network(id)
10305    dev[0].wait_connected()
10306
10307    with fail_test(dev[0], 1,
10308                   "os_get_random;wpa_supplicant_ctrl_iface_wps_ap_pin"):
10309        if "FAIL" not in dev[0].request("WPS_AP_PIN random"):
10310            raise Exception("WPS_AP_PIN random accepted")
10311    with alloc_fail(dev[0], 1, "wpas_wps_ap_pin_set"):
10312        if "FAIL" not in dev[0].request("WPS_AP_PIN set 12345670"):
10313            raise Exception("WPS_AP_PIN set accepted")
10314
10315    dev[0].request("DISCONNECT")
10316    dev[0].wait_disconnected()
10317
10318def test_ap_wps_random_uuid(dev, apdev, params):
10319    """WPS and random UUID on Enrollee"""
10320    ssid = "test-wps-conf"
10321    hapd = hostapd.add_ap(apdev[0],
10322                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10323                           "wpa_passphrase": "12345678", "wpa": "2",
10324                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
10325
10326    config = os.path.join(params['logdir'], 'ap_wps_random_uuid.conf')
10327    with open(config, "w") as f:
10328        f.write("auto_uuid=1\n")
10329
10330    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
10331
10332    uuid = []
10333    for i in range(3):
10334        wpas.interface_add("wlan5", config=config)
10335
10336        wpas.scan_for_bss(apdev[0]['bssid'], freq="2412")
10337        wpas.dump_monitor()
10338        wpas.request("WPS_PBC " + apdev[0]['bssid'])
10339
10340        ev = hapd.wait_event(["WPS-ENROLLEE-SEEN"], timeout=10)
10341        if ev is None:
10342            raise Exception("Enrollee not seen")
10343        uuid.append(ev.split(' ')[2])
10344        wpas.request("WPS_CANCEL")
10345        wpas.dump_monitor()
10346
10347        wpas.interface_remove("wlan5")
10348
10349        for j in range(3):
10350            ev = hapd.wait_event(["WPS-ENROLLEE-SEEN"], timeout=1)
10351            if ev:
10352                logger.info("Ignored extra event at the end: " + ev)
10353        hapd.dump_monitor()
10354
10355    logger.info("Seen UUIDs: " + str(uuid))
10356    if uuid[0] == uuid[1] or uuid[0] == uuid[2] or uuid[1] == uuid[2]:
10357        raise Exception("Same UUID used multiple times")
10358
10359def test_ap_wps_conf_pin_gcmp_128(dev, apdev):
10360    """WPS PIN provisioning with configured AP using GCMP-128"""
10361    run_ap_wps_conf_pin_cipher(dev, apdev, "GCMP")
10362
10363def test_ap_wps_conf_pin_gcmp_256(dev, apdev):
10364    """WPS PIN provisioning with configured AP using GCMP-256"""
10365    run_ap_wps_conf_pin_cipher(dev, apdev, "GCMP-256")
10366
10367def test_ap_wps_conf_pin_ccmp_256(dev, apdev):
10368    """WPS PIN provisioning with configured AP using CCMP-256"""
10369    run_ap_wps_conf_pin_cipher(dev, apdev, "CCMP-256")
10370
10371def run_ap_wps_conf_pin_cipher(dev, apdev, cipher):
10372    if cipher not in dev[0].get_capability("pairwise"):
10373        raise HwsimSkip("Cipher %s not supported" % cipher)
10374    ssid = "test-wps-conf-pin"
10375    hapd = hostapd.add_ap(apdev[0],
10376                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10377                           "wpa_passphrase": "12345678", "wpa": "2",
10378                           "wpa_key_mgmt": "WPA-PSK",
10379                           "rsn_pairwise": cipher})
10380    logger.info("WPS provisioning step")
10381    pin = dev[0].wps_read_pin()
10382    hapd.request("WPS_PIN any " + pin)
10383    dev[0].flush_scan_cache()
10384    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
10385    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
10386    dev[0].wait_connected(timeout=15)
10387
10388def test_ap_wps_and_sae(dev, apdev):
10389    """Initial AP configuration with first WPS Enrollee and adding SAE"""
10390    skip_without_tkip(dev[0])
10391    skip_without_tkip(dev[1])
10392    try:
10393        run_ap_wps_and_sae(dev, apdev)
10394    finally:
10395        dev[0].set("wps_cred_add_sae", "0")
10396
10397def run_ap_wps_and_sae(dev, apdev):
10398    check_sae_capab(dev[0])
10399    ssid = "test-wps-sae"
10400    hapd = hostapd.add_ap(apdev[0],
10401                          {"ssid": ssid, "eap_server": "1", "wps_state": "1",
10402                           "wps_cred_add_sae": "1"})
10403    logger.info("WPS provisioning step")
10404    pin = dev[0].wps_read_pin()
10405    hapd.request("WPS_PIN any " + pin)
10406
10407    dev[0].flush_scan_cache()
10408    dev[0].set("wps_cred_add_sae", "1")
10409    dev[0].request("SET sae_groups ")
10410    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
10411    dev[0].request("WPS_PIN " + apdev[0]['bssid'] + " " + pin)
10412    dev[0].wait_connected(timeout=30)
10413    status = dev[0].get_status()
10414    if status['key_mgmt'] != "SAE":
10415        raise Exception("SAE not used")
10416    if 'pmf' not in status or status['pmf'] != "1":
10417        raise Exception("PMF not enabled")
10418
10419    dev[1].flush_scan_cache()
10420    pin = dev[1].wps_read_pin()
10421    hapd.request("WPS_PIN any " + pin)
10422    dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
10423    dev[1].request("WPS_PIN " + apdev[0]['bssid'] + " " + pin)
10424    dev[1].wait_connected(timeout=30)
10425    status = dev[1].get_status()
10426    if status['key_mgmt'] != "WPA2-PSK":
10427        raise Exception("WPA2-PSK not used")
10428    if 'pmf' in status:
10429        raise Exception("PMF enabled")
10430
10431def test_ap_wps_conf_and_sae(dev, apdev):
10432    """WPS PBC provisioning with configured AP using PSK+SAE"""
10433    try:
10434        run_ap_wps_conf_and_sae(dev, apdev)
10435    finally:
10436        dev[0].set("wps_cred_add_sae", "0")
10437
10438def run_ap_wps_conf_and_sae(dev, apdev):
10439    check_sae_capab(dev[0])
10440    ssid = "test-wps-conf-sae"
10441    hapd = hostapd.add_ap(apdev[0],
10442                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10443                           "wpa_passphrase": "12345678", "wpa": "2",
10444                           "ieee80211w": "1", "sae_require_mfp": "1",
10445                           "wpa_key_mgmt": "WPA-PSK SAE",
10446                           "rsn_pairwise": "CCMP"})
10447
10448    dev[0].set("wps_cred_add_sae", "1")
10449    dev[0].request("SET sae_groups ")
10450    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
10451    pin = dev[0].wps_read_pin()
10452    hapd.request("WPS_PIN any " + pin)
10453    dev[0].request("WPS_PIN " + apdev[0]['bssid'] + " " + pin)
10454    dev[0].wait_connected(timeout=30)
10455    status = dev[0].get_status()
10456    if status['key_mgmt'] != "SAE":
10457        raise Exception("SAE not used")
10458    if 'pmf' not in status or status['pmf'] != "1":
10459        raise Exception("PMF not enabled")
10460
10461    dev[1].connect(ssid, psk="12345678", scan_freq="2412", proto="WPA2",
10462                   key_mgmt="WPA-PSK", ieee80211w="0")
10463
10464def test_ap_wps_conf_and_sae_h2e(dev, apdev):
10465    """WPS PIN provisioning with configured AP using PSK+SAE(H2E)"""
10466    try:
10467        run_ap_wps_conf_and_sae_h2e(dev, apdev)
10468    finally:
10469        dev[0].set("wps_cred_add_sae", "0")
10470        dev[0].set("sae_pwe", "0")
10471
10472def run_ap_wps_conf_and_sae_h2e(dev, apdev):
10473    check_sae_capab(dev[0])
10474    ssid = "test-wps-conf-sae"
10475    hapd = hostapd.add_ap(apdev[0],
10476                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10477                           "wpa_passphrase": "12345678", "wpa": "2",
10478                           "ieee80211w": "1", "sae_require_mfp": "1",
10479                           "sae_pwe": "1",
10480                           "wpa_key_mgmt": "WPA-PSK SAE",
10481                           "rsn_pairwise": "CCMP"})
10482
10483    dev[0].set("wps_cred_add_sae", "1")
10484    dev[0].set("sae_pwe", "1")
10485    dev[0].request("SET sae_groups ")
10486    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
10487    pin = dev[0].wps_read_pin()
10488    hapd.request("WPS_PIN any " + pin)
10489    dev[0].request("WPS_PIN " + apdev[0]['bssid'] + " " + pin)
10490    dev[0].wait_connected(timeout=30)
10491    status = dev[0].get_status()
10492    if status['key_mgmt'] != "SAE":
10493        raise Exception("SAE not used")
10494    if 'pmf' not in status or status['pmf'] != "1":
10495        raise Exception("PMF not enabled")
10496
10497def test_ap_wps_reg_config_and_sae(dev, apdev):
10498    """WPS registrar configuring an AP using AP PIN and using PSK+SAE"""
10499    try:
10500        run_ap_wps_reg_config_and_sae(dev, apdev)
10501    finally:
10502        dev[0].set("wps_cred_add_sae", "0")
10503
10504def run_ap_wps_reg_config_and_sae(dev, apdev):
10505    check_sae_capab(dev[0])
10506    ssid = "test-wps-init-ap-pin-sae"
10507    appin = "12345670"
10508    hostapd.add_ap(apdev[0],
10509                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10510                    "ap_pin": appin, "wps_cred_add_sae": "1"})
10511    logger.info("WPS configuration step")
10512    dev[0].flush_scan_cache()
10513    dev[0].set("wps_cred_add_sae", "1")
10514    dev[0].request("SET sae_groups ")
10515    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
10516    dev[0].dump_monitor()
10517    new_ssid = "wps-new-ssid"
10518    new_passphrase = "1234567890"
10519    dev[0].wps_reg(apdev[0]['bssid'], appin, new_ssid, "WPA2PSK", "CCMP",
10520                   new_passphrase)
10521    status = dev[0].get_status()
10522    if status['key_mgmt'] != "SAE":
10523        raise Exception("SAE not used")
10524    if 'pmf' not in status or status['pmf'] != "1":
10525        raise Exception("PMF not enabled")
10526
10527    dev[1].connect(new_ssid, psk=new_passphrase, scan_freq="2412", proto="WPA2",
10528                   key_mgmt="WPA-PSK", ieee80211w="0")
10529
10530def test_ap_wps_appl_ext(dev, apdev):
10531    """WPS Application Extension attribute"""
10532    ssid = "test-wps-conf"
10533    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10534              "wps_application_ext": 16*"11" + 5*"ee",
10535              "wpa_passphrase": "12345678", "wpa": "2",
10536              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
10537    hapd = hostapd.add_ap(apdev[0], params)
10538    pin = dev[0].wps_read_pin()
10539    hapd.request("WPS_PIN any " + pin)
10540    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
10541    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
10542    dev[0].wait_connected(timeout=30)
10543
10544@long_duration_test
10545def test_ap_wps_pbc_ap_timeout(dev, apdev):
10546    """WPS PBC timeout on AP"""
10547    run_ap_wps_ap_timeout(dev, apdev, "WPS_PBC")
10548
10549@long_duration_test
10550def test_ap_wps_pin_ap_timeout(dev, apdev):
10551    """WPS PIN timeout on AP"""
10552    run_ap_wps_ap_timeout(dev, apdev, "WPS_PIN any 12345670 10")
10553
10554def run_ap_wps_ap_timeout(dev, apdev, cmd):
10555    ssid = "test-wps-conf"
10556    hapd = hostapd.add_ap(apdev[0],
10557                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10558                           "wpa_passphrase": "12345678", "wpa": "2",
10559                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
10560    bssid = hapd.own_addr()
10561    hapd.request(cmd)
10562    time.sleep(1)
10563    dev[0].scan_for_bss(bssid, freq="2412")
10564    bss = dev[0].get_bss(bssid)
10565    logger.info("BSS during active Registrar: " + str(bss))
10566    if not bss['ie'].endswith("0106ffffffffffff"):
10567        raise Exception("Authorized MAC not included")
10568    ev = hapd.wait_event(["WPS-TIMEOUT"], timeout=130)
10569    if ev is None and "PBC" in cmd:
10570        raise Exception("WPS-TIMEOUT not reported")
10571    if "PBC" in cmd and \
10572       "PBC Status: Timed-out" not in hapd.request("WPS_GET_STATUS"):
10573        raise Exception("PBC status not shown correctly")
10574
10575    time.sleep(5)
10576    dev[0].flush_scan_cache()
10577    dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
10578    bss = dev[0].get_bss(bssid)
10579    logger.info("BSS after timeout: " + str(bss))
10580    if bss['ie'].endswith("0106ffffffffffff"):
10581        raise Exception("Authorized MAC not removed")
10582
10583def test_ap_wps_er_unsubscribe_errors(dev, apdev):
10584    """WPS ER and UNSUBSCRIBE errors"""
10585    start_wps_ap(apdev[0])
10586    tests = [(1, "http_client_url_parse;wps_er_ap_unsubscribe"),
10587             (1, "wpabuf_alloc;wps_er_ap_unsubscribe"),
10588             (1, "http_client_addr;wps_er_ap_unsubscribe")]
10589    try:
10590        for count, func in tests:
10591            start_wps_er(dev[0])
10592            with alloc_fail(dev[0], count, func):
10593                dev[0].request("WPS_ER_STOP")
10594            dev[0].request("REMOVE_NETWORK all")
10595            dev[0].wait_disconnected()
10596            dev[0].dump_monitor()
10597    finally:
10598        dev[0].request("WPS_ER_STOP")
10599
10600def start_wps_ap(apdev):
10601    ssid = "wps-er-ap-config"
10602    ap_pin = "12345670"
10603    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
10604    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10605              "wpa_passphrase": "12345678", "wpa": "2",
10606              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
10607              "device_name": "Wireless AP", "manufacturer": "Company",
10608              "model_name": "WAP", "model_number": "123",
10609              "serial_number": "12345", "device_type": "6-0050F204-1",
10610              "os_version": "01020300",
10611              "config_methods": "label push_button",
10612              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
10613    hostapd.add_ap(apdev, params)
10614
10615def start_wps_er(dev):
10616    ssid = "wps-er-ap-config"
10617    dev.connect(ssid, psk="12345678", scan_freq="2412")
10618    dev.request("WPS_ER_START ifname=lo")
10619    ev = dev.wait_event(["WPS-ER-AP-ADD"], timeout=15)
10620    if ev is None:
10621        raise Exception("AP discovery timed out")
10622
10623def test_ap_wps_registrar_init_errors(dev, apdev):
10624    """WPS Registrar init errors"""
10625    hapd = wps_start_ap(apdev[0], extra_cred="wps-mixed-cred")
10626    hapd.disable()
10627    tests = [(1, "wps_registrar_init"),
10628             (1, "wpabuf_alloc_copy;wps_registrar_init"),
10629             (1, "wps_set_ie;wps_registrar_init")]
10630    for count, func in tests:
10631        with alloc_fail(hapd, count, func):
10632            if "FAIL" not in hapd.request("ENABLE"):
10633                raise Exception("ENABLE succeeded unexpectedly")
10634
10635def test_ap_wps_config_without_wps(dev, apdev):
10636    """AP configuration attempt using wps_config when WPS is disabled"""
10637    ssid = "test-wps-init-config"
10638    hapd = hostapd.add_ap(apdev[0], {"ssid": ssid})
10639    if "FAIL" not in hapd.request("WPS_CONFIG " + binascii.hexlify(ssid.encode()).decode() + " WPA2PSK CCMP " + binascii.hexlify(b"12345678").decode()):
10640        raise Exception("WPS_CONFIG command succeeded unexpectedly")
10641
10642def test_ap_wps_passive_scan(dev, apdev):
10643    """WPS PBC provisioning with configured AP and passive scanning"""
10644    ssid = "test-wps-conf"
10645    hapd = hostapd.add_ap(apdev[0],
10646                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10647                           "wpa_passphrase": "12345678", "wpa": "2",
10648                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
10649    dev[0].scan_for_bss(hapd.own_addr(), freq="2412")
10650    hapd.request("WPS_PBC")
10651    dev[0].scan_for_bss(hapd.own_addr(), 2412, force_scan=True, passive=True)
10652    hapd.set("ext_mgmt_frame_handling", "1")
10653    dev[0].dump_monitor()
10654    dev[0].request("WPS_PBC " + hapd.own_addr())
10655    req = None
10656    for i in range(0, 10):
10657        req = hapd.mgmt_rx()
10658        if req is None:
10659            raise Exception("MGMT RX wait timed out")
10660        if req['subtype'] == 11:
10661            break
10662        req = None
10663    if not req:
10664        raise Exception("Authentication frame not received")
10665    hapd.set("ext_mgmt_frame_handling", "0")
10666    dev[0].wait_connected(timeout=30)
10667