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;?hostap_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;?hostap_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;?hostap_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;?hostap_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;?hostap_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    addr = dev.own_addr()
5590    bssid = apdev['bssid']
5591    ssid = "test-wps-conf"
5592    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
5593              "wpa_passphrase": "12345678", "wpa": "2",
5594              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
5595    hapd = hostapd.add_ap(apdev, params)
5596
5597    if pbc:
5598        hapd.request("WPS_PBC")
5599    else:
5600        if pin is None:
5601            pin = dev.wps_read_pin()
5602        hapd.request("WPS_PIN any " + pin)
5603    dev.scan_for_bss(bssid, freq="2412")
5604    hapd.request("SET ext_eapol_frame_io 1")
5605    dev.request("SET ext_eapol_frame_io 1")
5606
5607    if pbc:
5608        dev.request("WPS_PBC " + bssid)
5609    else:
5610        dev.request("WPS_PIN " + bssid + " " + pin)
5611    return addr, bssid, hapd
5612
5613def wps_auth_corrupt(dst, src, addr):
5614    ev = src.wait_event(["EAPOL-TX"], timeout=10)
5615    if ev is None:
5616        raise Exception("Timeout on EAPOL-TX")
5617    src.request("SET ext_eapol_frame_io 0")
5618    dst.request("SET ext_eapol_frame_io 0")
5619    msg = ev.split(' ')[2]
5620    if msg[-24:-16] != '10050008':
5621        raise Exception("Could not find Authenticator attribute")
5622    # Corrupt Authenticator value
5623    msg = msg[:-1] + '%x' % ((int(msg[-1], 16) + 1) % 16)
5624    res = dst.request("EAPOL_RX " + addr + " " + msg)
5625    if "OK" not in res:
5626        raise Exception("EAPOL_RX failed")
5627
5628def wps_fail_finish(hapd, dev, fail_str):
5629    ev = hapd.wait_event(["WPS-FAIL"], timeout=5)
5630    if ev is None:
5631        raise Exception("WPS-FAIL not indicated")
5632    if fail_str not in ev:
5633        raise Exception("Unexpected WPS-FAIL value: " + ev)
5634    dev.request("WPS_CANCEL")
5635    dev.wait_disconnected()
5636
5637def wps_auth_corrupt_from_ap(dev, hapd, bssid, fail_str):
5638    wps_auth_corrupt(dev, hapd, bssid)
5639    wps_fail_finish(hapd, dev, fail_str)
5640
5641def wps_auth_corrupt_to_ap(dev, hapd, addr, fail_str):
5642    wps_auth_corrupt(hapd, dev, addr)
5643    wps_fail_finish(hapd, dev, fail_str)
5644
5645def test_ap_wps_authenticator_mismatch_m2(dev, apdev):
5646    """WPS and Authenticator attribute mismatch in M2"""
5647    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5648    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5649    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5650    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5651    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5652    logger.debug("M2")
5653    wps_auth_corrupt_from_ap(dev[0], hapd, bssid, "msg=5")
5654
5655def test_ap_wps_authenticator_mismatch_m3(dev, apdev):
5656    """WPS and Authenticator attribute mismatch in M3"""
5657    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5658    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5659    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5660    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5661    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5662    wps_ext_eap_wsc(dev[0], hapd, bssid, "M2")
5663    logger.debug("M3")
5664    wps_auth_corrupt_to_ap(dev[0], hapd, addr, "msg=7")
5665
5666def test_ap_wps_authenticator_mismatch_m4(dev, apdev):
5667    """WPS and Authenticator attribute mismatch in M4"""
5668    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5669    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5670    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5671    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5672    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5673    wps_ext_eap_wsc(dev[0], hapd, bssid, "M2")
5674    wps_ext_eap_wsc(hapd, dev[0], addr, "M3")
5675    logger.debug("M4")
5676    wps_auth_corrupt_from_ap(dev[0], hapd, bssid, "msg=8")
5677
5678def test_ap_wps_authenticator_mismatch_m5(dev, apdev):
5679    """WPS and Authenticator attribute mismatch in M5"""
5680    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5681    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5682    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5683    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5684    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5685    wps_ext_eap_wsc(dev[0], hapd, bssid, "M2")
5686    wps_ext_eap_wsc(hapd, dev[0], addr, "M3")
5687    wps_ext_eap_wsc(dev[0], hapd, bssid, "M4")
5688    logger.debug("M5")
5689    wps_auth_corrupt_to_ap(dev[0], hapd, addr, "msg=9")
5690
5691def test_ap_wps_authenticator_mismatch_m6(dev, apdev):
5692    """WPS and Authenticator attribute mismatch in M6"""
5693    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5694    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5695    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5696    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5697    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5698    wps_ext_eap_wsc(dev[0], hapd, bssid, "M2")
5699    wps_ext_eap_wsc(hapd, dev[0], addr, "M3")
5700    wps_ext_eap_wsc(dev[0], hapd, bssid, "M4")
5701    wps_ext_eap_wsc(hapd, dev[0], addr, "M5")
5702    logger.debug("M6")
5703    wps_auth_corrupt_from_ap(dev[0], hapd, bssid, "msg=10")
5704
5705def test_ap_wps_authenticator_mismatch_m7(dev, apdev):
5706    """WPS and Authenticator attribute mismatch in M7"""
5707    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5708    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5709    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5710    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5711    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5712    wps_ext_eap_wsc(dev[0], hapd, bssid, "M2")
5713    wps_ext_eap_wsc(hapd, dev[0], addr, "M3")
5714    wps_ext_eap_wsc(dev[0], hapd, bssid, "M4")
5715    wps_ext_eap_wsc(hapd, dev[0], addr, "M5")
5716    wps_ext_eap_wsc(dev[0], hapd, bssid, "M6")
5717    logger.debug("M7")
5718    wps_auth_corrupt_to_ap(dev[0], hapd, addr, "msg=11")
5719
5720def test_ap_wps_authenticator_mismatch_m8(dev, apdev):
5721    """WPS and Authenticator attribute mismatch in M8"""
5722    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5723    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5724    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5725    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5726    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5727    wps_ext_eap_wsc(dev[0], hapd, bssid, "M2")
5728    wps_ext_eap_wsc(hapd, dev[0], addr, "M3")
5729    wps_ext_eap_wsc(dev[0], hapd, bssid, "M4")
5730    wps_ext_eap_wsc(hapd, dev[0], addr, "M5")
5731    wps_ext_eap_wsc(dev[0], hapd, bssid, "M6")
5732    wps_ext_eap_wsc(hapd, dev[0], addr, "M7")
5733    logger.debug("M8")
5734    wps_auth_corrupt_from_ap(dev[0], hapd, bssid, "msg=12")
5735
5736def test_ap_wps_authenticator_missing_m2(dev, apdev):
5737    """WPS and Authenticator attribute missing from M2"""
5738    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5739    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5740    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5741    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5742    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5743    logger.debug("M2")
5744    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5745    if ev is None:
5746        raise Exception("Timeout on EAPOL-TX")
5747    hapd.request("SET ext_eapol_frame_io 0")
5748    dev[0].request("SET ext_eapol_frame_io 0")
5749    msg = ev.split(' ')[2]
5750    if msg[-24:-16] != '10050008':
5751        raise Exception("Could not find Authenticator attribute")
5752    # Remove Authenticator value
5753    msg = msg[:-24]
5754    mlen = "%04x" % (int(msg[4:8], 16) - 12)
5755    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:]
5756    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5757    if "OK" not in res:
5758        raise Exception("EAPOL_RX failed")
5759    wps_fail_finish(hapd, dev[0], "msg=5")
5760
5761def test_ap_wps_m2_dev_passwd_id_p2p(dev, apdev):
5762    """WPS and M2 with different Device Password ID (P2P)"""
5763    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5764    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5765    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5766    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5767    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5768    logger.debug("M2")
5769    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5770    if ev is None:
5771        raise Exception("Timeout on EAPOL-TX")
5772    hapd.request("SET ext_eapol_frame_io 0")
5773    dev[0].request("SET ext_eapol_frame_io 0")
5774    msg = ev.split(' ')[2]
5775    if msg[722:730] != '10120002':
5776        raise Exception("Could not find Device Password ID attribute")
5777    # Replace Device Password ID value. This will fail Authenticator check, but
5778    # allows the code path in wps_process_dev_pw_id() to be checked from debug
5779    # log.
5780    msg = msg[0:730] + "0005" + msg[734:]
5781    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5782    if "OK" not in res:
5783        raise Exception("EAPOL_RX failed")
5784    wps_fail_finish(hapd, dev[0], "msg=5")
5785
5786def test_ap_wps_m2_dev_passwd_id_change_pin_to_pbc(dev, apdev):
5787    """WPS and M2 with different Device Password ID (PIN to PBC)"""
5788    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5789    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5790    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5791    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5792    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5793    logger.debug("M2")
5794    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5795    if ev is None:
5796        raise Exception("Timeout on EAPOL-TX")
5797    hapd.request("SET ext_eapol_frame_io 0")
5798    dev[0].request("SET ext_eapol_frame_io 0")
5799    msg = ev.split(' ')[2]
5800    if msg[722:730] != '10120002':
5801        raise Exception("Could not find Device Password ID attribute")
5802    # Replace Device Password ID value (PIN --> PBC). This will be rejected.
5803    msg = msg[0:730] + "0004" + msg[734:]
5804    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5805    if "OK" not in res:
5806        raise Exception("EAPOL_RX failed")
5807    wps_fail_finish(hapd, dev[0], "msg=5")
5808
5809def test_ap_wps_m2_dev_passwd_id_change_pbc_to_pin(dev, apdev):
5810    """WPS and M2 with different Device Password ID (PBC to PIN)"""
5811    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
5812    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5813    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5814    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5815    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5816    logger.debug("M2")
5817    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5818    if ev is None:
5819        raise Exception("Timeout on EAPOL-TX")
5820    hapd.request("SET ext_eapol_frame_io 0")
5821    dev[0].request("SET ext_eapol_frame_io 0")
5822    msg = ev.split(' ')[2]
5823    if msg[722:730] != '10120002':
5824        raise Exception("Could not find Device Password ID attribute")
5825    # Replace Device Password ID value. This will fail Authenticator check, but
5826    # allows the code path in wps_process_dev_pw_id() to be checked from debug
5827    # log.
5828    msg = msg[0:730] + "0000" + msg[734:]
5829    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5830    if "OK" not in res:
5831        raise Exception("EAPOL_RX failed")
5832    wps_fail_finish(hapd, dev[0], "msg=5")
5833    dev[0].flush_scan_cache()
5834
5835def test_ap_wps_m2_missing_dev_passwd_id(dev, apdev):
5836    """WPS and M2 without Device Password ID"""
5837    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0])
5838    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5839    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5840    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5841    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5842    logger.debug("M2")
5843    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5844    if ev is None:
5845        raise Exception("Timeout on EAPOL-TX")
5846    hapd.request("SET ext_eapol_frame_io 0")
5847    dev[0].request("SET ext_eapol_frame_io 0")
5848    msg = ev.split(' ')[2]
5849    if msg[722:730] != '10120002':
5850        raise Exception("Could not find Device Password ID attribute")
5851    # Remove Device Password ID value. This will fail Authenticator check, but
5852    # allows the code path in wps_process_dev_pw_id() to be checked from debug
5853    # log.
5854    mlen = "%04x" % (int(msg[4:8], 16) - 6)
5855    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:722] + msg[734:]
5856    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5857    if "OK" not in res:
5858        raise Exception("EAPOL_RX failed")
5859    wps_fail_finish(hapd, dev[0], "msg=5")
5860
5861def test_ap_wps_m2_missing_registrar_nonce(dev, apdev):
5862    """WPS and M2 without Registrar Nonce"""
5863    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
5864    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5865    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5866    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5867    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5868    logger.debug("M2")
5869    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5870    if ev is None:
5871        raise Exception("Timeout on EAPOL-TX")
5872    hapd.request("SET ext_eapol_frame_io 0")
5873    dev[0].request("SET ext_eapol_frame_io 0")
5874    msg = ev.split(' ')[2]
5875    if msg[96:104] != '10390010':
5876        raise Exception("Could not find Registrar Nonce attribute")
5877    # Remove Registrar Nonce. This will fail Authenticator check, but
5878    # allows the code path in wps_process_registrar_nonce() to be checked from
5879    # the debug log.
5880    mlen = "%04x" % (int(msg[4:8], 16) - 20)
5881    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:96] + msg[136:]
5882    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5883    if "OK" not in res:
5884        raise Exception("EAPOL_RX failed")
5885    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECT"], timeout=5)
5886    if ev is None:
5887        raise Exception("Disconnect event not seen")
5888    dev[0].request("WPS_CANCEL")
5889    dev[0].flush_scan_cache()
5890
5891def test_ap_wps_m2_missing_enrollee_nonce(dev, apdev):
5892    """WPS and M2 without Enrollee Nonce"""
5893    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
5894    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5895    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5896    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5897    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5898    logger.debug("M2")
5899    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5900    if ev is None:
5901        raise Exception("Timeout on EAPOL-TX")
5902    hapd.request("SET ext_eapol_frame_io 0")
5903    dev[0].request("SET ext_eapol_frame_io 0")
5904    msg = ev.split(' ')[2]
5905    if msg[56:64] != '101a0010':
5906        raise Exception("Could not find enrollee Nonce attribute")
5907    # Remove Enrollee Nonce. This will fail Authenticator check, but
5908    # allows the code path in wps_process_enrollee_nonce() to be checked from
5909    # the debug log.
5910    mlen = "%04x" % (int(msg[4:8], 16) - 20)
5911    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:56] + msg[96:]
5912    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5913    if "OK" not in res:
5914        raise Exception("EAPOL_RX failed")
5915    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECT"], timeout=5)
5916    if ev is None:
5917        raise Exception("Disconnect event not seen")
5918    dev[0].request("WPS_CANCEL")
5919    dev[0].flush_scan_cache()
5920
5921def test_ap_wps_m2_missing_uuid_r(dev, apdev):
5922    """WPS and M2 without UUID-R"""
5923    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
5924    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5925    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5926    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5927    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5928    logger.debug("M2")
5929    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5930    if ev is None:
5931        raise Exception("Timeout on EAPOL-TX")
5932    hapd.request("SET ext_eapol_frame_io 0")
5933    dev[0].request("SET ext_eapol_frame_io 0")
5934    msg = ev.split(' ')[2]
5935    if msg[136:144] != '10480010':
5936        raise Exception("Could not find enrollee Nonce attribute")
5937    # Remove UUID-R. This will fail Authenticator check, but allows the code
5938    # path in wps_process_uuid_r() to be checked from the debug log.
5939    mlen = "%04x" % (int(msg[4:8], 16) - 20)
5940    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:136] + msg[176:]
5941    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5942    if "OK" not in res:
5943        raise Exception("EAPOL_RX failed")
5944    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECT"], timeout=5)
5945    if ev is None:
5946        raise Exception("Disconnect event not seen")
5947    dev[0].request("WPS_CANCEL")
5948    dev[0].flush_scan_cache()
5949
5950def test_ap_wps_m2_invalid(dev, apdev):
5951    """WPS and M2 parsing failure"""
5952    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
5953    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5954    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5955    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5956    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5957    logger.debug("M2")
5958    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5959    if ev is None:
5960        raise Exception("Timeout on EAPOL-TX")
5961    hapd.request("SET ext_eapol_frame_io 0")
5962    dev[0].request("SET ext_eapol_frame_io 0")
5963    msg = ev.split(' ')[2]
5964    if msg[136:144] != '10480010':
5965        raise Exception("Could not find enrollee Nonce attribute")
5966    # Remove UUID-R. This will fail Authenticator check, but allows the code
5967    # path in wps_process_uuid_r() to be checked from the debug log.
5968    mlen = "%04x" % (int(msg[4:8], 16) - 1)
5969    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:-2]
5970    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
5971    if "OK" not in res:
5972        raise Exception("EAPOL_RX failed")
5973    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECT"], timeout=5)
5974    if ev is None:
5975        raise Exception("Disconnect event not seen")
5976    dev[0].request("WPS_CANCEL")
5977    dev[0].flush_scan_cache()
5978
5979def test_ap_wps_m2_missing_msg_type(dev, apdev):
5980    """WPS and M2 without Message Type"""
5981    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
5982    wps_ext_eap_identity_req(dev[0], hapd, bssid)
5983    wps_ext_eap_identity_resp(hapd, dev[0], addr)
5984    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
5985    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
5986    logger.debug("M2")
5987    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
5988    if ev is None:
5989        raise Exception("Timeout on EAPOL-TX")
5990    hapd.request("SET ext_eapol_frame_io 0")
5991    dev[0].request("SET ext_eapol_frame_io 0")
5992    msg = ev.split(' ')[2]
5993    if msg[46:54] != '10220001':
5994        raise Exception("Could not find Message Type attribute")
5995    # Remove Message Type. This will fail Authenticator check, but allows the
5996    # code path in wps_process_wsc_msg() to be checked from the debug log.
5997    mlen = "%04x" % (int(msg[4:8], 16) - 5)
5998    msg = msg[0:4] + mlen + msg[8:12] + mlen + msg[16:46] + msg[56:]
5999    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
6000    if "OK" not in res:
6001        raise Exception("EAPOL_RX failed")
6002    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECT"], timeout=5)
6003    if ev is None:
6004        raise Exception("Disconnect event not seen")
6005    dev[0].request("WPS_CANCEL")
6006    dev[0].flush_scan_cache()
6007
6008def test_ap_wps_m2_unknown_msg_type(dev, apdev):
6009    """WPS and M2 but unknown Message Type"""
6010    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
6011    wps_ext_eap_identity_req(dev[0], hapd, bssid)
6012    wps_ext_eap_identity_resp(hapd, dev[0], addr)
6013    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
6014    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
6015    logger.debug("M2")
6016    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
6017    if ev is None:
6018        raise Exception("Timeout on EAPOL-TX")
6019    hapd.request("SET ext_eapol_frame_io 0")
6020    dev[0].request("SET ext_eapol_frame_io 0")
6021    msg = ev.split(' ')[2]
6022    if msg[46:54] != '10220001':
6023        raise Exception("Could not find Message Type attribute")
6024    # Replace Message Type value. This will be rejected.
6025    msg = msg[0:54] + "00" + msg[56:]
6026    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
6027    if "OK" not in res:
6028        raise Exception("EAPOL_RX failed")
6029    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECT"], timeout=5)
6030    if ev is None:
6031        raise Exception("Disconnect event not seen")
6032    dev[0].request("WPS_CANCEL")
6033    dev[0].flush_scan_cache()
6034
6035def test_ap_wps_m2_unknown_opcode(dev, apdev):
6036    """WPS and M2 but unknown opcode"""
6037    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
6038    wps_ext_eap_identity_req(dev[0], hapd, bssid)
6039    wps_ext_eap_identity_resp(hapd, dev[0], addr)
6040    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
6041    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
6042    logger.debug("M2")
6043    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
6044    if ev is None:
6045        raise Exception("Timeout on EAPOL-TX")
6046    hapd.request("SET ext_eapol_frame_io 0")
6047    dev[0].request("SET ext_eapol_frame_io 0")
6048    msg = ev.split(' ')[2]
6049    # Replace opcode. This will be discarded in EAP-WSC processing.
6050    msg = msg[0:32] + "00" + msg[34:]
6051    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
6052    if "OK" not in res:
6053        raise Exception("EAPOL_RX failed")
6054    dev[0].request("WPS_CANCEL")
6055    dev[0].wait_disconnected()
6056    dev[0].flush_scan_cache()
6057
6058def test_ap_wps_m2_unknown_opcode2(dev, apdev):
6059    """WPS and M2 but unknown opcode (WSC_Start)"""
6060    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
6061    wps_ext_eap_identity_req(dev[0], hapd, bssid)
6062    wps_ext_eap_identity_resp(hapd, dev[0], addr)
6063    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
6064    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
6065    logger.debug("M2")
6066    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
6067    if ev is None:
6068        raise Exception("Timeout on EAPOL-TX")
6069    hapd.request("SET ext_eapol_frame_io 0")
6070    dev[0].request("SET ext_eapol_frame_io 0")
6071    msg = ev.split(' ')[2]
6072    # Replace opcode. This will be discarded in EAP-WSC processing.
6073    msg = msg[0:32] + "01" + msg[34:]
6074    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
6075    if "OK" not in res:
6076        raise Exception("EAPOL_RX failed")
6077    dev[0].request("WPS_CANCEL")
6078    dev[0].wait_disconnected()
6079    dev[0].flush_scan_cache()
6080
6081def test_ap_wps_m2_unknown_opcode3(dev, apdev):
6082    """WPS and M2 but unknown opcode (WSC_Done)"""
6083    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
6084    wps_ext_eap_identity_req(dev[0], hapd, bssid)
6085    wps_ext_eap_identity_resp(hapd, dev[0], addr)
6086    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
6087    wps_ext_eap_wsc(hapd, dev[0], addr, "M1")
6088    logger.debug("M2")
6089    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
6090    if ev is None:
6091        raise Exception("Timeout on EAPOL-TX")
6092    hapd.request("SET ext_eapol_frame_io 0")
6093    dev[0].request("SET ext_eapol_frame_io 0")
6094    msg = ev.split(' ')[2]
6095    # Replace opcode. This will be discarded in WPS Enrollee processing.
6096    msg = msg[0:32] + "05" + msg[34:]
6097    res = dev[0].request("EAPOL_RX " + bssid + " " + msg)
6098    if "OK" not in res:
6099        raise Exception("EAPOL_RX failed")
6100    dev[0].request("WPS_CANCEL")
6101    dev[0].wait_disconnected()
6102    dev[0].flush_scan_cache()
6103
6104def wps_m2_but_other(dev, apdev, title, msgtype):
6105    addr, bssid, hapd = wps_start_ext(apdev, dev)
6106    wps_ext_eap_identity_req(dev, hapd, bssid)
6107    wps_ext_eap_identity_resp(hapd, dev, addr)
6108    wps_ext_eap_wsc(dev, hapd, bssid, "EAP-WSC/Start")
6109    wps_ext_eap_wsc(hapd, dev, addr, "M1")
6110    logger.debug(title)
6111    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
6112    if ev is None:
6113        raise Exception("Timeout on EAPOL-TX")
6114    hapd.request("SET ext_eapol_frame_io 0")
6115    dev.request("SET ext_eapol_frame_io 0")
6116    msg = ev.split(' ')[2]
6117    if msg[46:54] != '10220001':
6118        raise Exception("Could not find Message Type attribute")
6119    # Replace Message Type value. This will be rejected.
6120    msg = msg[0:54] + msgtype + msg[56:]
6121    res = dev.request("EAPOL_RX " + bssid + " " + msg)
6122    if "OK" not in res:
6123        raise Exception("EAPOL_RX failed")
6124    ev = dev.wait_event(["WPS-FAIL"], timeout=5)
6125    if ev is None:
6126        raise Exception("WPS-FAIL event not seen")
6127    dev.request("WPS_CANCEL")
6128    dev.wait_disconnected()
6129
6130def wps_m4_but_other(dev, apdev, title, msgtype):
6131    addr, bssid, hapd = wps_start_ext(apdev, dev)
6132    wps_ext_eap_identity_req(dev, hapd, bssid)
6133    wps_ext_eap_identity_resp(hapd, dev, addr)
6134    wps_ext_eap_wsc(dev, hapd, bssid, "EAP-WSC/Start")
6135    wps_ext_eap_wsc(hapd, dev, addr, "M1")
6136    wps_ext_eap_wsc(dev, hapd, bssid, "M2")
6137    wps_ext_eap_wsc(hapd, dev, addr, "M3")
6138    logger.debug(title)
6139    ev = hapd.wait_event(["EAPOL-TX"], timeout=10)
6140    if ev is None:
6141        raise Exception("Timeout on EAPOL-TX")
6142    hapd.request("SET ext_eapol_frame_io 0")
6143    dev.request("SET ext_eapol_frame_io 0")
6144    msg = ev.split(' ')[2]
6145    if msg[46:54] != '10220001':
6146        raise Exception("Could not find Message Type attribute")
6147    # Replace Message Type value. This will be rejected.
6148    msg = msg[0:54] + msgtype + msg[56:]
6149    res = dev.request("EAPOL_RX " + bssid + " " + msg)
6150    if "OK" not in res:
6151        raise Exception("EAPOL_RX failed")
6152    ev = hapd.wait_event(["WPS-FAIL"], timeout=5)
6153    if ev is None:
6154        raise Exception("WPS-FAIL event not seen")
6155    dev.request("WPS_CANCEL")
6156    dev.wait_disconnected()
6157
6158def test_ap_wps_m2_msg_type_m4(dev, apdev):
6159    """WPS and M2 but Message Type M4"""
6160    wps_m2_but_other(dev[0], apdev[0], "M2/M4", "08")
6161
6162def test_ap_wps_m2_msg_type_m6(dev, apdev):
6163    """WPS and M2 but Message Type M6"""
6164    wps_m2_but_other(dev[0], apdev[0], "M2/M6", "0a")
6165
6166def test_ap_wps_m2_msg_type_m8(dev, apdev):
6167    """WPS and M2 but Message Type M8"""
6168    wps_m2_but_other(dev[0], apdev[0], "M2/M8", "0c")
6169
6170def test_ap_wps_m4_msg_type_m2(dev, apdev):
6171    """WPS and M4 but Message Type M2"""
6172    wps_m4_but_other(dev[0], apdev[0], "M4/M2", "05")
6173
6174def test_ap_wps_m4_msg_type_m2d(dev, apdev):
6175    """WPS and M4 but Message Type M2D"""
6176    wps_m4_but_other(dev[0], apdev[0], "M4/M2D", "06")
6177
6178@remote_compatible
6179def test_ap_wps_config_methods(dev, apdev):
6180    """WPS configuration method parsing"""
6181    ssid = "test-wps-conf"
6182    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
6183              "wpa_passphrase": "12345678", "wpa": "2",
6184              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
6185              "config_methods": "ethernet display ext_nfc_token int_nfc_token physical_display physical_push_button"}
6186    hapd = hostapd.add_ap(apdev[0], params)
6187    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
6188              "wpa_passphrase": "12345678", "wpa": "2",
6189              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
6190              "config_methods": "display push_button"}
6191    hapd2 = hostapd.add_ap(apdev[1], params)
6192
6193def test_ap_wps_set_selected_registrar_proto(dev, apdev):
6194    """WPS UPnP SetSelectedRegistrar protocol testing"""
6195    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
6196    hapd = add_ssdp_ap(apdev[0], ap_uuid)
6197
6198    location = ssdp_get_location(ap_uuid)
6199    urls = upnp_get_urls(location)
6200    eventurl = urlparse(urls['event_sub_url'])
6201    ctrlurl = urlparse(urls['control_url'])
6202    url = urlparse(location)
6203    conn = HTTPConnection(url.netloc)
6204
6205    class WPSERHTTPServer(StreamRequestHandler):
6206        def handle(self):
6207            data = self.rfile.readline().strip()
6208            logger.debug(data)
6209            self.wfile.write(gen_wps_event())
6210
6211    server = MyTCPServer(("127.0.0.1", 12345), WPSERHTTPServer)
6212    server.timeout = 1
6213
6214    headers = {"callback": '<http://127.0.0.1:12345/event>',
6215               "NT": "upnp:event",
6216               "timeout": "Second-1234"}
6217    conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
6218    resp = conn.getresponse()
6219    if resp.status != 200:
6220        raise Exception("Unexpected HTTP response: %d" % resp.status)
6221    sid = resp.getheader("sid")
6222    logger.debug("Subscription SID " + sid)
6223    server.handle_request()
6224
6225    tests = [(500, "10"),
6226             (200, "104a000110" + "1041000101" + "101200020000" +
6227              "105300023148" +
6228              "1049002c00372a0001200124111111111111222222222222333333333333444444444444555555555555666666666666" +
6229              "10480010362db47ba53a519188fb5458b986b2e4"),
6230             (200, "104a000110" + "1041000100" + "101200020000" +
6231              "105300020000"),
6232             (200, "104a000110" + "1041000100"),
6233             (200, "104a000110")]
6234    for status, test in tests:
6235        tlvs = binascii.unhexlify(test)
6236        newmsg = base64.b64encode(tlvs).decode()
6237        msg = '<?xml version="1.0"?>\n'
6238        msg += '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">'
6239        msg += '<s:Body>'
6240        msg += '<u:SetSelectedRegistrar xmlns:u="urn:schemas-wifialliance-org:service:WFAWLANConfig:1">'
6241        msg += '<NewMessage>'
6242        msg += newmsg
6243        msg += "</NewMessage></u:SetSelectedRegistrar></s:Body></s:Envelope>"
6244        headers = {"Content-type": 'text/xml; charset="utf-8"'}
6245        headers["SOAPAction"] = '"urn:schemas-wifialliance-org:service:WFAWLANConfig:1#%s"' % "SetSelectedRegistrar"
6246        conn.request("POST", ctrlurl.path, msg, headers)
6247        resp = conn.getresponse()
6248        if resp.status != status:
6249            raise Exception("Unexpected HTTP response: %d (expected %d)" % (resp.status, status))
6250
6251def test_ap_wps_adv_oom(dev, apdev):
6252    """WPS AP and advertisement OOM"""
6253    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
6254    hapd = add_ssdp_ap(apdev[0], ap_uuid)
6255
6256    with alloc_fail(hapd, 1, "=msearchreply_state_machine_start"):
6257        ssdp_send_msearch("urn:schemas-wifialliance-org:service:WFAWLANConfig:1",
6258                          no_recv=True)
6259        time.sleep(0.2)
6260
6261    with alloc_fail(hapd, 1, "eloop_register_timeout;msearchreply_state_machine_start"):
6262        ssdp_send_msearch("urn:schemas-wifialliance-org:service:WFAWLANConfig:1",
6263                          no_recv=True)
6264        time.sleep(0.2)
6265
6266    with alloc_fail(hapd, 1,
6267                    "next_advertisement;advertisement_state_machine_stop"):
6268        hapd.disable()
6269
6270    with alloc_fail(hapd, 1, "ssdp_listener_start"):
6271        if "FAIL" not in hapd.request("ENABLE"):
6272            raise Exception("ENABLE succeeded during OOM")
6273
6274def test_wps_config_methods(dev):
6275    """WPS config method update"""
6276    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
6277    wpas.interface_add("wlan5")
6278    if "OK" not in wpas.request("SET config_methods display label"):
6279        raise Exception("Failed to set config_methods")
6280    if wpas.request("GET config_methods").strip() != "display label":
6281        raise Exception("config_methods were not updated")
6282    if "OK" not in wpas.request("SET config_methods "):
6283        raise Exception("Failed to clear config_methods")
6284    if wpas.request("GET config_methods").strip() != "":
6285        raise Exception("config_methods were not cleared")
6286
6287WPS_VENDOR_ID_WFA = 14122
6288WPS_VENDOR_TYPE = 1
6289
6290# EAP-WSC Op-Code values
6291WSC_Start = 0x01
6292WSC_ACK = 0x02
6293WSC_NACK = 0x03
6294WSC_MSG = 0x04
6295WSC_Done = 0x05
6296WSC_FRAG_ACK = 0x06
6297
6298ATTR_AP_CHANNEL = 0x1001
6299ATTR_ASSOC_STATE = 0x1002
6300ATTR_AUTH_TYPE = 0x1003
6301ATTR_AUTH_TYPE_FLAGS = 0x1004
6302ATTR_AUTHENTICATOR = 0x1005
6303ATTR_CONFIG_METHODS = 0x1008
6304ATTR_CONFIG_ERROR = 0x1009
6305ATTR_CONFIRM_URL4 = 0x100a
6306ATTR_CONFIRM_URL6 = 0x100b
6307ATTR_CONN_TYPE = 0x100c
6308ATTR_CONN_TYPE_FLAGS = 0x100d
6309ATTR_CRED = 0x100e
6310ATTR_ENCR_TYPE = 0x100f
6311ATTR_ENCR_TYPE_FLAGS = 0x1010
6312ATTR_DEV_NAME = 0x1011
6313ATTR_DEV_PASSWORD_ID = 0x1012
6314ATTR_E_HASH1 = 0x1014
6315ATTR_E_HASH2 = 0x1015
6316ATTR_E_SNONCE1 = 0x1016
6317ATTR_E_SNONCE2 = 0x1017
6318ATTR_ENCR_SETTINGS = 0x1018
6319ATTR_ENROLLEE_NONCE = 0x101a
6320ATTR_FEATURE_ID = 0x101b
6321ATTR_IDENTITY = 0x101c
6322ATTR_IDENTITY_PROOF = 0x101d
6323ATTR_KEY_WRAP_AUTH = 0x101e
6324ATTR_KEY_ID = 0x101f
6325ATTR_MAC_ADDR = 0x1020
6326ATTR_MANUFACTURER = 0x1021
6327ATTR_MSG_TYPE = 0x1022
6328ATTR_MODEL_NAME = 0x1023
6329ATTR_MODEL_NUMBER = 0x1024
6330ATTR_NETWORK_INDEX = 0x1026
6331ATTR_NETWORK_KEY = 0x1027
6332ATTR_NETWORK_KEY_INDEX = 0x1028
6333ATTR_NEW_DEVICE_NAME = 0x1029
6334ATTR_NEW_PASSWORD = 0x102a
6335ATTR_OOB_DEVICE_PASSWORD = 0x102c
6336ATTR_OS_VERSION = 0x102d
6337ATTR_POWER_LEVEL = 0x102f
6338ATTR_PSK_CURRENT = 0x1030
6339ATTR_PSK_MAX = 0x1031
6340ATTR_PUBLIC_KEY = 0x1032
6341ATTR_RADIO_ENABLE = 0x1033
6342ATTR_REBOOT = 0x1034
6343ATTR_REGISTRAR_CURRENT = 0x1035
6344ATTR_REGISTRAR_ESTABLISHED = 0x1036
6345ATTR_REGISTRAR_LIST = 0x1037
6346ATTR_REGISTRAR_MAX = 0x1038
6347ATTR_REGISTRAR_NONCE = 0x1039
6348ATTR_REQUEST_TYPE = 0x103a
6349ATTR_RESPONSE_TYPE = 0x103b
6350ATTR_RF_BANDS = 0x103c
6351ATTR_R_HASH1 = 0x103d
6352ATTR_R_HASH2 = 0x103e
6353ATTR_R_SNONCE1 = 0x103f
6354ATTR_R_SNONCE2 = 0x1040
6355ATTR_SELECTED_REGISTRAR = 0x1041
6356ATTR_SERIAL_NUMBER = 0x1042
6357ATTR_WPS_STATE = 0x1044
6358ATTR_SSID = 0x1045
6359ATTR_TOTAL_NETWORKS = 0x1046
6360ATTR_UUID_E = 0x1047
6361ATTR_UUID_R = 0x1048
6362ATTR_VENDOR_EXT = 0x1049
6363ATTR_VERSION = 0x104a
6364ATTR_X509_CERT_REQ = 0x104b
6365ATTR_X509_CERT = 0x104c
6366ATTR_EAP_IDENTITY = 0x104d
6367ATTR_MSG_COUNTER = 0x104e
6368ATTR_PUBKEY_HASH = 0x104f
6369ATTR_REKEY_KEY = 0x1050
6370ATTR_KEY_LIFETIME = 0x1051
6371ATTR_PERMITTED_CFG_METHODS = 0x1052
6372ATTR_SELECTED_REGISTRAR_CONFIG_METHODS = 0x1053
6373ATTR_PRIMARY_DEV_TYPE = 0x1054
6374ATTR_SECONDARY_DEV_TYPE_LIST = 0x1055
6375ATTR_PORTABLE_DEV = 0x1056
6376ATTR_AP_SETUP_LOCKED = 0x1057
6377ATTR_APPLICATION_EXT = 0x1058
6378ATTR_EAP_TYPE = 0x1059
6379ATTR_IV = 0x1060
6380ATTR_KEY_PROVIDED_AUTO = 0x1061
6381ATTR_802_1X_ENABLED = 0x1062
6382ATTR_APPSESSIONKEY = 0x1063
6383ATTR_WEPTRANSMITKEY = 0x1064
6384ATTR_REQUESTED_DEV_TYPE = 0x106a
6385
6386# Message Type
6387WPS_Beacon = 0x01
6388WPS_ProbeRequest = 0x02
6389WPS_ProbeResponse = 0x03
6390WPS_M1 = 0x04
6391WPS_M2 = 0x05
6392WPS_M2D = 0x06
6393WPS_M3 = 0x07
6394WPS_M4 = 0x08
6395WPS_M5 = 0x09
6396WPS_M6 = 0x0a
6397WPS_M7 = 0x0b
6398WPS_M8 = 0x0c
6399WPS_WSC_ACK = 0x0d
6400WPS_WSC_NACK = 0x0e
6401WPS_WSC_DONE = 0x0f
6402
6403def get_wsc_msg(dev):
6404    ev = dev.wait_event(["EAPOL-TX"], timeout=10)
6405    if ev is None:
6406        raise Exception("Timeout on EAPOL-TX")
6407    data = binascii.unhexlify(ev.split(' ')[2])
6408    msg = {}
6409
6410    # Parse EAPOL header
6411    if len(data) < 4:
6412        raise Exception("No room for EAPOL header")
6413    version, type, length = struct.unpack('>BBH', data[0:4])
6414    msg['eapol_version'] = version
6415    msg['eapol_type'] = type
6416    msg['eapol_length'] = length
6417    data = data[4:]
6418    if length != len(data):
6419        raise Exception("EAPOL header length mismatch (%d != %d)" % (length, len(data)))
6420    if type != 0:
6421        raise Exception("Unexpected EAPOL header type: %d" % type)
6422
6423    # Parse EAP header
6424    if len(data) < 4:
6425        raise Exception("No room for EAP header")
6426    code, identifier, length = struct.unpack('>BBH', data[0:4])
6427    msg['eap_code'] = code
6428    msg['eap_identifier'] = identifier
6429    msg['eap_length'] = length
6430    data = data[4:]
6431    if msg['eapol_length'] != msg['eap_length']:
6432        raise Exception("EAP header length mismatch (%d != %d)" % (msg['eapol_length'], length))
6433
6434    # Parse EAP expanded header
6435    if len(data) < 1:
6436        raise Exception("No EAP type included")
6437    msg['eap_type'], = struct.unpack('B', data[0:1])
6438    data = data[1:]
6439
6440    if msg['eap_type'] == 254:
6441        if len(data) < 3 + 4:
6442            raise Exception("Truncated EAP expanded header")
6443        msg['eap_vendor_id'], msg['eap_vendor_type'] = struct.unpack('>LL', b'\x00' + data[0:7])
6444        data = data[7:]
6445    else:
6446        raise Exception("Unexpected EAP type")
6447
6448    if msg['eap_vendor_id'] != WPS_VENDOR_ID_WFA:
6449        raise Exception("Unexpected Vendor-Id")
6450    if msg['eap_vendor_type'] != WPS_VENDOR_TYPE:
6451        raise Exception("Unexpected Vendor-Type")
6452
6453    # Parse EAP-WSC header
6454    if len(data) < 2:
6455        raise Exception("Truncated EAP-WSC header")
6456    msg['wsc_opcode'], msg['wsc_flags'] = struct.unpack('BB', data[0:2])
6457    data = data[2:]
6458
6459    # Parse WSC attributes
6460    msg['raw_attrs'] = data
6461    attrs = {}
6462    while len(data) > 0:
6463        if len(data) < 4:
6464            raise Exception("Truncated attribute header")
6465        attr, length = struct.unpack('>HH', data[0:4])
6466        data = data[4:]
6467        if length > len(data):
6468            raise Exception("Truncated attribute 0x%04x" % attr)
6469        attrs[attr] = data[0:length]
6470        data = data[length:]
6471    msg['wsc_attrs'] = attrs
6472
6473    if ATTR_MSG_TYPE in attrs:
6474        msg['wsc_msg_type'], = struct.unpack('B', attrs[ATTR_MSG_TYPE])
6475
6476    return msg
6477
6478def recv_wsc_msg(dev, opcode, msg_type):
6479    msg = get_wsc_msg(dev)
6480    if msg['wsc_opcode'] != opcode or msg['wsc_msg_type'] != msg_type:
6481        raise Exception("Unexpected Op-Code/MsgType")
6482    return msg, msg['wsc_attrs'], msg['raw_attrs']
6483
6484def build_wsc_attr(attr, payload):
6485    _payload = payload if type(payload) == bytes else payload.encode()
6486    return struct.pack('>HH', attr, len(_payload)) + _payload
6487
6488def build_attr_msg_type(msg_type):
6489    return build_wsc_attr(ATTR_MSG_TYPE, struct.pack('B', msg_type))
6490
6491def build_eap_wsc(eap_code, eap_id, payload, opcode=WSC_MSG):
6492    length = 4 + 8 + 2 + len(payload)
6493    # EAPOL header
6494    msg = struct.pack('>BBH', 2, 0, length)
6495    # EAP header
6496    msg += struct.pack('>BBH', eap_code, eap_id, length)
6497    # EAP expanded header for EAP-WSC
6498    msg += struct.pack('B', 254)
6499    msg += struct.pack('>L', WPS_VENDOR_ID_WFA)[1:4]
6500    msg += struct.pack('>L', WPS_VENDOR_TYPE)
6501    # EAP-WSC header
6502    msg += struct.pack('BB', opcode, 0)
6503    # WSC attributes
6504    msg += payload
6505    return msg
6506
6507def build_eap_success(eap_id):
6508    length = 4
6509    # EAPOL header
6510    msg = struct.pack('>BBH', 2, 0, length)
6511    # EAP header
6512    msg += struct.pack('>BBH', 3, eap_id, length)
6513    return msg
6514
6515def build_eap_failure(eap_id):
6516    length = 4
6517    # EAPOL header
6518    msg = struct.pack('>BBH', 2, 0, length)
6519    # EAP header
6520    msg += struct.pack('>BBH', 4, eap_id, length)
6521    return msg
6522
6523def send_wsc_msg(dev, src, msg):
6524    res = dev.request("EAPOL_RX " + src + " " + binascii.hexlify(msg).decode())
6525    if "OK" not in res:
6526        raise Exception("EAPOL_RX failed")
6527
6528group_5_prime = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF
6529group_5_generator = 2
6530
6531def wsc_kdf(key, label, bits):
6532    result = b''
6533    i = 1
6534    while len(result) * 8 < bits:
6535        data = struct.pack('>L', i) + label.encode() + struct.pack('>L', bits)
6536        m = hmac.new(key, data, hashlib.sha256)
6537        result += m.digest()
6538        i += 1
6539    return result[0:bits // 8]
6540
6541def wsc_keys(kdk):
6542    keys = wsc_kdf(kdk, "Wi-Fi Easy and Secure Key Derivation", 640)
6543    authkey = keys[0:32]
6544    keywrapkey = keys[32:48]
6545    emsk = keys[48:80]
6546    return authkey, keywrapkey, emsk
6547
6548def wsc_dev_pw_half_psk(authkey, dev_pw):
6549    m = hmac.new(authkey, dev_pw.encode(), hashlib.sha256)
6550    return m.digest()[0:16]
6551
6552def wsc_dev_pw_psk(authkey, dev_pw):
6553    dev_pw_1 = dev_pw[0:len(dev_pw) // 2]
6554    dev_pw_2 = dev_pw[len(dev_pw) // 2:]
6555    psk1 = wsc_dev_pw_half_psk(authkey, dev_pw_1)
6556    psk2 = wsc_dev_pw_half_psk(authkey, dev_pw_2)
6557    return psk1, psk2
6558
6559def build_attr_authenticator(authkey, prev_msg, curr_msg):
6560    m = hmac.new(authkey, prev_msg + curr_msg, hashlib.sha256)
6561    auth = m.digest()[0:8]
6562    return build_wsc_attr(ATTR_AUTHENTICATOR, auth)
6563
6564def build_attr_encr_settings(authkey, keywrapkey, data):
6565    m = hmac.new(authkey, data, hashlib.sha256)
6566    kwa = m.digest()[0:8]
6567    data += build_wsc_attr(ATTR_KEY_WRAP_AUTH, kwa)
6568    iv = 16*b'\x99'
6569    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
6570    pad_len = 16 - len(data) % 16
6571    ps = pad_len * struct.pack('B', pad_len)
6572    data += ps
6573    wrapped = aes.encrypt(data)
6574    return build_wsc_attr(ATTR_ENCR_SETTINGS, iv + wrapped)
6575
6576def decrypt_attr_encr_settings(authkey, keywrapkey, data):
6577    if len(data) < 32 or len(data) % 16 != 0:
6578        raise Exception("Unexpected Encrypted Settings length: %d" % len(data))
6579    iv = data[0:16]
6580    encr = data[16:]
6581    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
6582    decrypted = aes.decrypt(encr)
6583    pad_len, = struct.unpack('B', decrypted[-1:])
6584    if pad_len > len(decrypted):
6585        raise Exception("Invalid padding in Encrypted Settings")
6586    for i in range(-pad_len, -1):
6587        if decrypted[i] != decrypted[-1]:
6588            raise Exception("Invalid PS value in Encrypted Settings")
6589
6590    decrypted = decrypted[0:len(decrypted) - pad_len]
6591    if len(decrypted) < 12:
6592        raise Exception("Truncated Encrypted Settings plaintext")
6593    kwa = decrypted[-12:]
6594    attr, length = struct.unpack(">HH", kwa[0:4])
6595    if attr != ATTR_KEY_WRAP_AUTH or length != 8:
6596        raise Exception("Invalid KWA header")
6597    kwa = kwa[4:]
6598    decrypted = decrypted[0:len(decrypted) - 12]
6599
6600    m = hmac.new(authkey, decrypted, hashlib.sha256)
6601    calc_kwa = m.digest()[0:8]
6602    if kwa != calc_kwa:
6603        raise Exception("KWA mismatch")
6604
6605    return decrypted
6606
6607def zeropad_str(val, pad_len):
6608    while len(val) < pad_len * 2:
6609        val = '0' + val
6610    return val
6611
6612def wsc_dh_init():
6613    # For now, use a hardcoded private key. In theory, this is supposed to be
6614    # randomly selected.
6615    own_private = 0x123456789
6616    own_public = pow(group_5_generator, own_private, group_5_prime)
6617    pk = binascii.unhexlify(zeropad_str(format(own_public, '02x'), 192))
6618    return own_private, pk
6619
6620def wsc_dh_kdf(peer_pk, own_private, mac_addr, e_nonce, r_nonce):
6621    peer_public = int(binascii.hexlify(peer_pk), 16)
6622    if peer_public < 2 or peer_public >= group_5_prime:
6623        raise Exception("Invalid peer public key")
6624    if pow(peer_public, (group_5_prime - 1) // 2, group_5_prime) != 1:
6625        raise Exception("Unexpected Legendre symbol for peer public key")
6626
6627    shared_secret = pow(peer_public, own_private, group_5_prime)
6628    ss = zeropad_str(format(shared_secret, "02x"), 192)
6629    logger.debug("DH shared secret: " + ss)
6630
6631    dhkey = hashlib.sha256(binascii.unhexlify(ss)).digest()
6632    logger.debug("DHKey: " + binascii.hexlify(dhkey).decode())
6633
6634    m = hmac.new(dhkey, e_nonce + mac_addr + r_nonce, hashlib.sha256)
6635    kdk = m.digest()
6636    logger.debug("KDK: " + binascii.hexlify(kdk).decode())
6637    authkey, keywrapkey, emsk = wsc_keys(kdk)
6638    logger.debug("AuthKey: " + binascii.hexlify(authkey).decode())
6639    logger.debug("KeyWrapKey: " + binascii.hexlify(keywrapkey).decode())
6640    logger.debug("EMSK: " + binascii.hexlify(emsk).decode())
6641    return authkey, keywrapkey
6642
6643def wsc_dev_pw_hash(authkey, dev_pw, e_pk, r_pk):
6644    psk1, psk2 = wsc_dev_pw_psk(authkey, dev_pw)
6645    logger.debug("PSK1: " + binascii.hexlify(psk1).decode())
6646    logger.debug("PSK2: " + binascii.hexlify(psk2).decode())
6647
6648    # Note: Secret values are supposed to be random, but hardcoded values are
6649    # fine for testing.
6650    s1 = 16*b'\x77'
6651    m = hmac.new(authkey, s1 + psk1 + e_pk + r_pk, hashlib.sha256)
6652    hash1 = m.digest()
6653    logger.debug("Hash1: " + binascii.hexlify(hash1).decode())
6654
6655    s2 = 16*b'\x88'
6656    m = hmac.new(authkey, s2 + psk2 + e_pk + r_pk, hashlib.sha256)
6657    hash2 = m.digest()
6658    logger.debug("Hash2: " + binascii.hexlify(hash2).decode())
6659    return s1, s2, hash1, hash2
6660
6661def build_m1(eap_id, uuid_e, mac_addr, e_nonce, e_pk,
6662             manufacturer='', model_name='', config_methods='\x00\x00'):
6663    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6664    attrs += build_attr_msg_type(WPS_M1)
6665    attrs += build_wsc_attr(ATTR_UUID_E, uuid_e)
6666    attrs += build_wsc_attr(ATTR_MAC_ADDR, mac_addr)
6667    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
6668    attrs += build_wsc_attr(ATTR_PUBLIC_KEY, e_pk)
6669    attrs += build_wsc_attr(ATTR_AUTH_TYPE_FLAGS, '\x00\x00')
6670    attrs += build_wsc_attr(ATTR_ENCR_TYPE_FLAGS, '\x00\x00')
6671    attrs += build_wsc_attr(ATTR_CONN_TYPE_FLAGS, '\x00')
6672    attrs += build_wsc_attr(ATTR_CONFIG_METHODS, config_methods)
6673    attrs += build_wsc_attr(ATTR_WPS_STATE, '\x00')
6674    attrs += build_wsc_attr(ATTR_MANUFACTURER, manufacturer)
6675    attrs += build_wsc_attr(ATTR_MODEL_NAME, model_name)
6676    attrs += build_wsc_attr(ATTR_MODEL_NUMBER, '')
6677    attrs += build_wsc_attr(ATTR_SERIAL_NUMBER, '')
6678    attrs += build_wsc_attr(ATTR_PRIMARY_DEV_TYPE, 8*'\x00')
6679    attrs += build_wsc_attr(ATTR_DEV_NAME, '')
6680    attrs += build_wsc_attr(ATTR_RF_BANDS, '\x00')
6681    attrs += build_wsc_attr(ATTR_ASSOC_STATE, '\x00\x00')
6682    attrs += build_wsc_attr(ATTR_DEV_PASSWORD_ID, '\x00\x00')
6683    attrs += build_wsc_attr(ATTR_CONFIG_ERROR, '\x00\x00')
6684    attrs += build_wsc_attr(ATTR_OS_VERSION, '\x00\x00\x00\x00')
6685    m1 = build_eap_wsc(2, eap_id, attrs)
6686    return m1, attrs
6687
6688def build_m2(authkey, m1, eap_id, e_nonce, r_nonce, uuid_r, r_pk,
6689             dev_pw_id='\x00\x00', eap_code=1):
6690    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6691    attrs += build_attr_msg_type(WPS_M2)
6692    if e_nonce:
6693        attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
6694    if r_nonce:
6695        attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
6696    attrs += build_wsc_attr(ATTR_UUID_R, uuid_r)
6697    if r_pk:
6698        attrs += build_wsc_attr(ATTR_PUBLIC_KEY, r_pk)
6699    attrs += build_wsc_attr(ATTR_AUTH_TYPE_FLAGS, '\x00\x00')
6700    attrs += build_wsc_attr(ATTR_ENCR_TYPE_FLAGS, '\x00\x00')
6701    attrs += build_wsc_attr(ATTR_CONN_TYPE_FLAGS, '\x00')
6702    attrs += build_wsc_attr(ATTR_CONFIG_METHODS, '\x00\x00')
6703    attrs += build_wsc_attr(ATTR_MANUFACTURER, '')
6704    attrs += build_wsc_attr(ATTR_MODEL_NAME, '')
6705    attrs += build_wsc_attr(ATTR_MODEL_NUMBER, '')
6706    attrs += build_wsc_attr(ATTR_SERIAL_NUMBER, '')
6707    attrs += build_wsc_attr(ATTR_PRIMARY_DEV_TYPE, 8*'\x00')
6708    attrs += build_wsc_attr(ATTR_DEV_NAME, '')
6709    attrs += build_wsc_attr(ATTR_RF_BANDS, '\x00')
6710    attrs += build_wsc_attr(ATTR_ASSOC_STATE, '\x00\x00')
6711    attrs += build_wsc_attr(ATTR_CONFIG_ERROR, '\x00\x00')
6712    attrs += build_wsc_attr(ATTR_DEV_PASSWORD_ID, dev_pw_id)
6713    attrs += build_wsc_attr(ATTR_OS_VERSION, '\x00\x00\x00\x00')
6714    attrs += build_attr_authenticator(authkey, m1, attrs)
6715    m2 = build_eap_wsc(eap_code, eap_id, attrs)
6716    return m2, attrs
6717
6718def build_m2d(m1, eap_id, e_nonce, r_nonce, uuid_r, dev_pw_id=None, eap_code=1):
6719    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6720    attrs += build_attr_msg_type(WPS_M2D)
6721    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
6722    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
6723    attrs += build_wsc_attr(ATTR_UUID_R, uuid_r)
6724    attrs += build_wsc_attr(ATTR_AUTH_TYPE_FLAGS, '\x00\x00')
6725    attrs += build_wsc_attr(ATTR_ENCR_TYPE_FLAGS, '\x00\x00')
6726    attrs += build_wsc_attr(ATTR_CONN_TYPE_FLAGS, '\x00')
6727    attrs += build_wsc_attr(ATTR_CONFIG_METHODS, '\x00\x00')
6728    attrs += build_wsc_attr(ATTR_MANUFACTURER, '')
6729    attrs += build_wsc_attr(ATTR_MODEL_NAME, '')
6730    #attrs += build_wsc_attr(ATTR_MODEL_NUMBER, '')
6731    attrs += build_wsc_attr(ATTR_SERIAL_NUMBER, '')
6732    attrs += build_wsc_attr(ATTR_PRIMARY_DEV_TYPE, 8*'\x00')
6733    attrs += build_wsc_attr(ATTR_DEV_NAME, '')
6734    attrs += build_wsc_attr(ATTR_RF_BANDS, '\x00')
6735    attrs += build_wsc_attr(ATTR_ASSOC_STATE, '\x00\x00')
6736    attrs += build_wsc_attr(ATTR_CONFIG_ERROR, '\x00\x00')
6737    attrs += build_wsc_attr(ATTR_OS_VERSION, '\x00\x00\x00\x00')
6738    if dev_pw_id:
6739        attrs += build_wsc_attr(ATTR_DEV_PASSWORD_ID, dev_pw_id)
6740    m2d = build_eap_wsc(eap_code, eap_id, attrs)
6741    return m2d, attrs
6742
6743def build_ack(eap_id, e_nonce, r_nonce, msg_type=WPS_WSC_ACK, eap_code=1):
6744    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6745    if msg_type is not None:
6746        attrs += build_attr_msg_type(msg_type)
6747    if e_nonce:
6748        attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
6749    if r_nonce:
6750        attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
6751    msg = build_eap_wsc(eap_code, eap_id, attrs, opcode=WSC_ACK)
6752    return msg, attrs
6753
6754def build_nack(eap_id, e_nonce, r_nonce, config_error='\x00\x00',
6755               msg_type=WPS_WSC_NACK, eap_code=1):
6756    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6757    if msg_type is not None:
6758        attrs += build_attr_msg_type(msg_type)
6759    if e_nonce:
6760        attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
6761    if r_nonce:
6762        attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
6763    if config_error:
6764        attrs += build_wsc_attr(ATTR_CONFIG_ERROR, config_error)
6765    msg = build_eap_wsc(eap_code, eap_id, attrs, opcode=WSC_NACK)
6766    return msg, attrs
6767
6768def test_wps_ext(dev, apdev):
6769    """WPS against external implementation"""
6770    pin = "12345670"
6771    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
6772    wps_ext_eap_identity_req(dev[0], hapd, bssid)
6773    wps_ext_eap_identity_resp(hapd, dev[0], addr)
6774
6775    logger.debug("Receive WSC/Start from AP")
6776    msg = get_wsc_msg(hapd)
6777    if msg['wsc_opcode'] != WSC_Start:
6778        raise Exception("Unexpected Op-Code for WSC/Start")
6779    wsc_start_id = msg['eap_identifier']
6780
6781    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
6782    uuid_e = 16*b'\x11'
6783    e_nonce = 16*b'\x22'
6784    own_private, e_pk = wsc_dh_init()
6785
6786    logger.debug("Send M1 to AP")
6787    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
6788                                e_nonce, e_pk)
6789    send_wsc_msg(hapd, addr, m1)
6790
6791    logger.debug("Receive M2 from AP")
6792    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
6793
6794    authkey, keywrapkey = wsc_dh_kdf(m2_attrs[ATTR_PUBLIC_KEY], own_private,
6795                                     mac_addr, e_nonce,
6796                                     m2_attrs[ATTR_REGISTRAR_NONCE])
6797    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk,
6798                                                   m2_attrs[ATTR_PUBLIC_KEY])
6799
6800    logger.debug("Send M3 to AP")
6801    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6802    attrs += build_attr_msg_type(WPS_M3)
6803    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE,
6804                            m2_attrs[ATTR_REGISTRAR_NONCE])
6805    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
6806    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
6807    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
6808    raw_m3_attrs = attrs
6809    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
6810    send_wsc_msg(hapd, addr, m3)
6811
6812    logger.debug("Receive M4 from AP")
6813    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
6814
6815    logger.debug("Send M5 to AP")
6816    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6817    attrs += build_attr_msg_type(WPS_M5)
6818    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE,
6819                            m2_attrs[ATTR_REGISTRAR_NONCE])
6820    data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
6821    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
6822    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
6823    raw_m5_attrs = attrs
6824    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
6825    send_wsc_msg(hapd, addr, m5)
6826
6827    logger.debug("Receive M6 from AP")
6828    msg, m6_attrs, raw_m6_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M6)
6829
6830    logger.debug("Send M7 to AP")
6831    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6832    attrs += build_attr_msg_type(WPS_M7)
6833    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE,
6834                            m2_attrs[ATTR_REGISTRAR_NONCE])
6835    data = build_wsc_attr(ATTR_E_SNONCE2, e_s2)
6836    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
6837    attrs += build_attr_authenticator(authkey, raw_m6_attrs, attrs)
6838    m7 = build_eap_wsc(2, msg['eap_identifier'], attrs)
6839    raw_m7_attrs = attrs
6840    send_wsc_msg(hapd, addr, m7)
6841
6842    logger.debug("Receive M8 from AP")
6843    msg, m8_attrs, raw_m8_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M8)
6844    m8_cred = decrypt_attr_encr_settings(authkey, keywrapkey,
6845                                         m8_attrs[ATTR_ENCR_SETTINGS])
6846    logger.debug("M8 Credential: " + binascii.hexlify(m8_cred).decode())
6847
6848    logger.debug("Prepare WSC_Done")
6849    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6850    attrs += build_attr_msg_type(WPS_WSC_DONE)
6851    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
6852    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE,
6853                            m2_attrs[ATTR_REGISTRAR_NONCE])
6854    wsc_done = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
6855    # Do not send WSC_Done yet to allow exchangw with STA complete before the
6856    # AP disconnects.
6857
6858    uuid_r = 16*b'\x33'
6859    r_nonce = 16*b'\x44'
6860
6861    eap_id = wsc_start_id
6862    logger.debug("Send WSC/Start to STA")
6863    wsc_start = build_eap_wsc(1, eap_id, b'', opcode=WSC_Start)
6864    send_wsc_msg(dev[0], bssid, wsc_start)
6865    eap_id = (eap_id + 1) % 256
6866
6867    logger.debug("Receive M1 from STA")
6868    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
6869
6870    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
6871                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
6872                                     r_nonce)
6873    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
6874                                                   m1_attrs[ATTR_PUBLIC_KEY],
6875                                                   e_pk)
6876
6877    logger.debug("Send M2 to STA")
6878    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
6879                                m1_attrs[ATTR_ENROLLEE_NONCE],
6880                                r_nonce, uuid_r, e_pk)
6881    send_wsc_msg(dev[0], bssid, m2)
6882    eap_id = (eap_id + 1) % 256
6883
6884    logger.debug("Receive M3 from STA")
6885    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
6886
6887    logger.debug("Send M4 to STA")
6888    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6889    attrs += build_attr_msg_type(WPS_M4)
6890    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, m1_attrs[ATTR_ENROLLEE_NONCE])
6891    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
6892    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
6893    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
6894    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
6895    attrs += build_attr_authenticator(authkey, raw_m3_attrs, attrs)
6896    raw_m4_attrs = attrs
6897    m4 = build_eap_wsc(1, eap_id, attrs)
6898    send_wsc_msg(dev[0], bssid, m4)
6899    eap_id = (eap_id + 1) % 256
6900
6901    logger.debug("Receive M5 from STA")
6902    msg, m5_attrs, raw_m5_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M5)
6903
6904    logger.debug("Send M6 to STA")
6905    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6906    attrs += build_attr_msg_type(WPS_M6)
6907    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE,
6908                            m1_attrs[ATTR_ENROLLEE_NONCE])
6909    data = build_wsc_attr(ATTR_R_SNONCE2, r_s2)
6910    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
6911    attrs += build_attr_authenticator(authkey, raw_m5_attrs, attrs)
6912    raw_m6_attrs = attrs
6913    m6 = build_eap_wsc(1, eap_id, attrs)
6914    send_wsc_msg(dev[0], bssid, m6)
6915    eap_id = (eap_id + 1) % 256
6916
6917    logger.debug("Receive M7 from STA")
6918    msg, m7_attrs, raw_m7_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M7)
6919
6920    logger.debug("Send M8 to STA")
6921    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6922    attrs += build_attr_msg_type(WPS_M8)
6923    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE,
6924                            m1_attrs[ATTR_ENROLLEE_NONCE])
6925    attrs += build_attr_encr_settings(authkey, keywrapkey, m8_cred)
6926    attrs += build_attr_authenticator(authkey, raw_m7_attrs, attrs)
6927    raw_m8_attrs = attrs
6928    m8 = build_eap_wsc(1, eap_id, attrs)
6929    send_wsc_msg(dev[0], bssid, m8)
6930    eap_id = (eap_id + 1) % 256
6931
6932    ev = dev[0].wait_event(["WPS-CRED-RECEIVED"], timeout=5)
6933    if ev is None:
6934        raise Exception("wpa_supplicant did not report credential")
6935
6936    logger.debug("Receive WSC_Done from STA")
6937    msg = get_wsc_msg(dev[0])
6938    if msg['wsc_opcode'] != WSC_Done or msg['wsc_msg_type'] != WPS_WSC_DONE:
6939        raise Exception("Unexpected Op-Code/MsgType for WSC_Done")
6940
6941    logger.debug("Send WSC_Done to AP")
6942    hapd.request("SET ext_eapol_frame_io 0")
6943    dev[0].request("SET ext_eapol_frame_io 0")
6944    send_wsc_msg(hapd, addr, wsc_done)
6945
6946    ev = hapd.wait_event(["WPS-REG-SUCCESS"], timeout=5)
6947    if ev is None:
6948        raise Exception("hostapd did not report WPS success")
6949
6950    dev[0].wait_connected()
6951
6952def wps_start_kwa(dev, apdev):
6953    pin = "12345670"
6954    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
6955    wps_ext_eap_identity_req(dev[0], hapd, bssid)
6956    wps_ext_eap_identity_resp(hapd, dev[0], addr)
6957    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
6958
6959    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
6960    uuid_r = 16*b'\x33'
6961    r_nonce = 16*b'\x44'
6962    own_private, e_pk = wsc_dh_init()
6963
6964    logger.debug("Receive M1 from STA")
6965    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
6966    eap_id = (msg['eap_identifier'] + 1) % 256
6967
6968    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
6969                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
6970                                     r_nonce)
6971    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
6972                                                   m1_attrs[ATTR_PUBLIC_KEY],
6973                                                   e_pk)
6974
6975    logger.debug("Send M2 to STA")
6976    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
6977                                m1_attrs[ATTR_ENROLLEE_NONCE],
6978                                r_nonce, uuid_r, e_pk)
6979    send_wsc_msg(dev[0], bssid, m2)
6980    eap_id = (eap_id + 1) % 256
6981
6982    logger.debug("Receive M3 from STA")
6983    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
6984
6985    logger.debug("Send M4 to STA")
6986    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
6987    attrs += build_attr_msg_type(WPS_M4)
6988    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, m1_attrs[ATTR_ENROLLEE_NONCE])
6989    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
6990    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
6991
6992    return r_s1, keywrapkey, authkey, raw_m3_attrs, eap_id, bssid, attrs
6993
6994def wps_stop_kwa(dev, bssid, attrs, authkey, raw_m3_attrs, eap_id):
6995    attrs += build_attr_authenticator(authkey, raw_m3_attrs, attrs)
6996    m4 = build_eap_wsc(1, eap_id, attrs)
6997    send_wsc_msg(dev[0], bssid, m4)
6998    eap_id = (eap_id + 1) % 256
6999
7000    logger.debug("Receive M5 from STA")
7001    msg = get_wsc_msg(dev[0])
7002    if msg['wsc_opcode'] != WSC_NACK:
7003        raise Exception("Unexpected message - expected WSC_Nack")
7004
7005    dev[0].request("WPS_CANCEL")
7006    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7007    dev[0].wait_disconnected()
7008
7009def test_wps_ext_kwa_proto_no_kwa(dev, apdev):
7010    """WPS and KWA error: No KWA attribute"""
7011    r_s1, keywrapkey, authkey, raw_m3_attrs, eap_id, bssid, attrs = wps_start_kwa(dev, apdev)
7012    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7013    # Encrypted Settings without KWA
7014    iv = 16*b'\x99'
7015    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
7016    pad_len = 16 - len(data) % 16
7017    ps = pad_len * struct.pack('B', pad_len)
7018    data += ps
7019    wrapped = aes.encrypt(data)
7020    attrs += build_wsc_attr(ATTR_ENCR_SETTINGS, iv + wrapped)
7021    wps_stop_kwa(dev, bssid, attrs, authkey, raw_m3_attrs, eap_id)
7022
7023def test_wps_ext_kwa_proto_data_after_kwa(dev, apdev):
7024    """WPS and KWA error: Data after KWA"""
7025    r_s1, keywrapkey, authkey, raw_m3_attrs, eap_id, bssid, attrs = wps_start_kwa(dev, apdev)
7026    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7027    # Encrypted Settings and data after KWA
7028    m = hmac.new(authkey, data, hashlib.sha256)
7029    kwa = m.digest()[0:8]
7030    data += build_wsc_attr(ATTR_KEY_WRAP_AUTH, kwa)
7031    data += build_wsc_attr(ATTR_VENDOR_EXT, "1234567890")
7032    iv = 16*b'\x99'
7033    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
7034    pad_len = 16 - len(data) % 16
7035    ps = pad_len * struct.pack('B', pad_len)
7036    data += ps
7037    wrapped = aes.encrypt(data)
7038    attrs += build_wsc_attr(ATTR_ENCR_SETTINGS, iv + wrapped)
7039    wps_stop_kwa(dev, bssid, attrs, authkey, raw_m3_attrs, eap_id)
7040
7041def test_wps_ext_kwa_proto_kwa_mismatch(dev, apdev):
7042    """WPS and KWA error: KWA mismatch"""
7043    r_s1, keywrapkey, authkey, raw_m3_attrs, eap_id, bssid, attrs = wps_start_kwa(dev, apdev)
7044    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7045    # Encrypted Settings and KWA with incorrect value
7046    data += build_wsc_attr(ATTR_KEY_WRAP_AUTH, 8*'\x00')
7047    iv = 16*b'\x99'
7048    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
7049    pad_len = 16 - len(data) % 16
7050    ps = pad_len * struct.pack('B', pad_len)
7051    data += ps
7052    wrapped = aes.encrypt(data)
7053    attrs += build_wsc_attr(ATTR_ENCR_SETTINGS, iv + wrapped)
7054    wps_stop_kwa(dev, bssid, attrs, authkey, raw_m3_attrs, eap_id)
7055
7056def wps_run_cred_proto(dev, apdev, m8_cred, connect=False, no_connect=False):
7057    pin = "12345670"
7058    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7059    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7060    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7061    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7062
7063    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7064    uuid_r = 16*b'\x33'
7065    r_nonce = 16*b'\x44'
7066    own_private, e_pk = wsc_dh_init()
7067
7068    logger.debug("Receive M1 from STA")
7069    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7070    eap_id = (msg['eap_identifier'] + 1) % 256
7071
7072    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7073                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7074                                     r_nonce)
7075    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7076                                                   m1_attrs[ATTR_PUBLIC_KEY],
7077                                                   e_pk)
7078
7079    logger.debug("Send M2 to STA")
7080    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7081                                m1_attrs[ATTR_ENROLLEE_NONCE],
7082                                r_nonce, uuid_r, e_pk)
7083    send_wsc_msg(dev[0], bssid, m2)
7084    eap_id = (eap_id + 1) % 256
7085
7086    logger.debug("Receive M3 from STA")
7087    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
7088
7089    logger.debug("Send M4 to STA")
7090    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7091    attrs += build_attr_msg_type(WPS_M4)
7092    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, m1_attrs[ATTR_ENROLLEE_NONCE])
7093    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7094    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7095    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7096    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7097    attrs += build_attr_authenticator(authkey, raw_m3_attrs, attrs)
7098    raw_m4_attrs = attrs
7099    m4 = build_eap_wsc(1, eap_id, attrs)
7100    send_wsc_msg(dev[0], bssid, m4)
7101    eap_id = (eap_id + 1) % 256
7102
7103    logger.debug("Receive M5 from STA")
7104    msg, m5_attrs, raw_m5_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M5)
7105
7106    logger.debug("Send M6 to STA")
7107    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7108    attrs += build_attr_msg_type(WPS_M6)
7109    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE,
7110                            m1_attrs[ATTR_ENROLLEE_NONCE])
7111    data = build_wsc_attr(ATTR_R_SNONCE2, r_s2)
7112    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7113    attrs += build_attr_authenticator(authkey, raw_m5_attrs, attrs)
7114    raw_m6_attrs = attrs
7115    m6 = build_eap_wsc(1, eap_id, attrs)
7116    send_wsc_msg(dev[0], bssid, m6)
7117    eap_id = (eap_id + 1) % 256
7118
7119    logger.debug("Receive M7 from STA")
7120    msg, m7_attrs, raw_m7_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M7)
7121
7122    logger.debug("Send M8 to STA")
7123    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7124    attrs += build_attr_msg_type(WPS_M8)
7125    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE,
7126                            m1_attrs[ATTR_ENROLLEE_NONCE])
7127    attrs += build_attr_encr_settings(authkey, keywrapkey, m8_cred)
7128    attrs += build_attr_authenticator(authkey, raw_m7_attrs, attrs)
7129    raw_m8_attrs = attrs
7130    m8 = build_eap_wsc(1, eap_id, attrs)
7131    send_wsc_msg(dev[0], bssid, m8)
7132    eap_id = (eap_id + 1) % 256
7133
7134    if no_connect:
7135        logger.debug("Receive WSC_Done from STA")
7136        msg = get_wsc_msg(dev[0])
7137        if msg['wsc_opcode'] != WSC_Done or msg['wsc_msg_type'] != WPS_WSC_DONE:
7138            raise Exception("Unexpected Op-Code/MsgType for WSC_Done")
7139
7140        hapd.request("SET ext_eapol_frame_io 0")
7141        dev[0].request("SET ext_eapol_frame_io 0")
7142
7143        send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7144
7145        dev[0].wait_disconnected()
7146        dev[0].request("REMOVE_NETWORK all")
7147    elif connect:
7148        logger.debug("Receive WSC_Done from STA")
7149        msg = get_wsc_msg(dev[0])
7150        if msg['wsc_opcode'] != WSC_Done or msg['wsc_msg_type'] != WPS_WSC_DONE:
7151            raise Exception("Unexpected Op-Code/MsgType for WSC_Done")
7152
7153        hapd.request("SET ext_eapol_frame_io 0")
7154        dev[0].request("SET ext_eapol_frame_io 0")
7155
7156        send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7157
7158        dev[0].wait_connected()
7159    else:
7160        # Verify STA NACK's the credential
7161        msg = get_wsc_msg(dev[0])
7162        if msg['wsc_opcode'] != WSC_NACK:
7163            raise Exception("Unexpected message - expected WSC_Nack")
7164        dev[0].request("WPS_CANCEL")
7165        send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7166        dev[0].wait_disconnected()
7167
7168def build_cred(nw_idx='\x01', ssid='test-wps-conf', auth_type='\x00\x20',
7169               encr_type='\x00\x08', nw_key="12345678",
7170               mac_addr='\x00\x00\x00\x00\x00\x00'):
7171    attrs = b''
7172    if nw_idx is not None:
7173        attrs += build_wsc_attr(ATTR_NETWORK_INDEX, nw_idx)
7174    if ssid is not None:
7175        attrs += build_wsc_attr(ATTR_SSID, ssid)
7176    if auth_type is not None:
7177        attrs += build_wsc_attr(ATTR_AUTH_TYPE, auth_type)
7178    if encr_type is not None:
7179        attrs += build_wsc_attr(ATTR_ENCR_TYPE, encr_type)
7180    if nw_key is not None:
7181        attrs += build_wsc_attr(ATTR_NETWORK_KEY, nw_key)
7182    if mac_addr is not None:
7183        attrs += build_wsc_attr(ATTR_MAC_ADDR, mac_addr)
7184    return build_wsc_attr(ATTR_CRED, attrs)
7185
7186def test_wps_ext_cred_proto_success(dev, apdev):
7187    """WPS and Credential: success"""
7188    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7189    m8_cred = build_cred(mac_addr=mac_addr)
7190    wps_run_cred_proto(dev, apdev, m8_cred, connect=True)
7191
7192def test_wps_ext_cred_proto_mac_addr_mismatch(dev, apdev):
7193    """WPS and Credential: MAC Address mismatch"""
7194    m8_cred = build_cred()
7195    wps_run_cred_proto(dev, apdev, m8_cred, connect=True)
7196
7197def test_wps_ext_cred_proto_zero_padding(dev, apdev):
7198    """WPS and Credential: zeropadded attributes"""
7199    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7200    m8_cred = build_cred(mac_addr=mac_addr, ssid='test-wps-conf\x00',
7201                         nw_key="12345678\x00")
7202    wps_run_cred_proto(dev, apdev, m8_cred, connect=True)
7203
7204def test_wps_ext_cred_proto_ssid_missing(dev, apdev):
7205    """WPS and Credential: SSID missing"""
7206    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7207    m8_cred = build_cred(mac_addr=mac_addr, ssid=None)
7208    wps_run_cred_proto(dev, apdev, m8_cred)
7209
7210def test_wps_ext_cred_proto_ssid_zero_len(dev, apdev):
7211    """WPS and Credential: Zero-length SSID"""
7212    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7213    m8_cred = build_cred(mac_addr=mac_addr, ssid="")
7214    wps_run_cred_proto(dev, apdev, m8_cred, no_connect=True)
7215
7216def test_wps_ext_cred_proto_auth_type_missing(dev, apdev):
7217    """WPS and Credential: Auth Type missing"""
7218    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7219    m8_cred = build_cred(mac_addr=mac_addr, auth_type=None)
7220    wps_run_cred_proto(dev, apdev, m8_cred)
7221
7222def test_wps_ext_cred_proto_encr_type_missing(dev, apdev):
7223    """WPS and Credential: Encr Type missing"""
7224    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7225    m8_cred = build_cred(mac_addr=mac_addr, encr_type=None)
7226    wps_run_cred_proto(dev, apdev, m8_cred)
7227
7228def test_wps_ext_cred_proto_network_key_missing(dev, apdev):
7229    """WPS and Credential: Network Key missing"""
7230    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7231    m8_cred = build_cred(mac_addr=mac_addr, nw_key=None)
7232    wps_run_cred_proto(dev, apdev, m8_cred)
7233
7234def test_wps_ext_cred_proto_network_key_missing_open(dev, apdev):
7235    """WPS and Credential: Network Key missing (open)"""
7236    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7237    m8_cred = build_cred(mac_addr=mac_addr, auth_type='\x00\x01',
7238                         encr_type='\x00\x01', nw_key=None, ssid="foo")
7239    wps_run_cred_proto(dev, apdev, m8_cred, no_connect=True)
7240
7241def test_wps_ext_cred_proto_mac_addr_missing(dev, apdev):
7242    """WPS and Credential: MAC Address missing"""
7243    m8_cred = build_cred(mac_addr=None)
7244    wps_run_cred_proto(dev, apdev, m8_cred)
7245
7246def test_wps_ext_cred_proto_invalid_encr_type(dev, apdev):
7247    """WPS and Credential: Invalid Encr Type"""
7248    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7249    m8_cred = build_cred(mac_addr=mac_addr, encr_type='\x00\x00')
7250    wps_run_cred_proto(dev, apdev, m8_cred)
7251
7252def test_wps_ext_cred_proto_missing_cred(dev, apdev):
7253    """WPS and Credential: Missing Credential"""
7254    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7255    m8_cred = b''
7256    wps_run_cred_proto(dev, apdev, m8_cred)
7257
7258def test_wps_ext_proto_m2_no_public_key(dev, apdev):
7259    """WPS and no Public Key in M2"""
7260    pin = "12345670"
7261    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7262    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7263    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7264    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7265
7266    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7267    uuid_r = 16*b'\x33'
7268    r_nonce = 16*b'\x44'
7269    own_private, e_pk = wsc_dh_init()
7270
7271    logger.debug("Receive M1 from STA")
7272    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7273    eap_id = (msg['eap_identifier'] + 1) % 256
7274
7275    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7276                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7277                                     r_nonce)
7278    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7279                                                   m1_attrs[ATTR_PUBLIC_KEY],
7280                                                   e_pk)
7281
7282    logger.debug("Send M2 to STA")
7283    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7284                                m1_attrs[ATTR_ENROLLEE_NONCE],
7285                                r_nonce, uuid_r, None)
7286    send_wsc_msg(dev[0], bssid, m2)
7287    eap_id = (eap_id + 1) % 256
7288
7289    # Verify STA NACK's the credential
7290    msg = get_wsc_msg(dev[0])
7291    if msg['wsc_opcode'] != WSC_NACK:
7292        raise Exception("Unexpected message - expected WSC_Nack")
7293    dev[0].request("WPS_CANCEL")
7294    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7295    dev[0].wait_disconnected()
7296
7297def test_wps_ext_proto_m2_invalid_public_key(dev, apdev):
7298    """WPS and invalid Public Key in M2"""
7299    pin = "12345670"
7300    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7301    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7302    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7303    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7304
7305    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7306    uuid_r = 16*b'\x33'
7307    r_nonce = 16*b'\x44'
7308    own_private, e_pk = wsc_dh_init()
7309
7310    logger.debug("Receive M1 from STA")
7311    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7312    eap_id = (msg['eap_identifier'] + 1) % 256
7313
7314    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7315                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7316                                     r_nonce)
7317    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7318                                                   m1_attrs[ATTR_PUBLIC_KEY],
7319                                                   e_pk)
7320
7321    logger.debug("Send M2 to STA")
7322    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7323                                m1_attrs[ATTR_ENROLLEE_NONCE],
7324                                r_nonce, uuid_r, 192*b'\xff')
7325    send_wsc_msg(dev[0], bssid, m2)
7326    eap_id = (eap_id + 1) % 256
7327
7328    # Verify STA NACK's the credential
7329    msg = get_wsc_msg(dev[0])
7330    if msg['wsc_opcode'] != WSC_NACK:
7331        raise Exception("Unexpected message - expected WSC_Nack")
7332    dev[0].request("WPS_CANCEL")
7333    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7334    dev[0].wait_disconnected()
7335
7336def test_wps_ext_proto_m2_public_key_oom(dev, apdev):
7337    """WPS and Public Key OOM in M2"""
7338    pin = "12345670"
7339    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7340    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7341    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7342    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7343
7344    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7345    uuid_r = 16*b'\x33'
7346    r_nonce = 16*b'\x44'
7347    own_private, e_pk = wsc_dh_init()
7348
7349    logger.debug("Receive M1 from STA")
7350    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7351    eap_id = (msg['eap_identifier'] + 1) % 256
7352
7353    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7354                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7355                                     r_nonce)
7356    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7357                                                   m1_attrs[ATTR_PUBLIC_KEY],
7358                                                   e_pk)
7359
7360    logger.debug("Send M2 to STA")
7361    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7362                                m1_attrs[ATTR_ENROLLEE_NONCE],
7363                                r_nonce, uuid_r, e_pk)
7364    with alloc_fail(dev[0], 1, "wpabuf_alloc_copy;wps_process_pubkey"):
7365        send_wsc_msg(dev[0], bssid, m2)
7366        eap_id = (eap_id + 1) % 256
7367
7368        # Verify STA NACK's the credential
7369        msg = get_wsc_msg(dev[0])
7370        if msg['wsc_opcode'] != WSC_NACK:
7371            raise Exception("Unexpected message - expected WSC_Nack")
7372        dev[0].request("WPS_CANCEL")
7373        send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7374        dev[0].wait_disconnected()
7375
7376def test_wps_ext_proto_nack_m3(dev, apdev):
7377    """WPS and NACK M3"""
7378    pin = "12345670"
7379    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7380    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7381    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7382    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7383
7384    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7385    uuid_r = 16*b'\x33'
7386    r_nonce = 16*b'\x44'
7387    own_private, e_pk = wsc_dh_init()
7388
7389    logger.debug("Receive M1 from STA")
7390    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7391    eap_id = (msg['eap_identifier'] + 1) % 256
7392
7393    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7394                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7395                                     r_nonce)
7396    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7397                                                   m1_attrs[ATTR_PUBLIC_KEY],
7398                                                   e_pk)
7399
7400    logger.debug("Send M2 to STA")
7401    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7402                                m1_attrs[ATTR_ENROLLEE_NONCE],
7403                                r_nonce, uuid_r, e_pk)
7404    send_wsc_msg(dev[0], bssid, m2)
7405    eap_id = (eap_id + 1) % 256
7406
7407    logger.debug("Receive M3 from STA")
7408    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
7409
7410    logger.debug("Send NACK to STA")
7411    msg, attrs = build_nack(eap_id, m1_attrs[ATTR_ENROLLEE_NONCE],
7412                            r_nonce, config_error='\x01\x23')
7413    send_wsc_msg(dev[0], bssid, msg)
7414    ev = dev[0].wait_event(["WPS-FAIL"], timeout=5)
7415    if ev is None:
7416        raise Exception("Failure not reported")
7417    if "msg=7 config_error=291" not in ev:
7418        raise Exception("Unexpected failure reason: " + ev)
7419
7420def test_wps_ext_proto_nack_m5(dev, apdev):
7421    """WPS and NACK M5"""
7422    pin = "12345670"
7423    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7424    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7425    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7426    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7427
7428    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7429    uuid_r = 16*b'\x33'
7430    r_nonce = 16*b'\x44'
7431    own_private, e_pk = wsc_dh_init()
7432
7433    logger.debug("Receive M1 from STA")
7434    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7435    eap_id = (msg['eap_identifier'] + 1) % 256
7436
7437    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7438                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7439                                     r_nonce)
7440    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7441                                                   m1_attrs[ATTR_PUBLIC_KEY],
7442                                                   e_pk)
7443
7444    logger.debug("Send M2 to STA")
7445    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7446                                m1_attrs[ATTR_ENROLLEE_NONCE],
7447                                r_nonce, uuid_r, e_pk)
7448    send_wsc_msg(dev[0], bssid, m2)
7449    eap_id = (eap_id + 1) % 256
7450
7451    logger.debug("Receive M3 from STA")
7452    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
7453
7454    logger.debug("Send M4 to STA")
7455    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7456    attrs += build_attr_msg_type(WPS_M4)
7457    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, m1_attrs[ATTR_ENROLLEE_NONCE])
7458    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7459    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7460    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7461    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7462    attrs += build_attr_authenticator(authkey, raw_m3_attrs, attrs)
7463    raw_m4_attrs = attrs
7464    m4 = build_eap_wsc(1, eap_id, attrs)
7465    send_wsc_msg(dev[0], bssid, m4)
7466    eap_id = (eap_id + 1) % 256
7467
7468    logger.debug("Receive M5 from STA")
7469    msg, m5_attrs, raw_m5_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M5)
7470
7471    logger.debug("Send NACK to STA")
7472    msg, attrs = build_nack(eap_id, m1_attrs[ATTR_ENROLLEE_NONCE],
7473                            r_nonce, config_error='\x01\x24')
7474    send_wsc_msg(dev[0], bssid, msg)
7475    ev = dev[0].wait_event(["WPS-FAIL"], timeout=5)
7476    if ev is None:
7477        raise Exception("Failure not reported")
7478    if "msg=9 config_error=292" not in ev:
7479        raise Exception("Unexpected failure reason: " + ev)
7480
7481def wps_nack_m3(dev, apdev):
7482    pin = "00000000"
7483    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pbc=True)
7484    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7485    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7486    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7487
7488    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7489    uuid_r = 16*b'\x33'
7490    r_nonce = 16*b'\x44'
7491    own_private, e_pk = wsc_dh_init()
7492
7493    logger.debug("Receive M1 from STA")
7494    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7495    eap_id = (msg['eap_identifier'] + 1) % 256
7496
7497    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7498                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7499                                     r_nonce)
7500    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7501                                                   m1_attrs[ATTR_PUBLIC_KEY],
7502                                                   e_pk)
7503
7504    logger.debug("Send M2 to STA")
7505    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7506                                m1_attrs[ATTR_ENROLLEE_NONCE],
7507                                r_nonce, uuid_r, e_pk, dev_pw_id='\x00\x04')
7508    send_wsc_msg(dev[0], bssid, m2)
7509    eap_id = (eap_id + 1) % 256
7510
7511    logger.debug("Receive M3 from STA")
7512    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
7513    return eap_id, m1_attrs[ATTR_ENROLLEE_NONCE], r_nonce, bssid
7514
7515def test_wps_ext_proto_nack_m3_no_config_error(dev, apdev):
7516    """WPS and NACK M3 missing Config Error"""
7517    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7518    logger.debug("Send NACK to STA")
7519    msg, attrs = build_nack(eap_id, e_nonce, r_nonce, config_error=None)
7520    send_wsc_msg(dev[0], bssid, msg)
7521    dev[0].request("WPS_CANCEL")
7522    dev[0].wait_disconnected()
7523    dev[0].flush_scan_cache()
7524
7525def test_wps_ext_proto_nack_m3_no_e_nonce(dev, apdev):
7526    """WPS and NACK M3 missing E-Nonce"""
7527    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7528    logger.debug("Send NACK to STA")
7529    msg, attrs = build_nack(eap_id, None, r_nonce)
7530    send_wsc_msg(dev[0], bssid, msg)
7531    dev[0].request("WPS_CANCEL")
7532    dev[0].wait_disconnected()
7533    dev[0].flush_scan_cache()
7534
7535def test_wps_ext_proto_nack_m3_e_nonce_mismatch(dev, apdev):
7536    """WPS and NACK M3 E-Nonce mismatch"""
7537    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7538    logger.debug("Send NACK to STA")
7539    msg, attrs = build_nack(eap_id, 16*'\x00', r_nonce)
7540    send_wsc_msg(dev[0], bssid, msg)
7541    dev[0].request("WPS_CANCEL")
7542    dev[0].wait_disconnected()
7543    dev[0].flush_scan_cache()
7544
7545def test_wps_ext_proto_nack_m3_no_r_nonce(dev, apdev):
7546    """WPS and NACK M3 missing R-Nonce"""
7547    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7548    logger.debug("Send NACK to STA")
7549    msg, attrs = build_nack(eap_id, e_nonce, None)
7550    send_wsc_msg(dev[0], bssid, msg)
7551    dev[0].request("WPS_CANCEL")
7552    dev[0].wait_disconnected()
7553    dev[0].flush_scan_cache()
7554
7555def test_wps_ext_proto_nack_m3_r_nonce_mismatch(dev, apdev):
7556    """WPS and NACK M3 R-Nonce mismatch"""
7557    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7558    logger.debug("Send NACK to STA")
7559    msg, attrs = build_nack(eap_id, e_nonce, 16*'\x00')
7560    send_wsc_msg(dev[0], bssid, msg)
7561    dev[0].request("WPS_CANCEL")
7562    dev[0].wait_disconnected()
7563    dev[0].flush_scan_cache()
7564
7565def test_wps_ext_proto_nack_m3_no_msg_type(dev, apdev):
7566    """WPS and NACK M3 no Message Type"""
7567    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7568    logger.debug("Send NACK to STA")
7569    msg, attrs = build_nack(eap_id, e_nonce, r_nonce, msg_type=None)
7570    send_wsc_msg(dev[0], bssid, msg)
7571    dev[0].request("WPS_CANCEL")
7572    dev[0].wait_disconnected()
7573    dev[0].flush_scan_cache()
7574
7575def test_wps_ext_proto_nack_m3_invalid_msg_type(dev, apdev):
7576    """WPS and NACK M3 invalid Message Type"""
7577    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7578    logger.debug("Send NACK to STA")
7579    msg, attrs = build_nack(eap_id, e_nonce, r_nonce, msg_type=123)
7580    send_wsc_msg(dev[0], bssid, msg)
7581    dev[0].request("WPS_CANCEL")
7582    dev[0].wait_disconnected()
7583    dev[0].flush_scan_cache()
7584
7585def test_wps_ext_proto_nack_m3_invalid_attr(dev, apdev):
7586    """WPS and NACK M3 invalid attribute"""
7587    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7588    logger.debug("Send NACK to STA")
7589    attrs = b'\x10\x10\x00'
7590    msg = build_eap_wsc(1, eap_id, attrs, opcode=WSC_NACK)
7591    send_wsc_msg(dev[0], bssid, msg)
7592    dev[0].request("WPS_CANCEL")
7593    dev[0].wait_disconnected()
7594    dev[0].flush_scan_cache()
7595
7596def test_wps_ext_proto_ack_m3_no_e_nonce(dev, apdev):
7597    """WPS and ACK M3 missing E-Nonce"""
7598    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7599    logger.debug("Send NACK to STA")
7600    msg, attrs = build_ack(eap_id, None, r_nonce)
7601    send_wsc_msg(dev[0], bssid, msg)
7602    dev[0].request("WPS_CANCEL")
7603    dev[0].wait_disconnected()
7604    dev[0].flush_scan_cache()
7605
7606def test_wps_ext_proto_ack_m3_e_nonce_mismatch(dev, apdev):
7607    """WPS and ACK M3 E-Nonce mismatch"""
7608    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7609    logger.debug("Send NACK to STA")
7610    msg, attrs = build_ack(eap_id, 16*'\x00', r_nonce)
7611    send_wsc_msg(dev[0], bssid, msg)
7612    dev[0].request("WPS_CANCEL")
7613    dev[0].wait_disconnected()
7614    dev[0].flush_scan_cache()
7615
7616def test_wps_ext_proto_ack_m3_no_r_nonce(dev, apdev):
7617    """WPS and ACK M3 missing R-Nonce"""
7618    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7619    logger.debug("Send NACK to STA")
7620    msg, attrs = build_ack(eap_id, e_nonce, None)
7621    send_wsc_msg(dev[0], bssid, msg)
7622    dev[0].request("WPS_CANCEL")
7623    dev[0].wait_disconnected()
7624    dev[0].flush_scan_cache()
7625
7626def test_wps_ext_proto_ack_m3_r_nonce_mismatch(dev, apdev):
7627    """WPS and ACK M3 R-Nonce mismatch"""
7628    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7629    logger.debug("Send NACK to STA")
7630    msg, attrs = build_ack(eap_id, e_nonce, 16*'\x00')
7631    send_wsc_msg(dev[0], bssid, msg)
7632    dev[0].request("WPS_CANCEL")
7633    dev[0].wait_disconnected()
7634    dev[0].flush_scan_cache()
7635
7636def test_wps_ext_proto_ack_m3_no_msg_type(dev, apdev):
7637    """WPS and ACK M3 no Message Type"""
7638    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7639    logger.debug("Send NACK to STA")
7640    msg, attrs = build_ack(eap_id, e_nonce, r_nonce, msg_type=None)
7641    send_wsc_msg(dev[0], bssid, msg)
7642    dev[0].request("WPS_CANCEL")
7643    dev[0].wait_disconnected()
7644    dev[0].flush_scan_cache()
7645
7646def test_wps_ext_proto_ack_m3_invalid_msg_type(dev, apdev):
7647    """WPS and ACK M3 invalid Message Type"""
7648    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7649    logger.debug("Send NACK to STA")
7650    msg, attrs = build_ack(eap_id, e_nonce, r_nonce, msg_type=123)
7651    send_wsc_msg(dev[0], bssid, msg)
7652    dev[0].request("WPS_CANCEL")
7653    dev[0].wait_disconnected()
7654    dev[0].flush_scan_cache()
7655
7656def test_wps_ext_proto_ack_m3_invalid_attr(dev, apdev):
7657    """WPS and ACK M3 invalid attribute"""
7658    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7659    logger.debug("Send ACK to STA")
7660    attrs = b'\x10\x10\x00'
7661    msg = build_eap_wsc(1, eap_id, attrs, opcode=WSC_ACK)
7662    send_wsc_msg(dev[0], bssid, msg)
7663    dev[0].request("WPS_CANCEL")
7664    dev[0].wait_disconnected()
7665    dev[0].flush_scan_cache()
7666
7667def test_wps_ext_proto_ack_m3(dev, apdev):
7668    """WPS and ACK M3"""
7669    eap_id, e_nonce, r_nonce, bssid = wps_nack_m3(dev, apdev)
7670    logger.debug("Send ACK to STA")
7671    msg, attrs = build_ack(eap_id, e_nonce, r_nonce)
7672    send_wsc_msg(dev[0], bssid, msg)
7673    dev[0].request("WPS_CANCEL")
7674    dev[0].wait_disconnected()
7675    dev[0].flush_scan_cache()
7676
7677def wps_to_m3_helper(dev, apdev):
7678    pin = "12345670"
7679    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
7680    wps_ext_eap_identity_req(dev[0], hapd, bssid)
7681    wps_ext_eap_identity_resp(hapd, dev[0], addr)
7682    wps_ext_eap_wsc(dev[0], hapd, bssid, "EAP-WSC/Start")
7683
7684    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
7685    uuid_r = 16*b'\x33'
7686    r_nonce = 16*b'\x44'
7687    own_private, e_pk = wsc_dh_init()
7688
7689    logger.debug("Receive M1 from STA")
7690    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M1)
7691    eap_id = (msg['eap_identifier'] + 1) % 256
7692
7693    authkey, keywrapkey = wsc_dh_kdf(m1_attrs[ATTR_PUBLIC_KEY], own_private,
7694                                     mac_addr, m1_attrs[ATTR_ENROLLEE_NONCE],
7695                                     r_nonce)
7696    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, pin,
7697                                                   m1_attrs[ATTR_PUBLIC_KEY],
7698                                                   e_pk)
7699
7700    logger.debug("Send M2 to STA")
7701    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, eap_id,
7702                                m1_attrs[ATTR_ENROLLEE_NONCE],
7703                                r_nonce, uuid_r, e_pk)
7704    send_wsc_msg(dev[0], bssid, m2)
7705    eap_id = (eap_id + 1) % 256
7706
7707    logger.debug("Receive M3 from STA")
7708    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M3)
7709    return eap_id, m1_attrs, r_nonce, bssid, r_hash1, r_hash2, r_s1, r_s2, raw_m3_attrs, authkey, keywrapkey
7710
7711def wps_to_m3(dev, apdev):
7712    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)
7713    return eap_id, m1_attrs[ATTR_ENROLLEE_NONCE], r_nonce, bssid, r_hash1, r_hash2, r_s1, raw_m3_attrs, authkey, keywrapkey
7714
7715def wps_to_m5(dev, apdev):
7716    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)
7717
7718    logger.debug("Send M4 to STA")
7719    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7720    attrs += build_attr_msg_type(WPS_M4)
7721    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, m1_attrs[ATTR_ENROLLEE_NONCE])
7722    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7723    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7724    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7725    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7726    attrs += build_attr_authenticator(authkey, raw_m3_attrs, attrs)
7727    raw_m4_attrs = attrs
7728    m4 = build_eap_wsc(1, eap_id, attrs)
7729    send_wsc_msg(dev[0], bssid, m4)
7730    eap_id = (eap_id + 1) % 256
7731
7732    logger.debug("Receive M5 from STA")
7733    msg, m5_attrs, raw_m5_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M5)
7734
7735    return eap_id, m1_attrs[ATTR_ENROLLEE_NONCE], r_nonce, bssid, r_hash1, r_hash2, r_s2, raw_m5_attrs, authkey, keywrapkey
7736
7737def test_wps_ext_proto_m4_missing_r_hash1(dev, apdev):
7738    """WPS and no R-Hash1 in M4"""
7739    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s1, m3, authkey, keywrapkey = wps_to_m3(dev, apdev)
7740
7741    logger.debug("Send M4 to STA")
7742    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7743    attrs += build_attr_msg_type(WPS_M4)
7744    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7745    #attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7746    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7747    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7748    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7749    attrs += build_attr_authenticator(authkey, m3, attrs)
7750    m4 = build_eap_wsc(1, eap_id, attrs)
7751    send_wsc_msg(dev[0], bssid, m4)
7752    eap_id = (eap_id + 1) % 256
7753
7754    logger.debug("Receive M5 (NACK) from STA")
7755    msg = get_wsc_msg(dev[0])
7756    if msg['wsc_opcode'] != WSC_NACK:
7757        raise Exception("Unexpected message - expected WSC_Nack")
7758
7759    dev[0].request("WPS_CANCEL")
7760    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7761    dev[0].wait_disconnected()
7762
7763def test_wps_ext_proto_m4_missing_r_hash2(dev, apdev):
7764    """WPS and no R-Hash2 in M4"""
7765    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s1, m3, authkey, keywrapkey = wps_to_m3(dev, apdev)
7766
7767    logger.debug("Send M4 to STA")
7768    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7769    attrs += build_attr_msg_type(WPS_M4)
7770    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7771    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7772    #attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7773    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7774    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7775    attrs += build_attr_authenticator(authkey, m3, attrs)
7776    m4 = build_eap_wsc(1, eap_id, attrs)
7777    send_wsc_msg(dev[0], bssid, m4)
7778    eap_id = (eap_id + 1) % 256
7779
7780    logger.debug("Receive M5 (NACK) from STA")
7781    msg = get_wsc_msg(dev[0])
7782    if msg['wsc_opcode'] != WSC_NACK:
7783        raise Exception("Unexpected message - expected WSC_Nack")
7784
7785    dev[0].request("WPS_CANCEL")
7786    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7787    dev[0].wait_disconnected()
7788
7789def test_wps_ext_proto_m4_missing_r_snonce1(dev, apdev):
7790    """WPS and no R-SNonce1 in M4"""
7791    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s1, m3, authkey, keywrapkey = wps_to_m3(dev, apdev)
7792
7793    logger.debug("Send M4 to STA")
7794    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7795    attrs += build_attr_msg_type(WPS_M4)
7796    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7797    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7798    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7799    #data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7800    data = b''
7801    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7802    attrs += build_attr_authenticator(authkey, m3, attrs)
7803    m4 = build_eap_wsc(1, eap_id, attrs)
7804    send_wsc_msg(dev[0], bssid, m4)
7805    eap_id = (eap_id + 1) % 256
7806
7807    logger.debug("Receive M5 (NACK) from STA")
7808    msg = get_wsc_msg(dev[0])
7809    if msg['wsc_opcode'] != WSC_NACK:
7810        raise Exception("Unexpected message - expected WSC_Nack")
7811
7812    dev[0].request("WPS_CANCEL")
7813    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7814    dev[0].wait_disconnected()
7815
7816def test_wps_ext_proto_m4_invalid_pad_string(dev, apdev):
7817    """WPS and invalid pad string in M4"""
7818    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s1, m3, authkey, keywrapkey = wps_to_m3(dev, apdev)
7819
7820    logger.debug("Send M4 to STA")
7821    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7822    attrs += build_attr_msg_type(WPS_M4)
7823    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7824    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7825    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7826    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7827
7828    m = hmac.new(authkey, data, hashlib.sha256)
7829    kwa = m.digest()[0:8]
7830    data += build_wsc_attr(ATTR_KEY_WRAP_AUTH, kwa)
7831    iv = 16*b'\x99'
7832    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
7833    pad_len = 16 - len(data) % 16
7834    ps = (pad_len - 1) * struct.pack('B', pad_len) + struct.pack('B', pad_len - 1)
7835    data += ps
7836    wrapped = aes.encrypt(data)
7837    attrs += build_wsc_attr(ATTR_ENCR_SETTINGS, iv + wrapped)
7838
7839    attrs += build_attr_authenticator(authkey, m3, attrs)
7840    m4 = build_eap_wsc(1, eap_id, attrs)
7841    send_wsc_msg(dev[0], bssid, m4)
7842    eap_id = (eap_id + 1) % 256
7843
7844    logger.debug("Receive M5 (NACK) from STA")
7845    msg = get_wsc_msg(dev[0])
7846    if msg['wsc_opcode'] != WSC_NACK:
7847        raise Exception("Unexpected message - expected WSC_Nack")
7848
7849    dev[0].request("WPS_CANCEL")
7850    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7851    dev[0].wait_disconnected()
7852
7853def test_wps_ext_proto_m4_invalid_pad_value(dev, apdev):
7854    """WPS and invalid pad value in M4"""
7855    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s1, m3, authkey, keywrapkey = wps_to_m3(dev, apdev)
7856
7857    logger.debug("Send M4 to STA")
7858    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7859    attrs += build_attr_msg_type(WPS_M4)
7860    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7861    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7862    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7863    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
7864
7865    m = hmac.new(authkey, data, hashlib.sha256)
7866    kwa = m.digest()[0:8]
7867    data += build_wsc_attr(ATTR_KEY_WRAP_AUTH, kwa)
7868    iv = 16*b'\x99'
7869    aes = AES.new(keywrapkey, AES.MODE_CBC, iv)
7870    pad_len = 16 - len(data) % 16
7871    ps = (pad_len - 1) * struct.pack('B', pad_len) + struct.pack('B', 255)
7872    data += ps
7873    wrapped = aes.encrypt(data)
7874    attrs += build_wsc_attr(ATTR_ENCR_SETTINGS, iv + wrapped)
7875
7876    attrs += build_attr_authenticator(authkey, m3, attrs)
7877    m4 = build_eap_wsc(1, eap_id, attrs)
7878    send_wsc_msg(dev[0], bssid, m4)
7879    eap_id = (eap_id + 1) % 256
7880
7881    logger.debug("Receive M5 (NACK) from STA")
7882    msg = get_wsc_msg(dev[0])
7883    if msg['wsc_opcode'] != WSC_NACK:
7884        raise Exception("Unexpected message - expected WSC_Nack")
7885
7886    dev[0].request("WPS_CANCEL")
7887    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7888    dev[0].wait_disconnected()
7889
7890def test_wps_ext_proto_m4_no_encr_settings(dev, apdev):
7891    """WPS and no Encr Settings in M4"""
7892    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s1, m3, authkey, keywrapkey = wps_to_m3(dev, apdev)
7893
7894    logger.debug("Send M4 to STA")
7895    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7896    attrs += build_attr_msg_type(WPS_M4)
7897    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7898    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
7899    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
7900    attrs += build_attr_authenticator(authkey, m3, attrs)
7901    m4 = build_eap_wsc(1, eap_id, attrs)
7902    send_wsc_msg(dev[0], bssid, m4)
7903    eap_id = (eap_id + 1) % 256
7904
7905    logger.debug("Receive M5 (NACK) from STA")
7906    msg = get_wsc_msg(dev[0])
7907    if msg['wsc_opcode'] != WSC_NACK:
7908        raise Exception("Unexpected message - expected WSC_Nack")
7909
7910    dev[0].request("WPS_CANCEL")
7911    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7912    dev[0].wait_disconnected()
7913
7914def test_wps_ext_proto_m6_missing_r_snonce2(dev, apdev):
7915    """WPS and no R-SNonce2 in M6"""
7916    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s2, m5, authkey, keywrapkey = wps_to_m5(dev, apdev)
7917
7918    logger.debug("Send M6 to STA")
7919    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7920    attrs += build_attr_msg_type(WPS_M6)
7921    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7922    #data = build_wsc_attr(ATTR_R_SNONCE2, r_s2)
7923    data = b''
7924    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7925    attrs += build_attr_authenticator(authkey, m5, attrs)
7926    m6 = build_eap_wsc(1, eap_id, attrs)
7927    send_wsc_msg(dev[0], bssid, m6)
7928    eap_id = (eap_id + 1) % 256
7929
7930    logger.debug("Receive M7 (NACK) from STA")
7931    msg = get_wsc_msg(dev[0])
7932    if msg['wsc_opcode'] != WSC_NACK:
7933        raise Exception("Unexpected message - expected WSC_Nack")
7934
7935    dev[0].request("WPS_CANCEL")
7936    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7937    dev[0].wait_disconnected()
7938
7939def test_wps_ext_proto_m6_no_encr_settings(dev, apdev):
7940    """WPS and no Encr Settings in M6"""
7941    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s2, m5, authkey, keywrapkey = wps_to_m5(dev, apdev)
7942
7943    logger.debug("Send M6 to STA")
7944    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7945    attrs += build_attr_msg_type(WPS_M6)
7946    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7947    data = build_wsc_attr(ATTR_R_SNONCE2, r_s2)
7948    #attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7949    attrs += build_attr_authenticator(authkey, m5, attrs)
7950    m6 = build_eap_wsc(1, eap_id, attrs)
7951    send_wsc_msg(dev[0], bssid, m6)
7952    eap_id = (eap_id + 1) % 256
7953
7954    logger.debug("Receive M7 (NACK) from STA")
7955    msg = get_wsc_msg(dev[0])
7956    if msg['wsc_opcode'] != WSC_NACK:
7957        raise Exception("Unexpected message - expected WSC_Nack")
7958
7959    dev[0].request("WPS_CANCEL")
7960    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7961    dev[0].wait_disconnected()
7962
7963def test_wps_ext_proto_m8_no_encr_settings(dev, apdev):
7964    """WPS and no Encr Settings in M6"""
7965    eap_id, e_nonce, r_nonce, bssid, r_hash1, r_hash2, r_s2, m5, authkey, keywrapkey = wps_to_m5(dev, apdev)
7966
7967    logger.debug("Send M6 to STA")
7968    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7969    attrs += build_attr_msg_type(WPS_M6)
7970    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7971    data = build_wsc_attr(ATTR_R_SNONCE2, r_s2)
7972    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
7973    attrs += build_attr_authenticator(authkey, m5, attrs)
7974    raw_m6_attrs = attrs
7975    m6 = build_eap_wsc(1, eap_id, attrs)
7976    send_wsc_msg(dev[0], bssid, m6)
7977    eap_id = (eap_id + 1) % 256
7978
7979    logger.debug("Receive M7 from STA")
7980    msg, m7_attrs, raw_m7_attrs = recv_wsc_msg(dev[0], WSC_MSG, WPS_M7)
7981
7982    logger.debug("Send M8 to STA")
7983    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
7984    attrs += build_attr_msg_type(WPS_M8)
7985    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
7986    #attrs += build_attr_encr_settings(authkey, keywrapkey, m8_cred)
7987    attrs += build_attr_authenticator(authkey, raw_m7_attrs, attrs)
7988    raw_m8_attrs = attrs
7989    m8 = build_eap_wsc(1, eap_id, attrs)
7990    send_wsc_msg(dev[0], bssid, m8)
7991
7992    logger.debug("Receive WSC_Done (NACK) from STA")
7993    msg = get_wsc_msg(dev[0])
7994    if msg['wsc_opcode'] != WSC_NACK:
7995        raise Exception("Unexpected message - expected WSC_Nack")
7996
7997    dev[0].request("WPS_CANCEL")
7998    send_wsc_msg(dev[0], bssid, build_eap_failure(eap_id))
7999    dev[0].wait_disconnected()
8000
8001def wps_start_ext_reg(apdev, dev):
8002    addr = dev.own_addr()
8003    bssid = apdev['bssid']
8004    ssid = "test-wps-conf"
8005    appin = "12345670"
8006    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
8007              "wpa_passphrase": "12345678", "wpa": "2",
8008              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
8009              "ap_pin": appin}
8010    hapd = hostapd.add_ap(apdev, params)
8011
8012    dev.scan_for_bss(bssid, freq="2412")
8013    hapd.request("SET ext_eapol_frame_io 1")
8014    dev.request("SET ext_eapol_frame_io 1")
8015
8016    dev.request("WPS_REG " + bssid + " " + appin)
8017
8018    return addr, bssid, hapd
8019
8020def wps_run_ap_settings_proto(dev, apdev, ap_settings, success):
8021    addr, bssid, hapd = wps_start_ext_reg(apdev[0], dev[0])
8022    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8023    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8024
8025    logger.debug("Receive M1 from AP")
8026    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M1)
8027    mac_addr = m1_attrs[ATTR_MAC_ADDR]
8028    e_nonce = m1_attrs[ATTR_ENROLLEE_NONCE]
8029    e_pk = m1_attrs[ATTR_PUBLIC_KEY]
8030
8031    appin = '12345670'
8032    uuid_r = 16*b'\x33'
8033    r_nonce = 16*b'\x44'
8034    own_private, r_pk = wsc_dh_init()
8035    authkey, keywrapkey = wsc_dh_kdf(e_pk, own_private, mac_addr, e_nonce,
8036                                     r_nonce)
8037    r_s1, r_s2, r_hash1, r_hash2 = wsc_dev_pw_hash(authkey, appin, e_pk, r_pk)
8038
8039    logger.debug("Send M2 to AP")
8040    m2, raw_m2_attrs = build_m2(authkey, raw_m1_attrs, msg['eap_identifier'],
8041                                e_nonce, r_nonce, uuid_r, r_pk, eap_code=2)
8042    send_wsc_msg(hapd, addr, m2)
8043
8044    logger.debug("Receive M3 from AP")
8045    msg, m3_attrs, raw_m3_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M3)
8046
8047    logger.debug("Send M4 to AP")
8048    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8049    attrs += build_attr_msg_type(WPS_M4)
8050    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
8051    attrs += build_wsc_attr(ATTR_R_HASH1, r_hash1)
8052    attrs += build_wsc_attr(ATTR_R_HASH2, r_hash2)
8053    data = build_wsc_attr(ATTR_R_SNONCE1, r_s1)
8054    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8055    attrs += build_attr_authenticator(authkey, raw_m3_attrs, attrs)
8056    raw_m4_attrs = attrs
8057    m4 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8058    send_wsc_msg(hapd, addr, m4)
8059
8060    logger.debug("Receive M5 from AP")
8061    msg, m5_attrs, raw_m5_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M5)
8062
8063    logger.debug("Send M6 to STA")
8064    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8065    attrs += build_attr_msg_type(WPS_M6)
8066    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
8067    data = build_wsc_attr(ATTR_R_SNONCE2, r_s2)
8068    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8069    attrs += build_attr_authenticator(authkey, raw_m5_attrs, attrs)
8070    raw_m6_attrs = attrs
8071    m6 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8072    send_wsc_msg(hapd, addr, m6)
8073
8074    logger.debug("Receive M7 from AP")
8075    msg, m7_attrs, raw_m7_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M7)
8076
8077    logger.debug("Send M8 to STA")
8078    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8079    attrs += build_attr_msg_type(WPS_M8)
8080    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
8081    if ap_settings:
8082        attrs += build_attr_encr_settings(authkey, keywrapkey, ap_settings)
8083    attrs += build_attr_authenticator(authkey, raw_m7_attrs, attrs)
8084    raw_m8_attrs = attrs
8085    m8 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8086    send_wsc_msg(hapd, addr, m8)
8087
8088    if success:
8089        ev = hapd.wait_event(["WPS-NEW-AP-SETTINGS"], timeout=5)
8090        if ev is None:
8091            raise Exception("New AP settings not reported")
8092        logger.debug("Receive WSC_Done from AP")
8093        msg = get_wsc_msg(hapd)
8094        if msg['wsc_opcode'] != WSC_Done:
8095            raise Exception("Unexpected message - expected WSC_Done")
8096
8097        logger.debug("Send WSC_ACK to AP")
8098        ack, attrs = build_ack(msg['eap_identifier'], e_nonce, r_nonce,
8099                               eap_code=2)
8100        send_wsc_msg(hapd, addr, ack)
8101        dev[0].wait_disconnected()
8102    else:
8103        ev = hapd.wait_event(["WPS-FAIL"], timeout=5)
8104        if ev is None:
8105            raise Exception("WPS failure not reported")
8106        logger.debug("Receive WSC_NACK from AP")
8107        msg = get_wsc_msg(hapd)
8108        if msg['wsc_opcode'] != WSC_NACK:
8109            raise Exception("Unexpected message - expected WSC_NACK")
8110
8111        logger.debug("Send WSC_NACK to AP")
8112        nack, attrs = build_nack(msg['eap_identifier'], e_nonce, r_nonce,
8113                                 eap_code=2)
8114        send_wsc_msg(hapd, addr, nack)
8115        dev[0].wait_disconnected()
8116
8117def test_wps_ext_ap_settings_success(dev, apdev):
8118    """WPS and AP Settings: success"""
8119    ap_settings = build_wsc_attr(ATTR_NETWORK_INDEX, '\x01')
8120    ap_settings += build_wsc_attr(ATTR_SSID, "test")
8121    ap_settings += build_wsc_attr(ATTR_AUTH_TYPE, '\x00\x01')
8122    ap_settings += build_wsc_attr(ATTR_ENCR_TYPE, '\x00\x01')
8123    ap_settings += build_wsc_attr(ATTR_NETWORK_KEY, '')
8124    ap_settings += build_wsc_attr(ATTR_MAC_ADDR, binascii.unhexlify(apdev[0]['bssid'].replace(':', '')))
8125    wps_run_ap_settings_proto(dev, apdev, ap_settings, True)
8126
8127@remote_compatible
8128def test_wps_ext_ap_settings_missing(dev, apdev):
8129    """WPS and AP Settings: missing"""
8130    wps_run_ap_settings_proto(dev, apdev, None, False)
8131
8132@remote_compatible
8133def test_wps_ext_ap_settings_mac_addr_mismatch(dev, apdev):
8134    """WPS and AP Settings: MAC Address mismatch"""
8135    ap_settings = build_wsc_attr(ATTR_NETWORK_INDEX, '\x01')
8136    ap_settings += build_wsc_attr(ATTR_SSID, "test")
8137    ap_settings += build_wsc_attr(ATTR_AUTH_TYPE, '\x00\x01')
8138    ap_settings += build_wsc_attr(ATTR_ENCR_TYPE, '\x00\x01')
8139    ap_settings += build_wsc_attr(ATTR_NETWORK_KEY, '')
8140    ap_settings += build_wsc_attr(ATTR_MAC_ADDR, '\x00\x00\x00\x00\x00\x00')
8141    wps_run_ap_settings_proto(dev, apdev, ap_settings, True)
8142
8143@remote_compatible
8144def test_wps_ext_ap_settings_mac_addr_missing(dev, apdev):
8145    """WPS and AP Settings: missing MAC Address"""
8146    ap_settings = build_wsc_attr(ATTR_NETWORK_INDEX, '\x01')
8147    ap_settings += build_wsc_attr(ATTR_SSID, "test")
8148    ap_settings += build_wsc_attr(ATTR_AUTH_TYPE, '\x00\x01')
8149    ap_settings += build_wsc_attr(ATTR_ENCR_TYPE, '\x00\x01')
8150    ap_settings += build_wsc_attr(ATTR_NETWORK_KEY, '')
8151    wps_run_ap_settings_proto(dev, apdev, ap_settings, False)
8152
8153@remote_compatible
8154def test_wps_ext_ap_settings_reject_encr_type(dev, apdev):
8155    """WPS and AP Settings: reject Encr Type"""
8156    ap_settings = build_wsc_attr(ATTR_NETWORK_INDEX, '\x01')
8157    ap_settings += build_wsc_attr(ATTR_SSID, "test")
8158    ap_settings += build_wsc_attr(ATTR_AUTH_TYPE, '\x00\x01')
8159    ap_settings += build_wsc_attr(ATTR_ENCR_TYPE, '\x00\x00')
8160    ap_settings += build_wsc_attr(ATTR_NETWORK_KEY, '')
8161    ap_settings += build_wsc_attr(ATTR_MAC_ADDR, binascii.unhexlify(apdev[0]['bssid'].replace(':', '')))
8162    wps_run_ap_settings_proto(dev, apdev, ap_settings, False)
8163
8164@remote_compatible
8165def test_wps_ext_ap_settings_m2d(dev, apdev):
8166    """WPS and AP Settings: M2D"""
8167    addr, bssid, hapd = wps_start_ext_reg(apdev[0], dev[0])
8168    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8169    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8170
8171    logger.debug("Receive M1 from AP")
8172    msg, m1_attrs, raw_m1_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M1)
8173    e_nonce = m1_attrs[ATTR_ENROLLEE_NONCE]
8174
8175    r_nonce = 16*'\x44'
8176    uuid_r = 16*'\x33'
8177
8178    logger.debug("Send M2D to AP")
8179    m2d, raw_m2d_attrs = build_m2d(raw_m1_attrs, msg['eap_identifier'],
8180                                   e_nonce, r_nonce, uuid_r,
8181                                   dev_pw_id='\x00\x00', eap_code=2)
8182    send_wsc_msg(hapd, addr, m2d)
8183
8184    ev = hapd.wait_event(["WPS-M2D"], timeout=5)
8185    if ev is None:
8186        raise Exception("M2D not reported")
8187
8188    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8189
8190def wps_wait_ap_nack(hapd, dev, e_nonce, r_nonce):
8191    logger.debug("Receive WSC_NACK from AP")
8192    msg = get_wsc_msg(hapd)
8193    if msg['wsc_opcode'] != WSC_NACK:
8194        raise Exception("Unexpected message - expected WSC_NACK")
8195
8196    logger.debug("Send WSC_NACK to AP")
8197    nack, attrs = build_nack(msg['eap_identifier'], e_nonce, r_nonce,
8198                             eap_code=2)
8199    send_wsc_msg(hapd, dev.own_addr(), nack)
8200    dev.wait_disconnected()
8201
8202@remote_compatible
8203def test_wps_ext_m3_missing_e_hash1(dev, apdev):
8204    """WPS proto: M3 missing E-Hash1"""
8205    pin = "12345670"
8206    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8207    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8208    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8209
8210    logger.debug("Receive WSC/Start from AP")
8211    msg = get_wsc_msg(hapd)
8212    if msg['wsc_opcode'] != WSC_Start:
8213        raise Exception("Unexpected Op-Code for WSC/Start")
8214
8215    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8216    uuid_e = 16*b'\x11'
8217    e_nonce = 16*b'\x22'
8218    own_private, e_pk = wsc_dh_init()
8219
8220    logger.debug("Send M1 to AP")
8221    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8222                                e_nonce, e_pk)
8223    send_wsc_msg(hapd, addr, m1)
8224
8225    logger.debug("Receive M2 from AP")
8226    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8227    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8228    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8229
8230    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8231                                     r_nonce)
8232    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8233
8234    logger.debug("Send M3 to AP")
8235    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8236    attrs += build_attr_msg_type(WPS_M3)
8237    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8238    #attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8239    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8240    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8241    raw_m3_attrs = attrs
8242    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8243    send_wsc_msg(hapd, addr, m3)
8244
8245    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8246
8247@remote_compatible
8248def test_wps_ext_m3_missing_e_hash2(dev, apdev):
8249    """WPS proto: M3 missing E-Hash2"""
8250    pin = "12345670"
8251    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8252    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8253    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8254
8255    logger.debug("Receive WSC/Start from AP")
8256    msg = get_wsc_msg(hapd)
8257    if msg['wsc_opcode'] != WSC_Start:
8258        raise Exception("Unexpected Op-Code for WSC/Start")
8259
8260    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8261    uuid_e = 16*b'\x11'
8262    e_nonce = 16*b'\x22'
8263    own_private, e_pk = wsc_dh_init()
8264
8265    logger.debug("Send M1 to AP")
8266    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8267                                e_nonce, e_pk)
8268    send_wsc_msg(hapd, addr, m1)
8269
8270    logger.debug("Receive M2 from AP")
8271    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8272    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8273    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8274
8275    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8276                                     r_nonce)
8277    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8278
8279    logger.debug("Send M3 to AP")
8280    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8281    attrs += build_attr_msg_type(WPS_M3)
8282    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8283    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8284    #attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8285    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8286    raw_m3_attrs = attrs
8287    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8288    send_wsc_msg(hapd, addr, m3)
8289
8290    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8291
8292@remote_compatible
8293def test_wps_ext_m5_missing_e_snonce1(dev, apdev):
8294    """WPS proto: M5 missing E-SNonce1"""
8295    pin = "12345670"
8296    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8297    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8298    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8299
8300    logger.debug("Receive WSC/Start from AP")
8301    msg = get_wsc_msg(hapd)
8302    if msg['wsc_opcode'] != WSC_Start:
8303        raise Exception("Unexpected Op-Code for WSC/Start")
8304
8305    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8306    uuid_e = 16*b'\x11'
8307    e_nonce = 16*b'\x22'
8308    own_private, e_pk = wsc_dh_init()
8309
8310    logger.debug("Send M1 to AP")
8311    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8312                                e_nonce, e_pk)
8313    send_wsc_msg(hapd, addr, m1)
8314
8315    logger.debug("Receive M2 from AP")
8316    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8317    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8318    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8319
8320    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8321                                     r_nonce)
8322    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8323
8324    logger.debug("Send M3 to AP")
8325    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8326    attrs += build_attr_msg_type(WPS_M3)
8327    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8328    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8329    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8330    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8331    raw_m3_attrs = attrs
8332    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8333    send_wsc_msg(hapd, addr, m3)
8334
8335    logger.debug("Receive M4 from AP")
8336    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
8337
8338    logger.debug("Send M5 to AP")
8339    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8340    attrs += build_attr_msg_type(WPS_M5)
8341    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8342    #data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
8343    data = b''
8344    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8345    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
8346    raw_m5_attrs = attrs
8347    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8348    send_wsc_msg(hapd, addr, m5)
8349
8350    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8351
8352@remote_compatible
8353def test_wps_ext_m5_e_snonce1_mismatch(dev, apdev):
8354    """WPS proto: M5 E-SNonce1 mismatch"""
8355    pin = "12345670"
8356    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8357    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8358    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8359
8360    logger.debug("Receive WSC/Start from AP")
8361    msg = get_wsc_msg(hapd)
8362    if msg['wsc_opcode'] != WSC_Start:
8363        raise Exception("Unexpected Op-Code for WSC/Start")
8364
8365    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8366    uuid_e = 16*b'\x11'
8367    e_nonce = 16*b'\x22'
8368    own_private, e_pk = wsc_dh_init()
8369
8370    logger.debug("Send M1 to AP")
8371    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8372                                e_nonce, e_pk)
8373    send_wsc_msg(hapd, addr, m1)
8374
8375    logger.debug("Receive M2 from AP")
8376    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8377    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8378    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8379
8380    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8381                                     r_nonce)
8382    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8383
8384    logger.debug("Send M3 to AP")
8385    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8386    attrs += build_attr_msg_type(WPS_M3)
8387    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8388    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8389    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8390    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8391    raw_m3_attrs = attrs
8392    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8393    send_wsc_msg(hapd, addr, m3)
8394
8395    logger.debug("Receive M4 from AP")
8396    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
8397
8398    logger.debug("Send M5 to AP")
8399    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8400    attrs += build_attr_msg_type(WPS_M5)
8401    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8402    data = build_wsc_attr(ATTR_E_SNONCE1, 16*'\x00')
8403    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8404    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
8405    raw_m5_attrs = attrs
8406    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8407    send_wsc_msg(hapd, addr, m5)
8408
8409    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8410
8411def test_wps_ext_m7_missing_e_snonce2(dev, apdev):
8412    """WPS proto: M7 missing E-SNonce2"""
8413    pin = "12345670"
8414    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8415    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8416    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8417
8418    logger.debug("Receive WSC/Start from AP")
8419    msg = get_wsc_msg(hapd)
8420    if msg['wsc_opcode'] != WSC_Start:
8421        raise Exception("Unexpected Op-Code for WSC/Start")
8422
8423    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8424    uuid_e = 16*b'\x11'
8425    e_nonce = 16*b'\x22'
8426    own_private, e_pk = wsc_dh_init()
8427
8428    logger.debug("Send M1 to AP")
8429    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8430                                e_nonce, e_pk)
8431    send_wsc_msg(hapd, addr, m1)
8432
8433    logger.debug("Receive M2 from AP")
8434    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8435    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8436    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8437
8438    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8439                                     r_nonce)
8440    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8441
8442    logger.debug("Send M3 to AP")
8443    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8444    attrs += build_attr_msg_type(WPS_M3)
8445    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8446    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8447    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8448    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8449    raw_m3_attrs = attrs
8450    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8451    send_wsc_msg(hapd, addr, m3)
8452
8453    logger.debug("Receive M4 from AP")
8454    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
8455
8456    logger.debug("Send M5 to AP")
8457    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8458    attrs += build_attr_msg_type(WPS_M5)
8459    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8460    data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
8461    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8462    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
8463    raw_m5_attrs = attrs
8464    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8465    send_wsc_msg(hapd, addr, m5)
8466
8467    logger.debug("Receive M6 from AP")
8468    msg, m6_attrs, raw_m6_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M6)
8469
8470    logger.debug("Send M7 to AP")
8471    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8472    attrs += build_attr_msg_type(WPS_M7)
8473    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8474    #data = build_wsc_attr(ATTR_E_SNONCE2, e_s2)
8475    data = b''
8476    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8477    attrs += build_attr_authenticator(authkey, raw_m6_attrs, attrs)
8478    m7 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8479    raw_m7_attrs = attrs
8480    send_wsc_msg(hapd, addr, m7)
8481
8482    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8483
8484@remote_compatible
8485def test_wps_ext_m7_e_snonce2_mismatch(dev, apdev):
8486    """WPS proto: M7 E-SNonce2 mismatch"""
8487    pin = "12345670"
8488    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8489    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8490    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8491
8492    logger.debug("Receive WSC/Start from AP")
8493    msg = get_wsc_msg(hapd)
8494    if msg['wsc_opcode'] != WSC_Start:
8495        raise Exception("Unexpected Op-Code for WSC/Start")
8496
8497    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8498    uuid_e = 16*b'\x11'
8499    e_nonce = 16*b'\x22'
8500    own_private, e_pk = wsc_dh_init()
8501
8502    logger.debug("Send M1 to AP")
8503    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8504                                e_nonce, e_pk)
8505    send_wsc_msg(hapd, addr, m1)
8506
8507    logger.debug("Receive M2 from AP")
8508    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8509    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8510    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8511
8512    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8513                                     r_nonce)
8514    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8515
8516    logger.debug("Send M3 to AP")
8517    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8518    attrs += build_attr_msg_type(WPS_M3)
8519    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8520    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8521    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8522    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8523    raw_m3_attrs = attrs
8524    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8525    send_wsc_msg(hapd, addr, m3)
8526
8527    logger.debug("Receive M4 from AP")
8528    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
8529
8530    logger.debug("Send M5 to AP")
8531    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8532    attrs += build_attr_msg_type(WPS_M5)
8533    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8534    data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
8535    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8536    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
8537    raw_m5_attrs = attrs
8538    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8539    send_wsc_msg(hapd, addr, m5)
8540
8541    logger.debug("Receive M6 from AP")
8542    msg, m6_attrs, raw_m6_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M6)
8543
8544    logger.debug("Send M7 to AP")
8545    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8546    attrs += build_attr_msg_type(WPS_M7)
8547    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8548    data = build_wsc_attr(ATTR_E_SNONCE2, 16*'\x00')
8549    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8550    attrs += build_attr_authenticator(authkey, raw_m6_attrs, attrs)
8551    m7 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8552    raw_m7_attrs = attrs
8553    send_wsc_msg(hapd, addr, m7)
8554
8555    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8556
8557@remote_compatible
8558def test_wps_ext_m1_pubkey_oom(dev, apdev):
8559    """WPS proto: M1 PubKey OOM"""
8560    pin = "12345670"
8561    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8562    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8563    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8564
8565    logger.debug("Receive WSC/Start from AP")
8566    msg = get_wsc_msg(hapd)
8567    if msg['wsc_opcode'] != WSC_Start:
8568        raise Exception("Unexpected Op-Code for WSC/Start")
8569
8570    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8571    uuid_e = 16*'\x11'
8572    e_nonce = 16*'\x22'
8573    own_private, e_pk = wsc_dh_init()
8574
8575    logger.debug("Send M1 to AP")
8576    with alloc_fail(hapd, 1, "wpabuf_alloc_copy;wps_process_pubkey"):
8577        m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8578                                    e_nonce, e_pk)
8579        send_wsc_msg(hapd, addr, m1)
8580        wps_wait_eap_failure(hapd, dev[0])
8581
8582def wps_wait_eap_failure(hapd, dev):
8583    ev = hapd.wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
8584    if ev is None:
8585        raise Exception("EAP-Failure not reported")
8586    dev.wait_disconnected()
8587
8588@remote_compatible
8589def test_wps_ext_m3_m1(dev, apdev):
8590    """WPS proto: M3 replaced with M1"""
8591    pin = "12345670"
8592    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8593    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8594    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8595
8596    logger.debug("Receive WSC/Start from AP")
8597    msg = get_wsc_msg(hapd)
8598    if msg['wsc_opcode'] != WSC_Start:
8599        raise Exception("Unexpected Op-Code for WSC/Start")
8600
8601    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8602    uuid_e = 16*b'\x11'
8603    e_nonce = 16*b'\x22'
8604    own_private, e_pk = wsc_dh_init()
8605
8606    logger.debug("Send M1 to AP")
8607    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8608                                e_nonce, e_pk)
8609    send_wsc_msg(hapd, addr, m1)
8610
8611    logger.debug("Receive M2 from AP")
8612    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8613    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8614    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8615
8616    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8617                                     r_nonce)
8618    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8619
8620    logger.debug("Send M3(M1) to AP")
8621    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8622    attrs += build_attr_msg_type(WPS_M1)
8623    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8624    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8625    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8626    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8627    raw_m3_attrs = attrs
8628    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8629    send_wsc_msg(hapd, addr, m3)
8630
8631    wps_wait_eap_failure(hapd, dev[0])
8632
8633@remote_compatible
8634def test_wps_ext_m5_m3(dev, apdev):
8635    """WPS proto: M5 replaced with M3"""
8636    pin = "12345670"
8637    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8638    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8639    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8640
8641    logger.debug("Receive WSC/Start from AP")
8642    msg = get_wsc_msg(hapd)
8643    if msg['wsc_opcode'] != WSC_Start:
8644        raise Exception("Unexpected Op-Code for WSC/Start")
8645
8646    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8647    uuid_e = 16*b'\x11'
8648    e_nonce = 16*b'\x22'
8649    own_private, e_pk = wsc_dh_init()
8650
8651    logger.debug("Send M1 to AP")
8652    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8653                                e_nonce, e_pk)
8654    send_wsc_msg(hapd, addr, m1)
8655
8656    logger.debug("Receive M2 from AP")
8657    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8658    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8659    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8660
8661    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8662                                     r_nonce)
8663    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8664
8665    logger.debug("Send M3 to AP")
8666    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8667    attrs += build_attr_msg_type(WPS_M3)
8668    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8669    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8670    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8671    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8672    raw_m3_attrs = attrs
8673    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8674    send_wsc_msg(hapd, addr, m3)
8675
8676    logger.debug("Receive M4 from AP")
8677    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
8678
8679    logger.debug("Send M5(M3) to AP")
8680    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8681    attrs += build_attr_msg_type(WPS_M3)
8682    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8683    data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
8684    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
8685    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
8686    raw_m5_attrs = attrs
8687    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8688    send_wsc_msg(hapd, addr, m5)
8689
8690    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8691
8692@remote_compatible
8693def test_wps_ext_m3_m2(dev, apdev):
8694    """WPS proto: M3 replaced with M2"""
8695    pin = "12345670"
8696    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8697    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8698    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8699
8700    logger.debug("Receive WSC/Start from AP")
8701    msg = get_wsc_msg(hapd)
8702    if msg['wsc_opcode'] != WSC_Start:
8703        raise Exception("Unexpected Op-Code for WSC/Start")
8704
8705    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8706    uuid_e = 16*b'\x11'
8707    e_nonce = 16*b'\x22'
8708    own_private, e_pk = wsc_dh_init()
8709
8710    logger.debug("Send M1 to AP")
8711    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8712                                e_nonce, e_pk)
8713    send_wsc_msg(hapd, addr, m1)
8714
8715    logger.debug("Receive M2 from AP")
8716    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8717    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8718    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8719
8720    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8721                                     r_nonce)
8722    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8723
8724    logger.debug("Send M3(M2) to AP")
8725    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8726    attrs += build_attr_msg_type(WPS_M2)
8727    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8728    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8729    raw_m3_attrs = attrs
8730    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8731    send_wsc_msg(hapd, addr, m3)
8732
8733    wps_wait_eap_failure(hapd, dev[0])
8734
8735@remote_compatible
8736def test_wps_ext_m3_m5(dev, apdev):
8737    """WPS proto: M3 replaced with M5"""
8738    pin = "12345670"
8739    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8740    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8741    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8742
8743    logger.debug("Receive WSC/Start from AP")
8744    msg = get_wsc_msg(hapd)
8745    if msg['wsc_opcode'] != WSC_Start:
8746        raise Exception("Unexpected Op-Code for WSC/Start")
8747
8748    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8749    uuid_e = 16*b'\x11'
8750    e_nonce = 16*b'\x22'
8751    own_private, e_pk = wsc_dh_init()
8752
8753    logger.debug("Send M1 to AP")
8754    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8755                                e_nonce, e_pk)
8756    send_wsc_msg(hapd, addr, m1)
8757
8758    logger.debug("Receive M2 from AP")
8759    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8760    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8761    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8762
8763    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8764                                     r_nonce)
8765    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8766
8767    logger.debug("Send M3(M5) to AP")
8768    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8769    attrs += build_attr_msg_type(WPS_M5)
8770    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8771    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8772    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8773    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8774    raw_m3_attrs = attrs
8775    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8776    send_wsc_msg(hapd, addr, m3)
8777
8778    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8779
8780@remote_compatible
8781def test_wps_ext_m3_m7(dev, apdev):
8782    """WPS proto: M3 replaced with M7"""
8783    pin = "12345670"
8784    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8785    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8786    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8787
8788    logger.debug("Receive WSC/Start from AP")
8789    msg = get_wsc_msg(hapd)
8790    if msg['wsc_opcode'] != WSC_Start:
8791        raise Exception("Unexpected Op-Code for WSC/Start")
8792
8793    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8794    uuid_e = 16*b'\x11'
8795    e_nonce = 16*b'\x22'
8796    own_private, e_pk = wsc_dh_init()
8797
8798    logger.debug("Send M1 to AP")
8799    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8800                                e_nonce, e_pk)
8801    send_wsc_msg(hapd, addr, m1)
8802
8803    logger.debug("Receive M2 from AP")
8804    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8805    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8806    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8807
8808    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8809                                     r_nonce)
8810    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8811
8812    logger.debug("Send M3(M7) to AP")
8813    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8814    attrs += build_attr_msg_type(WPS_M7)
8815    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
8816    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
8817    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
8818    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8819    raw_m3_attrs = attrs
8820    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
8821    send_wsc_msg(hapd, addr, m3)
8822
8823    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
8824
8825@remote_compatible
8826def test_wps_ext_m3_done(dev, apdev):
8827    """WPS proto: M3 replaced with WSC_Done"""
8828    pin = "12345670"
8829    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8830    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8831    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8832
8833    logger.debug("Receive WSC/Start from AP")
8834    msg = get_wsc_msg(hapd)
8835    if msg['wsc_opcode'] != WSC_Start:
8836        raise Exception("Unexpected Op-Code for WSC/Start")
8837
8838    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8839    uuid_e = 16*b'\x11'
8840    e_nonce = 16*b'\x22'
8841    own_private, e_pk = wsc_dh_init()
8842
8843    logger.debug("Send M1 to AP")
8844    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8845                                e_nonce, e_pk)
8846    send_wsc_msg(hapd, addr, m1)
8847
8848    logger.debug("Receive M2 from AP")
8849    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8850    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8851    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8852
8853    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8854                                     r_nonce)
8855    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8856
8857    logger.debug("Send M3(WSC_Done) to AP")
8858    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
8859    attrs += build_attr_msg_type(WPS_WSC_DONE)
8860    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
8861    raw_m3_attrs = attrs
8862    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
8863    send_wsc_msg(hapd, addr, m3)
8864
8865    wps_wait_eap_failure(hapd, dev[0])
8866
8867@remote_compatible
8868def test_wps_ext_m2_nack_invalid(dev, apdev):
8869    """WPS proto: M2 followed by invalid NACK"""
8870    pin = "12345670"
8871    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8872    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8873    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8874
8875    logger.debug("Receive WSC/Start from AP")
8876    msg = get_wsc_msg(hapd)
8877    if msg['wsc_opcode'] != WSC_Start:
8878        raise Exception("Unexpected Op-Code for WSC/Start")
8879
8880    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8881    uuid_e = 16*b'\x11'
8882    e_nonce = 16*b'\x22'
8883    own_private, e_pk = wsc_dh_init()
8884
8885    logger.debug("Send M1 to AP")
8886    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8887                                e_nonce, e_pk)
8888    send_wsc_msg(hapd, addr, m1)
8889
8890    logger.debug("Receive M2 from AP")
8891    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8892    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8893    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8894
8895    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8896                                     r_nonce)
8897    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8898
8899    logger.debug("Send WSC_NACK to AP")
8900    attrs = b'\x10\x00\x00'
8901    nack = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_NACK)
8902    send_wsc_msg(hapd, addr, nack)
8903
8904    wps_wait_eap_failure(hapd, dev[0])
8905
8906@remote_compatible
8907def test_wps_ext_m2_nack_no_msg_type(dev, apdev):
8908    """WPS proto: M2 followed by NACK without Msg Type"""
8909    pin = "12345670"
8910    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8911    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8912    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8913
8914    logger.debug("Receive WSC/Start from AP")
8915    msg = get_wsc_msg(hapd)
8916    if msg['wsc_opcode'] != WSC_Start:
8917        raise Exception("Unexpected Op-Code for WSC/Start")
8918
8919    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8920    uuid_e = 16*b'\x11'
8921    e_nonce = 16*b'\x22'
8922    own_private, e_pk = wsc_dh_init()
8923
8924    logger.debug("Send M1 to AP")
8925    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8926                                e_nonce, e_pk)
8927    send_wsc_msg(hapd, addr, m1)
8928
8929    logger.debug("Receive M2 from AP")
8930    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8931    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8932    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8933
8934    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8935                                     r_nonce)
8936    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8937
8938    logger.debug("Send WSC_NACK to AP")
8939    nack, attrs = build_nack(msg['eap_identifier'], e_nonce, r_nonce,
8940                             msg_type=None, eap_code=2)
8941    send_wsc_msg(hapd, addr, nack)
8942
8943    wps_wait_eap_failure(hapd, dev[0])
8944
8945@remote_compatible
8946def test_wps_ext_m2_nack_invalid_msg_type(dev, apdev):
8947    """WPS proto: M2 followed by NACK with invalid Msg Type"""
8948    pin = "12345670"
8949    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8950    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8951    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8952
8953    logger.debug("Receive WSC/Start from AP")
8954    msg = get_wsc_msg(hapd)
8955    if msg['wsc_opcode'] != WSC_Start:
8956        raise Exception("Unexpected Op-Code for WSC/Start")
8957
8958    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8959    uuid_e = 16*b'\x11'
8960    e_nonce = 16*b'\x22'
8961    own_private, e_pk = wsc_dh_init()
8962
8963    logger.debug("Send M1 to AP")
8964    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
8965                                e_nonce, e_pk)
8966    send_wsc_msg(hapd, addr, m1)
8967
8968    logger.debug("Receive M2 from AP")
8969    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
8970    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
8971    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
8972
8973    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
8974                                     r_nonce)
8975    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
8976
8977    logger.debug("Send WSC_NACK to AP")
8978    nack, attrs = build_nack(msg['eap_identifier'], e_nonce, r_nonce,
8979                             msg_type=WPS_WSC_ACK, eap_code=2)
8980    send_wsc_msg(hapd, addr, nack)
8981
8982    wps_wait_eap_failure(hapd, dev[0])
8983
8984@remote_compatible
8985def test_wps_ext_m2_nack_e_nonce_mismatch(dev, apdev):
8986    """WPS proto: M2 followed by NACK with e-nonce mismatch"""
8987    pin = "12345670"
8988    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
8989    wps_ext_eap_identity_req(dev[0], hapd, bssid)
8990    wps_ext_eap_identity_resp(hapd, dev[0], addr)
8991
8992    logger.debug("Receive WSC/Start from AP")
8993    msg = get_wsc_msg(hapd)
8994    if msg['wsc_opcode'] != WSC_Start:
8995        raise Exception("Unexpected Op-Code for WSC/Start")
8996
8997    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
8998    uuid_e = 16*b'\x11'
8999    e_nonce = 16*b'\x22'
9000    own_private, e_pk = wsc_dh_init()
9001
9002    logger.debug("Send M1 to AP")
9003    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9004                                e_nonce, e_pk)
9005    send_wsc_msg(hapd, addr, m1)
9006
9007    logger.debug("Receive M2 from AP")
9008    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9009    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9010    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9011
9012    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9013                                     r_nonce)
9014    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9015
9016    logger.debug("Send WSC_NACK to AP")
9017    nack, attrs = build_nack(msg['eap_identifier'], 16*b'\x00', r_nonce,
9018                             eap_code=2)
9019    send_wsc_msg(hapd, addr, nack)
9020
9021    wps_wait_eap_failure(hapd, dev[0])
9022
9023@remote_compatible
9024def test_wps_ext_m2_nack_no_config_error(dev, apdev):
9025    """WPS proto: M2 followed by NACK without Config Error"""
9026    pin = "12345670"
9027    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9028    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9029    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9030
9031    logger.debug("Receive WSC/Start from AP")
9032    msg = get_wsc_msg(hapd)
9033    if msg['wsc_opcode'] != WSC_Start:
9034        raise Exception("Unexpected Op-Code for WSC/Start")
9035
9036    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9037    uuid_e = 16*b'\x11'
9038    e_nonce = 16*b'\x22'
9039    own_private, e_pk = wsc_dh_init()
9040
9041    logger.debug("Send M1 to AP")
9042    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9043                                e_nonce, e_pk)
9044    send_wsc_msg(hapd, addr, m1)
9045
9046    logger.debug("Receive M2 from AP")
9047    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9048    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9049    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9050
9051    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9052                                     r_nonce)
9053    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9054
9055    logger.debug("Send WSC_NACK to AP")
9056    nack, attrs = build_nack(msg['eap_identifier'], e_nonce, r_nonce,
9057                             config_error=None, eap_code=2)
9058    send_wsc_msg(hapd, addr, nack)
9059
9060    wps_wait_eap_failure(hapd, dev[0])
9061
9062@remote_compatible
9063def test_wps_ext_m2_ack_invalid(dev, apdev):
9064    """WPS proto: M2 followed by invalid ACK"""
9065    pin = "12345670"
9066    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9067    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9068    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9069
9070    logger.debug("Receive WSC/Start from AP")
9071    msg = get_wsc_msg(hapd)
9072    if msg['wsc_opcode'] != WSC_Start:
9073        raise Exception("Unexpected Op-Code for WSC/Start")
9074
9075    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9076    uuid_e = 16*b'\x11'
9077    e_nonce = 16*b'\x22'
9078    own_private, e_pk = wsc_dh_init()
9079
9080    logger.debug("Send M1 to AP")
9081    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9082                                e_nonce, e_pk)
9083    send_wsc_msg(hapd, addr, m1)
9084
9085    logger.debug("Receive M2 from AP")
9086    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9087    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9088    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9089
9090    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9091                                     r_nonce)
9092    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9093
9094    logger.debug("Send WSC_ACK to AP")
9095    attrs = b'\x10\x00\x00'
9096    ack = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_ACK)
9097    send_wsc_msg(hapd, addr, ack)
9098
9099    wps_wait_eap_failure(hapd, dev[0])
9100
9101@remote_compatible
9102def test_wps_ext_m2_ack(dev, apdev):
9103    """WPS proto: M2 followed by ACK"""
9104    pin = "12345670"
9105    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9106    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9107    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9108
9109    logger.debug("Receive WSC/Start from AP")
9110    msg = get_wsc_msg(hapd)
9111    if msg['wsc_opcode'] != WSC_Start:
9112        raise Exception("Unexpected Op-Code for WSC/Start")
9113
9114    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9115    uuid_e = 16*b'\x11'
9116    e_nonce = 16*b'\x22'
9117    own_private, e_pk = wsc_dh_init()
9118
9119    logger.debug("Send M1 to AP")
9120    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9121                                e_nonce, e_pk)
9122    send_wsc_msg(hapd, addr, m1)
9123
9124    logger.debug("Receive M2 from AP")
9125    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9126    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9127    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9128
9129    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9130                                     r_nonce)
9131    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9132
9133    logger.debug("Send WSC_ACK to AP")
9134    ack, attrs = build_ack(msg['eap_identifier'], e_nonce, r_nonce, eap_code=2)
9135    send_wsc_msg(hapd, addr, ack)
9136
9137    wps_wait_eap_failure(hapd, dev[0])
9138
9139@remote_compatible
9140def test_wps_ext_m2_ack_no_msg_type(dev, apdev):
9141    """WPS proto: M2 followed by ACK missing Msg Type"""
9142    pin = "12345670"
9143    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9144    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9145    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9146
9147    logger.debug("Receive WSC/Start from AP")
9148    msg = get_wsc_msg(hapd)
9149    if msg['wsc_opcode'] != WSC_Start:
9150        raise Exception("Unexpected Op-Code for WSC/Start")
9151
9152    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9153    uuid_e = 16*b'\x11'
9154    e_nonce = 16*b'\x22'
9155    own_private, e_pk = wsc_dh_init()
9156
9157    logger.debug("Send M1 to AP")
9158    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9159                                e_nonce, e_pk)
9160    send_wsc_msg(hapd, addr, m1)
9161
9162    logger.debug("Receive M2 from AP")
9163    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9164    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9165    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9166
9167    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9168                                     r_nonce)
9169    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9170
9171    logger.debug("Send WSC_ACK to AP")
9172    ack, attrs = build_ack(msg['eap_identifier'], e_nonce, r_nonce,
9173                           msg_type=None, eap_code=2)
9174    send_wsc_msg(hapd, addr, ack)
9175
9176    wps_wait_eap_failure(hapd, dev[0])
9177
9178@remote_compatible
9179def test_wps_ext_m2_ack_invalid_msg_type(dev, apdev):
9180    """WPS proto: M2 followed by ACK with invalid Msg Type"""
9181    pin = "12345670"
9182    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9183    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9184    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9185
9186    logger.debug("Receive WSC/Start from AP")
9187    msg = get_wsc_msg(hapd)
9188    if msg['wsc_opcode'] != WSC_Start:
9189        raise Exception("Unexpected Op-Code for WSC/Start")
9190
9191    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9192    uuid_e = 16*b'\x11'
9193    e_nonce = 16*b'\x22'
9194    own_private, e_pk = wsc_dh_init()
9195
9196    logger.debug("Send M1 to AP")
9197    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9198                                e_nonce, e_pk)
9199    send_wsc_msg(hapd, addr, m1)
9200
9201    logger.debug("Receive M2 from AP")
9202    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9203    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9204    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9205
9206    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9207                                     r_nonce)
9208    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9209
9210    logger.debug("Send WSC_ACK to AP")
9211    ack, attrs = build_ack(msg['eap_identifier'], e_nonce, r_nonce,
9212                          msg_type=WPS_WSC_NACK, eap_code=2)
9213    send_wsc_msg(hapd, addr, ack)
9214
9215    wps_wait_eap_failure(hapd, dev[0])
9216
9217@remote_compatible
9218def test_wps_ext_m2_ack_e_nonce_mismatch(dev, apdev):
9219    """WPS proto: M2 followed by ACK with e-nonce mismatch"""
9220    pin = "12345670"
9221    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9222    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9223    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9224
9225    logger.debug("Receive WSC/Start from AP")
9226    msg = get_wsc_msg(hapd)
9227    if msg['wsc_opcode'] != WSC_Start:
9228        raise Exception("Unexpected Op-Code for WSC/Start")
9229
9230    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9231    uuid_e = 16*b'\x11'
9232    e_nonce = 16*b'\x22'
9233    own_private, e_pk = wsc_dh_init()
9234
9235    logger.debug("Send M1 to AP")
9236    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9237                                e_nonce, e_pk)
9238    send_wsc_msg(hapd, addr, m1)
9239
9240    logger.debug("Receive M2 from AP")
9241    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9242    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9243    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9244
9245    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9246                                     r_nonce)
9247    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9248
9249    logger.debug("Send WSC_ACK to AP")
9250    ack, attrs = build_ack(msg['eap_identifier'], 16*b'\x00', r_nonce,
9251                           eap_code=2)
9252    send_wsc_msg(hapd, addr, ack)
9253
9254    wps_wait_eap_failure(hapd, dev[0])
9255
9256@remote_compatible
9257def test_wps_ext_m1_invalid(dev, apdev):
9258    """WPS proto: M1 failing parsing"""
9259    pin = "12345670"
9260    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9261    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9262    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9263
9264    logger.debug("Receive WSC/Start from AP")
9265    msg = get_wsc_msg(hapd)
9266    if msg['wsc_opcode'] != WSC_Start:
9267        raise Exception("Unexpected Op-Code for WSC/Start")
9268
9269    logger.debug("Send M1 to AP")
9270    attrs = b'\x10\x00\x00'
9271    m1 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9272    send_wsc_msg(hapd, addr, m1)
9273
9274    wps_wait_eap_failure(hapd, dev[0])
9275
9276def test_wps_ext_m1_missing_msg_type(dev, apdev):
9277    """WPS proto: M1 missing Msg Type"""
9278    pin = "12345670"
9279    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9280    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9281    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9282
9283    logger.debug("Receive WSC/Start from AP")
9284    msg = get_wsc_msg(hapd)
9285    if msg['wsc_opcode'] != WSC_Start:
9286        raise Exception("Unexpected Op-Code for WSC/Start")
9287
9288    logger.debug("Send M1 to AP")
9289    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9290    m1 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9291    send_wsc_msg(hapd, addr, m1)
9292
9293    wps_wait_ap_nack(hapd, dev[0], 16*b'\x00', 16*b'\x00')
9294
9295def wps_ext_wsc_done(dev, apdev):
9296    pin = "12345670"
9297    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9298    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9299    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9300
9301    logger.debug("Receive WSC/Start from AP")
9302    msg = get_wsc_msg(hapd)
9303    if msg['wsc_opcode'] != WSC_Start:
9304        raise Exception("Unexpected Op-Code for WSC/Start")
9305
9306    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9307    uuid_e = 16*b'\x11'
9308    e_nonce = 16*b'\x22'
9309    own_private, e_pk = wsc_dh_init()
9310
9311    logger.debug("Send M1 to AP")
9312    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9313                                e_nonce, e_pk)
9314    send_wsc_msg(hapd, addr, m1)
9315
9316    logger.debug("Receive M2 from AP")
9317    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9318    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9319    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9320
9321    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9322                                     r_nonce)
9323    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9324
9325    logger.debug("Send M3 to AP")
9326    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9327    attrs += build_attr_msg_type(WPS_M3)
9328    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9329    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
9330    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
9331    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
9332    raw_m3_attrs = attrs
9333    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9334    send_wsc_msg(hapd, addr, m3)
9335
9336    logger.debug("Receive M4 from AP")
9337    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
9338
9339    logger.debug("Send M5 to AP")
9340    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9341    attrs += build_attr_msg_type(WPS_M5)
9342    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9343    data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
9344    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
9345    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
9346    raw_m5_attrs = attrs
9347    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9348    send_wsc_msg(hapd, addr, m5)
9349
9350    logger.debug("Receive M6 from AP")
9351    msg, m6_attrs, raw_m6_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M6)
9352
9353    logger.debug("Send M7 to AP")
9354    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9355    attrs += build_attr_msg_type(WPS_M7)
9356    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9357    data = build_wsc_attr(ATTR_E_SNONCE2, e_s2)
9358    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
9359    attrs += build_attr_authenticator(authkey, raw_m6_attrs, attrs)
9360    m7 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9361    raw_m7_attrs = attrs
9362    send_wsc_msg(hapd, addr, m7)
9363
9364    logger.debug("Receive M8 from AP")
9365    msg, m8_attrs, raw_m8_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M8)
9366    return hapd, msg, e_nonce, r_nonce
9367
9368@remote_compatible
9369def test_wps_ext_wsc_done_invalid(dev, apdev):
9370    """WPS proto: invalid WSC_Done"""
9371    hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
9372
9373    logger.debug("Send WSC_Done to AP")
9374    attrs = b'\x10\x00\x00'
9375    wsc_done = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
9376    send_wsc_msg(hapd, dev[0].own_addr(), wsc_done)
9377
9378    wps_wait_eap_failure(hapd, dev[0])
9379
9380@remote_compatible
9381def test_wps_ext_wsc_done_no_msg_type(dev, apdev):
9382    """WPS proto: invalid WSC_Done"""
9383    hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
9384
9385    logger.debug("Send WSC_Done to AP")
9386    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9387    #attrs += build_attr_msg_type(WPS_WSC_DONE)
9388    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
9389    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9390    wsc_done = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
9391    send_wsc_msg(hapd, dev[0].own_addr(), wsc_done)
9392
9393    wps_wait_eap_failure(hapd, dev[0])
9394
9395@remote_compatible
9396def test_wps_ext_wsc_done_wrong_msg_type(dev, apdev):
9397    """WPS proto: WSC_Done with wrong Msg Type"""
9398    hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
9399
9400    logger.debug("Send WSC_Done to AP")
9401    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9402    attrs += build_attr_msg_type(WPS_WSC_ACK)
9403    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
9404    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9405    wsc_done = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
9406    send_wsc_msg(hapd, dev[0].own_addr(), wsc_done)
9407
9408    wps_wait_eap_failure(hapd, dev[0])
9409
9410@remote_compatible
9411def test_wps_ext_wsc_done_no_e_nonce(dev, apdev):
9412    """WPS proto: WSC_Done without e_nonce"""
9413    hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
9414
9415    logger.debug("Send WSC_Done to AP")
9416    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9417    attrs += build_attr_msg_type(WPS_WSC_DONE)
9418    #attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
9419    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9420    wsc_done = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
9421    send_wsc_msg(hapd, dev[0].own_addr(), wsc_done)
9422
9423    wps_wait_eap_failure(hapd, dev[0])
9424
9425def test_wps_ext_wsc_done_no_r_nonce(dev, apdev):
9426    """WPS proto: WSC_Done without r_nonce"""
9427    hapd, msg, e_nonce, r_nonce = wps_ext_wsc_done(dev, apdev)
9428
9429    logger.debug("Send WSC_Done to AP")
9430    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9431    attrs += build_attr_msg_type(WPS_WSC_DONE)
9432    attrs += build_wsc_attr(ATTR_ENROLLEE_NONCE, e_nonce)
9433    #attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9434    wsc_done = build_eap_wsc(2, msg['eap_identifier'], attrs, opcode=WSC_Done)
9435    send_wsc_msg(hapd, dev[0].own_addr(), wsc_done)
9436
9437    wps_wait_eap_failure(hapd, dev[0])
9438
9439@remote_compatible
9440def test_wps_ext_m7_no_encr_settings(dev, apdev):
9441    """WPS proto: M7 without Encr Settings"""
9442    pin = "12345670"
9443    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9444    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9445    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9446
9447    logger.debug("Receive WSC/Start from AP")
9448    msg = get_wsc_msg(hapd)
9449    if msg['wsc_opcode'] != WSC_Start:
9450        raise Exception("Unexpected Op-Code for WSC/Start")
9451
9452    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9453    uuid_e = 16*b'\x11'
9454    e_nonce = 16*b'\x22'
9455    own_private, e_pk = wsc_dh_init()
9456
9457    logger.debug("Send M1 to AP")
9458    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9459                                e_nonce, e_pk)
9460    send_wsc_msg(hapd, addr, m1)
9461
9462    logger.debug("Receive M2 from AP")
9463    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9464    r_nonce = m2_attrs[ATTR_REGISTRAR_NONCE]
9465    r_pk = m2_attrs[ATTR_PUBLIC_KEY]
9466
9467    authkey, keywrapkey = wsc_dh_kdf(r_pk, own_private, mac_addr, e_nonce,
9468                                     r_nonce)
9469    e_s1, e_s2, e_hash1, e_hash2 = wsc_dev_pw_hash(authkey, pin, e_pk, r_pk)
9470
9471    logger.debug("Send M3 to AP")
9472    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9473    attrs += build_attr_msg_type(WPS_M3)
9474    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9475    attrs += build_wsc_attr(ATTR_E_HASH1, e_hash1)
9476    attrs += build_wsc_attr(ATTR_E_HASH2, e_hash2)
9477    attrs += build_attr_authenticator(authkey, raw_m2_attrs, attrs)
9478    raw_m3_attrs = attrs
9479    m3 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9480    send_wsc_msg(hapd, addr, m3)
9481
9482    logger.debug("Receive M4 from AP")
9483    msg, m4_attrs, raw_m4_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M4)
9484
9485    logger.debug("Send M5 to AP")
9486    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9487    attrs += build_attr_msg_type(WPS_M5)
9488    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9489    data = build_wsc_attr(ATTR_E_SNONCE1, e_s1)
9490    attrs += build_attr_encr_settings(authkey, keywrapkey, data)
9491    attrs += build_attr_authenticator(authkey, raw_m4_attrs, attrs)
9492    raw_m5_attrs = attrs
9493    m5 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9494    send_wsc_msg(hapd, addr, m5)
9495
9496    logger.debug("Receive M6 from AP")
9497    msg, m6_attrs, raw_m6_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M6)
9498
9499    logger.debug("Send M7 to AP")
9500    attrs = build_wsc_attr(ATTR_VERSION, '\x10')
9501    attrs += build_attr_msg_type(WPS_M7)
9502    attrs += build_wsc_attr(ATTR_REGISTRAR_NONCE, r_nonce)
9503    #data = build_wsc_attr(ATTR_E_SNONCE2, e_s2)
9504    #attrs += build_attr_encr_settings(authkey, keywrapkey, data)
9505    attrs += build_attr_authenticator(authkey, raw_m6_attrs, attrs)
9506    m7 = build_eap_wsc(2, msg['eap_identifier'], attrs)
9507    raw_m7_attrs = attrs
9508    send_wsc_msg(hapd, addr, m7)
9509
9510    wps_wait_ap_nack(hapd, dev[0], e_nonce, r_nonce)
9511
9512@remote_compatible
9513def test_wps_ext_m1_workaround(dev, apdev):
9514    """WPS proto: M1 Manufacturer/Model workaround"""
9515    pin = "12345670"
9516    addr, bssid, hapd = wps_start_ext(apdev[0], dev[0], pin=pin)
9517    wps_ext_eap_identity_req(dev[0], hapd, bssid)
9518    wps_ext_eap_identity_resp(hapd, dev[0], addr)
9519
9520    logger.debug("Receive WSC/Start from AP")
9521    msg = get_wsc_msg(hapd)
9522    if msg['wsc_opcode'] != WSC_Start:
9523        raise Exception("Unexpected Op-Code for WSC/Start")
9524
9525    mac_addr = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
9526    uuid_e = 16*b'\x11'
9527    e_nonce = 16*b'\x22'
9528    own_private, e_pk = wsc_dh_init()
9529
9530    logger.debug("Send M1 to AP")
9531    m1, raw_m1_attrs = build_m1(msg['eap_identifier'], uuid_e, mac_addr,
9532                                e_nonce, e_pk, manufacturer='Apple TEST',
9533                                model_name='AirPort', config_methods=b'\xff\xff')
9534    send_wsc_msg(hapd, addr, m1)
9535
9536    logger.debug("Receive M2 from AP")
9537    msg, m2_attrs, raw_m2_attrs = recv_wsc_msg(hapd, WSC_MSG, WPS_M2)
9538
9539@remote_compatible
9540def test_ap_wps_disable_enable(dev, apdev):
9541    """WPS and DISABLE/ENABLE AP"""
9542    hapd = wps_start_ap(apdev[0])
9543    hapd.disable()
9544    hapd.enable()
9545    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
9546
9547def test_ap_wps_upnp_web_oom(dev, apdev, params):
9548    """hostapd WPS UPnP web OOM"""
9549    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
9550    hapd = add_ssdp_ap(apdev[0], ap_uuid)
9551
9552    location = ssdp_get_location(ap_uuid)
9553    url = urlparse(location)
9554    urls = upnp_get_urls(location)
9555    eventurl = urlparse(urls['event_sub_url'])
9556    ctrlurl = urlparse(urls['control_url'])
9557
9558    conn = HTTPConnection(url.netloc)
9559    with alloc_fail(hapd, 1, "web_connection_parse_get"):
9560        conn.request("GET", "/wps_device.xml")
9561        try:
9562            resp = conn.getresponse()
9563        except:
9564            pass
9565
9566    conn = HTTPConnection(url.netloc)
9567    conn.request("GET", "/unknown")
9568    resp = conn.getresponse()
9569    if resp.status != 404:
9570        raise Exception("Unexpected HTTP result for unknown URL: %d" + resp.status)
9571
9572    with alloc_fail(hapd, 1, "web_connection_parse_get"):
9573        conn.request("GET", "/unknown")
9574        try:
9575            resp = conn.getresponse()
9576            print(resp.status)
9577        except:
9578            pass
9579
9580    conn = HTTPConnection(url.netloc)
9581    conn.request("GET", "/wps_device.xml")
9582    resp = conn.getresponse()
9583    if resp.status != 200:
9584        raise Exception("GET /wps_device.xml failed")
9585
9586    conn = HTTPConnection(url.netloc)
9587    resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
9588    if resp.status != 200:
9589        raise Exception("GetDeviceInfo failed")
9590
9591    with alloc_fail(hapd, 1, "web_process_get_device_info"):
9592        conn = HTTPConnection(url.netloc)
9593        resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
9594        if resp.status != 500:
9595            raise Exception("Internal error not reported from GetDeviceInfo OOM")
9596
9597    with alloc_fail(hapd, 1, "wps_build_m1;web_process_get_device_info"):
9598        conn = HTTPConnection(url.netloc)
9599        resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
9600        if resp.status != 500:
9601            raise Exception("Internal error not reported from GetDeviceInfo OOM")
9602
9603    with alloc_fail(hapd, 1, "wpabuf_alloc;web_connection_send_reply"):
9604        conn = HTTPConnection(url.netloc)
9605        try:
9606            resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
9607        except:
9608            pass
9609
9610    conn = HTTPConnection(url.netloc)
9611    resp = upnp_soap_action(conn, ctrlurl.path, "GetDeviceInfo")
9612    if resp.status != 200:
9613        raise Exception("GetDeviceInfo failed")
9614
9615    # No NewWLANEventType in PutWLANResponse NewMessage
9616    conn = HTTPConnection(url.netloc)
9617    resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse", newmsg="foo")
9618    if resp.status != 600:
9619        raise Exception("Unexpected HTTP response: %d" % resp.status)
9620
9621    # No NewWLANEventMAC in PutWLANResponse NewMessage
9622    conn = HTTPConnection(url.netloc)
9623    resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse",
9624                            newmsg="foo", neweventtype="1")
9625    if resp.status != 600:
9626        raise Exception("Unexpected HTTP response: %d" % resp.status)
9627
9628    # Invalid NewWLANEventMAC in PutWLANResponse NewMessage
9629    conn = HTTPConnection(url.netloc)
9630    resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse",
9631                            newmsg="foo", neweventtype="1",
9632                            neweventmac="foo")
9633    if resp.status != 600:
9634        raise Exception("Unexpected HTTP response: %d" % resp.status)
9635
9636    # Workaround for NewWLANEventMAC in PutWLANResponse NewMessage
9637    # Ignored unexpected PutWLANResponse WLANEventType 1
9638    conn = HTTPConnection(url.netloc)
9639    resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse",
9640                            newmsg="foo", neweventtype="1",
9641                            neweventmac="00.11.22.33.44.55")
9642    if resp.status != 500:
9643        raise Exception("Unexpected HTTP response: %d" % resp.status)
9644
9645    # PutWLANResponse NewMessage with invalid EAP message
9646    conn = HTTPConnection(url.netloc)
9647    resp = upnp_soap_action(conn, ctrlurl.path, "PutWLANResponse",
9648                            newmsg="foo", neweventtype="2",
9649                            neweventmac="00:11:22:33:44:55")
9650    if resp.status != 200:
9651        raise Exception("Unexpected HTTP response: %d" % resp.status)
9652
9653    with alloc_fail(hapd, 1, "web_connection_parse_subscribe"):
9654        conn = HTTPConnection(url.netloc)
9655        headers = {"callback": '<http://127.0.0.1:12345/event>',
9656                   "NT": "upnp:event",
9657                   "timeout": "Second-1234"}
9658        conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
9659        try:
9660            resp = conn.getresponse()
9661        except:
9662            pass
9663
9664    with alloc_fail(hapd, 1, "dup_binstr;web_connection_parse_subscribe"):
9665        conn = HTTPConnection(url.netloc)
9666        headers = {"callback": '<http://127.0.0.1:12345/event>',
9667                   "NT": "upnp:event",
9668                   "timeout": "Second-1234"}
9669        conn.request("SUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
9670        resp = conn.getresponse()
9671        if resp.status != 500:
9672            raise Exception("Unexpected HTTP response: %d" % resp.status)
9673
9674    with alloc_fail(hapd, 1, "wpabuf_alloc;web_connection_parse_unsubscribe"):
9675        conn = HTTPConnection(url.netloc)
9676        headers = {"callback": '<http://127.0.0.1:12345/event>',
9677                   "NT": "upnp:event",
9678                   "timeout": "Second-1234"}
9679        conn.request("UNSUBSCRIBE", eventurl.path, "\r\n\r\n", headers)
9680        try:
9681            resp = conn.getresponse()
9682        except:
9683            pass
9684
9685    with alloc_fail(hapd, 1, "web_connection_unimplemented"):
9686        conn = HTTPConnection(url.netloc)
9687        conn.request("HEAD", "/wps_device.xml")
9688        try:
9689            resp = conn.getresponse()
9690        except:
9691            pass
9692
9693def test_ap_wps_frag_ack_oom(dev, apdev):
9694    """WPS and fragment ack OOM"""
9695    dev[0].request("SET wps_fragment_size 50")
9696    hapd = wps_start_ap(apdev[0])
9697    with alloc_fail(hapd, 1, "eap_wsc_build_frag_ack"):
9698        wps_run_pbc_fail_ap(apdev[0], dev[0], hapd)
9699
9700def wait_scan_stopped(dev):
9701    dev.request("ABORT_SCAN")
9702    for i in range(50):
9703        res = dev.get_driver_status_field("scan_state")
9704        if "SCAN_STARTED" not in res and "SCAN_REQUESTED" not in res:
9705            break
9706        logger.debug("Waiting for scan to complete")
9707        time.sleep(0.1)
9708
9709@remote_compatible
9710def test_ap_wps_eap_wsc_errors(dev, apdev):
9711    """WPS and EAP-WSC error cases"""
9712    ssid = "test-wps-conf-pin"
9713    appin = "12345670"
9714    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
9715              "wpa_passphrase": "12345678", "wpa": "2",
9716              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
9717              "fragment_size": "300", "ap_pin": appin}
9718    hapd = hostapd.add_ap(apdev[0], params)
9719    bssid = apdev[0]['bssid']
9720
9721    pin = dev[0].wps_read_pin()
9722    hapd.request("WPS_PIN any " + pin)
9723    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
9724    dev[0].dump_monitor()
9725
9726    dev[0].wps_reg(bssid, appin + " new_ssid=a", "new ssid", "WPA2PSK", "CCMP",
9727                   "new passphrase", no_wait=True)
9728    ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
9729    if ev is None:
9730        raise Exception("WPS-FAIL not reported")
9731    dev[0].request("WPS_CANCEL")
9732    dev[0].wait_disconnected()
9733    wait_scan_stopped(dev[0])
9734    dev[0].dump_monitor()
9735
9736    dev[0].wps_reg(bssid, appin, "new ssid", "FOO", "CCMP",
9737                   "new passphrase", no_wait=True)
9738    ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
9739    if ev is None:
9740        raise Exception("WPS-FAIL not reported")
9741    dev[0].request("WPS_CANCEL")
9742    dev[0].wait_disconnected()
9743    wait_scan_stopped(dev[0])
9744    dev[0].dump_monitor()
9745
9746    dev[0].wps_reg(bssid, appin, "new ssid", "WPA2PSK", "FOO",
9747                   "new passphrase", no_wait=True)
9748    ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
9749    if ev is None:
9750        raise Exception("WPS-FAIL not reported")
9751    dev[0].request("WPS_CANCEL")
9752    dev[0].wait_disconnected()
9753    wait_scan_stopped(dev[0])
9754    dev[0].dump_monitor()
9755
9756    dev[0].wps_reg(bssid, appin + "new_key=a", "new ssid", "WPA2PSK", "CCMP",
9757                   "new passphrase", no_wait=True)
9758    ev = dev[0].wait_event(["WPS-FAIL"], timeout=10)
9759    if ev is None:
9760        raise Exception("WPS-FAIL not reported")
9761    dev[0].request("WPS_CANCEL")
9762    dev[0].wait_disconnected()
9763    wait_scan_stopped(dev[0])
9764    dev[0].dump_monitor()
9765
9766    tests = ["eap_wsc_init",
9767             "eap_msg_alloc;eap_wsc_build_msg",
9768             "wpabuf_alloc;eap_wsc_process_fragment"]
9769    for func in tests:
9770        with alloc_fail(dev[0], 1, func):
9771            dev[0].request("WPS_PIN %s %s" % (bssid, pin))
9772            wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
9773            dev[0].request("WPS_CANCEL")
9774            dev[0].wait_disconnected()
9775            wait_scan_stopped(dev[0])
9776            dev[0].dump_monitor()
9777
9778    tests = [(1, "wps_decrypt_encr_settings"),
9779             (2, "hmac_sha256;wps_derive_psk")]
9780    for count, func in tests:
9781        hapd.request("WPS_PIN any " + pin)
9782        with fail_test(dev[0], count, func):
9783            dev[0].request("WPS_PIN %s %s" % (bssid, pin))
9784            wait_fail_trigger(dev[0], "GET_FAIL")
9785            dev[0].request("WPS_CANCEL")
9786            dev[0].wait_disconnected()
9787            wait_scan_stopped(dev[0])
9788            dev[0].dump_monitor()
9789
9790    with alloc_fail(dev[0], 1, "eap_msg_alloc;eap_sm_build_expanded_nak"):
9791        dev[0].wps_reg(bssid, appin + " new_ssid=a", "new ssid", "WPA2PSK",
9792                       "CCMP", "new passphrase", no_wait=True)
9793        wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
9794        dev[0].request("WPS_CANCEL")
9795        dev[0].wait_disconnected()
9796        wait_scan_stopped(dev[0])
9797        dev[0].dump_monitor()
9798
9799def test_ap_wps_eap_wsc(dev, apdev):
9800    """WPS and EAP-WSC in network profile"""
9801    params = int_eap_server_params()
9802    params["wps_state"] = "2"
9803    hapd = hostapd.add_ap(apdev[0], params)
9804    bssid = apdev[0]['bssid']
9805
9806    logger.info("Unexpected identity")
9807    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9808                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-unexpected",
9809                   wait_connect=False)
9810    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9811    if ev is None:
9812        raise Exception("No EAP-Failure seen")
9813    dev[0].request("REMOVE_NETWORK all")
9814    dev[0].wait_disconnected()
9815
9816    logger.info("No phase1 parameter")
9817    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9818                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9819                   wait_connect=False)
9820    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9821    if ev is None:
9822        raise Exception("Timeout on EAP method start")
9823    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9824    if ev is None:
9825        raise Exception("No EAP-Failure seen")
9826    dev[0].request("REMOVE_NETWORK all")
9827    dev[0].wait_disconnected()
9828
9829    logger.info("No PIN/PBC in phase1")
9830    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9831                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9832                   phase1="foo", wait_connect=False)
9833    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9834    if ev is None:
9835        raise Exception("Timeout on EAP method start")
9836    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9837    if ev is None:
9838        raise Exception("No EAP-Failure seen")
9839    dev[0].request("REMOVE_NETWORK all")
9840    dev[0].wait_disconnected()
9841
9842    logger.info("Invalid pkhash in phase1")
9843    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9844                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9845                   phase1="foo pkhash=q pbc=1", wait_connect=False)
9846    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9847    if ev is None:
9848        raise Exception("Timeout on EAP method start")
9849    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9850    if ev is None:
9851        raise Exception("No EAP-Failure seen")
9852    dev[0].request("REMOVE_NETWORK all")
9853    dev[0].wait_disconnected()
9854
9855    logger.info("Zero fragment_size")
9856    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9857                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9858                   fragment_size="0", phase1="pin=12345670", wait_connect=False)
9859    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9860    if ev is None:
9861        raise Exception("Timeout on EAP method start")
9862    ev = dev[0].wait_event(["WPS-M2D"], timeout=5)
9863    if ev is None:
9864        raise Exception("No M2D seen")
9865    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9866    if ev is None:
9867        raise Exception("No EAP-Failure seen")
9868    dev[0].request("REMOVE_NETWORK all")
9869    dev[0].wait_disconnected()
9870
9871    logger.info("Missing new_auth")
9872    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9873                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9874                   phase1="pin=12345670 new_ssid=aa", wait_connect=False)
9875    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9876    if ev is None:
9877        raise Exception("Timeout on EAP method start")
9878    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9879    if ev is None:
9880        raise Exception("No EAP-Failure seen")
9881    dev[0].request("REMOVE_NETWORK all")
9882    dev[0].wait_disconnected()
9883
9884    logger.info("Missing new_encr")
9885    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9886                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9887                   phase1="pin=12345670 new_auth=WPA2PSK new_ssid=aa", wait_connect=False)
9888    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9889    if ev is None:
9890        raise Exception("Timeout on EAP method start")
9891    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9892    if ev is None:
9893        raise Exception("No EAP-Failure seen")
9894    dev[0].request("REMOVE_NETWORK all")
9895    dev[0].wait_disconnected()
9896
9897    logger.info("Missing new_key")
9898    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", scan_freq="2412",
9899                   eap="WSC", identity="WFA-SimpleConfig-Enrollee-1-0",
9900                   phase1="pin=12345670 new_auth=WPA2PSK new_ssid=aa new_encr=CCMP",
9901                   wait_connect=False)
9902    ev = dev[0].wait_event(["CTRL-EVENT-EAP-PROPOSED-METHOD"], timeout=5)
9903    if ev is None:
9904        raise Exception("Timeout on EAP method start")
9905    ev = dev[0].wait_event(["CTRL-EVENT-EAP-FAILURE"], timeout=5)
9906    if ev is None:
9907        raise Exception("No EAP-Failure seen")
9908    dev[0].request("REMOVE_NETWORK all")
9909    dev[0].wait_disconnected()
9910
9911def test_ap_wps_and_bss_limit(dev, apdev):
9912    """WPS and wpa_supplicant BSS entry limit"""
9913    try:
9914        _test_ap_wps_and_bss_limit(dev, apdev)
9915    finally:
9916        dev[0].request("SET bss_max_count 200")
9917        pass
9918
9919def _test_ap_wps_and_bss_limit(dev, apdev):
9920    params = {"ssid": "test-wps", "eap_server": "1", "wps_state": "2",
9921              "wpa_passphrase": "12345678", "wpa": "2",
9922              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
9923    hapd = hostapd.add_ap(apdev[0], params)
9924
9925    params = {"ssid": "test-wps-2", "eap_server": "1", "wps_state": "2",
9926              "wpa_passphrase": "1234567890", "wpa": "2",
9927              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
9928    hapd2 = hostapd.add_ap(apdev[1], params)
9929
9930    id = dev[1].add_network()
9931    dev[1].set_network(id, "mode", "2")
9932    dev[1].set_network_quoted(id, "ssid", "wpas-ap-no-wps")
9933    dev[1].set_network_quoted(id, "psk", "12345678")
9934    dev[1].set_network(id, "frequency", "2462")
9935    dev[1].set_network(id, "scan_freq", "2462")
9936    dev[1].set_network(id, "wps_disabled", "1")
9937    dev[1].select_network(id)
9938
9939    id = dev[2].add_network()
9940    dev[2].set_network(id, "mode", "2")
9941    dev[2].set_network_quoted(id, "ssid", "wpas-ap")
9942    dev[2].set_network_quoted(id, "psk", "12345678")
9943    dev[2].set_network(id, "frequency", "2437")
9944    dev[2].set_network(id, "scan_freq", "2437")
9945    dev[2].select_network(id)
9946
9947    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
9948    wpas.interface_add("wlan5")
9949    id = wpas.add_network()
9950    wpas.set_network(id, "mode", "2")
9951    wpas.set_network_quoted(id, "ssid", "wpas-ap")
9952    wpas.set_network_quoted(id, "psk", "12345678")
9953    wpas.set_network(id, "frequency", "2437")
9954    wpas.set_network(id, "scan_freq", "2437")
9955    wpas.select_network(id)
9956
9957    dev[1].wait_connected()
9958    dev[2].wait_connected()
9959    wpas.wait_connected()
9960    wpas.request("WPS_PIN any 12345670")
9961
9962    hapd.request("WPS_PBC")
9963    hapd2.request("WPS_PBC")
9964
9965    dev[0].request("SET bss_max_count 1")
9966
9967    id = dev[0].add_network()
9968    dev[0].set_network_quoted(id, "ssid", "testing")
9969
9970    id = dev[0].add_network()
9971    dev[0].set_network_quoted(id, "ssid", "testing")
9972    dev[0].set_network(id, "key_mgmt", "WPS")
9973
9974    dev[0].request("WPS_PBC")
9975    ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"], timeout=10)
9976    dev[0].request("WPS_CANCEL")
9977
9978    id = dev[0].add_network()
9979    dev[0].set_network_quoted(id, "ssid", "testing")
9980    dev[0].set_network(id, "key_mgmt", "WPS")
9981
9982    dev[0].scan(freq="2412")
9983
9984def test_ap_wps_pbc_2ap(dev, apdev):
9985    """WPS PBC with two APs advertising same SSID"""
9986    params = {"ssid": "wps", "eap_server": "1", "wps_state": "2",
9987              "wpa_passphrase": "12345678", "wpa": "2",
9988              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
9989              "wps_independent": "1"}
9990    hapd = hostapd.add_ap(apdev[0], params)
9991    params = {"ssid": "wps", "eap_server": "1", "wps_state": "2",
9992              "wpa_passphrase": "123456789", "wpa": "2",
9993              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
9994              "wps_independent": "1"}
9995    hapd2 = hostapd.add_ap(apdev[1], params)
9996    hapd.request("WPS_PBC")
9997
9998    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
9999    wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
10000    wpas.dump_monitor()
10001    wpas.flush_scan_cache()
10002
10003    wpas.scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
10004    wpas.scan_for_bss(apdev[1]['bssid'], freq="2412")
10005    wpas.request("WPS_PBC")
10006    wpas.wait_connected()
10007    wpas.request("DISCONNECT")
10008    hapd.request("DISABLE")
10009    hapd2.request("DISABLE")
10010    wpas.flush_scan_cache()
10011
10012def test_ap_wps_er_enrollee_to_conf_ap(dev, apdev):
10013    """WPS ER enrolling a new device to a configured AP"""
10014    try:
10015        _test_ap_wps_er_enrollee_to_conf_ap(dev, apdev)
10016    finally:
10017        dev[0].request("WPS_ER_STOP")
10018
10019def _test_ap_wps_er_enrollee_to_conf_ap(dev, apdev):
10020    ssid = "wps-er-enrollee-to-conf-ap"
10021    ap_pin = "12345670"
10022    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
10023    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10024              "wpa_passphrase": "12345678", "wpa": "2",
10025              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
10026              "device_name": "Wireless AP", "manufacturer": "Company",
10027              "model_name": "WAP", "model_number": "123",
10028              "serial_number": "12345", "device_type": "6-0050F204-1",
10029              "os_version": "01020300",
10030              "config_methods": "label push_button",
10031              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
10032    hapd = hostapd.add_ap(apdev[0], params)
10033    bssid = hapd.own_addr()
10034
10035    id = dev[0].connect(ssid, psk="12345678", scan_freq="2412")
10036    dev[0].dump_monitor()
10037
10038    dev[0].request("WPS_ER_START ifname=lo")
10039    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
10040    if ev is None:
10041        raise Exception("AP discovery timed out")
10042    if ap_uuid not in ev:
10043        raise Exception("Expected AP UUID not found")
10044
10045    pin = dev[2].wps_read_pin()
10046    addr2 = dev[2].own_addr()
10047    dev[0].dump_monitor()
10048    dev[2].scan_for_bss(bssid, freq=2412)
10049    dev[2].dump_monitor()
10050    dev[2].request("WPS_PIN %s %s" % (bssid, pin))
10051
10052    for i in range(3):
10053        ev = dev[0].wait_event(["WPS-ER-ENROLLEE-ADD"], timeout=10)
10054        if ev is None:
10055            raise Exception("Enrollee not seen")
10056        if addr2 in ev:
10057            break
10058    if addr2 not in ev:
10059        raise Exception("Unexpected Enrollee MAC address")
10060    dev[0].dump_monitor()
10061
10062    dev[0].request("WPS_ER_SET_CONFIG " + ap_uuid + " " + str(id))
10063    dev[0].request("WPS_ER_PIN " + addr2 + " " + pin + " " + addr2)
10064    dev[2].wait_connected(timeout=30)
10065    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
10066    if ev is None:
10067        raise Exception("WPS ER did not report success")
10068
10069def test_ap_wps_er_enrollee_to_conf_ap2(dev, apdev):
10070    """WPS ER enrolling a new device to a configured AP (2)"""
10071    try:
10072        _test_ap_wps_er_enrollee_to_conf_ap2(dev, apdev)
10073    finally:
10074        dev[0].request("WPS_ER_STOP")
10075
10076def _test_ap_wps_er_enrollee_to_conf_ap2(dev, apdev):
10077    ssid = "wps-er-enrollee-to-conf-ap"
10078    ap_pin = "12345670"
10079    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
10080    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10081              "wpa_passphrase": "12345678", "wpa": "2",
10082              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
10083              "device_name": "Wireless AP", "manufacturer": "Company",
10084              "model_name": "WAP", "model_number": "123",
10085              "serial_number": "12345", "device_type": "6-0050F204-1",
10086              "os_version": "01020300",
10087              "config_methods": "label push_button",
10088              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
10089    hapd = hostapd.add_ap(apdev[0], params)
10090    bssid = hapd.own_addr()
10091
10092    id = dev[0].connect(ssid, psk="12345678", scan_freq="2412")
10093    dev[0].dump_monitor()
10094
10095    dev[0].request("WPS_ER_START ifname=lo")
10096    ev = dev[0].wait_event(["WPS-ER-AP-ADD"], timeout=15)
10097    if ev is None:
10098        raise Exception("AP discovery timed out")
10099    if ap_uuid not in ev:
10100        raise Exception("Expected AP UUID not found")
10101
10102    dev[0].request("WPS_ER_LEARN " + ap_uuid + " " + ap_pin)
10103    ev = dev[0].wait_event(["WPS-ER-AP-SETTINGS"], timeout=15)
10104    if ev is None:
10105        raise Exception("AP learn timed out")
10106    if ap_uuid not in ev:
10107        raise Exception("Expected AP UUID not in settings")
10108    ev = dev[0].wait_event(["WPS-FAIL"], timeout=15)
10109    if ev is None:
10110        raise Exception("WPS-FAIL after AP learn timed out")
10111    time.sleep(0.1)
10112
10113    pin = dev[1].wps_read_pin()
10114    addr1 = dev[1].own_addr()
10115    dev[0].dump_monitor()
10116    dev[0].request("WPS_ER_PIN any " + pin)
10117    time.sleep(0.1)
10118    dev[1].scan_for_bss(bssid, freq=2412)
10119    dev[1].request("WPS_PIN any %s" % pin)
10120    ev = dev[1].wait_event(["WPS-SUCCESS"], timeout=30)
10121    if ev is None:
10122        raise Exception("Enrollee did not report success")
10123    dev[1].wait_connected(timeout=15)
10124    ev = dev[0].wait_event(["WPS-SUCCESS"], timeout=15)
10125    if ev is None:
10126        raise Exception("WPS ER did not report success")
10127
10128def test_ap_wps_ignore_broadcast_ssid(dev, apdev):
10129    """WPS AP trying to ignore broadcast SSID"""
10130    ssid = "test-wps"
10131    hapd = hostapd.add_ap(apdev[0],
10132                          {"ssid": ssid, "eap_server": "1", "wps_state": "1",
10133                           "ignore_broadcast_ssid": "1"})
10134    if "FAIL" not in hapd.request("WPS_PBC"):
10135        raise Exception("WPS unexpectedly enabled")
10136
10137def test_ap_wps_wep(dev, apdev):
10138    """WPS AP trying to enable WEP"""
10139    check_wep_capa(dev[0])
10140    ssid = "test-wps"
10141    hapd = hostapd.add_ap(apdev[0],
10142                          {"ssid": ssid, "eap_server": "1", "wps_state": "1",
10143                           "ieee80211n": "0", "wep_key0": '"hello"'})
10144    if "FAIL" not in hapd.request("WPS_PBC"):
10145        raise Exception("WPS unexpectedly enabled")
10146
10147def test_ap_wps_tkip(dev, apdev):
10148    """WPS AP trying to enable TKIP"""
10149    ssid = "test-wps"
10150    hapd = hostapd.add_ap(apdev[0],
10151                          {"ssid": ssid, "eap_server": "1", "wps_state": "1",
10152                           "ieee80211n": "0", "wpa": '1',
10153                           "wpa_key_mgmt": "WPA-PSK",
10154                           "wpa_passphrase": "12345678"})
10155    if "FAIL" not in hapd.request("WPS_PBC"):
10156        raise Exception("WPS unexpectedly enabled")
10157
10158def test_ap_wps_conf_stub_cred(dev, apdev):
10159    """WPS PIN provisioning with configured AP using stub cred"""
10160    ssid = "test-wps-conf"
10161    hapd = hostapd.add_ap(apdev[0],
10162                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10163                           "wpa_passphrase": "12345678", "wpa": "2",
10164                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
10165    hapd.request("WPS_PIN any 12345670")
10166    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
10167    dev[0].dump_monitor()
10168    try:
10169        hapd.set("wps_testing_stub_cred", "1")
10170        dev[0].request("WPS_PIN " + apdev[0]['bssid'] + " 12345670")
10171        for i in range(1, 3):
10172            ev = dev[0].wait_event(["WPS-CRED-RECEIVED"], timeout=15)
10173            if ev is None:
10174                raise Exception("WPS credential %d not received" % i)
10175        dev[0].wait_connected(timeout=30)
10176    finally:
10177        hapd.set("wps_testing_stub_cred", "0")
10178
10179def test_ap_wps_rf_bands(dev, apdev):
10180    """WPS and wps_rf_bands configuration"""
10181    ssid = "test-wps-conf"
10182    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10183              "wpa_passphrase": "12345678", "wpa": "2",
10184              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
10185              "wps_rf_bands": "ag"}
10186
10187    hapd = hostapd.add_ap(apdev[0], params)
10188    bssid = hapd.own_addr()
10189    hapd.request("WPS_PBC")
10190    dev[0].scan_for_bss(bssid, freq="2412")
10191    dev[0].dump_monitor()
10192    dev[0].request("WPS_PBC " + bssid)
10193    dev[0].wait_connected(timeout=30)
10194    bss = dev[0].get_bss(bssid)
10195    logger.info("BSS: " + str(bss))
10196    if "103c000103" not in bss['ie']:
10197        raise Exception("RF Bands attribute with expected values not found")
10198    dev[0].request("DISCONNECT")
10199    dev[0].wait_disconnected()
10200    hapd.set("wps_rf_bands", "ad")
10201    hapd.set("wps_rf_bands", "a")
10202    hapd.set("wps_rf_bands", "g")
10203    hapd.set("wps_rf_bands", "b")
10204    hapd.set("wps_rf_bands", "ga")
10205    hapd.disable()
10206    dev[0].dump_monitor()
10207    dev[0].flush_scan_cache()
10208
10209def test_ap_wps_pbc_in_m1(dev, apdev):
10210    """WPS and pbc_in_m1"""
10211    ssid = "test-wps-conf"
10212    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10213              "wpa_passphrase": "12345678", "wpa": "2",
10214              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
10215              "config_methods": "virtual_push_button virtual_display",
10216              "pbc_in_m1": "1"}
10217
10218    hapd = hostapd.add_ap(apdev[0], params)
10219    bssid = hapd.own_addr()
10220    hapd.request("WPS_PBC")
10221    dev[0].scan_for_bss(bssid, freq="2412")
10222    dev[0].dump_monitor()
10223    dev[0].request("WPS_PBC " + bssid)
10224    dev[0].wait_connected(timeout=30)
10225    dev[0].request("DISCONNECT")
10226    dev[0].wait_disconnected()
10227    hapd.disable()
10228    dev[0].dump_monitor()
10229    dev[0].flush_scan_cache()
10230
10231def test_ap_wps_pbc_mac_addr_change(dev, apdev, params):
10232    """WPS M1 with MAC address change"""
10233    skip_without_tkip(dev[0])
10234    ssid = "test-wps-mac-addr-change"
10235    hapd = hostapd.add_ap(apdev[0],
10236                          {"ssid": ssid, "eap_server": "1", "wps_state": "1"})
10237    hapd.request("WPS_PBC")
10238    if "PBC Status: Active" not in hapd.request("WPS_GET_STATUS"):
10239        raise Exception("PBC status not shown correctly")
10240    dev[0].flush_scan_cache()
10241
10242    test_addr = '02:11:22:33:44:55'
10243    addr = dev[0].get_status_field("address")
10244    if addr == test_addr:
10245        raise Exception("Unexpected initial MAC address")
10246
10247    try:
10248        subprocess.call(['ip', 'link', 'set', 'dev', dev[0].ifname, 'down'])
10249        subprocess.call(['ip', 'link', 'set', 'dev', dev[0].ifname, 'address',
10250                         test_addr])
10251        subprocess.call(['ip', 'link', 'set', 'dev', dev[0].ifname, 'up'])
10252        addr1 = dev[0].get_status_field("address")
10253        if addr1 != test_addr:
10254            raise Exception("Failed to change MAC address")
10255
10256        dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
10257        dev[0].request("WPS_PBC " + apdev[0]['bssid'])
10258        dev[0].wait_connected(timeout=30)
10259        status = dev[0].get_status()
10260        if status['wpa_state'] != 'COMPLETED' or \
10261           status['bssid'] != apdev[0]['bssid']:
10262            raise Exception("Not fully connected")
10263
10264        out = run_tshark(os.path.join(params['logdir'], "hwsim0.pcapng"),
10265                         "wps.message_type == 0x04",
10266                         display=["wps.mac_address"])
10267        res = out.splitlines()
10268
10269        if len(res) < 1:
10270            raise Exception("No M1 message with MAC address found")
10271        if res[0] != addr1:
10272            raise Exception("Wrong M1 MAC address")
10273        dev[0].request("DISCONNECT")
10274        dev[0].wait_disconnected()
10275        hapd.disable()
10276        dev[0].dump_monitor()
10277        dev[0].flush_scan_cache()
10278    finally:
10279        # Restore MAC address
10280        subprocess.call(['ip', 'link', 'set', 'dev', dev[0].ifname, 'down'])
10281        subprocess.call(['ip', 'link', 'set', 'dev', dev[0].ifname, 'address',
10282                         addr])
10283        subprocess.call(['ip', 'link', 'set', 'dev', dev[0].ifname, 'up'])
10284
10285def test_ap_wps_pin_start_failure(dev, apdev):
10286    """WPS_PIN start failure"""
10287    with alloc_fail(dev[0], 1, "wpas_wps_start_dev_pw"):
10288        if "FAIL" not in dev[0].request("WPS_PIN any 12345670"):
10289            raise Exception("WPS_PIN not rejected during OOM")
10290    with alloc_fail(dev[0], 1, "wpas_wps_start_dev_pw"):
10291        if "FAIL" not in dev[0].request("WPS_PIN any"):
10292            raise Exception("WPS_PIN not rejected during OOM")
10293
10294def test_ap_wps_ap_pin_failure(dev, apdev):
10295    """WPS_AP_PIN failure"""
10296    id = dev[0].add_network()
10297    dev[0].set_network(id, "mode", "2")
10298    dev[0].set_network_quoted(id, "ssid", "wpas-ap-wps")
10299    dev[0].set_network_quoted(id, "psk", "1234567890")
10300    dev[0].set_network(id, "frequency", "2412")
10301    dev[0].set_network(id, "scan_freq", "2412")
10302    dev[0].select_network(id)
10303    dev[0].wait_connected()
10304
10305    with fail_test(dev[0], 1,
10306                   "os_get_random;wpa_supplicant_ctrl_iface_wps_ap_pin"):
10307        if "FAIL" not in dev[0].request("WPS_AP_PIN random"):
10308            raise Exception("WPS_AP_PIN random accepted")
10309    with alloc_fail(dev[0], 1, "wpas_wps_ap_pin_set"):
10310        if "FAIL" not in dev[0].request("WPS_AP_PIN set 12345670"):
10311            raise Exception("WPS_AP_PIN set accepted")
10312
10313    dev[0].request("DISCONNECT")
10314    dev[0].wait_disconnected()
10315
10316def test_ap_wps_random_uuid(dev, apdev, params):
10317    """WPS and random UUID on Enrollee"""
10318    ssid = "test-wps-conf"
10319    hapd = hostapd.add_ap(apdev[0],
10320                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10321                           "wpa_passphrase": "12345678", "wpa": "2",
10322                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
10323
10324    config = os.path.join(params['logdir'], 'ap_wps_random_uuid.conf')
10325    with open(config, "w") as f:
10326        f.write("auto_uuid=1\n")
10327
10328    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
10329
10330    uuid = []
10331    for i in range(3):
10332        wpas.interface_add("wlan5", config=config)
10333
10334        wpas.scan_for_bss(apdev[0]['bssid'], freq="2412")
10335        wpas.dump_monitor()
10336        wpas.request("WPS_PBC " + apdev[0]['bssid'])
10337
10338        ev = hapd.wait_event(["WPS-ENROLLEE-SEEN"], timeout=10)
10339        if ev is None:
10340            raise Exception("Enrollee not seen")
10341        uuid.append(ev.split(' ')[2])
10342        wpas.request("WPS_CANCEL")
10343        wpas.dump_monitor()
10344
10345        wpas.interface_remove("wlan5")
10346
10347        for j in range(3):
10348            ev = hapd.wait_event(["WPS-ENROLLEE-SEEN"], timeout=1)
10349            if ev:
10350                logger.info("Ignored extra event at the end: " + ev)
10351        hapd.dump_monitor()
10352
10353    logger.info("Seen UUIDs: " + str(uuid))
10354    if uuid[0] == uuid[1] or uuid[0] == uuid[2] or uuid[1] == uuid[2]:
10355        raise Exception("Same UUID used multiple times")
10356
10357def test_ap_wps_conf_pin_gcmp_128(dev, apdev):
10358    """WPS PIN provisioning with configured AP using GCMP-128"""
10359    run_ap_wps_conf_pin_cipher(dev, apdev, "GCMP")
10360
10361def test_ap_wps_conf_pin_gcmp_256(dev, apdev):
10362    """WPS PIN provisioning with configured AP using GCMP-256"""
10363    run_ap_wps_conf_pin_cipher(dev, apdev, "GCMP-256")
10364
10365def test_ap_wps_conf_pin_ccmp_256(dev, apdev):
10366    """WPS PIN provisioning with configured AP using CCMP-256"""
10367    run_ap_wps_conf_pin_cipher(dev, apdev, "CCMP-256")
10368
10369def run_ap_wps_conf_pin_cipher(dev, apdev, cipher):
10370    if cipher not in dev[0].get_capability("pairwise"):
10371        raise HwsimSkip("Cipher %s not supported" % cipher)
10372    ssid = "test-wps-conf-pin"
10373    hapd = hostapd.add_ap(apdev[0],
10374                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10375                           "wpa_passphrase": "12345678", "wpa": "2",
10376                           "wpa_key_mgmt": "WPA-PSK",
10377                           "rsn_pairwise": cipher})
10378    logger.info("WPS provisioning step")
10379    pin = dev[0].wps_read_pin()
10380    hapd.request("WPS_PIN any " + pin)
10381    dev[0].flush_scan_cache()
10382    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
10383    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
10384    dev[0].wait_connected(timeout=15)
10385
10386def test_ap_wps_and_sae(dev, apdev):
10387    """Initial AP configuration with first WPS Enrollee and adding SAE"""
10388    skip_without_tkip(dev[0])
10389    skip_without_tkip(dev[1])
10390    try:
10391        run_ap_wps_and_sae(dev, apdev)
10392    finally:
10393        dev[0].set("wps_cred_add_sae", "0")
10394
10395def run_ap_wps_and_sae(dev, apdev):
10396    check_sae_capab(dev[0])
10397    ssid = "test-wps-sae"
10398    hapd = hostapd.add_ap(apdev[0],
10399                          {"ssid": ssid, "eap_server": "1", "wps_state": "1",
10400                           "wps_cred_add_sae": "1"})
10401    logger.info("WPS provisioning step")
10402    pin = dev[0].wps_read_pin()
10403    hapd.request("WPS_PIN any " + pin)
10404
10405    dev[0].flush_scan_cache()
10406    dev[0].set("wps_cred_add_sae", "1")
10407    dev[0].request("SET sae_groups ")
10408    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
10409    dev[0].request("WPS_PIN " + apdev[0]['bssid'] + " " + pin)
10410    dev[0].wait_connected(timeout=30)
10411    status = dev[0].get_status()
10412    if status['key_mgmt'] != "SAE":
10413        raise Exception("SAE not used")
10414    if 'pmf' not in status or status['pmf'] != "1":
10415        raise Exception("PMF not enabled")
10416
10417    dev[1].flush_scan_cache()
10418    pin = dev[1].wps_read_pin()
10419    hapd.request("WPS_PIN any " + pin)
10420    dev[1].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True)
10421    dev[1].request("WPS_PIN " + apdev[0]['bssid'] + " " + pin)
10422    dev[1].wait_connected(timeout=30)
10423    status = dev[1].get_status()
10424    if status['key_mgmt'] != "WPA2-PSK":
10425        raise Exception("WPA2-PSK not used")
10426    if 'pmf' in status:
10427        raise Exception("PMF enabled")
10428
10429def test_ap_wps_conf_and_sae(dev, apdev):
10430    """WPS PBC provisioning with configured AP using PSK+SAE"""
10431    try:
10432        run_ap_wps_conf_and_sae(dev, apdev)
10433    finally:
10434        dev[0].set("wps_cred_add_sae", "0")
10435
10436def run_ap_wps_conf_and_sae(dev, apdev):
10437    check_sae_capab(dev[0])
10438    ssid = "test-wps-conf-sae"
10439    hapd = hostapd.add_ap(apdev[0],
10440                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10441                           "wpa_passphrase": "12345678", "wpa": "2",
10442                           "ieee80211w": "1", "sae_require_mfp": "1",
10443                           "wpa_key_mgmt": "WPA-PSK SAE",
10444                           "rsn_pairwise": "CCMP"})
10445
10446    dev[0].set("wps_cred_add_sae", "1")
10447    dev[0].request("SET sae_groups ")
10448    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
10449    pin = dev[0].wps_read_pin()
10450    hapd.request("WPS_PIN any " + pin)
10451    dev[0].request("WPS_PIN " + apdev[0]['bssid'] + " " + pin)
10452    dev[0].wait_connected(timeout=30)
10453    status = dev[0].get_status()
10454    if status['key_mgmt'] != "SAE":
10455        raise Exception("SAE not used")
10456    if 'pmf' not in status or status['pmf'] != "1":
10457        raise Exception("PMF not enabled")
10458
10459    dev[1].connect(ssid, psk="12345678", scan_freq="2412", proto="WPA2",
10460                   key_mgmt="WPA-PSK", ieee80211w="0")
10461
10462def test_ap_wps_conf_and_sae_h2e(dev, apdev):
10463    """WPS PIN provisioning with configured AP using PSK+SAE(H2E)"""
10464    try:
10465        run_ap_wps_conf_and_sae_h2e(dev, apdev)
10466    finally:
10467        dev[0].set("wps_cred_add_sae", "0")
10468        dev[0].set("sae_pwe", "0")
10469
10470def run_ap_wps_conf_and_sae_h2e(dev, apdev):
10471    check_sae_capab(dev[0])
10472    ssid = "test-wps-conf-sae"
10473    hapd = hostapd.add_ap(apdev[0],
10474                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10475                           "wpa_passphrase": "12345678", "wpa": "2",
10476                           "ieee80211w": "1", "sae_require_mfp": "1",
10477                           "sae_pwe": "1",
10478                           "wpa_key_mgmt": "WPA-PSK SAE",
10479                           "rsn_pairwise": "CCMP"})
10480
10481    dev[0].set("wps_cred_add_sae", "1")
10482    dev[0].set("sae_pwe", "1")
10483    dev[0].request("SET sae_groups ")
10484    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
10485    pin = dev[0].wps_read_pin()
10486    hapd.request("WPS_PIN any " + pin)
10487    dev[0].request("WPS_PIN " + apdev[0]['bssid'] + " " + pin)
10488    dev[0].wait_connected(timeout=30)
10489    status = dev[0].get_status()
10490    if status['key_mgmt'] != "SAE":
10491        raise Exception("SAE not used")
10492    if 'pmf' not in status or status['pmf'] != "1":
10493        raise Exception("PMF not enabled")
10494
10495def test_ap_wps_reg_config_and_sae(dev, apdev):
10496    """WPS registrar configuring an AP using AP PIN and using PSK+SAE"""
10497    try:
10498        run_ap_wps_reg_config_and_sae(dev, apdev)
10499    finally:
10500        dev[0].set("wps_cred_add_sae", "0")
10501
10502def run_ap_wps_reg_config_and_sae(dev, apdev):
10503    check_sae_capab(dev[0])
10504    ssid = "test-wps-init-ap-pin-sae"
10505    appin = "12345670"
10506    hostapd.add_ap(apdev[0],
10507                   {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10508                    "ap_pin": appin, "wps_cred_add_sae": "1"})
10509    logger.info("WPS configuration step")
10510    dev[0].flush_scan_cache()
10511    dev[0].set("wps_cred_add_sae", "1")
10512    dev[0].request("SET sae_groups ")
10513    dev[0].scan_for_bss(apdev[0]['bssid'], freq=2412)
10514    dev[0].dump_monitor()
10515    new_ssid = "wps-new-ssid"
10516    new_passphrase = "1234567890"
10517    dev[0].wps_reg(apdev[0]['bssid'], appin, new_ssid, "WPA2PSK", "CCMP",
10518                   new_passphrase)
10519    status = dev[0].get_status()
10520    if status['key_mgmt'] != "SAE":
10521        raise Exception("SAE not used")
10522    if 'pmf' not in status or status['pmf'] != "1":
10523        raise Exception("PMF not enabled")
10524
10525    dev[1].connect(new_ssid, psk=new_passphrase, scan_freq="2412", proto="WPA2",
10526                   key_mgmt="WPA-PSK", ieee80211w="0")
10527
10528def test_ap_wps_appl_ext(dev, apdev):
10529    """WPS Application Extension attribute"""
10530    ssid = "test-wps-conf"
10531    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10532              "wps_application_ext": 16*"11" + 5*"ee",
10533              "wpa_passphrase": "12345678", "wpa": "2",
10534              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}
10535    hapd = hostapd.add_ap(apdev[0], params)
10536    pin = dev[0].wps_read_pin()
10537    hapd.request("WPS_PIN any " + pin)
10538    dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
10539    dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin))
10540    dev[0].wait_connected(timeout=30)
10541
10542@long_duration_test
10543def test_ap_wps_pbc_ap_timeout(dev, apdev):
10544    """WPS PBC timeout on AP"""
10545    run_ap_wps_ap_timeout(dev, apdev, "WPS_PBC")
10546
10547@long_duration_test
10548def test_ap_wps_pin_ap_timeout(dev, apdev):
10549    """WPS PIN timeout on AP"""
10550    run_ap_wps_ap_timeout(dev, apdev, "WPS_PIN any 12345670 10")
10551
10552def run_ap_wps_ap_timeout(dev, apdev, cmd):
10553    ssid = "test-wps-conf"
10554    hapd = hostapd.add_ap(apdev[0],
10555                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10556                           "wpa_passphrase": "12345678", "wpa": "2",
10557                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
10558    bssid = hapd.own_addr()
10559    hapd.request(cmd)
10560    time.sleep(1)
10561    dev[0].scan_for_bss(bssid, freq="2412")
10562    bss = dev[0].get_bss(bssid)
10563    logger.info("BSS during active Registrar: " + str(bss))
10564    if not bss['ie'].endswith("0106ffffffffffff"):
10565        raise Exception("Authorized MAC not included")
10566    ev = hapd.wait_event(["WPS-TIMEOUT"], timeout=130)
10567    if ev is None and "PBC" in cmd:
10568        raise Exception("WPS-TIMEOUT not reported")
10569    if "PBC" in cmd and \
10570       "PBC Status: Timed-out" not in hapd.request("WPS_GET_STATUS"):
10571        raise Exception("PBC status not shown correctly")
10572
10573    time.sleep(5)
10574    dev[0].flush_scan_cache()
10575    dev[0].scan_for_bss(bssid, freq="2412", force_scan=True)
10576    bss = dev[0].get_bss(bssid)
10577    logger.info("BSS after timeout: " + str(bss))
10578    if bss['ie'].endswith("0106ffffffffffff"):
10579        raise Exception("Authorized MAC not removed")
10580
10581def test_ap_wps_er_unsubscribe_errors(dev, apdev):
10582    """WPS ER and UNSUBSCRIBE errors"""
10583    start_wps_ap(apdev[0])
10584    tests = [(1, "http_client_url_parse;wps_er_ap_unsubscribe"),
10585             (1, "wpabuf_alloc;wps_er_ap_unsubscribe"),
10586             (1, "http_client_addr;wps_er_ap_unsubscribe")]
10587    try:
10588        for count, func in tests:
10589            start_wps_er(dev[0])
10590            with alloc_fail(dev[0], count, func):
10591                dev[0].request("WPS_ER_STOP")
10592            dev[0].request("REMOVE_NETWORK all")
10593            dev[0].wait_disconnected()
10594            dev[0].dump_monitor()
10595    finally:
10596        dev[0].request("WPS_ER_STOP")
10597
10598def start_wps_ap(apdev):
10599    ssid = "wps-er-ap-config"
10600    ap_pin = "12345670"
10601    ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e"
10602    params = {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10603              "wpa_passphrase": "12345678", "wpa": "2",
10604              "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP",
10605              "device_name": "Wireless AP", "manufacturer": "Company",
10606              "model_name": "WAP", "model_number": "123",
10607              "serial_number": "12345", "device_type": "6-0050F204-1",
10608              "os_version": "01020300",
10609              "config_methods": "label push_button",
10610              "ap_pin": ap_pin, "uuid": ap_uuid, "upnp_iface": "lo"}
10611    hostapd.add_ap(apdev, params)
10612
10613def start_wps_er(dev):
10614    ssid = "wps-er-ap-config"
10615    dev.connect(ssid, psk="12345678", scan_freq="2412")
10616    dev.request("WPS_ER_START ifname=lo")
10617    ev = dev.wait_event(["WPS-ER-AP-ADD"], timeout=15)
10618    if ev is None:
10619        raise Exception("AP discovery timed out")
10620
10621def test_ap_wps_registrar_init_errors(dev, apdev):
10622    """WPS Registrar init errors"""
10623    hapd = wps_start_ap(apdev[0], extra_cred="wps-mixed-cred")
10624    hapd.disable()
10625    tests = [(1, "wps_registrar_init"),
10626             (1, "wpabuf_alloc_copy;wps_registrar_init"),
10627             (1, "wps_set_ie;wps_registrar_init")]
10628    for count, func in tests:
10629        with alloc_fail(hapd, count, func):
10630            if "FAIL" not in hapd.request("ENABLE"):
10631                raise Exception("ENABLE succeeded unexpectedly")
10632
10633def test_ap_wps_config_without_wps(dev, apdev):
10634    """AP configuration attempt using wps_config when WPS is disabled"""
10635    ssid = "test-wps-init-config"
10636    hapd = hostapd.add_ap(apdev[0], {"ssid": ssid})
10637    if "FAIL" not in hapd.request("WPS_CONFIG " + binascii.hexlify(ssid.encode()).decode() + " WPA2PSK CCMP " + binascii.hexlify(b"12345678").decode()):
10638        raise Exception("WPS_CONFIG command succeeded unexpectedly")
10639
10640def test_ap_wps_passive_scan(dev, apdev):
10641    """WPS PBC provisioning with configured AP and passive scanning"""
10642    ssid = "test-wps-conf"
10643    hapd = hostapd.add_ap(apdev[0],
10644                          {"ssid": ssid, "eap_server": "1", "wps_state": "2",
10645                           "wpa_passphrase": "12345678", "wpa": "2",
10646                           "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"})
10647    dev[0].scan_for_bss(hapd.own_addr(), freq="2412")
10648    hapd.request("WPS_PBC")
10649    dev[0].scan_for_bss(hapd.own_addr(), 2412, force_scan=True, passive=True)
10650    hapd.set("ext_mgmt_frame_handling", "1")
10651    dev[0].dump_monitor()
10652    dev[0].request("WPS_PBC " + hapd.own_addr())
10653    req = None
10654    for i in range(0, 10):
10655        req = hapd.mgmt_rx()
10656        if req is None:
10657            raise Exception("MGMT RX wait timed out")
10658        if req['subtype'] == 11:
10659            break
10660        req = None
10661    if not req:
10662        raise Exception("Authentication frame not received")
10663    hapd.set("ext_mgmt_frame_handling", "0")
10664    dev[0].wait_connected(timeout=30)
10665