![Jouni Malinen](/assets/img/avatar_default.png)
These test cases are using externally generated PMKSA cache entry which does not support use of PFS. This will start failing if the station claims to support PFS in such cases, so explicitly disable PFS functionality in these test cases for now. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
5339 lines
232 KiB
Python
5339 lines
232 KiB
Python
# Test cases for Device Provisioning Protocol (DPP)
|
|
# Copyright (c) 2017, Qualcomm Atheros, Inc.
|
|
# Copyright (c) 2018-2019, The Linux Foundation
|
|
#
|
|
# This software may be distributed under the terms of the BSD license.
|
|
# See README for more details.
|
|
|
|
import base64
|
|
import binascii
|
|
import hashlib
|
|
import logging
|
|
logger = logging.getLogger()
|
|
import os
|
|
import socket
|
|
import struct
|
|
import subprocess
|
|
import time
|
|
|
|
import hostapd
|
|
import hwsim_utils
|
|
from hwsim import HWSimRadio
|
|
from utils import *
|
|
from wpasupplicant import WpaSupplicant
|
|
from wlantest import WlantestCapture
|
|
|
|
try:
|
|
import OpenSSL
|
|
openssl_imported = True
|
|
except ImportError:
|
|
openssl_imported = False
|
|
|
|
def check_dpp_capab(dev, brainpool=False, min_ver=1):
|
|
if "UNKNOWN COMMAND" in dev.request("DPP_BOOTSTRAP_GET_URI 0"):
|
|
raise HwsimSkip("DPP not supported")
|
|
if brainpool:
|
|
tls = dev.request("GET tls_library")
|
|
if not tls.startswith("OpenSSL") or "run=BoringSSL" in tls:
|
|
raise HwsimSkip("Crypto library does not support Brainpool curves: " + tls)
|
|
capa = dev.request("GET_CAPABILITY dpp")
|
|
ver = 1
|
|
if capa.startswith("DPP="):
|
|
ver = int(capa[4:])
|
|
if ver < min_ver:
|
|
raise HwsimSkip("DPP version %d not supported" % min_ver)
|
|
return ver
|
|
|
|
def wait_dpp_fail(dev, expected=None):
|
|
ev = dev.wait_event(["DPP-FAIL"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Failure not reported")
|
|
if expected and expected not in ev:
|
|
raise Exception("Unexpected result: " + ev)
|
|
|
|
def test_dpp_qr_code_parsing(dev, apdev):
|
|
"""DPP QR Code parsing"""
|
|
check_dpp_capab(dev[0])
|
|
id = []
|
|
|
|
tests = ["DPP:C:81/1,115/36;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;;",
|
|
"DPP:C:81/1,81/2,81/3,81/4,81/5,81/6,81/7,81/8,81/9,81/10,81/11,81/12,81/13,82/14,83/1,83/2,83/3,83/4,83/5,83/6,83/7,83/8,83/9,84/5,84/6,84/7,84/8,84/9,84/10,84/11,84/12,84/13,115/36;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;;",
|
|
"DPP:C:81/1,2,3,4,5,6,7,8,9,10,11,12,13,82/14,83/1,2,3,4,5,6,7,8,9,84/5,6,7,8,9,10,11,12,13,115/36;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;;",
|
|
"DPP:C:81/1,2,3;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;;",
|
|
"DPP:I:SN=4774LH2b4044;M:010203040506;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;;",
|
|
"DPP:I:;M:010203040506;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;;"]
|
|
for uri in tests:
|
|
id.append(dev[0].dpp_qr_code(uri))
|
|
|
|
uri2 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id[-1])
|
|
if uri != uri2:
|
|
raise Exception("Returned URI does not match")
|
|
|
|
tests = ["foo",
|
|
"DPP:",
|
|
"DPP:;;",
|
|
"DPP:C:1/2;M:;K;;",
|
|
"DPP:I:;M:01020304050;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;;",
|
|
"DPP:K:" + base64.b64encode(b"hello").decode() + ";;",
|
|
"DPP:K:MEkwEwYHKoZIzj0CAQYIKoZIzj0DAQEDMgAEXiJuIWt1Q/CPCkuULechh37UsXPmbUANOeN5U9sOQROE4o/NEFeFEejROHYwwehF;;",
|
|
"DPP:K:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANNZaZA4T/kRDjnmpI1ACOJhAuTIIEk2KFOpS6XPpGF+EVr/ao3XemkE0/nzXmGaLzLqTUCJknSdxTnVPeWfCVsCAwEAAQ==;;",
|
|
"DPP:K:MIIBCjCB0wYHKoZIzj0CATCBxwIBATAkBgcqhkjOPQEBAhkA/////////////////////v//////////MEsEGP////////////////////7//////////AQYZCEFGeWcgOcPp+mrciQwSf643uzBRrmxAxUAMEWub8hCL2TtV5Uo04Eg6uEhltUEMQQYjagOsDCQ9ny/IOtDoYgA9P8K/YL/EBIHGSuV/8jaeGMQEe1rJM3Vc/l3oR55SBECGQD///////////////+Z3vg2FGvJsbTSKDECAQEDMgAEXiJuIWt1Q/CPCkuULechh37UsXPmbUANOeN5U9sOQROE4o/NEFeFEejROHYwwehF;;",
|
|
"DPP:I:foo\tbar;M:010203040506;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;;",
|
|
"DPP:C:1;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkqa24e0rsrfMP9K1Tm8gx+ovP0I=;;",
|
|
"DPP:C:81/1a;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkqa24e0rsrfMP9K1Tm8gx+ovP0I=;;",
|
|
"DPP:C:1/2000,81/-1;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkqa24e0rsrfMP9K1Tm8gx+ovP0I=;;",
|
|
"DPP:C:-1/1;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkqa24e0rsrfMP9K1Tm8gx+ovP0I=;;"]
|
|
for t in tests:
|
|
res = dev[0].request("DPP_QR_CODE " + t)
|
|
if "FAIL" not in res:
|
|
raise Exception("Accepted invalid QR Code: " + t)
|
|
|
|
logger.info("ID: " + str(id))
|
|
if id[0] == id[1] or id[0] == id[2] or id[1] == id[2]:
|
|
raise Exception("Duplicate ID returned")
|
|
|
|
if "FAIL" not in dev[0].request("DPP_BOOTSTRAP_REMOVE 12345678"):
|
|
raise Exception("DPP_BOOTSTRAP_REMOVE accepted unexpectedly")
|
|
if "OK" not in dev[0].request("DPP_BOOTSTRAP_REMOVE %d" % id[1]):
|
|
raise Exception("DPP_BOOTSTRAP_REMOVE failed")
|
|
|
|
id = dev[0].dpp_bootstrap_gen()
|
|
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id)
|
|
logger.info("Generated URI: " + uri)
|
|
|
|
dev[0].dpp_qr_code(uri)
|
|
|
|
id = dev[0].dpp_bootstrap_gen(chan="81/1,115/36", mac="010203040506",
|
|
info="foo")
|
|
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id)
|
|
logger.info("Generated URI: " + uri)
|
|
|
|
dev[0].dpp_qr_code(uri)
|
|
|
|
def test_dpp_qr_code_parsing_fail(dev, apdev):
|
|
"""DPP QR Code parsing local failure"""
|
|
check_dpp_capab(dev[0])
|
|
with alloc_fail(dev[0], 1, "dpp_parse_uri_info"):
|
|
if "FAIL" not in dev[0].request("DPP_QR_CODE DPP:I:SN=4774LH2b4044;M:010203040506;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;;"):
|
|
raise Exception("DPP_QR_CODE failure not reported")
|
|
|
|
with alloc_fail(dev[0], 1, "dpp_parse_uri_pk"):
|
|
if "FAIL" not in dev[0].request("DPP_QR_CODE DPP:K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;;"):
|
|
raise Exception("DPP_QR_CODE failure not reported")
|
|
|
|
with fail_test(dev[0], 1, "dpp_parse_uri_pk"):
|
|
if "FAIL" not in dev[0].request("DPP_QR_CODE DPP:K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;;"):
|
|
raise Exception("DPP_QR_CODE failure not reported")
|
|
|
|
with alloc_fail(dev[0], 1, "dpp_parse_uri"):
|
|
if "FAIL" not in dev[0].request("DPP_QR_CODE DPP:I:SN=4774LH2b4044;M:010203040506;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADURzxmttZoIRIPWGoQMV00XHWCAQIhXruVWOz0NjlkIA=;;"):
|
|
raise Exception("DPP_QR_CODE failure not reported")
|
|
|
|
dpp_key_p256 = "30570201010420777fc55dc51e967c10ec051b91d860b5f1e6c934e48d5daffef98d032c64b170a00a06082a8648ce3d030107a124032200020c804188c7f85beb6e91070d2b3e5e39b90ca77b4d3c5251bc1844d6ca29dcad"
|
|
dpp_key_p384 = "307402010104302f56fdd83b5345cacb630eb7c22fa5ad5daba37307c95191e2a75756d137003bd8b32dbcb00eb5650c1eb499ecfcaec0a00706052b81040022a13403320003615ec2141b5b77aebb6523f8a012755f9a34405a8398d2ceeeebca7f5ce868bf55056cba4c4ec62fad3ed26dd29e0f23"
|
|
dpp_key_p521 = "308198020101044200c8010d5357204c252551aaf4e210343111e503fd1dc615b257058997c49b6b643c975226e93be8181cca3d83a7072defd161dfbdf433c19abe1f2ad51867a05761a00706052b81040023a1460344000301cdf3608b1305fe34a1f976095dcf001182b9973354efe156291a66830292f9babd8f412ad462958663e7a75d1d0610abdfc3dd95d40669f7ab3bc001668cfb3b7c"
|
|
dpp_key_bp256 = "3058020101042057133a676fb60bf2a3e6797e19833c7b0f89dc192ab99ab5fa377ae23a157765a00b06092b2403030208010107a12403220002945d9bf7ce30c9c1ac0ff21ca62b984d5bb80ff69d2be8c9716ab39a10d2caf0"
|
|
dpp_key_bp384 = "307802010104304902df9f3033a9b7128554c0851dc7127c3573eed150671dae74c0013e9896a9b1c22b6f7d43d8a2ebb7cd474dc55039a00b06092b240303020801010ba13403320003623cb5e68787f351faababf3425161571560add2e6f9a306fcbffb507735bf955bb46dd20ba246b0d5cadce73e5bd6a6"
|
|
dpp_key_bp512 = "30819802010104405803494226eb7e50bf0e90633f37e7e35d33f5fa502165eeba721d927f9f846caf12e925701d18e123abaaaf4a7edb4fc4de21ce18bc10c4d12e8b3439f74e40a00b06092b240303020801010da144034200033b086ccd47486522d35dc16fbb2229642c2e9e87897d45abbf21f9fb52acb5a6272b31d1b227c3e53720769cc16b4cb181b26cd0d35fe463218aaedf3b6ec00a"
|
|
|
|
def test_dpp_qr_code_curves(dev, apdev):
|
|
"""DPP QR Code and supported curves"""
|
|
check_dpp_capab(dev[0])
|
|
tests = [("prime256v1", dpp_key_p256),
|
|
("secp384r1", dpp_key_p384),
|
|
("secp521r1", dpp_key_p521)]
|
|
for curve, hex in tests:
|
|
id = dev[0].dpp_bootstrap_gen(key=hex)
|
|
info = dev[0].request("DPP_BOOTSTRAP_INFO %d" % id)
|
|
if "FAIL" in info:
|
|
raise Exception("Failed to get info for " + curve)
|
|
if "curve=" + curve not in info:
|
|
raise Exception("Curve mismatch for " + curve)
|
|
|
|
def test_dpp_qr_code_curves_brainpool(dev, apdev):
|
|
"""DPP QR Code and supported Brainpool curves"""
|
|
check_dpp_capab(dev[0], brainpool=True)
|
|
tests = [("brainpoolP256r1", dpp_key_bp256),
|
|
("brainpoolP384r1", dpp_key_bp384),
|
|
("brainpoolP512r1", dpp_key_bp512)]
|
|
for curve, hex in tests:
|
|
id = dev[0].dpp_bootstrap_gen(key=hex)
|
|
info = dev[0].request("DPP_BOOTSTRAP_INFO %d" % id)
|
|
if "FAIL" in info:
|
|
raise Exception("Failed to get info for " + curve)
|
|
if "curve=" + curve not in info:
|
|
raise Exception("Curve mismatch for " + curve)
|
|
|
|
def test_dpp_qr_code_unsupported_curve(dev, apdev):
|
|
"""DPP QR Code and unsupported curve"""
|
|
check_dpp_capab(dev[0])
|
|
|
|
id = dev[0].request("DPP_BOOTSTRAP_GEN type=qrcode curve=unsupported")
|
|
if "FAIL" not in id:
|
|
raise Exception("Unsupported curve accepted")
|
|
|
|
tests = ["30",
|
|
"305f02010104187f723ed9e1b41979ec5cd02eb82696efc76b40e277661049a00a06082a8648ce3d030101a134033200043f292614dea97c43f500f069e79ae9fb48f8b07369180de5eec8fa2bc9eea5af7a46dc335f52f10cb1c0e9464201d41b"]
|
|
for hex in tests:
|
|
id = dev[0].request("DPP_BOOTSTRAP_GEN type=qrcode key=" + hex)
|
|
if "FAIL" not in id:
|
|
raise Exception("Unsupported/invalid curve accepted")
|
|
|
|
def test_dpp_qr_code_keygen_fail(dev, apdev):
|
|
"""DPP QR Code and keygen failure"""
|
|
check_dpp_capab(dev[0])
|
|
|
|
with alloc_fail(dev[0], 1, "dpp_bootstrap_key_der;dpp_keygen"):
|
|
if "FAIL" not in dev[0].request("DPP_BOOTSTRAP_GEN type=qrcode"):
|
|
raise Exception("Failure not reported")
|
|
|
|
with alloc_fail(dev[0], 1, "base64_gen_encode;dpp_keygen"):
|
|
if "FAIL" not in dev[0].request("DPP_BOOTSTRAP_GEN type=qrcode"):
|
|
raise Exception("Failure not reported")
|
|
|
|
def test_dpp_qr_code_curve_select(dev, apdev):
|
|
"""DPP QR Code and curve selection"""
|
|
check_dpp_capab(dev[0], brainpool=True)
|
|
check_dpp_capab(dev[1], brainpool=True)
|
|
|
|
bi = []
|
|
for key in [dpp_key_p256, dpp_key_p384, dpp_key_p521,
|
|
dpp_key_bp256, dpp_key_bp384, dpp_key_bp512]:
|
|
id = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True, key=key)
|
|
info = dev[0].request("DPP_BOOTSTRAP_INFO %d" % id)
|
|
for i in info.splitlines():
|
|
if '=' in i:
|
|
name, val = i.split('=')
|
|
if name == "curve":
|
|
curve = val
|
|
break
|
|
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id)
|
|
bi.append((curve, uri))
|
|
|
|
for curve, uri in bi:
|
|
logger.info("Curve: " + curve)
|
|
logger.info("URI: " + uri)
|
|
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri)
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0],
|
|
allow_enrollee_failure=True, stop_responder=True,
|
|
stop_initiator=True)
|
|
|
|
def test_dpp_qr_code_auth_broadcast(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (broadcast)"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1")
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0)
|
|
wait_auth_success(dev[0], dev[1], stop_responder=True)
|
|
|
|
def test_dpp_qr_code_auth_unicast(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (unicast)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, None)
|
|
|
|
def test_dpp_qr_code_auth_unicast_ap_enrollee(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (AP enrollee)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, None, netrole="ap")
|
|
|
|
def run_dpp_configurator_enrollee(dev, apdev, conf_curve=None):
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, None, netrole="configurator",
|
|
configurator=True, conf_curve=conf_curve,
|
|
conf="configurator")
|
|
ev = dev[0].wait_event(["DPP-CONFIGURATOR-ID"], timeout=2)
|
|
if ev is None:
|
|
raise Exception("No Configurator instance added")
|
|
|
|
def test_dpp_configurator_enrollee(dev, apdev):
|
|
"""DPP Configurator enrolling"""
|
|
run_dpp_configurator_enrollee(dev, apdev)
|
|
|
|
def test_dpp_configurator_enrollee_prime256v1(dev, apdev):
|
|
"""DPP Configurator enrolling (prime256v1)"""
|
|
run_dpp_configurator_enrollee(dev, apdev, conf_curve="prime256v1")
|
|
|
|
def test_dpp_configurator_enrollee_secp384r1(dev, apdev):
|
|
"""DPP Configurator enrolling (secp384r1)"""
|
|
run_dpp_configurator_enrollee(dev, apdev, conf_curve="secp384r1")
|
|
|
|
def test_dpp_configurator_enrollee_secp521r1(dev, apdev):
|
|
"""DPP Configurator enrolling (secp521r1)"""
|
|
run_dpp_configurator_enrollee(dev, apdev, conf_curve="secp521r1")
|
|
|
|
def test_dpp_configurator_enrollee_brainpoolP256r1(dev, apdev):
|
|
"""DPP Configurator enrolling (brainpoolP256r1)"""
|
|
run_dpp_configurator_enrollee(dev, apdev, conf_curve="brainpoolP256r1")
|
|
|
|
def test_dpp_configurator_enrollee_brainpoolP384r1(dev, apdev):
|
|
"""DPP Configurator enrolling (brainpoolP384r1)"""
|
|
run_dpp_configurator_enrollee(dev, apdev, conf_curve="brainpoolP384r1")
|
|
|
|
def test_dpp_configurator_enrollee_brainpoolP512r1(dev, apdev):
|
|
"""DPP Configurator enrolling (brainpoolP512r1)"""
|
|
run_dpp_configurator_enrollee(dev, apdev, conf_curve="brainpoolP512r1")
|
|
|
|
def test_dpp_qr_code_curve_prime256v1(dev, apdev):
|
|
"""DPP QR Code and curve prime256v1"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1")
|
|
|
|
def test_dpp_qr_code_curve_secp384r1(dev, apdev):
|
|
"""DPP QR Code and curve secp384r1"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "secp384r1")
|
|
|
|
def test_dpp_qr_code_curve_secp521r1(dev, apdev):
|
|
"""DPP QR Code and curve secp521r1"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "secp521r1")
|
|
|
|
def test_dpp_qr_code_curve_brainpoolP256r1(dev, apdev):
|
|
"""DPP QR Code and curve brainpoolP256r1"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "brainpoolP256r1")
|
|
|
|
def test_dpp_qr_code_curve_brainpoolP384r1(dev, apdev):
|
|
"""DPP QR Code and curve brainpoolP384r1"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "brainpoolP384r1")
|
|
|
|
def test_dpp_qr_code_curve_brainpoolP512r1(dev, apdev):
|
|
"""DPP QR Code and curve brainpoolP512r1"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "brainpoolP512r1")
|
|
|
|
def test_dpp_qr_code_set_key(dev, apdev):
|
|
"""DPP QR Code and fixed bootstrapping key"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, None, key="30770201010420e5143ac74682cc6869a830e8f5301a5fa569130ac329b1d7dd6f2a7495dbcbe1a00a06082a8648ce3d030107a144034200045e13e167c33dbc7d85541e5509600aa8139bbb3e39e25898992c5d01be92039ee2850f17e71506ded0d6b25677441eae249f8e225c68dd15a6354dca54006383")
|
|
|
|
def run_dpp_qr_code_auth_unicast(dev, apdev, curve, netrole=None, key=None,
|
|
require_conf_success=False, init_extra=None,
|
|
require_conf_failure=False,
|
|
configurator=False, conf_curve=None,
|
|
conf=None):
|
|
check_dpp_capab(dev[0], curve and "brainpool" in curve)
|
|
check_dpp_capab(dev[1], curve and "brainpool" in curve)
|
|
if configurator:
|
|
conf_id = dev[1].dpp_configurator_add(curve=conf_curve)
|
|
else:
|
|
conf_id = None
|
|
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True, curve=curve, key=key)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412, netrole=netrole)
|
|
dev[1].dpp_auth_init(uri=uri0, extra=init_extra, configurator=conf_id,
|
|
conf=conf)
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0],
|
|
allow_enrollee_failure=True,
|
|
allow_configurator_failure=not require_conf_success,
|
|
require_configurator_failure=require_conf_failure,
|
|
stop_responder=True)
|
|
|
|
def test_dpp_qr_code_auth_mutual(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (mutual)"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
logger.info("dev1 displays QR Code")
|
|
id1b = dev[1].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri1b = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1b)
|
|
|
|
logger.info("dev0 scans QR Code")
|
|
id0b = dev[0].dpp_qr_code(uri1b)
|
|
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0, own=id1b)
|
|
|
|
ev = dev[1].wait_event(["DPP-AUTH-DIRECTION"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP authentication direction not indicated (Initiator)")
|
|
if "mutual=1" not in ev:
|
|
raise Exception("Mutual authentication not used")
|
|
|
|
wait_auth_success(dev[0], dev[1], stop_responder=True)
|
|
|
|
def test_dpp_qr_code_auth_mutual2(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (mutual2)"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
logger.info("dev1 displays QR Code")
|
|
id1b = dev[1].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri1b = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1b)
|
|
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412, qr="mutual")
|
|
dev[1].dpp_auth_init(uri=uri0, own=id1b)
|
|
|
|
ev = dev[1].wait_event(["DPP-RESPONSE-PENDING"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Pending response not reported")
|
|
ev = dev[0].wait_event(["DPP-SCAN-PEER-QR-CODE"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("QR Code scan for mutual authentication not requested")
|
|
|
|
logger.info("dev0 scans QR Code")
|
|
id0b = dev[0].dpp_qr_code(uri1b)
|
|
|
|
ev = dev[1].wait_event(["DPP-AUTH-DIRECTION"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP authentication direction not indicated (Initiator)")
|
|
if "mutual=1" not in ev:
|
|
raise Exception("Mutual authentication not used")
|
|
|
|
wait_auth_success(dev[0], dev[1], stop_responder=True)
|
|
|
|
def test_dpp_qr_code_auth_mutual_p_256(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (mutual, autogen P-256)"""
|
|
run_dpp_qr_code_auth_mutual(dev, apdev, "P-256")
|
|
|
|
def test_dpp_qr_code_auth_mutual_p_384(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (mutual, autogen P-384)"""
|
|
run_dpp_qr_code_auth_mutual(dev, apdev, "P-384")
|
|
|
|
def test_dpp_qr_code_auth_mutual_p_521(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (mutual, autogen P-521)"""
|
|
run_dpp_qr_code_auth_mutual(dev, apdev, "P-521")
|
|
|
|
def test_dpp_qr_code_auth_mutual_bp_256(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (mutual, autogen BP-256)"""
|
|
run_dpp_qr_code_auth_mutual(dev, apdev, "BP-256")
|
|
|
|
def test_dpp_qr_code_auth_mutual_bp_384(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (mutual, autogen BP-384)"""
|
|
run_dpp_qr_code_auth_mutual(dev, apdev, "BP-384")
|
|
|
|
def test_dpp_qr_code_auth_mutual_bp_512(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (mutual, autogen BP-512)"""
|
|
run_dpp_qr_code_auth_mutual(dev, apdev, "BP-512")
|
|
|
|
def run_dpp_qr_code_auth_mutual(dev, apdev, curve):
|
|
check_dpp_capab(dev[0], curve and "BP-" in curve)
|
|
check_dpp_capab(dev[1], curve and "BP-" in curve)
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True, curve=curve)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412, qr="mutual")
|
|
dev[1].dpp_auth_init(uri=uri0)
|
|
|
|
ev = dev[1].wait_event(["DPP-RESPONSE-PENDING"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Pending response not reported")
|
|
uri = ev.split(' ')[1]
|
|
|
|
ev = dev[0].wait_event(["DPP-SCAN-PEER-QR-CODE"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("QR Code scan for mutual authentication not requested")
|
|
|
|
logger.info("dev0 scans QR Code")
|
|
dev[0].dpp_qr_code(uri)
|
|
|
|
ev = dev[1].wait_event(["DPP-AUTH-DIRECTION"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP authentication direction not indicated (Initiator)")
|
|
if "mutual=1" not in ev:
|
|
raise Exception("Mutual authentication not used")
|
|
|
|
wait_auth_success(dev[0], dev[1], stop_responder=True)
|
|
|
|
def test_dpp_auth_resp_retries(dev, apdev):
|
|
"""DPP Authentication Response retries"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[0].set("dpp_resp_max_tries", "3")
|
|
dev[0].set("dpp_resp_retry_time", "100")
|
|
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
logger.info("dev1 displays QR Code")
|
|
id1b = dev[1].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri1b = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1b)
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412, qr="mutual")
|
|
dev[1].dpp_auth_init(uri=uri0, own=id1b)
|
|
|
|
ev = dev[1].wait_event(["DPP-RESPONSE-PENDING"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Pending response not reported")
|
|
ev = dev[0].wait_event(["DPP-SCAN-PEER-QR-CODE"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("QR Code scan for mutual authentication not requested")
|
|
|
|
# Stop Initiator from listening to frames to force retransmission of the
|
|
# DPP Authentication Response frame with Status=0
|
|
dev[1].request("DPP_STOP_LISTEN")
|
|
|
|
dev[1].dump_monitor()
|
|
dev[0].dump_monitor()
|
|
|
|
logger.info("dev0 scans QR Code")
|
|
id0b = dev[0].dpp_qr_code(uri1b)
|
|
|
|
ev = dev[0].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None or "type=1" not in ev:
|
|
raise Exception("DPP Authentication Response not sent")
|
|
ev = dev[0].wait_event(["DPP-TX-STATUS"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("TX status for DPP Authentication Response not reported")
|
|
if "result=no-ACK" not in ev:
|
|
raise Exception("Unexpected TX status for Authentication Response: " + ev)
|
|
|
|
ev = dev[0].wait_event(["DPP-TX "], timeout=15)
|
|
if ev is None or "type=1" not in ev:
|
|
raise Exception("DPP Authentication Response retransmission not sent")
|
|
|
|
def test_dpp_qr_code_auth_mutual_not_used(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (mutual not used)"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
logger.info("dev1 displays QR Code")
|
|
id1b = dev[1].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri1b = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1b)
|
|
logger.info("dev0 does not scan QR Code")
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0, own=id1b)
|
|
|
|
ev = dev[1].wait_event(["DPP-AUTH-DIRECTION"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP authentication direction not indicated (Initiator)")
|
|
if "mutual=0" not in ev:
|
|
raise Exception("Mutual authentication not used")
|
|
|
|
wait_auth_success(dev[0], dev[1], stop_responder=True)
|
|
|
|
def test_dpp_qr_code_auth_mutual_curve_mismatch(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (mutual/mismatch)"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
logger.info("dev1 displays QR Code")
|
|
id1b = dev[1].dpp_bootstrap_gen(chan="81/1", mac=True, curve="secp384r1")
|
|
uri1b = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1b)
|
|
logger.info("dev0 scans QR Code")
|
|
id0b = dev[0].dpp_qr_code(uri1b)
|
|
logger.info("dev1 scans QR Code")
|
|
dev[1].dpp_auth_init(uri=uri0, own=id1b, expect_fail=True)
|
|
|
|
def test_dpp_qr_code_auth_hostapd_mutual2(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (hostapd mutual2)"""
|
|
check_dpp_capab(dev[0])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"})
|
|
check_dpp_capab(hapd)
|
|
logger.info("AP displays QR Code")
|
|
id_h = hapd.dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri_h = hapd.request("DPP_BOOTSTRAP_GET_URI %d" % id_h)
|
|
logger.info("dev0 displays QR Code")
|
|
id0b = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0b)
|
|
logger.info("dev0 scans QR Code and initiates DPP Authentication")
|
|
hapd.dpp_listen(2412, qr="mutual")
|
|
dev[0].dpp_auth_init(uri=uri_h, own=id0b)
|
|
|
|
ev = dev[0].wait_event(["DPP-RESPONSE-PENDING"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Pending response not reported")
|
|
ev = hapd.wait_event(["DPP-SCAN-PEER-QR-CODE"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("QR Code scan for mutual authentication not requested")
|
|
|
|
logger.info("AP scans QR Code")
|
|
hapd.dpp_qr_code(uri0)
|
|
|
|
wait_auth_success(hapd, dev[0], stop_responder=True)
|
|
|
|
def test_dpp_qr_code_listen_continue(dev, apdev):
|
|
"""DPP QR Code and listen operation needing continuation"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].dpp_listen(2412)
|
|
logger.info("Wait for listen to expire and get restarted")
|
|
time.sleep(5.5)
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[1].dpp_auth_init(uri=uri0)
|
|
wait_auth_success(dev[0], dev[1], stop_responder=True)
|
|
|
|
def test_dpp_qr_code_auth_initiator_enrollee(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (Initiator in Enrollee role)"""
|
|
try:
|
|
run_dpp_qr_code_auth_initiator_enrollee(dev, apdev)
|
|
finally:
|
|
dev[0].set("gas_address3", "0")
|
|
dev[1].set("gas_address3", "0")
|
|
|
|
def run_dpp_qr_code_auth_initiator_enrollee(dev, apdev):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[0].request("SET gas_address3 1")
|
|
dev[1].request("SET gas_address3 1")
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0, role="enrollee")
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[0], enrollee=dev[1],
|
|
allow_enrollee_failure=True, stop_responder=True)
|
|
|
|
def test_dpp_qr_code_auth_initiator_either_1(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (Initiator in either role)"""
|
|
run_dpp_qr_code_auth_initiator_either(dev, apdev, None, dev[1], dev[0])
|
|
|
|
def test_dpp_qr_code_auth_initiator_either_2(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (Initiator in either role)"""
|
|
run_dpp_qr_code_auth_initiator_either(dev, apdev, "enrollee",
|
|
dev[1], dev[0])
|
|
|
|
def test_dpp_qr_code_auth_initiator_either_3(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (Initiator in either role)"""
|
|
run_dpp_qr_code_auth_initiator_either(dev, apdev, "configurator",
|
|
dev[0], dev[1])
|
|
|
|
def run_dpp_qr_code_auth_initiator_either(dev, apdev, resp_role,
|
|
conf_dev, enrollee_dev):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412, role=resp_role)
|
|
dev[1].dpp_auth_init(uri=uri0, role="either")
|
|
wait_auth_success(dev[0], dev[1], configurator=conf_dev,
|
|
enrollee=enrollee_dev, allow_enrollee_failure=True,
|
|
stop_responder=True)
|
|
|
|
def run_init_incompatible_roles(dev, role="enrollee"):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
logger.info("dev1 scans QR Code")
|
|
id1 = dev[1].dpp_qr_code(uri0)
|
|
|
|
logger.info("dev1 initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412, role=role)
|
|
return id1
|
|
|
|
def test_dpp_qr_code_auth_incompatible_roles(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (incompatible roles)"""
|
|
id1 = run_init_incompatible_roles(dev)
|
|
dev[1].dpp_auth_init(peer=id1, role="enrollee")
|
|
ev = dev[1].wait_event(["DPP-NOT-COMPATIBLE"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP-NOT-COMPATIBLE event on initiator timed out")
|
|
ev = dev[0].wait_event(["DPP-NOT-COMPATIBLE"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("DPP-NOT-COMPATIBLE event on responder timed out")
|
|
dev[1].dpp_auth_init(peer=id1, role="configurator")
|
|
wait_auth_success(dev[0], dev[1], stop_responder=True)
|
|
|
|
def test_dpp_qr_code_auth_incompatible_roles2(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (incompatible roles 2)"""
|
|
id1 = run_init_incompatible_roles(dev, role="configurator")
|
|
dev[1].dpp_auth_init(peer=id1, role="configurator")
|
|
ev = dev[1].wait_event(["DPP-NOT-COMPATIBLE"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP-NOT-COMPATIBLE event on initiator timed out")
|
|
ev = dev[0].wait_event(["DPP-NOT-COMPATIBLE"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("DPP-NOT-COMPATIBLE event on responder timed out")
|
|
|
|
def test_dpp_qr_code_auth_incompatible_roles_failure(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (incompatible roles failure)"""
|
|
id1 = run_init_incompatible_roles(dev, role="configurator")
|
|
with alloc_fail(dev[0], 1, "dpp_auth_build_resp_status"):
|
|
dev[1].dpp_auth_init(peer=id1, role="configurator")
|
|
ev = dev[0].wait_event(["DPP-NOT-COMPATIBLE"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("DPP-NOT-COMPATIBLE event on responder timed out")
|
|
|
|
def test_dpp_qr_code_auth_incompatible_roles_failure2(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (incompatible roles failure 2)"""
|
|
id1 = run_init_incompatible_roles(dev, role="configurator")
|
|
with alloc_fail(dev[1], 1, "dpp_auth_resp_rx_status"):
|
|
dev[1].dpp_auth_init(peer=id1, role="configurator")
|
|
wait_fail_trigger(dev[1], "GET_ALLOC_FAIL")
|
|
|
|
def test_dpp_qr_code_auth_incompatible_roles_failure3(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (incompatible roles failure 3)"""
|
|
id1 = run_init_incompatible_roles(dev, role="configurator")
|
|
with fail_test(dev[1], 1, "dpp_auth_resp_rx_status"):
|
|
dev[1].dpp_auth_init(peer=id1, role="configurator")
|
|
wait_dpp_fail(dev[1], "AES-SIV decryption failed")
|
|
|
|
def test_dpp_qr_code_auth_neg_chan(dev, apdev):
|
|
"""DPP QR Code and authentication exchange with requested different channel"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
conf_id = dev[1].dpp_configurator_add()
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0, conf="sta-dpp", neg_freq=2462,
|
|
configurator=conf_id)
|
|
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP Authentication Request not sent")
|
|
if "freq=2412 type=0" not in ev:
|
|
raise Exception("Unexpected TX data for Authentication Request: " + ev)
|
|
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP Authentication Request not received")
|
|
if "freq=2412 type=0" not in ev:
|
|
raise Exception("Unexpected RX data for Authentication Request: " + ev)
|
|
|
|
ev = dev[1].wait_event(["DPP-TX-STATUS"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("TX status for DPP Authentication Request not reported")
|
|
if "freq=2412 result=SUCCESS" not in ev:
|
|
raise Exception("Unexpected TX status for Authentication Request: " + ev)
|
|
|
|
ev = dev[0].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP Authentication Response not sent")
|
|
if "freq=2462 type=1" not in ev:
|
|
raise Exception("Unexpected TX data for Authentication Response: " + ev)
|
|
|
|
ev = dev[1].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP Authentication Response not received")
|
|
if "freq=2462 type=1" not in ev:
|
|
raise Exception("Unexpected RX data for Authentication Response: " + ev)
|
|
|
|
ev = dev[0].wait_event(["DPP-TX-STATUS"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("TX status for DPP Authentication Response not reported")
|
|
if "freq=2462 result=SUCCESS" not in ev:
|
|
raise Exception("Unexpected TX status for Authentication Response: " + ev)
|
|
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP Authentication Confirm not sent")
|
|
if "freq=2462 type=2" not in ev:
|
|
raise Exception("Unexpected TX data for Authentication Confirm: " + ev)
|
|
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP Authentication Confirm not received")
|
|
if "freq=2462 type=2" not in ev:
|
|
raise Exception("Unexpected RX data for Authentication Confirm: " + ev)
|
|
|
|
ev = dev[1].wait_event(["DPP-TX-STATUS"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("TX status for DPP Authentication Confirm not reported")
|
|
if "freq=2462 result=SUCCESS" not in ev:
|
|
raise Exception("Unexpected TX status for Authentication Confirm: " + ev)
|
|
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0],
|
|
stop_responder=True)
|
|
|
|
def test_dpp_config_legacy(dev, apdev):
|
|
"""DPP Config Object for legacy network using passphrase"""
|
|
check_dpp_capab(dev[1])
|
|
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}'
|
|
dev[1].set("dpp_config_obj_override", conf)
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
require_conf_success=True)
|
|
|
|
def test_dpp_config_legacy_psk_hex(dev, apdev):
|
|
"""DPP Config Object for legacy network using PSK"""
|
|
check_dpp_capab(dev[1])
|
|
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","psk_hex":"' + 32*"12" + '"}}'
|
|
dev[1].set("dpp_config_obj_override", conf)
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
require_conf_success=True)
|
|
|
|
def test_dpp_config_fragmentation(dev, apdev):
|
|
"""DPP Config Object for legacy network requiring fragmentation"""
|
|
check_dpp_capab(dev[1])
|
|
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
|
|
dev[1].set("dpp_config_obj_override", conf)
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
require_conf_success=True)
|
|
|
|
def test_dpp_config_legacy_gen(dev, apdev):
|
|
"""Generate DPP Config Object for legacy network"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
init_extra="conf=sta-psk pass=%s" % binascii.hexlify(b"passphrase").decode(),
|
|
require_conf_success=True)
|
|
|
|
def test_dpp_config_legacy_gen_psk(dev, apdev):
|
|
"""Generate DPP Config Object for legacy network (PSK)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
init_extra="conf=sta-psk psk=0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
require_conf_success=True)
|
|
|
|
def test_dpp_config_dpp_gen_prime256v1(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network (P-256)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True)
|
|
|
|
def test_dpp_config_dpp_gen_secp384r1(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network (P-384)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "secp384r1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True)
|
|
|
|
def test_dpp_config_dpp_gen_secp521r1(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network (P-521)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "secp521r1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True)
|
|
|
|
def test_dpp_config_dpp_gen_prime256v1_prime256v1(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network (P-256 + P-256)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True,
|
|
conf_curve="prime256v1")
|
|
|
|
def test_dpp_config_dpp_gen_prime256v1_secp384r1(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network (P-256 + P-384)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True,
|
|
conf_curve="secp384r1")
|
|
|
|
def test_dpp_config_dpp_gen_prime256v1_secp521r1(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network (P-256 + P-521)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True,
|
|
conf_curve="secp521r1")
|
|
|
|
def test_dpp_config_dpp_gen_secp384r1_prime256v1(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network (P-384 + P-256)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "secp384r1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True,
|
|
conf_curve="prime256v1")
|
|
|
|
def test_dpp_config_dpp_gen_secp384r1_secp384r1(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network (P-384 + P-384)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "secp384r1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True,
|
|
conf_curve="secp384r1")
|
|
|
|
def test_dpp_config_dpp_gen_secp384r1_secp521r1(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network (P-384 + P-521)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "secp384r1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True,
|
|
conf_curve="secp521r1")
|
|
|
|
def test_dpp_config_dpp_gen_secp521r1_prime256v1(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network (P-521 + P-256)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "secp521r1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True,
|
|
conf_curve="prime256v1")
|
|
|
|
def test_dpp_config_dpp_gen_secp521r1_secp384r1(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network (P-521 + P-384)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "secp521r1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True,
|
|
conf_curve="secp384r1")
|
|
|
|
def test_dpp_config_dpp_gen_secp521r1_secp521r1(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network (P-521 + P-521)"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "secp521r1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True,
|
|
conf_curve="secp521r1")
|
|
|
|
def test_dpp_config_dpp_gen_expiry(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network with expiry value"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
init_extra="conf=sta-dpp expiry=%d" % (time.time() + 1000),
|
|
require_conf_success=True,
|
|
configurator=True)
|
|
|
|
def test_dpp_config_dpp_gen_expired_key(dev, apdev):
|
|
"""Generate DPP Config Object for DPP network with expiry value"""
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
init_extra="conf=sta-dpp expiry=%d" % (time.time() - 10),
|
|
require_conf_failure=True,
|
|
configurator=True)
|
|
|
|
def test_dpp_config_dpp_override_prime256v1(dev, apdev):
|
|
"""DPP Config Object override (P-256)"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{"akm":"dpp","signedConnector":"eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJUbkdLaklsTlphYXRyRUFZcmJiamlCNjdyamtMX0FHVldYTzZxOWhESktVIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6InN0YSJ9XSwibmV0QWNjZXNzS2V5Ijp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiYVRGNEpFR0lQS1NaMFh2OXpkQ01qbS10bjVYcE1zWUlWWjl3eVNBejFnSSIsInkiOiJRR2NIV0FfNnJiVTlYRFhBenRvWC1NNVEzc3VUbk1hcUVoVUx0bjdTU1h3In19._sm6YswxMf6hJLVTyYoU1uYUeY2VVkUNjrzjSiEhY42StD_RWowStEE-9CRsdCvLmsTptZ72_g40vTFwdId20A","csign":{"kty":"EC","crv":"P-256","x":"W4-Y5N1Pkos3UWb9A5qme0KUYRtY3CVUpekx_MapZ9s","y":"Et-M4NSF4NGjvh2VCh4B1sJ9eSCZ4RNzP2DBdP137VE","kid":"TnGKjIlNZaatrEAYrbbjiB67rjkL_AGVWXO6q9hDJKU"}}}'
|
|
dev[0].set("dpp_ignore_netaccesskey_mismatch", "1")
|
|
dev[1].set("dpp_config_obj_override", conf)
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
require_conf_success=True)
|
|
|
|
def test_dpp_config_dpp_override_secp384r1(dev, apdev):
|
|
"""DPP Config Object override (P-384)"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{"akm":"dpp","signedConnector":"eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJabi1iMndjbjRLM2pGQklkYmhGZkpVTHJTXzdESS0yMWxFQi02R3gxNjl3IiwiYWxnIjoiRVMzODQifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6InN0YSJ9XSwibmV0QWNjZXNzS2V5Ijp7Imt0eSI6IkVDIiwiY3J2IjoiUC0zODQiLCJ4IjoickdrSGg1UUZsOUtfWjdqYUZkVVhmbThoY1RTRjM1b25Xb1NIRXVsbVNzWW9oX1RXZGpoRjhiVGdiS0ZRN2tBViIsInkiOiJBbU1QVDA5VmFENWpGdzMwTUFKQlp2VkZXeGNlVVlKLXR5blQ0bVJ5N0xOZWxhZ0dEWHpfOExaRlpOU2FaNUdLIn19.Yn_F7m-bbOQ5PlaYQJ9-1qsuqYQ6V-rAv8nWw1COKiCYwwbt3WFBJ8DljY0dPrlg5CHJC4saXwkytpI-CpELW1yUdzYb4Lrun07d20Eo_g10ICyOl5sqQCAUElKMe_Xr","csign":{"kty":"EC","crv":"P-384","x":"dmTyXXiPV2Y8a01fujL-jo08gvzyby23XmzOtzjAiujKQZZgPJsbhfEKrZDlc6ey","y":"H5Z0av5c7bqInxYb2_OOJdNiMhVf3zlcULR0516ZZitOY4U31KhL4wl4KGV7g2XW","kid":"Zn-b2wcn4K3jFBIdbhFfJULrS_7DI-21lEB-6Gx169w"}}}'
|
|
dev[0].set("dpp_ignore_netaccesskey_mismatch", "1")
|
|
dev[1].set("dpp_config_obj_override", conf)
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "secp384r1",
|
|
require_conf_success=True)
|
|
|
|
def test_dpp_config_dpp_override_secp521r1(dev, apdev):
|
|
"""DPP Config Object override (P-521)"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{"akm":"dpp","signedConnector":"eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJMZkhKY3hnV2ZKcG1uS2IwenZRT0F2VDB2b0ZKc0JjZnBmYzgxY3Y5ZXFnIiwiYWxnIjoiRVM1MTIifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6InN0YSJ9XSwibmV0QWNjZXNzS2V5Ijp7Imt0eSI6IkVDIiwiY3J2IjoiUC01MjEiLCJ4IjoiQVJlUFBrMFNISkRRR2NWbnlmM3lfbTlaQllHNjFJeElIbDN1NkdwRHVhMkU1WVd4TE1BSUtMMnZuUGtlSGFVRXljRmZaZlpYZ2JlNkViUUxMVkRVUm1VUSIsInkiOiJBWUtaYlNwUkFFNjJVYm9YZ2c1ZWRBVENzbEpzTlpwcm9RR1dUcW9Md04weXkzQkVoT3ZRZmZrOWhaR2lKZ295TzFobXFRRVRrS0pXb2tIYTBCQUpLSGZtIn19.ACEZLyPk13cM_OFScpLoCElQ2t1sxq5z2d_W_3_QslTQQe5SFiH_o8ycL4632YLAH4RV0gZcMKKRMtZdHgBYHjkzASDqgY-_aYN2SBmpfl8hw0YdDlUJWX3DJf-ofqNAlTbnGmhpSg69cEAhFn41Xgvx2MdwYcPVncxxESVOtWl5zNLK","csign":{"kty":"EC","crv":"P-521","x":"ADiOI_YJOAipEXHB-SpGl4KqokX8m8h3BVYCc8dgiwssZ061-nIIY3O1SIO6Re4Jjfy53RPgzDG6jitOgOGLtzZs","y":"AZKggKaQi0ExutSpJAU3-lqDV03sBQLA9C7KabfWoAn8qD6Vk4jU0WAJdt-wBBTF9o1nVuiqS2OxMVYrxN4lOz79","kid":"LfHJcxgWfJpmnKb0zvQOAvT0voFJsBcfpfc81cv9eqg"}}}'
|
|
dev[0].set("dpp_ignore_netaccesskey_mismatch", "1")
|
|
dev[1].set("dpp_config_obj_override", conf)
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "secp521r1",
|
|
require_conf_success=True)
|
|
|
|
def test_dpp_config_override_objects(dev, apdev):
|
|
"""Generate DPP Config Object and override objects)"""
|
|
check_dpp_capab(dev[1])
|
|
discovery = '{\n"ssid":"mywifi"\n}'
|
|
groups = '[\n {"groupId":"home","netRole":"sta"},\n {"groupId":"cottage","netRole":"sta"}\n]'
|
|
dev[1].set("dpp_discovery_override", discovery)
|
|
dev[1].set("dpp_groups_override", groups)
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True)
|
|
|
|
def build_conf_obj(kty="EC", crv="P-256",
|
|
x="W4-Y5N1Pkos3UWb9A5qme0KUYRtY3CVUpekx_MapZ9s",
|
|
y="Et-M4NSF4NGjvh2VCh4B1sJ9eSCZ4RNzP2DBdP137VE",
|
|
kid="TnGKjIlNZaatrEAYrbbjiB67rjkL_AGVWXO6q9hDJKU",
|
|
prot_hdr='{"typ":"dppCon","kid":"TnGKjIlNZaatrEAYrbbjiB67rjkL_AGVWXO6q9hDJKU","alg":"ES256"}',
|
|
signed_connector=None,
|
|
no_signed_connector=False,
|
|
csign=True):
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{'
|
|
conf += '"akm":"dpp",'
|
|
|
|
if signed_connector:
|
|
conn = signed_connector
|
|
conf += '"signedConnector":"%s",' % conn
|
|
elif not no_signed_connector:
|
|
payload = '{"groups":[{"groupId":"*","netRole":"sta"}],"netAccessKey":{"kty":"EC","crv":"P-256","x":"aTF4JEGIPKSZ0Xv9zdCMjm-tn5XpMsYIVZ9wySAz1gI","y":"QGcHWA_6rbU9XDXAztoX-M5Q3suTnMaqEhULtn7SSXw"}}'
|
|
sign = "_sm6YswxMf6hJLVTyYoU1uYUeY2VVkUNjrzjSiEhY42StD_RWowStEE-9CRsdCvLmsTptZ72_g40vTFwdId20A"
|
|
conn = base64.urlsafe_b64encode(prot_hdr.encode()).decode().rstrip('=') + '.'
|
|
conn += base64.urlsafe_b64encode(payload.encode()).decode().rstrip('=') + '.'
|
|
conn += sign
|
|
conf += '"signedConnector":"%s",' % conn
|
|
|
|
if csign:
|
|
conf += '"csign":{'
|
|
if kty:
|
|
conf += '"kty":"%s",' % kty
|
|
if crv:
|
|
conf += '"crv":"%s",' % crv
|
|
if x:
|
|
conf += '"x":"%s",' % x
|
|
if y:
|
|
conf += '"y":"%s",' % y
|
|
if kid:
|
|
conf += '"kid":"%s"' % kid
|
|
conf = conf.rstrip(',')
|
|
conf += '}'
|
|
else:
|
|
conf = conf.rstrip(',')
|
|
|
|
conf += '}}'
|
|
|
|
return conf
|
|
|
|
def run_dpp_config_error(dev, apdev, conf,
|
|
skip_net_access_key_mismatch=True,
|
|
conf_failure=True):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
if skip_net_access_key_mismatch:
|
|
dev[0].set("dpp_ignore_netaccesskey_mismatch", "1")
|
|
dev[1].set("dpp_config_obj_override", conf)
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1",
|
|
require_conf_success=not conf_failure,
|
|
require_conf_failure=conf_failure)
|
|
|
|
def test_dpp_config_jwk_error_no_kty(dev, apdev):
|
|
"""DPP Config Object JWK error - no kty"""
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(kty=None))
|
|
|
|
def test_dpp_config_jwk_error_unexpected_kty(dev, apdev):
|
|
"""DPP Config Object JWK error - unexpected kty"""
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(kty="unknown"))
|
|
|
|
def test_dpp_config_jwk_error_no_crv(dev, apdev):
|
|
"""DPP Config Object JWK error - no crv"""
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(crv=None))
|
|
|
|
def test_dpp_config_jwk_error_unsupported_crv(dev, apdev):
|
|
"""DPP Config Object JWK error - unsupported curve"""
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(crv="unsupported"))
|
|
|
|
def test_dpp_config_jwk_error_no_x(dev, apdev):
|
|
"""DPP Config Object JWK error - no x"""
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(x=None))
|
|
|
|
def test_dpp_config_jwk_error_invalid_x(dev, apdev):
|
|
"""DPP Config Object JWK error - invalid x"""
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(x="MTIz"))
|
|
|
|
def test_dpp_config_jwk_error_no_y(dev, apdev):
|
|
"""DPP Config Object JWK error - no y"""
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(y=None))
|
|
|
|
def test_dpp_config_jwk_error_invalid_y(dev, apdev):
|
|
"""DPP Config Object JWK error - invalid y"""
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(y="MTIz"))
|
|
|
|
def test_dpp_config_jwk_error_invalid_xy(dev, apdev):
|
|
"""DPP Config Object JWK error - invalid x,y"""
|
|
conf = build_conf_obj(x="MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY",
|
|
y="MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY")
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_jwk_error_no_kid(dev, apdev):
|
|
"""DPP Config Object JWK error - no kid"""
|
|
# csign kid is optional field, so this results in success
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(kid=None),
|
|
conf_failure=False)
|
|
|
|
def test_dpp_config_jws_error_prot_hdr_not_an_object(dev, apdev):
|
|
"""DPP Config Object JWS error - protected header not an object"""
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(prot_hdr="1"))
|
|
|
|
def test_dpp_config_jws_error_prot_hdr_no_typ(dev, apdev):
|
|
"""DPP Config Object JWS error - protected header - no typ"""
|
|
prot_hdr = '{"kid":"TnGKjIlNZaatrEAYrbbjiB67rjkL_AGVWXO6q9hDJKU","alg":"ES256"}'
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(prot_hdr=prot_hdr))
|
|
|
|
def test_dpp_config_jws_error_prot_hdr_unsupported_typ(dev, apdev):
|
|
"""DPP Config Object JWS error - protected header - unsupported typ"""
|
|
prot_hdr = '{"typ":"unsupported","kid":"TnGKjIlNZaatrEAYrbbjiB67rjkL_AGVWXO6q9hDJKU","alg":"ES256"}'
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(prot_hdr=prot_hdr))
|
|
|
|
def test_dpp_config_jws_error_prot_hdr_no_alg(dev, apdev):
|
|
"""DPP Config Object JWS error - protected header - no alg"""
|
|
prot_hdr = '{"typ":"dppCon","kid":"TnGKjIlNZaatrEAYrbbjiB67rjkL_AGVWXO6q9hDJKU"}'
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(prot_hdr=prot_hdr))
|
|
|
|
def test_dpp_config_jws_error_prot_hdr_unexpected_alg(dev, apdev):
|
|
"""DPP Config Object JWS error - protected header - unexpected alg"""
|
|
prot_hdr = '{"typ":"dppCon","kid":"TnGKjIlNZaatrEAYrbbjiB67rjkL_AGVWXO6q9hDJKU","alg":"unexpected"}'
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(prot_hdr=prot_hdr))
|
|
|
|
def test_dpp_config_jws_error_prot_hdr_no_kid(dev, apdev):
|
|
"""DPP Config Object JWS error - protected header - no kid"""
|
|
prot_hdr = '{"typ":"dppCon","alg":"ES256"}'
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(prot_hdr=prot_hdr))
|
|
|
|
def test_dpp_config_jws_error_prot_hdr_unexpected_kid(dev, apdev):
|
|
"""DPP Config Object JWS error - protected header - unexpected kid"""
|
|
prot_hdr = '{"typ":"dppCon","kid":"MTIz","alg":"ES256"}'
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(prot_hdr=prot_hdr))
|
|
|
|
def test_dpp_config_signed_connector_error_no_dot_1(dev, apdev):
|
|
"""DPP Config Object signedConnector error - no dot(1)"""
|
|
conn = "MTIz"
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(signed_connector=conn))
|
|
|
|
def test_dpp_config_signed_connector_error_no_dot_2(dev, apdev):
|
|
"""DPP Config Object signedConnector error - no dot(2)"""
|
|
conn = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJUbkdLaklsTlphYXRyRUFZcmJiamlCNjdyamtMX0FHVldYTzZxOWhESktVIiwiYWxnIjoiRVMyNTYifQ.MTIz"
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(signed_connector=conn))
|
|
|
|
def test_dpp_config_signed_connector_error_unexpected_signature_len(dev, apdev):
|
|
"""DPP Config Object signedConnector error - unexpected signature length"""
|
|
conn = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJUbkdLaklsTlphYXRyRUFZcmJiamlCNjdyamtMX0FHVldYTzZxOWhESktVIiwiYWxnIjoiRVMyNTYifQ.MTIz.MTIz"
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(signed_connector=conn))
|
|
|
|
def test_dpp_config_signed_connector_error_invalid_signature_der(dev, apdev):
|
|
"""DPP Config Object signedConnector error - invalid signature DER"""
|
|
conn = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJUbkdLaklsTlphYXRyRUFZcmJiamlCNjdyamtMX0FHVldYTzZxOWhESktVIiwiYWxnIjoiRVMyNTYifQ.MTIz.MTI"
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(signed_connector=conn))
|
|
|
|
def test_dpp_config_no_csign(dev, apdev):
|
|
"""DPP Config Object error - no csign"""
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(csign=False))
|
|
|
|
def test_dpp_config_no_signed_connector(dev, apdev):
|
|
"""DPP Config Object error - no signedConnector"""
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(no_signed_connector=True))
|
|
|
|
def test_dpp_config_unexpected_signed_connector_char(dev, apdev):
|
|
"""DPP Config Object error - unexpected signedConnector character"""
|
|
run_dpp_config_error(dev, apdev, build_conf_obj(signed_connector='a\nb'))
|
|
|
|
def test_dpp_config_root_not_an_object(dev, apdev):
|
|
"""DPP Config Object error - root not an object"""
|
|
conf = "1"
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_no_wi_fi_tech(dev, apdev):
|
|
"""DPP Config Object error - no wi-fi_tech"""
|
|
conf = "{}"
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_unsupported_wi_fi_tech(dev, apdev):
|
|
"""DPP Config Object error - unsupported wi-fi_tech"""
|
|
conf = '{"wi-fi_tech":"unsupported"}'
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_no_discovery(dev, apdev):
|
|
"""DPP Config Object error - no discovery"""
|
|
conf = '{"wi-fi_tech":"infra"}'
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_no_discovery_ssid(dev, apdev):
|
|
"""DPP Config Object error - no discovery::ssid"""
|
|
conf = '{"wi-fi_tech":"infra","discovery":{}}'
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_too_long_discovery_ssid(dev, apdev):
|
|
"""DPP Config Object error - too long discovery::ssid"""
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"%s"}}' % (33*'A')
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_no_cred(dev, apdev):
|
|
"""DPP Config Object error - no cred"""
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"}}'
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_no_cred_akm(dev, apdev):
|
|
"""DPP Config Object error - no cred::akm"""
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{}}'
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_unsupported_cred_akm(dev, apdev):
|
|
"""DPP Config Object error - unsupported cred::akm"""
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{"akm":"unsupported"}}'
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_error_legacy_no_pass(dev, apdev):
|
|
"""DPP Config Object legacy error - no pass/psk"""
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{"akm":"psk"}}'
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_error_legacy_too_short_pass(dev, apdev):
|
|
"""DPP Config Object legacy error - too short pass/psk"""
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"1"}}'
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_error_legacy_too_long_pass(dev, apdev):
|
|
"""DPP Config Object legacy error - too long pass/psk"""
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"%s"}}' % (64*'A')
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_error_legacy_psk_with_sae(dev, apdev):
|
|
"""DPP Config Object legacy error - psk_hex with SAE"""
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{"akm":"sae","psk_hex":"%s"}}' % (32*"12")
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_error_legacy_no_pass_for_sae(dev, apdev):
|
|
"""DPP Config Object legacy error - no pass for SAE"""
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{"akm":"psk+sae","psk_hex":"%s"}}' % (32*"12")
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_error_legacy_invalid_psk(dev, apdev):
|
|
"""DPP Config Object legacy error - invalid psk_hex"""
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{"akm":"psk","psk_hex":"%s"}}' % (32*"qa")
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def test_dpp_config_error_legacy_too_short_psk(dev, apdev):
|
|
"""DPP Config Object legacy error - too short psk_hex"""
|
|
conf = '{"wi-fi_tech":"infra","discovery":{"ssid":"test"},"cred":{"akm":"psk","psk_hex":"%s"}}' % (31*"12")
|
|
run_dpp_config_error(dev, apdev, conf)
|
|
|
|
def get_der_int_32(val):
|
|
a, b = struct.unpack('BB', val[0:2])
|
|
if a != 0x02:
|
|
raise Exception("Invalid DER encoding of INTEGER")
|
|
if b > len(val) - 2:
|
|
raise Exception("Invalid length of INTEGER (truncated)")
|
|
val = val[2:]
|
|
if b == 32:
|
|
r = val[0:32]
|
|
elif b == 33:
|
|
if val[0] != 0:
|
|
raise Exception("Too large INTEGER (32)")
|
|
r = val[1:33]
|
|
elif b < 32:
|
|
r = (32 - b) * b'\x00' + val[0:b]
|
|
else:
|
|
raise Exception("Invalid length of INTEGER (32): %d" % b)
|
|
return r, val[b:]
|
|
|
|
def ecdsa_sign(pkey, message, alg="sha256"):
|
|
sign = OpenSSL.crypto.sign(pkey, message, alg)
|
|
logger.debug("sign=" + binascii.hexlify(sign).decode())
|
|
a, b = struct.unpack('BB', sign[0:2])
|
|
if a != 0x30:
|
|
raise Exception("Invalid DER encoding of ECDSA signature")
|
|
if b != len(sign) - 2:
|
|
raise Exception("Invalid length of ECDSA signature")
|
|
sign = sign[2:]
|
|
|
|
r, sign = get_der_int_32(sign)
|
|
s, sign = get_der_int_32(sign)
|
|
if len(sign) != 0:
|
|
raise Exception("Extra data at the end of ECDSA signature")
|
|
|
|
logger.info("r=" + binascii.hexlify(r).decode())
|
|
logger.info("s=" + binascii.hexlify(s).decode())
|
|
raw_sign = r + s
|
|
return base64.urlsafe_b64encode(raw_sign).decode().rstrip('=')
|
|
|
|
p256_priv_key = """-----BEGIN EC PRIVATE KEY-----
|
|
MHcCAQEEIBVQij9ah629f1pu3tarDQGQvrzHgAkgYd1jHGiLxNajoAoGCCqGSM49
|
|
AwEHoUQDQgAEAC9d2/JirKu72F2qLuv5jEFMD1Cqu9EiyGk7cOzn/2DJ51p2mEoW
|
|
n03N6XRvTC+G7WPol9Ng97NAM2sK57+F/Q==
|
|
-----END EC PRIVATE KEY-----"""
|
|
p256_pub_key_x = binascii.unhexlify("002f5ddbf262acabbbd85daa2eebf98c414c0f50aabbd122c8693b70ece7ff60")
|
|
p256_pub_key_y = binascii.unhexlify("c9e75a76984a169f4dcde9746f4c2f86ed63e897d360f7b340336b0ae7bf85fd")
|
|
|
|
def run_dpp_config_connector(dev, apdev, expiry=None, payload=None,
|
|
skip_net_access_key_mismatch=True,
|
|
conf_failure=True):
|
|
if not openssl_imported:
|
|
raise HwsimSkip("OpenSSL python method not available")
|
|
pkey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM,
|
|
p256_priv_key)
|
|
x = base64.urlsafe_b64encode(p256_pub_key_x).decode().rstrip('=')
|
|
y = base64.urlsafe_b64encode(p256_pub_key_y).decode().rstrip('=')
|
|
|
|
pubkey = b'\x04' + p256_pub_key_x + p256_pub_key_y
|
|
kid = base64.urlsafe_b64encode(hashlib.sha256(pubkey).digest()).decode().rstrip('=')
|
|
|
|
prot_hdr = '{"typ":"dppCon","kid":"%s","alg":"ES256"}' % kid
|
|
|
|
if not payload:
|
|
payload = '{"groups":[{"groupId":"*","netRole":"sta"}],"netAccessKey":{"kty":"EC","crv":"P-256","x":"aTF4JEGIPKSZ0Xv9zdCMjm-tn5XpMsYIVZ9wySAz1gI","y":"QGcHWA_6rbU9XDXAztoX-M5Q3suTnMaqEhULtn7SSXw"}'
|
|
if expiry:
|
|
payload += ',"expiry":"%s"' % expiry
|
|
payload += '}'
|
|
conn = base64.urlsafe_b64encode(prot_hdr.encode()).decode().rstrip('=') + '.'
|
|
conn += base64.urlsafe_b64encode(payload.encode()).decode().rstrip('=')
|
|
sign = ecdsa_sign(pkey, conn)
|
|
conn += '.' + sign
|
|
run_dpp_config_error(dev, apdev,
|
|
build_conf_obj(x=x, y=y, signed_connector=conn),
|
|
skip_net_access_key_mismatch=skip_net_access_key_mismatch,
|
|
conf_failure=conf_failure)
|
|
|
|
def test_dpp_config_connector_error_ext_sign(dev, apdev):
|
|
"""DPP Config Object connector error - external signature calculation"""
|
|
run_dpp_config_connector(dev, apdev, conf_failure=False)
|
|
|
|
def test_dpp_config_connector_error_too_short_timestamp(dev, apdev):
|
|
"""DPP Config Object connector error - too short timestamp"""
|
|
run_dpp_config_connector(dev, apdev, expiry="1")
|
|
|
|
def test_dpp_config_connector_error_invalid_timestamp(dev, apdev):
|
|
"""DPP Config Object connector error - invalid timestamp"""
|
|
run_dpp_config_connector(dev, apdev, expiry=19*"1")
|
|
|
|
def test_dpp_config_connector_error_invalid_timestamp_date(dev, apdev):
|
|
"""DPP Config Object connector error - invalid timestamp date"""
|
|
run_dpp_config_connector(dev, apdev, expiry="9999-99-99T99:99:99Z")
|
|
|
|
def test_dpp_config_connector_error_invalid_time_zone(dev, apdev):
|
|
"""DPP Config Object connector error - invalid time zone"""
|
|
run_dpp_config_connector(dev, apdev, expiry="2018-01-01T00:00:00*")
|
|
|
|
def test_dpp_config_connector_error_invalid_time_zone_2(dev, apdev):
|
|
"""DPP Config Object connector error - invalid time zone 2"""
|
|
run_dpp_config_connector(dev, apdev, expiry="2018-01-01T00:00:00+")
|
|
|
|
def test_dpp_config_connector_error_expired_1(dev, apdev):
|
|
"""DPP Config Object connector error - expired 1"""
|
|
run_dpp_config_connector(dev, apdev, expiry="2018-01-01T00:00:00")
|
|
|
|
def test_dpp_config_connector_error_expired_2(dev, apdev):
|
|
"""DPP Config Object connector error - expired 2"""
|
|
run_dpp_config_connector(dev, apdev, expiry="2018-01-01T00:00:00Z")
|
|
|
|
def test_dpp_config_connector_error_expired_3(dev, apdev):
|
|
"""DPP Config Object connector error - expired 3"""
|
|
run_dpp_config_connector(dev, apdev, expiry="2018-01-01T00:00:00+01")
|
|
|
|
def test_dpp_config_connector_error_expired_4(dev, apdev):
|
|
"""DPP Config Object connector error - expired 4"""
|
|
run_dpp_config_connector(dev, apdev, expiry="2018-01-01T00:00:00+01:02")
|
|
|
|
def test_dpp_config_connector_error_expired_5(dev, apdev):
|
|
"""DPP Config Object connector error - expired 5"""
|
|
run_dpp_config_connector(dev, apdev, expiry="2018-01-01T00:00:00-01")
|
|
|
|
def test_dpp_config_connector_error_expired_6(dev, apdev):
|
|
"""DPP Config Object connector error - expired 6"""
|
|
run_dpp_config_connector(dev, apdev, expiry="2018-01-01T00:00:00-01:02")
|
|
|
|
def test_dpp_config_connector_error_no_groups(dev, apdev):
|
|
"""DPP Config Object connector error - no groups"""
|
|
payload = '{"netAccessKey":{"kty":"EC","crv":"P-256","x":"aTF4JEGIPKSZ0Xv9zdCMjm-tn5XpMsYIVZ9wySAz1gI","y":"QGcHWA_6rbU9XDXAztoX-M5Q3suTnMaqEhULtn7SSXw"}}'
|
|
run_dpp_config_connector(dev, apdev, payload=payload)
|
|
|
|
def test_dpp_config_connector_error_empty_groups(dev, apdev):
|
|
"""DPP Config Object connector error - empty groups"""
|
|
payload = '{"groups":[],"netAccessKey":{"kty":"EC","crv":"P-256","x":"aTF4JEGIPKSZ0Xv9zdCMjm-tn5XpMsYIVZ9wySAz1gI","y":"QGcHWA_6rbU9XDXAztoX-M5Q3suTnMaqEhULtn7SSXw"}}'
|
|
run_dpp_config_connector(dev, apdev, payload=payload)
|
|
|
|
def test_dpp_config_connector_error_missing_group_id(dev, apdev):
|
|
"""DPP Config Object connector error - missing groupId"""
|
|
payload = '{"groups":[{"netRole":"sta"}],"netAccessKey":{"kty":"EC","crv":"P-256","x":"aTF4JEGIPKSZ0Xv9zdCMjm-tn5XpMsYIVZ9wySAz1gI","y":"QGcHWA_6rbU9XDXAztoX-M5Q3suTnMaqEhULtn7SSXw"}}'
|
|
run_dpp_config_connector(dev, apdev, payload=payload)
|
|
|
|
def test_dpp_config_connector_error_missing_net_role(dev, apdev):
|
|
"""DPP Config Object connector error - missing netRole"""
|
|
payload = '{"groups":[{"groupId":"*"}],"netAccessKey":{"kty":"EC","crv":"P-256","x":"aTF4JEGIPKSZ0Xv9zdCMjm-tn5XpMsYIVZ9wySAz1gI","y":"QGcHWA_6rbU9XDXAztoX-M5Q3suTnMaqEhULtn7SSXw"}}'
|
|
run_dpp_config_connector(dev, apdev, payload=payload)
|
|
|
|
def test_dpp_config_connector_error_missing_net_access_key(dev, apdev):
|
|
"""DPP Config Object connector error - missing netAccessKey"""
|
|
payload = '{"groups":[{"groupId":"*","netRole":"sta"}]}'
|
|
run_dpp_config_connector(dev, apdev, payload=payload)
|
|
|
|
def test_dpp_config_connector_error_net_access_key_mismatch(dev, apdev):
|
|
"""DPP Config Object connector error - netAccessKey mismatch"""
|
|
payload = '{"groups":[{"groupId":"*","netRole":"sta"}],"netAccessKey":{"kty":"EC","crv":"P-256","x":"aTF4JEGIPKSZ0Xv9zdCMjm-tn5XpMsYIVZ9wySAz1gI","y":"QGcHWA_6rbU9XDXAztoX-M5Q3suTnMaqEhULtn7SSXw"}}'
|
|
run_dpp_config_connector(dev, apdev, payload=payload,
|
|
skip_net_access_key_mismatch=False)
|
|
|
|
def test_dpp_gas_timeout(dev, apdev):
|
|
"""DPP and GAS server timeout for a query"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].set("ext_mgmt_frame_handling", "1")
|
|
dev[0].dpp_listen(2412)
|
|
|
|
# Force GAS fragmentation
|
|
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
|
|
dev[1].set("dpp_config_obj_override", conf)
|
|
|
|
dev[1].dpp_auth_init(uri=uri0)
|
|
|
|
# DPP Authentication Request
|
|
msg = dev[0].mgmt_rx()
|
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(
|
|
msg['freq'], msg['datarate'], msg['ssi_signal'], binascii.hexlify(msg['frame']).decode())):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
|
|
# DPP Authentication Confirmation
|
|
msg = dev[0].mgmt_rx()
|
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(
|
|
msg['freq'], msg['datarate'], msg['ssi_signal'], binascii.hexlify(msg['frame']).decode())):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
|
|
wait_auth_success(dev[0], dev[1])
|
|
|
|
# DPP Configuration Response (GAS Initial Response frame)
|
|
msg = dev[0].mgmt_rx()
|
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(
|
|
msg['freq'], msg['datarate'], msg['ssi_signal'], binascii.hexlify(msg['frame']).decode())):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
|
|
# GAS Comeback Response frame
|
|
msg = dev[0].mgmt_rx()
|
|
# Do not continue to force timeout on GAS server
|
|
|
|
ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("GAS result not reported (Enrollee)")
|
|
if "result=TIMEOUT" not in ev:
|
|
raise Exception("Unexpected GAS result (Enrollee): " + ev)
|
|
dev[0].set("ext_mgmt_frame_handling", "0")
|
|
|
|
ev = dev[1].wait_event(["DPP-CONF-FAILED"], timeout=15)
|
|
if ev is None:
|
|
raise Exception("DPP configuration failure not reported (Configurator)")
|
|
|
|
ev = dev[0].wait_event(["DPP-CONF-FAILED"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("DPP configuration failure not reported (Enrollee)")
|
|
|
|
def test_dpp_akm_sha256(dev, apdev):
|
|
"""DPP AKM (SHA256)"""
|
|
run_dpp_akm(dev, apdev, 32)
|
|
|
|
def test_dpp_akm_sha384(dev, apdev):
|
|
"""DPP AKM (SHA384)"""
|
|
run_dpp_akm(dev, apdev, 48)
|
|
|
|
def test_dpp_akm_sha512(dev, apdev):
|
|
"""DPP AKM (SHA512)"""
|
|
run_dpp_akm(dev, apdev, 64)
|
|
|
|
def run_dpp_akm(dev, apdev, pmk_len):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
params = {"ssid": "dpp",
|
|
"wpa": "2",
|
|
"wpa_key_mgmt": "DPP",
|
|
"rsn_pairwise": "CCMP",
|
|
"ieee80211w": "2"}
|
|
try:
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
except:
|
|
raise HwsimSkip("DPP not supported")
|
|
|
|
id = dev[0].connect("dpp", key_mgmt="DPP", ieee80211w="2", scan_freq="2412",
|
|
dpp_pfs="2", wait_connect=False)
|
|
ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=2)
|
|
if not ev:
|
|
raise Exception("Network mismatch not reported")
|
|
dev[0].request("DISCONNECT")
|
|
dev[0].dump_monitor()
|
|
|
|
bssid = hapd.own_addr()
|
|
pmkid = 16*'11'
|
|
akmp = 2**23
|
|
pmk = pmk_len*'22'
|
|
cmd = "PMKSA_ADD %d %s %s %s 30240 43200 %d 0" % (id, bssid, pmkid, pmk, akmp)
|
|
if "OK" not in dev[0].request(cmd):
|
|
raise Exception("PMKSA_ADD failed (wpa_supplicant)")
|
|
dev[0].select_network(id, freq="2412")
|
|
ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=2)
|
|
dev[0].request("DISCONNECT")
|
|
dev[0].dump_monitor()
|
|
if not ev:
|
|
raise Exception("Association attempt was not rejected")
|
|
if "status_code=53" not in ev:
|
|
raise Exception("Unexpected status code: " + ev)
|
|
|
|
addr = dev[0].own_addr()
|
|
cmd = "PMKSA_ADD %s %s %s 0 %d" % (addr, pmkid, pmk, akmp)
|
|
if "OK" not in hapd.request(cmd):
|
|
raise Exception("PMKSA_ADD failed (hostapd)")
|
|
|
|
dev[0].select_network(id, freq="2412")
|
|
dev[0].wait_connected()
|
|
val = dev[0].get_status_field("key_mgmt")
|
|
if val != "DPP":
|
|
raise Exception("Unexpected key_mgmt: " + val)
|
|
|
|
params1_csign = "3059301306072a8648ce3d020106082a8648ce3d03010703420004d02e5bd81a120762b5f0f2994777f5d40297238a6c294fd575cdf35fabec44c050a6421c401d98d659fd2ed13c961cc8287944dd3202f516977800d3ab2f39ee"
|
|
params1_ap_connector = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJzOEFrYjg5bTV4UGhoYk5UbTVmVVo0eVBzNU5VMkdxYXNRY3hXUWhtQVFRIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6ImFwIn1dLCJuZXRBY2Nlc3NLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiIwOHF4TlNYRzRWemdCV3BjVUdNSmc1czNvbElOVFJsRVQ1aERpNkRKY3ZjIiwieSI6IlVhaGFYQXpKRVpRQk1YaHRUQnlZZVlrOWtJYjk5UDA3UV9NcW9TVVZTVEkifX0.a5_nfMVr7Qe1SW0ZL3u6oQRm5NUCYUSfixDAJOUFN3XUfECBZ6E8fm8xjeSfdOytgRidTz0CTlIRjzPQo82dmQ"
|
|
params1_ap_netaccesskey = "30770201010420f6531d17f29dfab655b7c9e923478d5a345164c489aadd44a3519c3e9dcc792da00a06082a8648ce3d030107a14403420004d3cab13525c6e15ce0056a5c506309839b37a2520d4d19444f98438ba0c972f751a85a5c0cc911940131786d4c1c9879893d9086fdf4fd3b43f32aa125154932"
|
|
params1_sta_connector = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJzOEFrYjg5bTV4UGhoYk5UbTVmVVo0eVBzNU5VMkdxYXNRY3hXUWhtQVFRIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6InN0YSJ9XSwibmV0QWNjZXNzS2V5Ijp7Imt0eSI6IkVDIiwiY3J2IjoiUC0yNTYiLCJ4IjoiZWMzR3NqQ3lQMzVBUUZOQUJJdEltQnN4WXVyMGJZX1dES1lfSE9zUGdjNCIsInkiOiJTRS1HVllkdWVnTFhLMU1TQXZNMEx2QWdLREpTNWoyQVhCbE9PMTdUSTRBIn19.PDK9zsGlK-e1pEOmNxVeJfCS8pNeay6ckIS1TXCQsR64AR-9wFPCNVjqOxWvVKltehyMFqVAtOcv0IrjtMJFqQ"
|
|
params1_sta_netaccesskey = "30770201010420bc33380c26fd2168b69cd8242ed1df07ba89aa4813f8d4e8523de6ca3f8dd28ba00a06082a8648ce3d030107a1440342000479cdc6b230b23f7e40405340048b48981b3162eaf46d8fd60ca63f1ceb0f81ce484f8655876e7a02d72b531202f3342ef020283252e63d805c194e3b5ed32380"
|
|
|
|
def test_dpp_network_introduction(dev, apdev):
|
|
"""DPP network introduction"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
params = {"ssid": "dpp",
|
|
"wpa": "2",
|
|
"wpa_key_mgmt": "DPP",
|
|
"ieee80211w": "2",
|
|
"rsn_pairwise": "CCMP",
|
|
"dpp_connector": params1_ap_connector,
|
|
"dpp_csign": params1_csign,
|
|
"dpp_netaccesskey": params1_ap_netaccesskey}
|
|
try:
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
except:
|
|
raise HwsimSkip("DPP not supported")
|
|
|
|
id = dev[0].connect("dpp", key_mgmt="DPP", scan_freq="2412",
|
|
ieee80211w="2",
|
|
dpp_csign=params1_csign,
|
|
dpp_connector=params1_sta_connector,
|
|
dpp_netaccesskey=params1_sta_netaccesskey)
|
|
val = dev[0].get_status_field("key_mgmt")
|
|
if val != "DPP":
|
|
raise Exception("Unexpected key_mgmt: " + val)
|
|
|
|
def test_dpp_network_introduction_expired(dev, apdev):
|
|
"""DPP network introduction with expired netaccesskey"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
params = {"ssid": "dpp",
|
|
"wpa": "2",
|
|
"wpa_key_mgmt": "DPP",
|
|
"ieee80211w": "2",
|
|
"rsn_pairwise": "CCMP",
|
|
"dpp_connector": params1_ap_connector,
|
|
"dpp_csign": params1_csign,
|
|
"dpp_netaccesskey": params1_ap_netaccesskey,
|
|
"dpp_netaccesskey_expiry": "1565530889"}
|
|
try:
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
except:
|
|
raise HwsimSkip("DPP not supported")
|
|
|
|
dev[0].connect("dpp", key_mgmt="DPP", scan_freq="2412",
|
|
ieee80211w="2",
|
|
dpp_csign=params1_csign,
|
|
dpp_connector=params1_sta_connector,
|
|
dpp_netaccesskey=params1_sta_netaccesskey,
|
|
wait_connect=False)
|
|
ev = hapd.wait_event(["DPP-RX"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("No DPP Peer Discovery Request seen")
|
|
if "type=5" not in ev:
|
|
raise Exception("Unexpected DPP message received: " + ev)
|
|
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
|
|
dev[0].request("DISCONNECT")
|
|
if ev:
|
|
raise Exception("Connection reported")
|
|
|
|
hapd.disable()
|
|
hapd.set("dpp_netaccesskey_expiry", "2565530889")
|
|
hapd.enable()
|
|
dev[0].request("RECONNECT")
|
|
dev[0].wait_connected()
|
|
|
|
def test_dpp_and_sae_akm(dev, apdev):
|
|
"""DPP and SAE AKMs"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
if "SAE" not in dev[1].get_capability("auth_alg"):
|
|
raise HwsimSkip("SAE not supported")
|
|
|
|
params = {"ssid": "dpp+sae",
|
|
"wpa": "2",
|
|
"wpa_key_mgmt": "DPP SAE",
|
|
"ieee80211w": "2",
|
|
"rsn_pairwise": "CCMP",
|
|
"sae_password": "sae-password",
|
|
"dpp_connector": params1_ap_connector,
|
|
"dpp_csign": params1_csign,
|
|
"dpp_netaccesskey": params1_ap_netaccesskey}
|
|
try:
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
except:
|
|
raise HwsimSkip("DPP not supported")
|
|
|
|
id = dev[0].connect("dpp+sae", key_mgmt="DPP", scan_freq="2412",
|
|
ieee80211w="2",
|
|
dpp_csign=params1_csign,
|
|
dpp_connector=params1_sta_connector,
|
|
dpp_netaccesskey=params1_sta_netaccesskey)
|
|
val = dev[0].get_status_field("key_mgmt")
|
|
if val != "DPP":
|
|
raise Exception("Unexpected key_mgmt for DPP: " + val)
|
|
|
|
dev[1].request("SET sae_groups ")
|
|
id = dev[1].connect("dpp+sae", key_mgmt="SAE", scan_freq="2412",
|
|
ieee80211w="2", psk="sae-password")
|
|
val = dev[1].get_status_field("key_mgmt")
|
|
if val != "SAE":
|
|
raise Exception("Unexpected key_mgmt for SAE: " + val)
|
|
|
|
def test_dpp_ap_config(dev, apdev):
|
|
"""DPP and AP configuration"""
|
|
run_dpp_ap_config(dev, apdev)
|
|
|
|
def test_dpp_ap_config_p256_p256(dev, apdev):
|
|
"""DPP and AP configuration (P-256 + P-256)"""
|
|
run_dpp_ap_config(dev, apdev, curve="P-256", conf_curve="P-256")
|
|
|
|
def test_dpp_ap_config_p256_p384(dev, apdev):
|
|
"""DPP and AP configuration (P-256 + P-384)"""
|
|
run_dpp_ap_config(dev, apdev, curve="P-256", conf_curve="P-384")
|
|
|
|
def test_dpp_ap_config_p256_p521(dev, apdev):
|
|
"""DPP and AP configuration (P-256 + P-521)"""
|
|
run_dpp_ap_config(dev, apdev, curve="P-256", conf_curve="P-521")
|
|
|
|
def test_dpp_ap_config_p384_p256(dev, apdev):
|
|
"""DPP and AP configuration (P-384 + P-256)"""
|
|
run_dpp_ap_config(dev, apdev, curve="P-384", conf_curve="P-256")
|
|
|
|
def test_dpp_ap_config_p384_p384(dev, apdev):
|
|
"""DPP and AP configuration (P-384 + P-384)"""
|
|
run_dpp_ap_config(dev, apdev, curve="P-384", conf_curve="P-384")
|
|
|
|
def test_dpp_ap_config_p384_p521(dev, apdev):
|
|
"""DPP and AP configuration (P-384 + P-521)"""
|
|
run_dpp_ap_config(dev, apdev, curve="P-384", conf_curve="P-521")
|
|
|
|
def test_dpp_ap_config_p521_p256(dev, apdev):
|
|
"""DPP and AP configuration (P-521 + P-256)"""
|
|
run_dpp_ap_config(dev, apdev, curve="P-521", conf_curve="P-256")
|
|
|
|
def test_dpp_ap_config_p521_p384(dev, apdev):
|
|
"""DPP and AP configuration (P-521 + P-384)"""
|
|
run_dpp_ap_config(dev, apdev, curve="P-521", conf_curve="P-384")
|
|
|
|
def test_dpp_ap_config_p521_p521(dev, apdev):
|
|
"""DPP and AP configuration (P-521 + P-521)"""
|
|
run_dpp_ap_config(dev, apdev, curve="P-521", conf_curve="P-521")
|
|
|
|
def test_dpp_ap_config_bp256_bp256(dev, apdev):
|
|
"""DPP and AP configuration (BP-256 + BP-256)"""
|
|
run_dpp_ap_config(dev, apdev, curve="BP-256", conf_curve="BP-256")
|
|
|
|
def test_dpp_ap_config_bp384_bp384(dev, apdev):
|
|
"""DPP and AP configuration (BP-384 + BP-384)"""
|
|
run_dpp_ap_config(dev, apdev, curve="BP-384", conf_curve="BP-384")
|
|
|
|
def test_dpp_ap_config_bp512_bp512(dev, apdev):
|
|
"""DPP and AP configuration (BP-512 + BP-512)"""
|
|
run_dpp_ap_config(dev, apdev, curve="BP-512", conf_curve="BP-512")
|
|
|
|
def test_dpp_ap_config_p256_bp256(dev, apdev):
|
|
"""DPP and AP configuration (P-256 + BP-256)"""
|
|
run_dpp_ap_config(dev, apdev, curve="P-256", conf_curve="BP-256")
|
|
|
|
def test_dpp_ap_config_bp256_p256(dev, apdev):
|
|
"""DPP and AP configuration (BP-256 + P-256)"""
|
|
run_dpp_ap_config(dev, apdev, curve="BP-256", conf_curve="P-256")
|
|
|
|
def test_dpp_ap_config_p521_bp512(dev, apdev):
|
|
"""DPP and AP configuration (P-521 + BP-512)"""
|
|
run_dpp_ap_config(dev, apdev, curve="P-521", conf_curve="BP-512")
|
|
|
|
def test_dpp_ap_config_bp512_p521(dev, apdev):
|
|
"""DPP and AP configuration (BP-512 + P-521)"""
|
|
run_dpp_ap_config(dev, apdev, curve="BP-512", conf_curve="P-521")
|
|
|
|
def test_dpp_ap_config_reconfig_configurator(dev, apdev):
|
|
"""DPP and AP configuration with Configurator reconfiguration"""
|
|
run_dpp_ap_config(dev, apdev, reconf_configurator=True)
|
|
|
|
def update_hapd_config(hapd):
|
|
ev = hapd.wait_event(["DPP-CONFOBJ-SSID"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("SSID not reported (AP)")
|
|
ssid = ev.split(' ')[1]
|
|
|
|
ev = hapd.wait_event(["DPP-CONNECTOR"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("Connector not reported (AP)")
|
|
connector = ev.split(' ')[1]
|
|
|
|
ev = hapd.wait_event(["DPP-C-SIGN-KEY"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("C-sign-key not reported (AP)")
|
|
p = ev.split(' ')
|
|
csign = p[1]
|
|
|
|
ev = hapd.wait_event(["DPP-NET-ACCESS-KEY"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("netAccessKey not reported (AP)")
|
|
p = ev.split(' ')
|
|
net_access_key = p[1]
|
|
net_access_key_expiry = p[2] if len(p) > 2 else None
|
|
|
|
logger.info("Update AP configuration to use key_mgmt=DPP")
|
|
hapd.disable()
|
|
hapd.set("ssid", ssid)
|
|
hapd.set("utf8_ssid", "1")
|
|
hapd.set("wpa", "2")
|
|
hapd.set("wpa_key_mgmt", "DPP")
|
|
hapd.set("ieee80211w", "2")
|
|
hapd.set("rsn_pairwise", "CCMP")
|
|
hapd.set("dpp_connector", connector)
|
|
hapd.set("dpp_csign", csign)
|
|
hapd.set("dpp_netaccesskey", net_access_key)
|
|
if net_access_key_expiry:
|
|
hapd.set("dpp_netaccesskey_expiry", net_access_key_expiry)
|
|
hapd.enable()
|
|
|
|
def run_dpp_ap_config(dev, apdev, curve=None, conf_curve=None,
|
|
reconf_configurator=False):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"})
|
|
check_dpp_capab(hapd)
|
|
|
|
id_h = hapd.dpp_bootstrap_gen(chan="81/1", mac=True, curve=curve)
|
|
uri = hapd.request("DPP_BOOTSTRAP_GET_URI %d" % id_h)
|
|
|
|
conf_id = dev[0].dpp_configurator_add(curve=conf_curve)
|
|
|
|
if reconf_configurator:
|
|
csign = dev[0].request("DPP_CONFIGURATOR_GET_KEY %d" % conf_id)
|
|
if "FAIL" in csign or len(csign) == 0:
|
|
raise Exception("DPP_CONFIGURATOR_GET_KEY failed")
|
|
|
|
dev[0].dpp_auth_init(uri=uri, conf="ap-dpp", configurator=conf_id)
|
|
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd)
|
|
update_hapd_config(hapd)
|
|
|
|
id1 = dev[1].dpp_bootstrap_gen(chan="81/1", mac=True, curve=curve)
|
|
uri1 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1)
|
|
|
|
if reconf_configurator:
|
|
dev[0].dpp_configurator_remove(conf_id)
|
|
conf_id = dev[0].dpp_configurator_add(curve=conf_curve, key=csign)
|
|
|
|
dev[1].dpp_listen(2412)
|
|
dev[0].dpp_auth_init(uri=uri1, conf="sta-dpp", configurator=conf_id)
|
|
wait_auth_success(dev[1], dev[0], configurator=dev[0], enrollee=dev[1],
|
|
stop_responder=True)
|
|
|
|
ev = dev[1].wait_event(["DPP-CONFOBJ-SSID"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("SSID not reported")
|
|
ssid = ev.split(' ')[1]
|
|
|
|
ev = dev[1].wait_event(["DPP-CONNECTOR"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("Connector not reported")
|
|
connector = ev.split(' ')[1]
|
|
|
|
ev = dev[1].wait_event(["DPP-C-SIGN-KEY"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("C-sign-key not reported")
|
|
p = ev.split(' ')
|
|
csign = p[1]
|
|
|
|
ev = dev[1].wait_event(["DPP-NET-ACCESS-KEY"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("netAccessKey not reported")
|
|
p = ev.split(' ')
|
|
net_access_key = p[1]
|
|
net_access_key_expiry = p[2] if len(p) > 2 else None
|
|
|
|
dev[1].dump_monitor()
|
|
|
|
id = dev[1].connect(ssid, key_mgmt="DPP", ieee80211w="2", scan_freq="2412",
|
|
only_add_network=True)
|
|
dev[1].set_network_quoted(id, "dpp_connector", connector)
|
|
dev[1].set_network(id, "dpp_csign", csign)
|
|
dev[1].set_network(id, "dpp_netaccesskey", net_access_key)
|
|
if net_access_key_expiry:
|
|
dev[1].set_network(id, "dpp_netaccess_expiry", net_access_key_expiry)
|
|
|
|
logger.info("Check data connection")
|
|
dev[1].select_network(id, freq="2412")
|
|
dev[1].wait_connected()
|
|
|
|
def test_dpp_auto_connect_1(dev, apdev):
|
|
"""DPP and auto connect (1)"""
|
|
try:
|
|
run_dpp_auto_connect(dev, apdev, 1)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_auto_connect_2(dev, apdev):
|
|
"""DPP and auto connect (2)"""
|
|
try:
|
|
run_dpp_auto_connect(dev, apdev, 2)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_auto_connect_2_connect_cmd(dev, apdev):
|
|
"""DPP and auto connect (2) using connect_cmd"""
|
|
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
|
|
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
|
|
dev_new = [wpas, dev[1]]
|
|
try:
|
|
run_dpp_auto_connect(dev_new, apdev, 2)
|
|
finally:
|
|
wpas.set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def run_dpp_auto_connect(dev, apdev, processing):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
csign = "30770201010420768240a3fc89d6662d9782f120527fe7fb9edc6366ab0b9c7dde96125cfd250fa00a06082a8648ce3d030107a144034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708"
|
|
csign_pub = "3059301306072a8648ce3d020106082a8648ce3d030107034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708"
|
|
ap_connector = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJwYWtZbXVzd1dCdWpSYTl5OEsweDViaTVrT3VNT3dzZHRlaml2UG55ZHZzIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6ImFwIn1dLCJuZXRBY2Nlc3NLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiIybU5vNXZuRkI5bEw3d1VWb1hJbGVPYzBNSEE1QXZKbnpwZXZULVVTYzVNIiwieSI6IlhzS3dqVHJlLTg5WWdpU3pKaG9CN1haeUttTU05OTl3V2ZaSVl0bi01Q3MifX0.XhjFpZgcSa7G2lHy0OCYTvaZFRo5Hyx6b7g7oYyusLC7C_73AJ4_BxEZQVYJXAtDuGvb3dXSkHEKxREP9Q6Qeg"
|
|
ap_netaccesskey = "30770201010420ceba752db2ad5200fa7bc565b9c05c69b7eb006751b0b329b0279de1c19ca67ca00a06082a8648ce3d030107a14403420004da6368e6f9c507d94bef0515a1722578e73430703902f267ce97af4fe51273935ec2b08d3adefbcf588224b3261a01ed76722a630cf7df7059f64862d9fee42b"
|
|
|
|
params = {"ssid": "test",
|
|
"wpa": "2",
|
|
"wpa_key_mgmt": "DPP",
|
|
"ieee80211w": "2",
|
|
"rsn_pairwise": "CCMP",
|
|
"dpp_connector": ap_connector,
|
|
"dpp_csign": csign_pub,
|
|
"dpp_netaccesskey": ap_netaccesskey}
|
|
try:
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
except:
|
|
raise HwsimSkip("DPP not supported")
|
|
|
|
conf_id = dev[1].dpp_configurator_add(key=csign)
|
|
dev[0].set("dpp_config_processing", str(processing))
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0, conf="sta-dpp", configurator=conf_id)
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0])
|
|
ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("DPP network profile not generated")
|
|
id = ev.split(' ')[1]
|
|
|
|
if processing == 1:
|
|
dev[0].select_network(id, freq=2412)
|
|
|
|
dev[0].wait_connected()
|
|
hwsim_utils.test_connectivity(dev[0], hapd)
|
|
|
|
def test_dpp_auto_connect_legacy(dev, apdev):
|
|
"""DPP and auto connect (legacy)"""
|
|
try:
|
|
run_dpp_auto_connect_legacy(dev, apdev)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_auto_connect_legacy_ssid_charset(dev, apdev):
|
|
"""DPP and auto connect (legacy, ssid_charset)"""
|
|
try:
|
|
run_dpp_auto_connect_legacy(dev, apdev, ssid_charset=12345)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_auto_connect_legacy_sae_1(dev, apdev):
|
|
"""DPP and auto connect (legacy SAE)"""
|
|
try:
|
|
run_dpp_auto_connect_legacy(dev, apdev, conf='sta-sae', psk_sae=True)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_auto_connect_legacy_sae_2(dev, apdev):
|
|
"""DPP and auto connect (legacy SAE)"""
|
|
try:
|
|
run_dpp_auto_connect_legacy(dev, apdev, conf='sta-sae', sae_only=True)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_auto_connect_legacy_psk_sae_1(dev, apdev):
|
|
"""DPP and auto connect (legacy PSK+SAE)"""
|
|
try:
|
|
run_dpp_auto_connect_legacy(dev, apdev, conf='sta-psk-sae',
|
|
psk_sae=True)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_auto_connect_legacy_psk_sae_2(dev, apdev):
|
|
"""DPP and auto connect (legacy PSK+SAE)"""
|
|
try:
|
|
run_dpp_auto_connect_legacy(dev, apdev, conf='sta-psk-sae',
|
|
sae_only=True)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_auto_connect_legacy_psk_sae_3(dev, apdev):
|
|
"""DPP and auto connect (legacy PSK+SAE)"""
|
|
try:
|
|
run_dpp_auto_connect_legacy(dev, apdev, conf='sta-psk-sae')
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def run_dpp_auto_connect_legacy(dev, apdev, conf='sta-psk',
|
|
ssid_charset=None,
|
|
psk_sae=False, sae_only=False):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
params = hostapd.wpa2_params(ssid="dpp-legacy",
|
|
passphrase="secret passphrase")
|
|
if sae_only:
|
|
params['wpa_key_mgmt'] = 'SAE'
|
|
params['ieee80211w'] = '2'
|
|
elif psk_sae:
|
|
params['wpa_key_mgmt'] = 'WPA-PSK SAE'
|
|
params['ieee80211w'] = '1'
|
|
params['sae_require_mfp'] = '1'
|
|
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
|
|
dev[0].request("SET sae_groups ")
|
|
dev[0].set("dpp_config_processing", "2")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0, conf=conf, ssid="dpp-legacy",
|
|
ssid_charset=ssid_charset,
|
|
passphrase="secret passphrase")
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0])
|
|
if ssid_charset:
|
|
ev = dev[0].wait_event(["DPP-CONFOBJ-SSID-CHARSET"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("ssid_charset not reported")
|
|
charset = ev.split(' ')[1]
|
|
if charset != str(ssid_charset):
|
|
raise Exception("Incorrect ssid_charset reported: " + ev)
|
|
ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("DPP network profile not generated")
|
|
id = ev.split(' ')[1]
|
|
|
|
dev[0].wait_connected()
|
|
|
|
def test_dpp_auto_connect_legacy_pmf_required(dev, apdev):
|
|
"""DPP and auto connect (legacy, PMF required)"""
|
|
try:
|
|
run_dpp_auto_connect_legacy_pmf_required(dev, apdev)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def run_dpp_auto_connect_legacy_pmf_required(dev, apdev):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
params = hostapd.wpa2_params(ssid="dpp-legacy",
|
|
passphrase="secret passphrase")
|
|
params['wpa_key_mgmt'] = "WPA-PSK-SHA256"
|
|
params['ieee80211w'] = "2"
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
|
|
dev[0].set("dpp_config_processing", "2")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0, conf="sta-psk", ssid="dpp-legacy",
|
|
passphrase="secret passphrase")
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0])
|
|
ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("DPP network profile not generated")
|
|
dev[0].wait_connected()
|
|
|
|
def test_dpp_qr_code_auth_responder_configurator(dev, apdev):
|
|
"""DPP QR Code and responder as the configurator"""
|
|
run_dpp_qr_code_auth_responder_configurator(dev, apdev, "")
|
|
|
|
def test_dpp_qr_code_auth_responder_configurator_group_id(dev, apdev):
|
|
"""DPP QR Code and responder as the configurator with group_id)"""
|
|
run_dpp_qr_code_auth_responder_configurator(dev, apdev,
|
|
" group_id=test-group")
|
|
|
|
def run_dpp_qr_code_auth_responder_configurator(dev, apdev, extra):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].set("dpp_configurator_params",
|
|
" conf=sta-dpp configurator=%d%s" % (conf_id, extra))
|
|
dev[0].dpp_listen(2412, role="configurator")
|
|
dev[1].dpp_auth_init(uri=uri0, role="enrollee")
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[0], enrollee=dev[1],
|
|
stop_responder=True)
|
|
|
|
def test_dpp_qr_code_auth_enrollee_init_netrole(dev, apdev):
|
|
"""DPP QR Code and enrollee initiating with netrole specified"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].set("dpp_configurator_params",
|
|
" conf=configurator configurator=%d" % conf_id)
|
|
dev[0].dpp_listen(2412, role="configurator")
|
|
dev[1].dpp_auth_init(uri=uri0, role="enrollee", netrole="configurator")
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[0], enrollee=dev[1],
|
|
stop_responder=True)
|
|
dev[0].dump_monitor()
|
|
dev[1].dump_monitor()
|
|
|
|
# verify that netrole resets back to sta, if not explicitly stated
|
|
dev[0].set("dpp_configurator_params",
|
|
"conf=sta-dpp configurator=%d" % conf_id)
|
|
dev[0].dpp_listen(2412, role="configurator")
|
|
dev[1].dpp_auth_init(uri=uri0, role="enrollee")
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[0], enrollee=dev[1],
|
|
stop_responder=True)
|
|
|
|
def test_dpp_qr_code_hostapd_init(dev, apdev):
|
|
"""DPP QR Code and hostapd as initiator"""
|
|
check_dpp_capab(dev[0])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
|
"channel": "6"})
|
|
check_dpp_capab(hapd)
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/6", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].set("dpp_configurator_params",
|
|
" conf=ap-dpp configurator=%d" % conf_id)
|
|
dev[0].dpp_listen(2437, role="configurator")
|
|
hapd.dpp_auth_init(uri=uri0, role="enrollee")
|
|
wait_auth_success(dev[0], hapd, configurator=dev[0], enrollee=hapd,
|
|
stop_responder=True)
|
|
|
|
def test_dpp_qr_code_hostapd_init_offchannel(dev, apdev):
|
|
"""DPP QR Code and hostapd as initiator (offchannel)"""
|
|
run_dpp_qr_code_hostapd_init_offchannel(dev, apdev, None)
|
|
|
|
def test_dpp_qr_code_hostapd_init_offchannel_neg_freq(dev, apdev):
|
|
"""DPP QR Code and hostapd as initiator (offchannel, neg_freq)"""
|
|
run_dpp_qr_code_hostapd_init_offchannel(dev, apdev, "neg_freq=2437")
|
|
|
|
def run_dpp_qr_code_hostapd_init_offchannel(dev, apdev, extra):
|
|
check_dpp_capab(dev[0])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
|
"channel": "6"})
|
|
check_dpp_capab(hapd)
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1,81/11", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].set("dpp_configurator_params",
|
|
" conf=ap-dpp configurator=%d" % conf_id)
|
|
dev[0].dpp_listen(2462, role="configurator")
|
|
hapd.dpp_auth_init(uri=uri0, role="enrollee", extra=extra)
|
|
wait_auth_success(dev[0], hapd, configurator=dev[0], enrollee=hapd,
|
|
stop_responder=True)
|
|
|
|
def test_dpp_test_vector_p_256(dev, apdev):
|
|
"""DPP P-256 test vector (mutual auth)"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
# Responder bootstrapping key
|
|
priv = "54ce181a98525f217216f59b245f60e9df30ac7f6b26c939418cfc3c42d1afa0"
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/11", mac=True, key="30310201010420" + priv + "a00a06082a8648ce3d030107")
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
# Responder protocol keypair override
|
|
priv = "f798ed2e19286f6a6efe210b1863badb99af2a14b497634dbfd2a97394fb5aa5"
|
|
dev[0].set("dpp_protocol_key_override",
|
|
"30310201010420" + priv + "a00a06082a8648ce3d030107")
|
|
|
|
dev[0].set("dpp_nonce_override", "3d0cfb011ca916d796f7029ff0b43393")
|
|
|
|
# Initiator bootstrapping key
|
|
priv = "15b2a83c5a0a38b61f2aa8200ee4994b8afdc01c58507d10d0a38f7eedf051bb"
|
|
id1 = dev[1].dpp_bootstrap_gen(key="30310201010420" + priv + "a00a06082a8648ce3d030107")
|
|
uri1 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1)
|
|
|
|
# Initiator protocol keypair override
|
|
priv = "a87de9afbb406c96e5f79a3df895ecac3ad406f95da66314c8cb3165e0c61783"
|
|
dev[1].set("dpp_protocol_key_override",
|
|
"30310201010420" + priv + "a00a06082a8648ce3d030107")
|
|
|
|
dev[1].set("dpp_nonce_override", "13f4602a16daeb69712263b9c46cba31")
|
|
|
|
dev[0].dpp_qr_code(uri1)
|
|
dev[0].dpp_listen(2462, qr="mutual")
|
|
dev[1].dpp_auth_init(uri=uri0, own=id1, neg_freq=2412)
|
|
wait_auth_success(dev[0], dev[1])
|
|
|
|
def test_dpp_test_vector_p_256_b(dev, apdev):
|
|
"""DPP P-256 test vector (Responder-only auth)"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
# Responder bootstrapping key
|
|
priv = "54ce181a98525f217216f59b245f60e9df30ac7f6b26c939418cfc3c42d1afa0"
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/11", mac=True, key="30310201010420" + priv + "a00a06082a8648ce3d030107")
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
# Responder protocol keypair override
|
|
priv = "f798ed2e19286f6a6efe210b1863badb99af2a14b497634dbfd2a97394fb5aa5"
|
|
dev[0].set("dpp_protocol_key_override",
|
|
"30310201010420" + priv + "a00a06082a8648ce3d030107")
|
|
|
|
dev[0].set("dpp_nonce_override", "3d0cfb011ca916d796f7029ff0b43393")
|
|
|
|
# Initiator bootstrapping key
|
|
priv = "15b2a83c5a0a38b61f2aa8200ee4994b8afdc01c58507d10d0a38f7eedf051bb"
|
|
id1 = dev[1].dpp_bootstrap_gen(key="30310201010420" + priv + "a00a06082a8648ce3d030107")
|
|
uri1 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1)
|
|
|
|
# Initiator protocol keypair override
|
|
priv = "a87de9afbb406c96e5f79a3df895ecac3ad406f95da66314c8cb3165e0c61783"
|
|
dev[1].set("dpp_protocol_key_override",
|
|
"30310201010420" + priv + "a00a06082a8648ce3d030107")
|
|
|
|
dev[1].set("dpp_nonce_override", "13f4602a16daeb69712263b9c46cba31")
|
|
|
|
dev[0].dpp_listen(2462)
|
|
dev[1].dpp_auth_init(uri=uri0, own=id1, neg_freq=2412)
|
|
wait_auth_success(dev[0], dev[1])
|
|
|
|
def der_priv_key_p_521(priv):
|
|
if len(priv) != 2 * 66:
|
|
raise Exception("Unexpected der_priv_key_p_521 parameter: " + priv)
|
|
der_prefix = "3081500201010442"
|
|
der_postfix = "a00706052b81040023"
|
|
return der_prefix + priv + der_postfix
|
|
|
|
def test_dpp_test_vector_p_521(dev, apdev):
|
|
"""DPP P-521 test vector (mutual auth)"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
# Responder bootstrapping key
|
|
priv = "0061e54f518cdf859735da3dd64c6f72c2f086f41a6fd52915152ea2fe0f24ddaecd8883730c9c9fd82cf7c043a41021696388cf5190b731dd83638bcd56d8b6c743"
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/11", mac=True,
|
|
key=der_priv_key_p_521(priv))
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
# Responder protocol keypair override
|
|
priv = "01d8b7b17cd1b0a33f7c66fb4220999329cdaf4f8b44b2ffadde8ab8ed8abffa9f5358c5b1caae26709ca4fb78e52a4d08f2e4f24111a36a6f440d20a0000ff51597"
|
|
dev[0].set("dpp_protocol_key_override", der_priv_key_p_521(priv))
|
|
|
|
dev[0].set("dpp_nonce_override",
|
|
"d749a782012eb0a8595af30b2dfc8d0880d004ebddb55ecc5afbdef18c400e01")
|
|
|
|
# Initiator bootstrapping key
|
|
priv = "0060c10df14af5ef27f6e362d31bdd9eeb44be77a323ba64b08f3f03d58b92cbfe05c182a91660caa081ca344243c47b5aa088bcdf738840eb35f0218b9f26881e02"
|
|
id1 = dev[1].dpp_bootstrap_gen(key=der_priv_key_p_521(priv))
|
|
uri1 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1)
|
|
|
|
# Initiator protocol keypair override
|
|
priv = "019c1c08caaeec38fb931894699b095bc3ab8c1ec7ef0622d2e3eba821477c8c6fca41774f21166ad98aebda37c067d9aa08a8a2e1b5c44c61f2bae02a61f85d9661"
|
|
dev[1].set("dpp_protocol_key_override", der_priv_key_p_521(priv))
|
|
|
|
dev[1].set("dpp_nonce_override",
|
|
"de972af3847bec3ba2aedd9f5c21cfdec7bf0bc5fe8b276cbcd0267807fb15b0")
|
|
|
|
dev[0].dpp_qr_code(uri1)
|
|
dev[0].dpp_listen(2462, qr="mutual")
|
|
dev[1].dpp_auth_init(uri=uri0, own=id1, neg_freq=2412)
|
|
wait_auth_success(dev[0], dev[1])
|
|
|
|
def test_dpp_pkex(dev, apdev):
|
|
"""DPP and PKEX"""
|
|
run_dpp_pkex(dev, apdev)
|
|
|
|
def test_dpp_pkex_p256(dev, apdev):
|
|
"""DPP and PKEX (P-256)"""
|
|
run_dpp_pkex(dev, apdev, "P-256")
|
|
|
|
def test_dpp_pkex_p384(dev, apdev):
|
|
"""DPP and PKEX (P-384)"""
|
|
run_dpp_pkex(dev, apdev, "P-384")
|
|
|
|
def test_dpp_pkex_p521(dev, apdev):
|
|
"""DPP and PKEX (P-521)"""
|
|
run_dpp_pkex(dev, apdev, "P-521")
|
|
|
|
def test_dpp_pkex_bp256(dev, apdev):
|
|
"""DPP and PKEX (BP-256)"""
|
|
run_dpp_pkex(dev, apdev, "brainpoolP256r1")
|
|
|
|
def test_dpp_pkex_bp384(dev, apdev):
|
|
"""DPP and PKEX (BP-384)"""
|
|
run_dpp_pkex(dev, apdev, "brainpoolP384r1")
|
|
|
|
def test_dpp_pkex_bp512(dev, apdev):
|
|
"""DPP and PKEX (BP-512)"""
|
|
run_dpp_pkex(dev, apdev, "brainpoolP512r1")
|
|
|
|
def test_dpp_pkex_config(dev, apdev):
|
|
"""DPP and PKEX with initiator as the configurator"""
|
|
check_dpp_capab(dev[1])
|
|
conf_id = dev[1].dpp_configurator_add()
|
|
run_dpp_pkex(dev, apdev,
|
|
init_extra="conf=sta-dpp configurator=%d" % (conf_id),
|
|
check_config=True)
|
|
|
|
def test_dpp_pkex_no_identifier(dev, apdev):
|
|
"""DPP and PKEX without identifier"""
|
|
run_dpp_pkex(dev, apdev, identifier_i=None, identifier_r=None)
|
|
|
|
def test_dpp_pkex_identifier_mismatch(dev, apdev):
|
|
"""DPP and PKEX with different identifiers"""
|
|
run_dpp_pkex(dev, apdev, identifier_i="foo", identifier_r="bar",
|
|
expect_no_resp=True)
|
|
|
|
def test_dpp_pkex_identifier_mismatch2(dev, apdev):
|
|
"""DPP and PKEX with initiator using identifier and the responder not"""
|
|
run_dpp_pkex(dev, apdev, identifier_i="foo", identifier_r=None,
|
|
expect_no_resp=True)
|
|
|
|
def test_dpp_pkex_identifier_mismatch3(dev, apdev):
|
|
"""DPP and PKEX with responder using identifier and the initiator not"""
|
|
run_dpp_pkex(dev, apdev, identifier_i=None, identifier_r="bar",
|
|
expect_no_resp=True)
|
|
|
|
def run_dpp_pkex(dev, apdev, curve=None, init_extra=None, check_config=False,
|
|
identifier_i="test", identifier_r="test",
|
|
expect_no_resp=False):
|
|
check_dpp_capab(dev[0], curve and "brainpool" in curve)
|
|
check_dpp_capab(dev[1], curve and "brainpool" in curve)
|
|
dev[0].dpp_pkex_resp(2437, identifier=identifier_r, code="secret",
|
|
curve=curve)
|
|
dev[1].dpp_pkex_init(identifier=identifier_i, code="secret", curve=curve,
|
|
extra=init_extra)
|
|
|
|
if expect_no_resp:
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("DPP PKEX frame not received")
|
|
ev = dev[1].wait_event(["DPP-AUTH-SUCCESS"], timeout=1)
|
|
if ev is not None:
|
|
raise Exception("DPP authentication succeeded")
|
|
ev = dev[0].wait_event(["DPP-AUTH-SUCCESS"], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("DPP authentication succeeded")
|
|
return
|
|
|
|
wait_auth_success(dev[0], dev[1],
|
|
configurator=dev[1] if check_config else None,
|
|
enrollee=dev[0] if check_config else None)
|
|
|
|
def test_dpp_pkex_5ghz(dev, apdev):
|
|
"""DPP and PKEX on 5 GHz"""
|
|
try:
|
|
dev[0].request("SET country US")
|
|
dev[1].request("SET country US")
|
|
ev = dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=1)
|
|
if ev is None:
|
|
ev = dev[0].wait_global_event(["CTRL-EVENT-REGDOM-CHANGE"],
|
|
timeout=1)
|
|
run_dpp_pkex_5ghz(dev, apdev)
|
|
finally:
|
|
dev[0].request("SET country 00")
|
|
dev[1].request("SET country 00")
|
|
subprocess.call(['iw', 'reg', 'set', '00'])
|
|
time.sleep(0.1)
|
|
|
|
def run_dpp_pkex_5ghz(dev, apdev):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[0].dpp_pkex_resp(5745, identifier="test", code="secret")
|
|
dev[1].dpp_pkex_init(identifier="test", code="secret")
|
|
wait_auth_success(dev[0], dev[1], timeout=20)
|
|
|
|
def test_dpp_pkex_test_vector(dev, apdev):
|
|
"""DPP and PKEX (P-256) test vector"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
init_addr = "ac:64:91:f4:52:07"
|
|
resp_addr = "6e:5e:ce:6e:f3:dd"
|
|
|
|
identifier = "joes_key"
|
|
code = "thisisreallysecret"
|
|
|
|
# Initiator bootstrapping private key
|
|
init_priv = "5941b51acfc702cdc1c347264beb2920db88eb1a0bf03a211868b1632233c269"
|
|
|
|
# Responder bootstrapping private key
|
|
resp_priv = "2ae8956293f49986b6d0b8169a86805d9232babb5f6813fdfe96f19d59536c60"
|
|
|
|
# Initiator x/X keypair override
|
|
init_x_priv = "8365c5ed93d751bef2d92b410dc6adfd95670889183fac1bd66759ad85c3187a"
|
|
|
|
# Responder y/Y keypair override
|
|
resp_y_priv = "d98faa24d7dd3f592665d71a95c862bfd02c4c48acb0c515a41cbc6e929675ea"
|
|
|
|
p256_prefix = "30310201010420"
|
|
p256_postfix = "a00a06082a8648ce3d030107"
|
|
|
|
dev[0].set("dpp_pkex_own_mac_override", resp_addr)
|
|
dev[0].set("dpp_pkex_peer_mac_override", init_addr)
|
|
dev[1].set("dpp_pkex_own_mac_override", init_addr)
|
|
dev[1].set("dpp_pkex_peer_mac_override", resp_addr)
|
|
|
|
# Responder y/Y keypair override
|
|
dev[0].set("dpp_pkex_ephemeral_key_override",
|
|
p256_prefix + resp_y_priv + p256_postfix)
|
|
|
|
# Initiator x/X keypair override
|
|
dev[1].set("dpp_pkex_ephemeral_key_override",
|
|
p256_prefix + init_x_priv + p256_postfix)
|
|
|
|
dev[0].dpp_pkex_resp(2437, identifier=identifier, code=code,
|
|
key=p256_prefix + resp_priv + p256_postfix)
|
|
dev[1].dpp_pkex_init(identifier=identifier, code=code,
|
|
key=p256_prefix + init_priv + p256_postfix)
|
|
wait_auth_success(dev[0], dev[1])
|
|
|
|
def test_dpp_pkex_code_mismatch(dev, apdev):
|
|
"""DPP and PKEX with mismatching code"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[0].dpp_pkex_resp(2437, identifier="test", code="secret")
|
|
id1 = dev[1].dpp_pkex_init(identifier="test", code="unknown")
|
|
wait_dpp_fail(dev[0], "possible PKEX code mismatch")
|
|
dev[0].dump_monitor()
|
|
dev[1].dump_monitor()
|
|
dev[1].dpp_pkex_init(identifier="test", code="secret", use_id=id1)
|
|
wait_auth_success(dev[0], dev[1])
|
|
|
|
def test_dpp_pkex_code_mismatch_limit(dev, apdev):
|
|
"""DPP and PKEX with mismatching code limit"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[0].dpp_pkex_resp(2437, identifier="test", code="secret")
|
|
|
|
id1 = None
|
|
for i in range(5):
|
|
dev[0].dump_monitor()
|
|
dev[1].dump_monitor()
|
|
id1 = dev[1].dpp_pkex_init(identifier="test", code="unknown",
|
|
use_id=id1)
|
|
wait_dpp_fail(dev[0], "possible PKEX code mismatch")
|
|
|
|
ev = dev[0].wait_event(["DPP-PKEX-T-LIMIT"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("PKEX t limit not reported")
|
|
|
|
def test_dpp_pkex_curve_mismatch(dev, apdev):
|
|
"""DPP and PKEX with mismatching curve"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[0].dpp_pkex_resp(2437, identifier="test", code="secret", curve="P-256")
|
|
dev[1].dpp_pkex_init(identifier="test", code="secret", curve="P-384")
|
|
wait_dpp_fail(dev[0], "Mismatching PKEX curve: peer=20 own=19")
|
|
wait_dpp_fail(dev[1], "Peer indicated mismatching PKEX group - proposed 19")
|
|
|
|
def test_dpp_pkex_curve_mismatch_failure(dev, apdev):
|
|
"""DPP and PKEX with mismatching curve (local failure)"""
|
|
run_dpp_pkex_curve_mismatch_failure(dev, apdev, "=dpp_pkex_rx_exchange_req")
|
|
|
|
def test_dpp_pkex_curve_mismatch_failure2(dev, apdev):
|
|
"""DPP and PKEX with mismatching curve (local failure 2)"""
|
|
run_dpp_pkex_curve_mismatch_failure(dev, apdev,
|
|
"dpp_pkex_build_exchange_resp")
|
|
|
|
def run_dpp_pkex_curve_mismatch_failure(dev, apdev, func):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[0].dpp_pkex_resp(2437, identifier="test", code="secret", curve="P-256")
|
|
|
|
with alloc_fail(dev[0], 1, func):
|
|
dev[1].dpp_pkex_init(identifier="test", code="secret", curve="P-384")
|
|
|
|
ev = dev[0].wait_event(["DPP-FAIL"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Failure not reported (dev 0)")
|
|
if "Mismatching PKEX curve: peer=20 own=19" not in ev:
|
|
raise Exception("Unexpected result: " + ev)
|
|
wait_dpp_fail(dev[0], "Mismatching PKEX curve: peer=20 own=19")
|
|
|
|
def test_dpp_pkex_exchange_resp_processing_failure(dev, apdev):
|
|
"""DPP and PKEX with local failure in processing Exchange Resp"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[0].dpp_pkex_resp(2437, identifier="test", code="secret")
|
|
|
|
with fail_test(dev[1], 1, "dpp_pkex_derive_Qr;dpp_pkex_rx_exchange_resp"):
|
|
dev[1].dpp_pkex_init(identifier="test", code="secret")
|
|
wait_fail_trigger(dev[1], "GET_FAIL")
|
|
|
|
def test_dpp_pkex_commit_reveal_req_processing_failure(dev, apdev):
|
|
"""DPP and PKEX with local failure in processing Commit Reveal Req"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[0].dpp_pkex_resp(2437, identifier="test", code="secret")
|
|
|
|
with alloc_fail(dev[0], 1,
|
|
"dpp_get_pubkey_point;dpp_pkex_rx_commit_reveal_req"):
|
|
dev[1].dpp_pkex_init(identifier="test", code="secret")
|
|
wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
|
|
|
|
def test_dpp_pkex_config2(dev, apdev):
|
|
"""DPP and PKEX with responder as the configurator"""
|
|
check_dpp_capab(dev[0])
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
dev[0].set("dpp_configurator_params",
|
|
" conf=sta-dpp configurator=%d" % conf_id)
|
|
run_dpp_pkex2(dev, apdev)
|
|
|
|
def run_dpp_pkex2(dev, apdev, curve=None, init_extra=""):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[0].dpp_pkex_resp(2437, identifier="test", code="secret", curve=curve,
|
|
listen_role="configurator")
|
|
dev[1].dpp_pkex_init(identifier="test", code="secret", role="enrollee",
|
|
curve=curve, extra=init_extra)
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[0], enrollee=dev[1])
|
|
|
|
def test_dpp_pkex_no_responder(dev, apdev):
|
|
"""DPP and PKEX with no responder (retry behavior)"""
|
|
check_dpp_capab(dev[0])
|
|
dev[0].dpp_pkex_init(identifier="test", code="secret")
|
|
|
|
for i in range(15):
|
|
ev = dev[0].wait_event(["DPP-TX ", "DPP-FAIL"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP PKEX failure not reported")
|
|
if "DPP-FAIL" not in ev:
|
|
continue
|
|
if "No response from PKEX peer" not in ev:
|
|
raise Exception("Unexpected failure reason: " + ev)
|
|
break
|
|
|
|
def test_dpp_pkex_after_retry(dev, apdev):
|
|
"""DPP and PKEX completing after retry"""
|
|
check_dpp_capab(dev[0])
|
|
dev[0].dpp_pkex_init(identifier="test", code="secret")
|
|
time.sleep(0.1)
|
|
dev[1].dpp_pkex_resp(2437, identifier="test", code="secret")
|
|
wait_auth_success(dev[1], dev[0], configurator=dev[0], enrollee=dev[1],
|
|
allow_enrollee_failure=True)
|
|
|
|
def test_dpp_pkex_hostapd_responder(dev, apdev):
|
|
"""DPP PKEX with hostapd as responder"""
|
|
check_dpp_capab(dev[0])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
|
"channel": "6"})
|
|
check_dpp_capab(hapd)
|
|
hapd.dpp_pkex_resp(2437, identifier="test", code="secret")
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
dev[0].dpp_pkex_init(identifier="test", code="secret",
|
|
extra="conf=ap-dpp configurator=%d" % conf_id)
|
|
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd,
|
|
stop_initiator=True)
|
|
|
|
def test_dpp_pkex_hostapd_initiator(dev, apdev):
|
|
"""DPP PKEX with hostapd as initiator"""
|
|
check_dpp_capab(dev[0])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
|
"channel": "6"})
|
|
check_dpp_capab(hapd)
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
dev[0].set("dpp_configurator_params",
|
|
" conf=ap-dpp configurator=%d" % conf_id)
|
|
dev[0].dpp_pkex_resp(2437, identifier="test", code="secret",
|
|
listen_role="configurator")
|
|
hapd.dpp_pkex_init(identifier="test", code="secret", role="enrollee")
|
|
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd,
|
|
stop_initiator=True)
|
|
|
|
def test_dpp_hostapd_configurator(dev, apdev):
|
|
"""DPP with hostapd as configurator/initiator"""
|
|
check_dpp_capab(dev[0])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
|
"channel": "1"})
|
|
check_dpp_capab(hapd)
|
|
conf_id = hapd.dpp_configurator_add()
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
id1 = hapd.dpp_qr_code(uri0)
|
|
res = hapd.request("DPP_BOOTSTRAP_INFO %d" % id1)
|
|
if "FAIL" in res:
|
|
raise Exception("DPP_BOOTSTRAP_INFO failed")
|
|
if "type=QRCODE" not in res:
|
|
raise Exception("DPP_BOOTSTRAP_INFO did not report correct type")
|
|
if "mac_addr=" + dev[0].own_addr() not in res:
|
|
raise Exception("DPP_BOOTSTRAP_INFO did not report correct mac_addr")
|
|
dev[0].dpp_listen(2412)
|
|
hapd.dpp_auth_init(peer=id1, configurator=conf_id, conf="sta-dpp")
|
|
wait_auth_success(dev[0], hapd, configurator=hapd, enrollee=dev[0],
|
|
stop_responder=True)
|
|
|
|
def test_dpp_hostapd_configurator_responder(dev, apdev):
|
|
"""DPP with hostapd as configurator/responder"""
|
|
check_dpp_capab(dev[0])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured",
|
|
"channel": "1"})
|
|
check_dpp_capab(hapd)
|
|
conf_id = hapd.dpp_configurator_add()
|
|
hapd.set("dpp_configurator_params",
|
|
" conf=sta-dpp configurator=%d" % conf_id)
|
|
id0 = hapd.dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = hapd.request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].dpp_auth_init(uri=uri0, role="enrollee")
|
|
wait_auth_success(hapd, dev[0], configurator=hapd, enrollee=dev[0],
|
|
stop_initiator=True)
|
|
|
|
def test_dpp_own_config(dev, apdev):
|
|
"""DPP configurator signing own connector"""
|
|
try:
|
|
run_dpp_own_config(dev, apdev)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_own_config_group_id(dev, apdev):
|
|
"""DPP configurator signing own connector"""
|
|
try:
|
|
run_dpp_own_config(dev, apdev, extra=" group_id=test-group")
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_own_config_curve_mismatch(dev, apdev):
|
|
"""DPP configurator signing own connector using mismatching curve"""
|
|
try:
|
|
run_dpp_own_config(dev, apdev, own_curve="BP-384", expect_failure=True)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def run_dpp_own_config(dev, apdev, own_curve=None, expect_failure=False,
|
|
extra=None):
|
|
check_dpp_capab(dev[0], own_curve and "BP" in own_curve)
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"})
|
|
check_dpp_capab(hapd)
|
|
id_h = hapd.dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri = hapd.request("DPP_BOOTSTRAP_GET_URI %d" % id_h)
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
dev[0].dpp_auth_init(uri=uri, conf="ap-dpp", configurator=conf_id,
|
|
extra=extra)
|
|
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd)
|
|
update_hapd_config(hapd)
|
|
|
|
dev[0].set("dpp_config_processing", "1")
|
|
cmd = "DPP_CONFIGURATOR_SIGN conf=sta-dpp configurator=%d%s" % (conf_id, extra)
|
|
if own_curve:
|
|
cmd += " curve=" + own_curve
|
|
res = dev[0].request(cmd)
|
|
if "FAIL" in res:
|
|
raise Exception("Failed to generate own configuration")
|
|
|
|
ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("DPP network profile not generated")
|
|
id = ev.split(' ')[1]
|
|
dev[0].select_network(id, freq="2412")
|
|
if expect_failure:
|
|
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected connection")
|
|
dev[0].request("DISCONNECT")
|
|
else:
|
|
dev[0].wait_connected()
|
|
|
|
def test_dpp_own_config_ap(dev, apdev):
|
|
"""DPP configurator (AP) signing own connector"""
|
|
try:
|
|
run_dpp_own_config_ap(dev, apdev)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_own_config_ap_group_id(dev, apdev):
|
|
"""DPP configurator (AP) signing own connector (group_id)"""
|
|
try:
|
|
run_dpp_own_config_ap(dev, apdev, extra=" group_id=test-group")
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_own_config_ap_reconf(dev, apdev):
|
|
"""DPP configurator (AP) signing own connector and configurator reconf"""
|
|
try:
|
|
run_dpp_own_config_ap(dev, apdev)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def run_dpp_own_config_ap(dev, apdev, reconf_configurator=False, extra=None):
|
|
check_dpp_capab(dev[0])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"})
|
|
check_dpp_capab(hapd)
|
|
conf_id = hapd.dpp_configurator_add()
|
|
if reconf_configurator:
|
|
csign = hapd.request("DPP_CONFIGURATOR_GET_KEY %d" % conf_id)
|
|
if "FAIL" in csign or len(csign) == 0:
|
|
raise Exception("DPP_CONFIGURATOR_GET_KEY failed")
|
|
|
|
cmd = "DPP_CONFIGURATOR_SIGN conf=ap-dpp configurator=%d%s" % (conf_id, extra)
|
|
res = hapd.request(cmd)
|
|
if "FAIL" in res:
|
|
raise Exception("Failed to generate own configuration")
|
|
update_hapd_config(hapd)
|
|
|
|
if reconf_configurator:
|
|
hapd.dpp_configurator_remove(conf_id)
|
|
conf_id = hapd.dpp_configurator_add(key=csign)
|
|
|
|
id = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id)
|
|
dev[0].set("dpp_config_processing", "2")
|
|
dev[0].dpp_listen(2412)
|
|
hapd.dpp_auth_init(uri=uri, conf="sta-dpp", configurator=conf_id,
|
|
extra=extra)
|
|
wait_auth_success(dev[0], hapd, configurator=hapd, enrollee=dev[0])
|
|
dev[0].wait_connected()
|
|
|
|
def test_dpp_intro_mismatch(dev, apdev):
|
|
"""DPP network introduction mismatch cases"""
|
|
try:
|
|
wpas = None
|
|
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
|
|
wpas.interface_add("wlan5")
|
|
check_dpp_capab(wpas)
|
|
run_dpp_intro_mismatch(dev, apdev, wpas)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
dev[2].set("dpp_config_processing", "0", allow_fail=True)
|
|
if wpas:
|
|
wpas.set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def run_dpp_intro_mismatch(dev, apdev, wpas):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
check_dpp_capab(dev[2])
|
|
logger.info("Start AP in unconfigured state")
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"})
|
|
check_dpp_capab(hapd)
|
|
id_h = hapd.dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri = hapd.request("DPP_BOOTSTRAP_GET_URI %d" % id_h)
|
|
logger.info("Provision AP with DPP configuration")
|
|
conf_id = dev[1].dpp_configurator_add()
|
|
dev[1].set("dpp_groups_override", '[{"groupId":"a","netRole":"ap"}]')
|
|
dev[1].dpp_auth_init(uri=uri, conf="ap-dpp", configurator=conf_id)
|
|
update_hapd_config(hapd)
|
|
|
|
logger.info("Provision STA0 with DPP Connector that has mismatching groupId")
|
|
dev[0].set("dpp_config_processing", "2")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].set("dpp_groups_override", '[{"groupId":"b","netRole":"sta"}]')
|
|
dev[1].dpp_auth_init(uri=uri0, conf="sta-dpp", configurator=conf_id)
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0])
|
|
|
|
logger.info("Provision STA2 with DPP Connector that has mismatching C-sign-key")
|
|
dev[2].set("dpp_config_processing", "2")
|
|
id2 = dev[2].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri2 = dev[2].request("DPP_BOOTSTRAP_GET_URI %d" % id2)
|
|
dev[2].dpp_listen(2412)
|
|
conf_id_2 = dev[1].dpp_configurator_add()
|
|
dev[1].set("dpp_groups_override", '')
|
|
dev[1].dpp_auth_init(uri=uri2, conf="sta-dpp", configurator=conf_id_2)
|
|
wait_auth_success(dev[2], dev[1], configurator=dev[1], enrollee=dev[2])
|
|
|
|
logger.info("Provision STA5 with DPP Connector that has mismatching netAccessKey EC group")
|
|
wpas.set("dpp_config_processing", "2")
|
|
id5 = wpas.dpp_bootstrap_gen(chan="81/1", mac=True, curve="P-521")
|
|
uri5 = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % id5)
|
|
wpas.dpp_listen(2412)
|
|
dev[1].set("dpp_groups_override", '')
|
|
dev[1].dpp_auth_init(uri=uri5, conf="sta-dpp", configurator=conf_id)
|
|
wait_auth_success(wpas, dev[1], configurator=dev[1], enrollee=wpas)
|
|
|
|
logger.info("Verify network introduction results")
|
|
ev = dev[0].wait_event(["DPP-INTRO"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("DPP network introduction result not seen on STA0")
|
|
if "status=8" not in ev:
|
|
raise Exception("Unexpected network introduction result on STA0: " + ev)
|
|
|
|
ev = dev[2].wait_event(["DPP-INTRO"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP network introduction result not seen on STA2")
|
|
if "status=8" not in ev:
|
|
raise Exception("Unexpected network introduction result on STA2: " + ev)
|
|
|
|
ev = wpas.wait_event(["DPP-INTRO"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("DPP network introduction result not seen on STA5")
|
|
if "status=7" not in ev:
|
|
raise Exception("Unexpected network introduction result on STA5: " + ev)
|
|
|
|
def run_dpp_proto_init(dev, test_dev, test, mutual=False, unicast=True,
|
|
listen=True, chan="81/1", init_enrollee=False,
|
|
incompatible_roles=False):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[test_dev].set("dpp_test", str(test))
|
|
if init_enrollee:
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
else:
|
|
conf_id = dev[1].dpp_configurator_add()
|
|
id0 = dev[0].dpp_bootstrap_gen(chan=chan, mac=unicast)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
if mutual:
|
|
id1b = dev[1].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri1b = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1b)
|
|
|
|
id0b = dev[0].dpp_qr_code(uri1b)
|
|
qr = "mutual"
|
|
else:
|
|
qr = None
|
|
|
|
if init_enrollee:
|
|
if incompatible_roles:
|
|
role = "enrollee"
|
|
else:
|
|
role = "configurator"
|
|
dev[0].set("dpp_configurator_params",
|
|
" conf=sta-dpp configurator=%d" % conf_id)
|
|
elif incompatible_roles:
|
|
role = "enrollee"
|
|
else:
|
|
role = None
|
|
|
|
if listen:
|
|
dev[0].dpp_listen(2412, qr=qr, role=role)
|
|
|
|
role = None
|
|
configurator = None
|
|
conf = None
|
|
own = None
|
|
|
|
if init_enrollee:
|
|
role="enrollee"
|
|
else:
|
|
configurator=conf_id
|
|
conf="sta-dpp"
|
|
if incompatible_roles:
|
|
role="enrollee"
|
|
if mutual:
|
|
own = id1b
|
|
dev[1].dpp_auth_init(uri=uri0, role=role, configurator=configurator,
|
|
conf=conf, own=own)
|
|
|
|
def test_dpp_proto_after_wrapped_data_auth_req(dev, apdev):
|
|
"""DPP protocol testing - attribute after Wrapped Data in Auth Req"""
|
|
run_dpp_proto_init(dev, 1, 1)
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP Authentication Request not seen")
|
|
if "type=0" not in ev or "ignore=invalid-attributes" not in ev:
|
|
raise Exception("Unexpected RX info: " + ev)
|
|
ev = dev[1].wait_event(["DPP-RX"], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected DPP message seen")
|
|
|
|
def test_dpp_auth_req_stop_after_ack(dev, apdev):
|
|
"""DPP initiator stopping after ACK, but no response"""
|
|
run_dpp_proto_init(dev, 1, 1, listen=True)
|
|
ev = dev[1].wait_event(["DPP-AUTH-INIT-FAILED"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Authentication failure not reported")
|
|
|
|
def test_dpp_auth_req_retries(dev, apdev):
|
|
"""DPP initiator retries with no ACK"""
|
|
check_dpp_capab(dev[1])
|
|
dev[1].set("dpp_init_max_tries", "3")
|
|
dev[1].set("dpp_init_retry_time", "1000")
|
|
dev[1].set("dpp_resp_wait_time", "100")
|
|
run_dpp_proto_init(dev, 1, 1, unicast=False, listen=False)
|
|
|
|
for i in range(3):
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Auth Req not sent (%d)" % i)
|
|
|
|
ev = dev[1].wait_event(["DPP-AUTH-INIT-FAILED"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Authentication failure not reported")
|
|
|
|
def test_dpp_auth_req_retries_multi_chan(dev, apdev):
|
|
"""DPP initiator retries with no ACK and multiple channels"""
|
|
check_dpp_capab(dev[1])
|
|
dev[1].set("dpp_init_max_tries", "3")
|
|
dev[1].set("dpp_init_retry_time", "1000")
|
|
dev[1].set("dpp_resp_wait_time", "100")
|
|
run_dpp_proto_init(dev, 1, 1, unicast=False, listen=False,
|
|
chan="81/1,81/6,81/11")
|
|
|
|
for i in range(3 * 3):
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Auth Req not sent (%d)" % i)
|
|
|
|
ev = dev[1].wait_event(["DPP-AUTH-INIT-FAILED"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Authentication failure not reported")
|
|
|
|
def test_dpp_proto_after_wrapped_data_auth_resp(dev, apdev):
|
|
"""DPP protocol testing - attribute after Wrapped Data in Auth Resp"""
|
|
run_dpp_proto_init(dev, 0, 2)
|
|
ev = dev[1].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP Authentication Response not seen")
|
|
if "type=1" not in ev or "ignore=invalid-attributes" not in ev:
|
|
raise Exception("Unexpected RX info: " + ev)
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=1)
|
|
if ev is None or "type=0" not in ev:
|
|
raise Exception("DPP Authentication Request not seen")
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected DPP message seen")
|
|
|
|
def test_dpp_proto_after_wrapped_data_auth_conf(dev, apdev):
|
|
"""DPP protocol testing - attribute after Wrapped Data in Auth Conf"""
|
|
run_dpp_proto_init(dev, 1, 3)
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None or "type=0" not in ev:
|
|
raise Exception("DPP Authentication Request not seen")
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP Authentication Confirm not seen")
|
|
if "type=2" not in ev or "ignore=invalid-attributes" not in ev:
|
|
raise Exception("Unexpected RX info: " + ev)
|
|
|
|
def test_dpp_proto_after_wrapped_data_conf_req(dev, apdev):
|
|
"""DPP protocol testing - attribute after Wrapped Data in Conf Req"""
|
|
run_dpp_proto_init(dev, 0, 6)
|
|
ev = dev[1].wait_event(["DPP-CONF-FAILED"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("DPP Configuration failure not seen")
|
|
|
|
def test_dpp_proto_after_wrapped_data_conf_resp(dev, apdev):
|
|
"""DPP protocol testing - attribute after Wrapped Data in Conf Resp"""
|
|
run_dpp_proto_init(dev, 1, 7)
|
|
ev = dev[0].wait_event(["DPP-CONF-FAILED"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("DPP Configuration failure not seen")
|
|
|
|
def test_dpp_proto_zero_i_capab(dev, apdev):
|
|
"""DPP protocol testing - zero I-capability in Auth Req"""
|
|
run_dpp_proto_init(dev, 1, 8)
|
|
wait_dpp_fail(dev[0], "Invalid role in I-capabilities 0x00")
|
|
ev = dev[1].wait_event(["DPP-RX"], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected DPP message seen")
|
|
|
|
def test_dpp_proto_zero_r_capab(dev, apdev):
|
|
"""DPP protocol testing - zero R-capability in Auth Resp"""
|
|
run_dpp_proto_init(dev, 0, 9)
|
|
wait_dpp_fail(dev[1], "Unexpected role in R-capabilities 0x00")
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=1)
|
|
if ev is None or "type=0" not in ev:
|
|
raise Exception("DPP Authentication Request not seen")
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected DPP message seen")
|
|
|
|
def run_dpp_proto_auth_req_missing(dev, test, reason, mutual=False):
|
|
run_dpp_proto_init(dev, 1, test, mutual=mutual)
|
|
wait_dpp_fail(dev[0], reason)
|
|
ev = dev[1].wait_event(["DPP-RX"], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected DPP message seen")
|
|
|
|
def test_dpp_proto_auth_req_no_r_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - no R-bootstrap key in Auth Req"""
|
|
run_dpp_proto_auth_req_missing(dev, 10, "Missing or invalid required Responder Bootstrapping Key Hash attribute")
|
|
|
|
def test_dpp_proto_auth_req_invalid_r_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - invalid R-bootstrap key in Auth Req"""
|
|
run_dpp_proto_auth_req_missing(dev, 68, "No matching own bootstrapping key found - ignore message")
|
|
|
|
def test_dpp_proto_auth_req_no_i_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - no I-bootstrap key in Auth Req"""
|
|
run_dpp_proto_auth_req_missing(dev, 11, "Missing or invalid required Initiator Bootstrapping Key Hash attribute")
|
|
|
|
def test_dpp_proto_auth_req_invalid_i_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - invalid I-bootstrap key in Auth Req"""
|
|
run_dpp_proto_init(dev, 1, 69, mutual=True)
|
|
ev = dev[0].wait_event(["DPP-SCAN-PEER-QR-CODE"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP scan request not seen")
|
|
ev = dev[1].wait_event(["DPP-RESPONSE-PENDING"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP response pending indivation not seen")
|
|
|
|
def test_dpp_proto_auth_req_no_i_proto_key(dev, apdev):
|
|
"""DPP protocol testing - no I-proto key in Auth Req"""
|
|
run_dpp_proto_auth_req_missing(dev, 12, "Missing required Initiator Protocol Key attribute")
|
|
|
|
def test_dpp_proto_auth_req_invalid_i_proto_key(dev, apdev):
|
|
"""DPP protocol testing - invalid I-proto key in Auth Req"""
|
|
run_dpp_proto_auth_req_missing(dev, 66, "Invalid Initiator Protocol Key")
|
|
|
|
def test_dpp_proto_auth_req_no_i_nonce(dev, apdev):
|
|
"""DPP protocol testing - no I-nonce in Auth Req"""
|
|
run_dpp_proto_auth_req_missing(dev, 13, "Missing or invalid I-nonce")
|
|
|
|
def test_dpp_proto_auth_req_invalid_i_nonce(dev, apdev):
|
|
"""DPP protocol testing - invalid I-nonce in Auth Req"""
|
|
run_dpp_proto_auth_req_missing(dev, 81, "Missing or invalid I-nonce")
|
|
|
|
def test_dpp_proto_auth_req_no_i_capab(dev, apdev):
|
|
"""DPP protocol testing - no I-capab in Auth Req"""
|
|
run_dpp_proto_auth_req_missing(dev, 14, "Missing or invalid I-capab")
|
|
|
|
def test_dpp_proto_auth_req_no_wrapped_data(dev, apdev):
|
|
"""DPP protocol testing - no Wrapped Data in Auth Req"""
|
|
run_dpp_proto_auth_req_missing(dev, 15, "Missing or invalid required Wrapped Data attribute")
|
|
|
|
def run_dpp_proto_auth_resp_missing(dev, test, reason,
|
|
incompatible_roles=False):
|
|
run_dpp_proto_init(dev, 0, test, mutual=True,
|
|
incompatible_roles=incompatible_roles)
|
|
if reason is None:
|
|
if incompatible_roles:
|
|
ev = dev[0].wait_event(["DPP-NOT-COMPATIBLE"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP-NOT-COMPATIBLE not reported")
|
|
time.sleep(0.1)
|
|
return
|
|
wait_dpp_fail(dev[1], reason)
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=1)
|
|
if ev is None or "type=0" not in ev:
|
|
raise Exception("DPP Authentication Request not seen")
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected DPP message seen")
|
|
|
|
def test_dpp_proto_auth_resp_no_status(dev, apdev):
|
|
"""DPP protocol testing - no Status in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 16, "Missing or invalid required DPP Status attribute")
|
|
|
|
def test_dpp_proto_auth_resp_status_no_status(dev, apdev):
|
|
"""DPP protocol testing - no Status in Auth Resp(status)"""
|
|
run_dpp_proto_auth_resp_missing(dev, 16,
|
|
"Missing or invalid required DPP Status attribute",
|
|
incompatible_roles=True)
|
|
|
|
def test_dpp_proto_auth_resp_invalid_status(dev, apdev):
|
|
"""DPP protocol testing - invalid Status in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 74, "Responder reported failure")
|
|
|
|
def test_dpp_proto_auth_resp_no_r_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - no R-bootstrap key in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 17, "Missing or invalid required Responder Bootstrapping Key Hash attribute")
|
|
|
|
def test_dpp_proto_auth_resp_status_no_r_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - no R-bootstrap key in Auth Resp(status)"""
|
|
run_dpp_proto_auth_resp_missing(dev, 17,
|
|
"Missing or invalid required Responder Bootstrapping Key Hash attribute",
|
|
incompatible_roles=True)
|
|
|
|
def test_dpp_proto_auth_resp_invalid_r_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - invalid R-bootstrap key in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 70, "Unexpected Responder Bootstrapping Key Hash value")
|
|
|
|
def test_dpp_proto_auth_resp_status_invalid_r_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - invalid R-bootstrap key in Auth Resp(status)"""
|
|
run_dpp_proto_auth_resp_missing(dev, 70,
|
|
"Unexpected Responder Bootstrapping Key Hash value",
|
|
incompatible_roles=True)
|
|
|
|
def test_dpp_proto_auth_resp_no_i_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - no I-bootstrap key in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 18, None)
|
|
|
|
def test_dpp_proto_auth_resp_status_no_i_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - no I-bootstrap key in Auth Resp(status)"""
|
|
run_dpp_proto_auth_resp_missing(dev, 18, None, incompatible_roles=True)
|
|
|
|
def test_dpp_proto_auth_resp_invalid_i_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - invalid I-bootstrap key in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 71, "Initiator Bootstrapping Key Hash attribute did not match")
|
|
|
|
def test_dpp_proto_auth_resp_status_invalid_i_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - invalid I-bootstrap key in Auth Resp(status)"""
|
|
run_dpp_proto_auth_resp_missing(dev, 71,
|
|
"Initiator Bootstrapping Key Hash attribute did not match",
|
|
incompatible_roles=True)
|
|
|
|
def test_dpp_proto_auth_resp_no_r_proto_key(dev, apdev):
|
|
"""DPP protocol testing - no R-Proto Key in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 19, "Missing required Responder Protocol Key attribute")
|
|
|
|
def test_dpp_proto_auth_resp_invalid_r_proto_key(dev, apdev):
|
|
"""DPP protocol testing - invalid R-Proto Key in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 67, "Invalid Responder Protocol Key")
|
|
|
|
def test_dpp_proto_auth_resp_no_r_nonce(dev, apdev):
|
|
"""DPP protocol testing - no R-nonce in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 20, "Missing or invalid R-nonce")
|
|
|
|
def test_dpp_proto_auth_resp_no_i_nonce(dev, apdev):
|
|
"""DPP protocol testing - no I-nonce in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 21, "Missing or invalid I-nonce")
|
|
|
|
def test_dpp_proto_auth_resp_status_no_i_nonce(dev, apdev):
|
|
"""DPP protocol testing - no I-nonce in Auth Resp(status)"""
|
|
run_dpp_proto_auth_resp_missing(dev, 21, "Missing or invalid I-nonce",
|
|
incompatible_roles=True)
|
|
|
|
def test_dpp_proto_auth_resp_no_r_capab(dev, apdev):
|
|
"""DPP protocol testing - no R-capab in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 22, "Missing or invalid R-capabilities")
|
|
|
|
def test_dpp_proto_auth_resp_no_r_auth(dev, apdev):
|
|
"""DPP protocol testing - no R-auth in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 23, "Missing or invalid Secondary Wrapped Data")
|
|
|
|
def test_dpp_proto_auth_resp_no_wrapped_data(dev, apdev):
|
|
"""DPP protocol testing - no Wrapped Data in Auth Resp"""
|
|
run_dpp_proto_auth_resp_missing(dev, 24, "Missing or invalid required Wrapped Data attribute")
|
|
|
|
def test_dpp_proto_auth_resp_i_nonce_mismatch(dev, apdev):
|
|
"""DPP protocol testing - I-nonce mismatch in Auth Resp"""
|
|
run_dpp_proto_init(dev, 0, 30, mutual=True)
|
|
wait_dpp_fail(dev[1], "I-nonce mismatch")
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=1)
|
|
if ev is None or "type=0" not in ev:
|
|
raise Exception("DPP Authentication Request not seen")
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected DPP message seen")
|
|
|
|
def test_dpp_proto_auth_resp_incompatible_r_capab(dev, apdev):
|
|
"""DPP protocol testing - Incompatible R-capab in Auth Resp"""
|
|
run_dpp_proto_init(dev, 0, 31, mutual=True)
|
|
wait_dpp_fail(dev[1], "Unexpected role in R-capabilities 0x02")
|
|
wait_dpp_fail(dev[0], "Peer reported incompatible R-capab role")
|
|
|
|
def test_dpp_proto_auth_resp_r_auth_mismatch(dev, apdev):
|
|
"""DPP protocol testing - R-auth mismatch in Auth Resp"""
|
|
run_dpp_proto_init(dev, 0, 32, mutual=True)
|
|
wait_dpp_fail(dev[1], "Mismatching Responder Authenticating Tag")
|
|
wait_dpp_fail(dev[0], "Peer reported authentication failure")
|
|
|
|
def test_dpp_proto_auth_resp_r_auth_mismatch_failure(dev, apdev):
|
|
"""DPP protocol testing - Auth Conf RX processing failure"""
|
|
with alloc_fail(dev[0], 1, "dpp_auth_conf_rx_failure"):
|
|
run_dpp_proto_init(dev, 0, 32, mutual=True)
|
|
wait_dpp_fail(dev[0], "Authentication failed")
|
|
|
|
def test_dpp_proto_auth_resp_r_auth_mismatch_failure2(dev, apdev):
|
|
"""DPP protocol testing - Auth Conf RX processing failure 2"""
|
|
with fail_test(dev[0], 1, "dpp_auth_conf_rx_failure"):
|
|
run_dpp_proto_init(dev, 0, 32, mutual=True)
|
|
wait_dpp_fail(dev[0], "AES-SIV decryption failed")
|
|
|
|
def run_dpp_proto_auth_conf_missing(dev, test, reason):
|
|
run_dpp_proto_init(dev, 1, test, mutual=True)
|
|
if reason is None:
|
|
time.sleep(0.1)
|
|
return
|
|
wait_dpp_fail(dev[0], reason)
|
|
|
|
def test_dpp_proto_auth_conf_no_status(dev, apdev):
|
|
"""DPP protocol testing - no Status in Auth Conf"""
|
|
run_dpp_proto_auth_conf_missing(dev, 25, "Missing or invalid required DPP Status attribute")
|
|
|
|
def test_dpp_proto_auth_conf_invalid_status(dev, apdev):
|
|
"""DPP protocol testing - invalid Status in Auth Conf"""
|
|
run_dpp_proto_auth_conf_missing(dev, 75, "Authentication failed")
|
|
|
|
def test_dpp_proto_auth_conf_no_r_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - no R-bootstrap key in Auth Conf"""
|
|
run_dpp_proto_auth_conf_missing(dev, 26, "Missing or invalid required Responder Bootstrapping Key Hash attribute")
|
|
|
|
def test_dpp_proto_auth_conf_invalid_r_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - invalid R-bootstrap key in Auth Conf"""
|
|
run_dpp_proto_auth_conf_missing(dev, 72, "Responder Bootstrapping Key Hash mismatch")
|
|
|
|
def test_dpp_proto_auth_conf_no_i_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - no I-bootstrap key in Auth Conf"""
|
|
run_dpp_proto_auth_conf_missing(dev, 27, "Missing Initiator Bootstrapping Key Hash attribute")
|
|
|
|
def test_dpp_proto_auth_conf_invalid_i_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - invalid I-bootstrap key in Auth Conf"""
|
|
run_dpp_proto_auth_conf_missing(dev, 73, "Initiator Bootstrapping Key Hash mismatch")
|
|
|
|
def test_dpp_proto_auth_conf_no_i_auth(dev, apdev):
|
|
"""DPP protocol testing - no I-Auth in Auth Conf"""
|
|
run_dpp_proto_auth_conf_missing(dev, 28, "Missing or invalid Initiator Authenticating Tag")
|
|
|
|
def test_dpp_proto_auth_conf_no_wrapped_data(dev, apdev):
|
|
"""DPP protocol testing - no Wrapped Data in Auth Conf"""
|
|
run_dpp_proto_auth_conf_missing(dev, 29, "Missing or invalid required Wrapped Data attribute")
|
|
|
|
def test_dpp_proto_auth_conf_i_auth_mismatch(dev, apdev):
|
|
"""DPP protocol testing - I-auth mismatch in Auth Conf"""
|
|
run_dpp_proto_init(dev, 1, 33, mutual=True)
|
|
wait_dpp_fail(dev[0], "Mismatching Initiator Authenticating Tag")
|
|
|
|
def test_dpp_proto_auth_conf_replaced_by_resp(dev, apdev):
|
|
"""DPP protocol testing - Auth Conf replaced by Resp"""
|
|
run_dpp_proto_init(dev, 1, 65, mutual=True)
|
|
wait_dpp_fail(dev[0], "Unexpected Authentication Response")
|
|
|
|
def run_dpp_proto_conf_req_missing(dev, test, reason):
|
|
run_dpp_proto_init(dev, 0, test)
|
|
wait_dpp_fail(dev[1], reason)
|
|
|
|
def test_dpp_proto_conf_req_no_e_nonce(dev, apdev):
|
|
"""DPP protocol testing - no E-nonce in Conf Req"""
|
|
run_dpp_proto_conf_req_missing(dev, 51,
|
|
"Missing or invalid Enrollee Nonce attribute")
|
|
|
|
def test_dpp_proto_conf_req_invalid_e_nonce(dev, apdev):
|
|
"""DPP protocol testing - invalid E-nonce in Conf Req"""
|
|
run_dpp_proto_conf_req_missing(dev, 83,
|
|
"Missing or invalid Enrollee Nonce attribute")
|
|
|
|
def test_dpp_proto_conf_req_no_config_attr_obj(dev, apdev):
|
|
"""DPP protocol testing - no Config Attr Obj in Conf Req"""
|
|
run_dpp_proto_conf_req_missing(dev, 52,
|
|
"Missing or invalid Config Attributes attribute")
|
|
|
|
def test_dpp_proto_conf_req_invalid_config_attr_obj(dev, apdev):
|
|
"""DPP protocol testing - invalid Config Attr Obj in Conf Req"""
|
|
run_dpp_proto_conf_req_missing(dev, 76,
|
|
"Unsupported wi-fi_tech")
|
|
|
|
def test_dpp_proto_conf_req_no_wrapped_data(dev, apdev):
|
|
"""DPP protocol testing - no Wrapped Data in Conf Req"""
|
|
run_dpp_proto_conf_req_missing(dev, 53,
|
|
"Missing or invalid required Wrapped Data attribute")
|
|
|
|
def run_dpp_proto_conf_resp_missing(dev, test, reason):
|
|
run_dpp_proto_init(dev, 1, test)
|
|
wait_dpp_fail(dev[0], reason)
|
|
|
|
def test_dpp_proto_conf_resp_no_e_nonce(dev, apdev):
|
|
"""DPP protocol testing - no E-nonce in Conf Resp"""
|
|
run_dpp_proto_conf_resp_missing(dev, 54,
|
|
"Missing or invalid Enrollee Nonce attribute")
|
|
|
|
def test_dpp_proto_conf_resp_no_config_obj(dev, apdev):
|
|
"""DPP protocol testing - no Config Object in Conf Resp"""
|
|
run_dpp_proto_conf_resp_missing(dev, 55,
|
|
"Missing required Configuration Object attribute")
|
|
|
|
def test_dpp_proto_conf_resp_no_status(dev, apdev):
|
|
"""DPP protocol testing - no Status in Conf Resp"""
|
|
run_dpp_proto_conf_resp_missing(dev, 56,
|
|
"Missing or invalid required DPP Status attribute")
|
|
|
|
def test_dpp_proto_conf_resp_no_wrapped_data(dev, apdev):
|
|
"""DPP protocol testing - no Wrapped Data in Conf Resp"""
|
|
run_dpp_proto_conf_resp_missing(dev, 57,
|
|
"Missing or invalid required Wrapped Data attribute")
|
|
|
|
def test_dpp_proto_conf_resp_invalid_status(dev, apdev):
|
|
"""DPP protocol testing - invalid Status in Conf Resp"""
|
|
run_dpp_proto_conf_resp_missing(dev, 58,
|
|
"Configurator rejected configuration")
|
|
|
|
def test_dpp_proto_conf_resp_e_nonce_mismatch(dev, apdev):
|
|
"""DPP protocol testing - E-nonce mismatch in Conf Resp"""
|
|
run_dpp_proto_conf_resp_missing(dev, 59,
|
|
"Enrollee Nonce mismatch")
|
|
|
|
def test_dpp_proto_stop_at_auth_req(dev, apdev):
|
|
"""DPP protocol testing - stop when receiving Auth Req"""
|
|
run_dpp_proto_init(dev, 0, 87)
|
|
ev = dev[1].wait_event(["DPP-AUTH-INIT-FAILED"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Authentication init failure not reported")
|
|
|
|
def test_dpp_proto_stop_at_auth_resp(dev, apdev):
|
|
"""DPP protocol testing - stop when receiving Auth Resp"""
|
|
run_dpp_proto_init(dev, 1, 88)
|
|
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Auth Req TX not seen")
|
|
|
|
ev = dev[0].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Auth Resp TX not seen")
|
|
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected Auth Conf TX")
|
|
|
|
def test_dpp_proto_stop_at_auth_conf(dev, apdev):
|
|
"""DPP protocol testing - stop when receiving Auth Conf"""
|
|
run_dpp_proto_init(dev, 0, 89, init_enrollee=True)
|
|
ev = dev[1].wait_event(["GAS-QUERY-START"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("Enrollee did not start GAS")
|
|
ev = dev[1].wait_event(["GAS-QUERY-DONE"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("Enrollee did not time out GAS")
|
|
if "result=TIMEOUT" not in ev:
|
|
raise Exception("Unexpected GAS result: " + ev)
|
|
|
|
def test_dpp_proto_stop_at_auth_conf_tx(dev, apdev):
|
|
"""DPP protocol testing - stop when transmitting Auth Conf (Registrar)"""
|
|
run_dpp_proto_init(dev, 1, 89, init_enrollee=True)
|
|
wait_auth_success(dev[0], dev[1], timeout=10)
|
|
ev = dev[1].wait_event(["GAS-QUERY-START"], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected GAS query")
|
|
|
|
# There is currently no timeout on GAS server side, so no event to wait for
|
|
# in this case.
|
|
|
|
def test_dpp_proto_stop_at_auth_conf_tx2(dev, apdev):
|
|
"""DPP protocol testing - stop when transmitting Auth Conf (Enrollee)"""
|
|
run_dpp_proto_init(dev, 1, 89)
|
|
wait_auth_success(dev[0], dev[1], timeout=10)
|
|
|
|
ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5)
|
|
if ev is None or "result=TIMEOUT" not in ev:
|
|
raise Exception("GAS query did not time out")
|
|
|
|
def test_dpp_proto_stop_at_conf_req(dev, apdev):
|
|
"""DPP protocol testing - stop when receiving Auth Req"""
|
|
run_dpp_proto_init(dev, 1, 90)
|
|
ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("Enrollee did not start GAS")
|
|
ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("Enrollee did not time out GAS")
|
|
if "result=TIMEOUT" not in ev:
|
|
raise Exception("Unexpected GAS result: " + ev)
|
|
|
|
def run_dpp_proto_init_pkex(dev, test_dev, test):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[test_dev].set("dpp_test", str(test))
|
|
dev[0].dpp_pkex_resp(2437, identifier="test", code="secret")
|
|
dev[1].dpp_pkex_init(identifier="test", code="secret")
|
|
|
|
def test_dpp_proto_after_wrapped_data_pkex_cr_req(dev, apdev):
|
|
"""DPP protocol testing - attribute after Wrapped Data in PKEX CR Req"""
|
|
run_dpp_proto_init_pkex(dev, 1, 4)
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None or "type=7" not in ev:
|
|
raise Exception("PKEX Exchange Request not seen")
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None or "type=9" not in ev:
|
|
raise Exception("PKEX Commit-Reveal Request not seen")
|
|
if "ignore=invalid-attributes" not in ev:
|
|
raise Exception("Unexpected RX info: " + ev)
|
|
|
|
def test_dpp_proto_after_wrapped_data_pkex_cr_resp(dev, apdev):
|
|
"""DPP protocol testing - attribute after Wrapped Data in PKEX CR Resp"""
|
|
run_dpp_proto_init_pkex(dev, 0, 5)
|
|
ev = dev[1].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None or "type=8" not in ev:
|
|
raise Exception("PKEX Exchange Response not seen")
|
|
ev = dev[1].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None or "type=10" not in ev:
|
|
raise Exception("PKEX Commit-Reveal Response not seen")
|
|
if "ignore=invalid-attributes" not in ev:
|
|
raise Exception("Unexpected RX info: " + ev)
|
|
|
|
def run_dpp_proto_pkex_req_missing(dev, test, reason):
|
|
run_dpp_proto_init_pkex(dev, 1, test)
|
|
wait_dpp_fail(dev[0], reason)
|
|
|
|
def run_dpp_proto_pkex_resp_missing(dev, test, reason):
|
|
run_dpp_proto_init_pkex(dev, 0, test)
|
|
wait_dpp_fail(dev[1], reason)
|
|
|
|
def test_dpp_proto_pkex_exchange_req_no_finite_cyclic_group(dev, apdev):
|
|
"""DPP protocol testing - no Finite Cyclic Group in PKEX Exchange Request"""
|
|
run_dpp_proto_pkex_req_missing(dev, 34,
|
|
"Missing or invalid Finite Cyclic Group attribute")
|
|
|
|
def test_dpp_proto_pkex_exchange_req_no_encrypted_key(dev, apdev):
|
|
"""DPP protocol testing - no Encrypted Key in PKEX Exchange Request"""
|
|
run_dpp_proto_pkex_req_missing(dev, 35,
|
|
"Missing Encrypted Key attribute")
|
|
|
|
def test_dpp_proto_pkex_exchange_resp_no_status(dev, apdev):
|
|
"""DPP protocol testing - no Status in PKEX Exchange Response"""
|
|
run_dpp_proto_pkex_resp_missing(dev, 36, "No DPP Status attribute")
|
|
|
|
def test_dpp_proto_pkex_exchange_resp_no_encrypted_key(dev, apdev):
|
|
"""DPP protocol testing - no Encrypted Key in PKEX Exchange Response"""
|
|
run_dpp_proto_pkex_resp_missing(dev, 37, "Missing Encrypted Key attribute")
|
|
|
|
def test_dpp_proto_pkex_cr_req_no_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - no Bootstrap Key in PKEX Commit-Reveal Request"""
|
|
run_dpp_proto_pkex_req_missing(dev, 38,
|
|
"No valid peer bootstrapping key found")
|
|
|
|
def test_dpp_proto_pkex_cr_req_no_i_auth_tag(dev, apdev):
|
|
"""DPP protocol testing - no I-Auth Tag in PKEX Commit-Reveal Request"""
|
|
run_dpp_proto_pkex_req_missing(dev, 39, "No valid u (I-Auth tag) found")
|
|
|
|
def test_dpp_proto_pkex_cr_req_no_wrapped_data(dev, apdev):
|
|
"""DPP protocol testing - no Wrapped Data in PKEX Commit-Reveal Request"""
|
|
run_dpp_proto_pkex_req_missing(dev, 40, "Missing or invalid required Wrapped Data attribute")
|
|
|
|
def test_dpp_proto_pkex_cr_resp_no_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - no Bootstrap Key in PKEX Commit-Reveal Response"""
|
|
run_dpp_proto_pkex_resp_missing(dev, 41,
|
|
"No valid peer bootstrapping key found")
|
|
|
|
def test_dpp_proto_pkex_cr_resp_no_r_auth_tag(dev, apdev):
|
|
"""DPP protocol testing - no R-Auth Tag in PKEX Commit-Reveal Response"""
|
|
run_dpp_proto_pkex_resp_missing(dev, 42, "No valid v (R-Auth tag) found")
|
|
|
|
def test_dpp_proto_pkex_cr_resp_no_wrapped_data(dev, apdev):
|
|
"""DPP protocol testing - no Wrapped Data in PKEX Commit-Reveal Response"""
|
|
run_dpp_proto_pkex_resp_missing(dev, 43, "Missing or invalid required Wrapped Data attribute")
|
|
|
|
def test_dpp_proto_pkex_exchange_req_invalid_encrypted_key(dev, apdev):
|
|
"""DPP protocol testing - invalid Encrypted Key in PKEX Exchange Request"""
|
|
run_dpp_proto_pkex_req_missing(dev, 44,
|
|
"Invalid Encrypted Key value")
|
|
|
|
def test_dpp_proto_pkex_exchange_resp_invalid_encrypted_key(dev, apdev):
|
|
"""DPP protocol testing - invalid Encrypted Key in PKEX Exchange Response"""
|
|
run_dpp_proto_pkex_resp_missing(dev, 45,
|
|
"Invalid Encrypted Key value")
|
|
|
|
def test_dpp_proto_pkex_exchange_resp_invalid_status(dev, apdev):
|
|
"""DPP protocol testing - invalid Status in PKEX Exchange Response"""
|
|
run_dpp_proto_pkex_resp_missing(dev, 46,
|
|
"PKEX failed (peer indicated failure)")
|
|
|
|
def test_dpp_proto_pkex_cr_req_invalid_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - invalid Bootstrap Key in PKEX Commit-Reveal Request"""
|
|
run_dpp_proto_pkex_req_missing(dev, 47,
|
|
"Peer bootstrapping key is invalid")
|
|
|
|
def test_dpp_proto_pkex_cr_resp_invalid_bootstrap_key(dev, apdev):
|
|
"""DPP protocol testing - invalid Bootstrap Key in PKEX Commit-Reveal Response"""
|
|
run_dpp_proto_pkex_resp_missing(dev, 48,
|
|
"Peer bootstrapping key is invalid")
|
|
|
|
def test_dpp_proto_pkex_cr_req_i_auth_tag_mismatch(dev, apdev):
|
|
"""DPP protocol testing - I-auth tag mismatch in PKEX Commit-Reveal Request"""
|
|
run_dpp_proto_pkex_req_missing(dev, 49, "No valid u (I-Auth tag) found")
|
|
|
|
def test_dpp_proto_pkex_cr_resp_r_auth_tag_mismatch(dev, apdev):
|
|
"""DPP protocol testing - R-auth tag mismatch in PKEX Commit-Reveal Response"""
|
|
run_dpp_proto_pkex_resp_missing(dev, 50, "No valid v (R-Auth tag) found")
|
|
|
|
def test_dpp_proto_stop_at_pkex_exchange_resp(dev, apdev):
|
|
"""DPP protocol testing - stop when receiving PKEX Exchange Response"""
|
|
run_dpp_proto_init_pkex(dev, 1, 84)
|
|
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("PKEX Exchange Req TX not seen")
|
|
|
|
ev = dev[0].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("PKEX Exchange Resp not seen")
|
|
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected PKEX CR Req TX")
|
|
|
|
def test_dpp_proto_stop_at_pkex_cr_req(dev, apdev):
|
|
"""DPP protocol testing - stop when receiving PKEX CR Request"""
|
|
run_dpp_proto_init_pkex(dev, 0, 85)
|
|
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("PKEX Exchange Req TX not seen")
|
|
|
|
ev = dev[0].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("PKEX Exchange Resp not seen")
|
|
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("PKEX CR Req TX not seen")
|
|
|
|
ev = dev[0].wait_event(["DPP-TX "], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected PKEX CR Resp TX")
|
|
|
|
def test_dpp_proto_stop_at_pkex_cr_resp(dev, apdev):
|
|
"""DPP protocol testing - stop when receiving PKEX CR Response"""
|
|
run_dpp_proto_init_pkex(dev, 1, 86)
|
|
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("PKEX Exchange Req TX not seen")
|
|
|
|
ev = dev[0].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("PKEX Exchange Resp not seen")
|
|
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("PKEX CR Req TX not seen")
|
|
|
|
ev = dev[0].wait_event(["DPP-TX "], timeout=5)
|
|
if ev is None:
|
|
raise Exception("PKEX CR Resp TX not seen")
|
|
|
|
ev = dev[1].wait_event(["DPP-TX "], timeout=0.1)
|
|
if ev is not None:
|
|
raise Exception("Unexpected Auth Req TX")
|
|
|
|
def test_dpp_proto_network_introduction(dev, apdev):
|
|
"""DPP protocol testing - network introduction"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
params = {"ssid": "dpp",
|
|
"wpa": "2",
|
|
"wpa_key_mgmt": "DPP",
|
|
"ieee80211w": "2",
|
|
"rsn_pairwise": "CCMP",
|
|
"dpp_connector": params1_ap_connector,
|
|
"dpp_csign": params1_csign,
|
|
"dpp_netaccesskey": params1_ap_netaccesskey}
|
|
try:
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
except:
|
|
raise HwsimSkip("DPP not supported")
|
|
|
|
for test in [60, 61, 80, 82]:
|
|
dev[0].set("dpp_test", str(test))
|
|
dev[0].connect("dpp", key_mgmt="DPP", scan_freq="2412", ieee80211w="2",
|
|
dpp_csign=params1_csign,
|
|
dpp_connector=params1_sta_connector,
|
|
dpp_netaccesskey=params1_sta_netaccesskey,
|
|
wait_connect=False)
|
|
|
|
ev = dev[0].wait_event(["DPP-TX "], timeout=10)
|
|
if ev is None or "type=5" not in ev:
|
|
raise Exception("Peer Discovery Request TX not reported")
|
|
ev = dev[0].wait_event(["DPP-TX-STATUS"], timeout=2)
|
|
if ev is None or "result=SUCCESS" not in ev:
|
|
raise Exception("Peer Discovery Request TX status not reported")
|
|
|
|
ev = hapd.wait_event(["DPP-RX"], timeout=10)
|
|
if ev is None or "type=5" not in ev:
|
|
raise Exception("Peer Discovery Request RX not reported")
|
|
|
|
if test == 80:
|
|
ev = dev[0].wait_event(["DPP-INTRO"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("DPP-INTRO not reported for test 80")
|
|
if "status=7" not in ev:
|
|
raise Exception("Unexpected result in test 80: " + ev)
|
|
|
|
dev[0].request("REMOVE_NETWORK all")
|
|
dev[0].dump_monitor()
|
|
hapd.dump_monitor()
|
|
dev[0].set("dpp_test", "0")
|
|
|
|
for test in [62, 63, 64, 77, 78, 79]:
|
|
hapd.set("dpp_test", str(test))
|
|
dev[0].connect("dpp", key_mgmt="DPP", scan_freq="2412", ieee80211w="2",
|
|
dpp_csign=params1_csign,
|
|
dpp_connector=params1_sta_connector,
|
|
dpp_netaccesskey=params1_sta_netaccesskey,
|
|
wait_connect=False)
|
|
|
|
ev = dev[0].wait_event(["DPP-INTRO"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("Peer introduction result not reported (test %d)" % test)
|
|
if test == 77:
|
|
if "fail=transaction_id_mismatch" not in ev:
|
|
raise Exception("Connector validation failure not reported")
|
|
elif test == 78:
|
|
if "status=254" not in ev:
|
|
raise Exception("Invalid status value not reported")
|
|
elif test == 79:
|
|
if "fail=peer_connector_validation_failed" not in ev:
|
|
raise Exception("Connector validation failure not reported")
|
|
elif "status=" in ev:
|
|
raise Exception("Unexpected peer introduction result (test %d): " % test + ev)
|
|
|
|
dev[0].request("REMOVE_NETWORK all")
|
|
dev[0].dump_monitor()
|
|
hapd.dump_monitor()
|
|
hapd.set("dpp_test", "0")
|
|
|
|
dev[0].connect("dpp", key_mgmt="DPP", scan_freq="2412", ieee80211w="2",
|
|
dpp_csign=params1_csign, dpp_connector=params1_sta_connector,
|
|
dpp_netaccesskey=params1_sta_netaccesskey)
|
|
|
|
def test_dpp_qr_code_no_chan_list_unicast(dev, apdev):
|
|
"""DPP QR Code and no channel list (unicast)"""
|
|
run_dpp_qr_code_chan_list(dev, apdev, True, 2417, None)
|
|
|
|
def test_dpp_qr_code_chan_list_unicast(dev, apdev):
|
|
"""DPP QR Code and 2.4 GHz channels (unicast)"""
|
|
run_dpp_qr_code_chan_list(dev, apdev, True, 2417,
|
|
"81/1,81/2,81/3,81/4,81/5,81/6,81/7,81/8,81/9,81/10,81/11,81/12,81/13")
|
|
|
|
def test_dpp_qr_code_chan_list_unicast2(dev, apdev):
|
|
"""DPP QR Code and 2.4 GHz channels (unicast 2)"""
|
|
run_dpp_qr_code_chan_list(dev, apdev, True, 2417,
|
|
"81/1,2,3,4,5,6,7,8,9,10,11,12,13")
|
|
|
|
def test_dpp_qr_code_chan_list_no_peer_unicast(dev, apdev):
|
|
"""DPP QR Code and channel list and no peer (unicast)"""
|
|
run_dpp_qr_code_chan_list(dev, apdev, True, 2417, "81/1,81/6,81/11",
|
|
no_wait=True)
|
|
ev = dev[1].wait_event(["DPP-AUTH-INIT-FAILED"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("Initiation failure not reported")
|
|
|
|
def test_dpp_qr_code_no_chan_list_broadcast(dev, apdev):
|
|
"""DPP QR Code and no channel list (broadcast)"""
|
|
run_dpp_qr_code_chan_list(dev, apdev, False, 2412, None)
|
|
|
|
def test_dpp_qr_code_chan_list_broadcast(dev, apdev):
|
|
"""DPP QR Code and some 2.4 GHz channels (broadcast)"""
|
|
run_dpp_qr_code_chan_list(dev, apdev, False, 2412, "81/1,81/6,81/11",
|
|
timeout=10)
|
|
|
|
def run_dpp_qr_code_chan_list(dev, apdev, unicast, listen_freq, chanlist,
|
|
no_wait=False, timeout=5):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[1].set("dpp_init_max_tries", "3")
|
|
dev[1].set("dpp_init_retry_time", "100")
|
|
dev[1].set("dpp_resp_wait_time", "1000")
|
|
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan=chanlist, mac=unicast)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].dpp_listen(listen_freq)
|
|
dev[1].dpp_auth_init(uri=uri0)
|
|
if no_wait:
|
|
return
|
|
wait_auth_success(dev[0], dev[1], timeout=timeout, configurator=dev[1],
|
|
enrollee=dev[0], allow_enrollee_failure=True,
|
|
stop_responder=True)
|
|
|
|
def test_dpp_qr_code_chan_list_no_match(dev, apdev):
|
|
"""DPP QR Code and no matching supported channel"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="123/123")
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[1].dpp_auth_init(uri=uri0, expect_fail=True)
|
|
|
|
def test_dpp_pkex_alloc_fail(dev, apdev):
|
|
"""DPP/PKEX and memory allocation failures"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
tests = [(1, "=dpp_keygen_configurator"),
|
|
(1, "base64_gen_encode;dpp_keygen_configurator")]
|
|
for count, func in tests:
|
|
with alloc_fail(dev[1], count, func):
|
|
cmd = "DPP_CONFIGURATOR_ADD"
|
|
res = dev[1].request(cmd)
|
|
if "FAIL" not in res:
|
|
raise Exception("Unexpected DPP_CONFIGURATOR_ADD success")
|
|
|
|
conf_id = dev[1].dpp_configurator_add()
|
|
|
|
id0 = None
|
|
id1 = None
|
|
|
|
# Local error cases on the Initiator
|
|
tests = [(1, "dpp_get_pubkey_point"),
|
|
(1, "dpp_alloc_msg;dpp_pkex_build_exchange_req"),
|
|
(1, "dpp_alloc_msg;dpp_pkex_build_commit_reveal_req"),
|
|
(1, "dpp_alloc_msg;dpp_auth_build_req"),
|
|
(1, "dpp_alloc_msg;dpp_auth_build_conf"),
|
|
(1, "dpp_bootstrap_key_hash"),
|
|
(1, "dpp_auth_init"),
|
|
(1, "dpp_alloc_auth"),
|
|
(1, "=dpp_auth_resp_rx"),
|
|
(1, "dpp_build_conf_start"),
|
|
(1, "dpp_build_conf_obj_dpp"),
|
|
(2, "dpp_build_conf_obj_dpp"),
|
|
(3, "dpp_build_conf_obj_dpp"),
|
|
(4, "dpp_build_conf_obj_dpp"),
|
|
(5, "dpp_build_conf_obj_dpp"),
|
|
(6, "dpp_build_conf_obj_dpp"),
|
|
(7, "dpp_build_conf_obj_dpp"),
|
|
(8, "dpp_build_conf_obj_dpp"),
|
|
(1, "dpp_conf_req_rx"),
|
|
(2, "dpp_conf_req_rx"),
|
|
(3, "dpp_conf_req_rx"),
|
|
(4, "dpp_conf_req_rx"),
|
|
(5, "dpp_conf_req_rx"),
|
|
(6, "dpp_conf_req_rx"),
|
|
(7, "dpp_conf_req_rx"),
|
|
(1, "dpp_pkex_init"),
|
|
(2, "dpp_pkex_init"),
|
|
(3, "dpp_pkex_init"),
|
|
(1, "dpp_pkex_derive_z"),
|
|
(1, "=dpp_pkex_rx_commit_reveal_resp"),
|
|
(1, "dpp_get_pubkey_point;dpp_build_jwk"),
|
|
(2, "dpp_get_pubkey_point;dpp_build_jwk"),
|
|
(1, "dpp_get_pubkey_point;dpp_auth_init")]
|
|
for count, func in tests:
|
|
dev[0].request("DPP_STOP_LISTEN")
|
|
dev[1].request("DPP_STOP_LISTEN")
|
|
dev[0].dump_monitor()
|
|
dev[1].dump_monitor()
|
|
id0 = dev[0].dpp_pkex_resp(2437, identifier="test", code="secret",
|
|
use_id=id0)
|
|
|
|
with alloc_fail(dev[1], count, func):
|
|
id1 = dev[1].dpp_pkex_init(identifier="test", code="secret",
|
|
use_id=id1,
|
|
extra="conf=sta-dpp configurator=%d" % conf_id,
|
|
allow_fail=True)
|
|
wait_fail_trigger(dev[1], "GET_ALLOC_FAIL", max_iter=100)
|
|
ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=0.01)
|
|
if ev:
|
|
dev[0].request("DPP_STOP_LISTEN")
|
|
dev[0].wait_event(["GAS-QUERY-DONE"], timeout=3)
|
|
|
|
# Local error cases on the Responder
|
|
tests = [(1, "dpp_get_pubkey_point"),
|
|
(1, "dpp_alloc_msg;dpp_pkex_build_exchange_resp"),
|
|
(1, "dpp_alloc_msg;dpp_pkex_build_commit_reveal_resp"),
|
|
(1, "dpp_alloc_msg;dpp_auth_build_resp"),
|
|
(1, "dpp_get_pubkey_point;dpp_auth_build_resp_ok"),
|
|
(1, "dpp_alloc_auth"),
|
|
(1, "=dpp_auth_req_rx"),
|
|
(1, "=dpp_auth_conf_rx"),
|
|
(1, "json_parse;dpp_parse_jws_prot_hdr"),
|
|
(1, "json_get_member_base64url;dpp_parse_jws_prot_hdr"),
|
|
(1, "json_get_member_base64url;dpp_parse_jwk"),
|
|
(2, "json_get_member_base64url;dpp_parse_jwk"),
|
|
(1, "json_parse;dpp_parse_connector"),
|
|
(1, "dpp_parse_jwk;dpp_parse_connector"),
|
|
(1, "dpp_parse_jwk;dpp_parse_cred_dpp"),
|
|
(1, "dpp_get_pubkey_point;dpp_check_pubkey_match"),
|
|
(1, "base64_gen_decode;dpp_process_signed_connector"),
|
|
(1, "dpp_parse_jws_prot_hdr;dpp_process_signed_connector"),
|
|
(2, "base64_gen_decode;dpp_process_signed_connector"),
|
|
(3, "base64_gen_decode;dpp_process_signed_connector"),
|
|
(4, "base64_gen_decode;dpp_process_signed_connector"),
|
|
(1, "json_parse;dpp_parse_conf_obj"),
|
|
(1, "dpp_conf_resp_rx"),
|
|
(1, "=dpp_pkex_derive_z"),
|
|
(1, "=dpp_pkex_rx_exchange_req"),
|
|
(2, "=dpp_pkex_rx_exchange_req"),
|
|
(3, "=dpp_pkex_rx_exchange_req"),
|
|
(1, "=dpp_pkex_rx_commit_reveal_req"),
|
|
(1, "dpp_get_pubkey_point;dpp_pkex_rx_commit_reveal_req"),
|
|
(1, "dpp_bootstrap_key_hash")]
|
|
for count, func in tests:
|
|
dev[0].request("DPP_STOP_LISTEN")
|
|
dev[1].request("DPP_STOP_LISTEN")
|
|
dev[0].dump_monitor()
|
|
dev[1].dump_monitor()
|
|
id0 = dev[0].dpp_pkex_resp(2437, identifier="test", code="secret",
|
|
use_id=id0)
|
|
|
|
with alloc_fail(dev[0], count, func):
|
|
id1 = dev[1].dpp_pkex_init(identifier="test", code="secret",
|
|
use_id=id1,
|
|
extra="conf=sta-dpp configurator=%d" % conf_id)
|
|
wait_fail_trigger(dev[0], "GET_ALLOC_FAIL", max_iter=100)
|
|
ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=0.01)
|
|
if ev:
|
|
dev[0].request("DPP_STOP_LISTEN")
|
|
dev[0].wait_event(["GAS-QUERY-DONE"], timeout=3)
|
|
|
|
def test_dpp_pkex_test_fail(dev, apdev):
|
|
"""DPP/PKEX and local failures"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
tests = [(1, "dpp_keygen_configurator")]
|
|
for count, func in tests:
|
|
with fail_test(dev[1], count, func):
|
|
cmd = "DPP_CONFIGURATOR_ADD"
|
|
res = dev[1].request(cmd)
|
|
if "FAIL" not in res:
|
|
raise Exception("Unexpected DPP_CONFIGURATOR_ADD success")
|
|
|
|
tests = [(1, "dpp_keygen")]
|
|
for count, func in tests:
|
|
with fail_test(dev[1], count, func):
|
|
cmd = "DPP_BOOTSTRAP_GEN type=pkex"
|
|
res = dev[1].request(cmd)
|
|
if "FAIL" not in res:
|
|
raise Exception("Unexpected DPP_BOOTSTRAP_GEN success")
|
|
|
|
conf_id = dev[1].dpp_configurator_add()
|
|
|
|
id0 = None
|
|
id1 = None
|
|
|
|
# Local error cases on the Initiator
|
|
tests = [(1, "aes_siv_encrypt;dpp_auth_build_req"),
|
|
(1, "os_get_random;dpp_auth_init"),
|
|
(1, "dpp_derive_k1;dpp_auth_init"),
|
|
(1, "dpp_hkdf_expand;dpp_derive_k1;dpp_auth_init"),
|
|
(1, "dpp_gen_i_auth;dpp_auth_build_conf"),
|
|
(1, "aes_siv_encrypt;dpp_auth_build_conf"),
|
|
(1, "dpp_derive_k2;dpp_auth_resp_rx"),
|
|
(1, "dpp_hkdf_expand;dpp_derive_k2;dpp_auth_resp_rx"),
|
|
(1, "dpp_derive_ke;dpp_auth_resp_rx"),
|
|
(1, "dpp_hkdf_expand;dpp_derive_ke;dpp_auth_resp_rx"),
|
|
(1, "dpp_gen_r_auth;dpp_auth_resp_rx"),
|
|
(1, "aes_siv_encrypt;dpp_build_conf_resp"),
|
|
(1, "dpp_pkex_derive_Qi;dpp_pkex_build_exchange_req"),
|
|
(1, "aes_siv_encrypt;dpp_pkex_build_commit_reveal_req"),
|
|
(1, "hmac_sha256_vector;dpp_pkex_rx_exchange_resp"),
|
|
(1, "aes_siv_decrypt;dpp_pkex_rx_commit_reveal_resp"),
|
|
(1, "hmac_sha256_vector;dpp_pkex_rx_commit_reveal_resp"),
|
|
(1, "dpp_bootstrap_key_hash")]
|
|
for count, func in tests:
|
|
dev[0].request("DPP_STOP_LISTEN")
|
|
dev[1].request("DPP_STOP_LISTEN")
|
|
dev[0].dump_monitor()
|
|
dev[1].dump_monitor()
|
|
id0 = dev[0].dpp_pkex_resp(2437, identifier="test", code="secret",
|
|
use_id=id0)
|
|
|
|
with fail_test(dev[1], count, func):
|
|
id1 = dev[1].dpp_pkex_init(identifier="test", code="secret",
|
|
use_id=id1,
|
|
extra="conf=sta-dpp configurator=%d" % conf_id,
|
|
allow_fail=True)
|
|
wait_fail_trigger(dev[1], "GET_FAIL", max_iter=100)
|
|
ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=0.01)
|
|
if ev:
|
|
dev[0].request("DPP_STOP_LISTEN")
|
|
dev[0].wait_event(["GAS-QUERY-DONE"], timeout=3)
|
|
|
|
# Local error cases on the Responder
|
|
tests = [(1, "aes_siv_encrypt;dpp_auth_build_resp"),
|
|
(1, "aes_siv_encrypt;dpp_auth_build_resp;dpp_auth_build_resp_ok"),
|
|
(1, "os_get_random;dpp_build_conf_req"),
|
|
(1, "aes_siv_encrypt;dpp_build_conf_req"),
|
|
(1, "os_get_random;dpp_auth_build_resp_ok"),
|
|
(1, "dpp_derive_k2;dpp_auth_build_resp_ok"),
|
|
(1, "dpp_derive_ke;dpp_auth_build_resp_ok"),
|
|
(1, "dpp_gen_r_auth;dpp_auth_build_resp_ok"),
|
|
(1, "aes_siv_encrypt;dpp_auth_build_resp_ok"),
|
|
(1, "dpp_derive_k1;dpp_auth_req_rx"),
|
|
(1, "aes_siv_decrypt;dpp_auth_req_rx"),
|
|
(1, "aes_siv_decrypt;dpp_auth_conf_rx"),
|
|
(1, "dpp_gen_i_auth;dpp_auth_conf_rx"),
|
|
(1, "dpp_check_pubkey_match"),
|
|
(1, "aes_siv_decrypt;dpp_conf_resp_rx"),
|
|
(1, "hmac_sha256_kdf;dpp_pkex_derive_z"),
|
|
(1, "dpp_pkex_derive_Qi;dpp_pkex_rx_exchange_req"),
|
|
(1, "dpp_pkex_derive_Qr;dpp_pkex_rx_exchange_req"),
|
|
(1, "aes_siv_encrypt;dpp_pkex_build_commit_reveal_resp"),
|
|
(1, "aes_siv_decrypt;dpp_pkex_rx_commit_reveal_req"),
|
|
(1, "hmac_sha256_vector;dpp_pkex_rx_commit_reveal_req"),
|
|
(2, "hmac_sha256_vector;dpp_pkex_rx_commit_reveal_req")]
|
|
for count, func in tests:
|
|
dev[0].request("DPP_STOP_LISTEN")
|
|
dev[1].request("DPP_STOP_LISTEN")
|
|
dev[0].dump_monitor()
|
|
dev[1].dump_monitor()
|
|
id0 = dev[0].dpp_pkex_resp(2437, identifier="test", code="secret",
|
|
use_id=id0)
|
|
|
|
with fail_test(dev[0], count, func):
|
|
id1 = dev[1].dpp_pkex_init(identifier="test", code="secret",
|
|
use_id=id1,
|
|
extra="conf=sta-dpp configurator=%d" % conf_id)
|
|
wait_fail_trigger(dev[0], "GET_FAIL", max_iter=100)
|
|
ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=0.01)
|
|
if ev:
|
|
dev[0].request("DPP_STOP_LISTEN")
|
|
dev[0].wait_event(["GAS-QUERY-DONE"], timeout=3)
|
|
|
|
def test_dpp_keygen_configurator_error(dev, apdev):
|
|
"""DPP Configurator keygen error case"""
|
|
check_dpp_capab(dev[0])
|
|
if "FAIL" not in dev[0].request("DPP_CONFIGURATOR_ADD curve=unknown"):
|
|
raise Exception("Unexpected success of invalid DPP_CONFIGURATOR_ADD")
|
|
|
|
def rx_process_frame(dev):
|
|
msg = dev.mgmt_rx()
|
|
if msg is None:
|
|
raise Exception("No management frame RX reported")
|
|
if "OK" not in dev.request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(
|
|
msg['freq'], msg['datarate'], msg['ssi_signal'], binascii.hexlify(msg['frame']).decode())):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
return msg
|
|
|
|
def wait_auth_success(responder, initiator, configurator=None, enrollee=None,
|
|
allow_enrollee_failure=False,
|
|
allow_configurator_failure=False,
|
|
require_configurator_failure=False,
|
|
timeout=5, stop_responder=False, stop_initiator=False):
|
|
res = {}
|
|
ev = responder.wait_event(["DPP-AUTH-SUCCESS", "DPP-FAIL"], timeout=timeout)
|
|
if ev is None or "DPP-AUTH-SUCCESS" not in ev:
|
|
raise Exception("DPP authentication did not succeed (Responder)")
|
|
ev = initiator.wait_event(["DPP-AUTH-SUCCESS", "DPP-FAIL"], timeout=5)
|
|
if ev is None or "DPP-AUTH-SUCCESS" not in ev:
|
|
raise Exception("DPP authentication did not succeed (Initiator)")
|
|
if configurator:
|
|
ev = configurator.wait_event(["DPP-CONF-SENT",
|
|
"DPP-CONF-FAILED"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP configuration not completed (Configurator)")
|
|
if "DPP-CONF-FAILED" in ev and not allow_configurator_failure:
|
|
raise Exception("DPP configuration did not succeed (Configurator)")
|
|
if "DPP-CONF-SENT" in ev and require_configurator_failure:
|
|
raise Exception("DPP configuration succeeded (Configurator)")
|
|
if "DPP-CONF-SENT" in ev and "wait_conn_status=1" in ev:
|
|
res['wait_conn_status'] = True
|
|
if enrollee:
|
|
ev = enrollee.wait_event(["DPP-CONF-RECEIVED",
|
|
"DPP-CONF-FAILED"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP configuration not completed (Enrollee)")
|
|
if "DPP-CONF-FAILED" in ev and not allow_enrollee_failure:
|
|
raise Exception("DPP configuration did not succeed (Enrollee)")
|
|
if stop_responder:
|
|
responder.request("DPP_STOP_LISTEN")
|
|
if stop_initiator:
|
|
initiator.request("DPP_STOP_LISTEN")
|
|
return res
|
|
|
|
def wait_conf_completion(configurator, enrollee):
|
|
ev = configurator.wait_event(["DPP-CONF-SENT"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP configuration not completed (Configurator)")
|
|
ev = enrollee.wait_event(["DPP-CONF-RECEIVED", "DPP-CONF-FAILED"],
|
|
timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP configuration not completed (Enrollee)")
|
|
|
|
def start_dpp(dev):
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' '
|
|
dev[0].set("dpp_config_obj_override", conf)
|
|
|
|
dev[0].set("ext_mgmt_frame_handling", "1")
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0, role="enrollee")
|
|
|
|
def test_dpp_gas_timeout_handling(dev, apdev):
|
|
"""DPP and GAS timeout handling"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
start_dpp(dev)
|
|
|
|
# DPP Authentication Request
|
|
rx_process_frame(dev[0])
|
|
|
|
# DPP Authentication Confirmation
|
|
rx_process_frame(dev[0])
|
|
|
|
wait_auth_success(dev[0], dev[1])
|
|
|
|
# DPP Configuration Request (GAS Initial Request frame)
|
|
rx_process_frame(dev[0])
|
|
|
|
# DPP Configuration Request (GAS Comeback Request frame)
|
|
rx_process_frame(dev[0])
|
|
|
|
# Wait for GAS timeout
|
|
ev = dev[1].wait_event(["DPP-CONF-FAILED"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP configuration not completed (Enrollee)")
|
|
|
|
def test_dpp_gas_comeback_after_failure(dev, apdev):
|
|
"""DPP and GAS comeback after failure"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
start_dpp(dev)
|
|
|
|
# DPP Authentication Request
|
|
rx_process_frame(dev[0])
|
|
|
|
# DPP Authentication Confirmation
|
|
rx_process_frame(dev[0])
|
|
|
|
wait_auth_success(dev[0], dev[1])
|
|
|
|
# DPP Configuration Request (GAS Initial Request frame)
|
|
rx_process_frame(dev[0])
|
|
|
|
# DPP Configuration Request (GAS Comeback Request frame)
|
|
msg = dev[0].mgmt_rx()
|
|
frame = binascii.hexlify(msg['frame']).decode()
|
|
with alloc_fail(dev[0], 1, "gas_build_comeback_resp;gas_server_handle_rx_comeback_req"):
|
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], frame)):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
|
|
# Try the same frame again - this is expected to fail since the response has
|
|
# already been freed.
|
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], frame)):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
|
|
# DPP Configuration Request (GAS Comeback Request frame retry)
|
|
msg = dev[0].mgmt_rx()
|
|
|
|
def test_dpp_gas(dev, apdev):
|
|
"""DPP and GAS protocol testing"""
|
|
ver0 = check_dpp_capab(dev[0])
|
|
ver1 = check_dpp_capab(dev[1])
|
|
start_dpp(dev)
|
|
|
|
# DPP Authentication Request
|
|
rx_process_frame(dev[0])
|
|
|
|
# DPP Authentication Confirmation
|
|
rx_process_frame(dev[0])
|
|
|
|
wait_auth_success(dev[0], dev[1])
|
|
|
|
# DPP Configuration Request (GAS Initial Request frame)
|
|
msg = dev[0].mgmt_rx()
|
|
|
|
# Protected Dual of GAS Initial Request frame (dropped by GAS server)
|
|
if msg == None:
|
|
raise Exception("MGMT_RX_PROCESS failed. <Please retry>")
|
|
frame = binascii.hexlify(msg['frame'])
|
|
frame = frame[0:48] + b"09" + frame[50:]
|
|
frame = frame.decode()
|
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], frame)):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
|
|
with alloc_fail(dev[0], 1, "gas_server_send_resp"):
|
|
frame = binascii.hexlify(msg['frame']).decode()
|
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], frame)):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
|
|
|
|
with alloc_fail(dev[0], 1, "gas_build_initial_resp;gas_server_send_resp"):
|
|
frame = binascii.hexlify(msg['frame']).decode()
|
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], frame)):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
|
|
|
|
# Add extra data after Query Request field to trigger
|
|
# "GAS: Ignored extra data after Query Request field"
|
|
frame = binascii.hexlify(msg['frame']).decode() + "00"
|
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], frame)):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
|
|
# DPP Configuration Request (GAS Comeback Request frame)
|
|
rx_process_frame(dev[0])
|
|
|
|
# DPP Configuration Request (GAS Comeback Request frame)
|
|
rx_process_frame(dev[0])
|
|
|
|
# DPP Configuration Request (GAS Comeback Request frame)
|
|
rx_process_frame(dev[0])
|
|
|
|
if ver0 >= 2 and ver1 >= 2:
|
|
# DPP Configuration Result
|
|
rx_process_frame(dev[0])
|
|
|
|
wait_conf_completion(dev[0], dev[1])
|
|
|
|
def test_dpp_truncated_attr(dev, apdev):
|
|
"""DPP and truncated attribute"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
start_dpp(dev)
|
|
|
|
# DPP Authentication Request
|
|
msg = dev[0].mgmt_rx()
|
|
frame = msg['frame']
|
|
|
|
# DPP: Truncated message - not enough room for the attribute - dropped
|
|
frame1 = binascii.hexlify(frame[0:36]).decode()
|
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], frame1)):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None or "ignore=invalid-attributes" not in ev:
|
|
raise Exception("Invalid attribute error not reported")
|
|
|
|
# DPP: Unexpected octets (3) after the last attribute
|
|
frame2 = binascii.hexlify(frame).decode() + "000000"
|
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], frame2)):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None or "ignore=invalid-attributes" not in ev:
|
|
raise Exception("Invalid attribute error not reported")
|
|
|
|
def test_dpp_bootstrap_key_autogen_issues(dev, apdev):
|
|
"""DPP bootstrap key autogen issues"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
logger.info("dev1 scans QR Code")
|
|
id1 = dev[1].dpp_qr_code(uri0)
|
|
|
|
logger.info("dev1 initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412)
|
|
with alloc_fail(dev[1], 1, "dpp_autogen_bootstrap_key"):
|
|
dev[1].dpp_auth_init(peer=id1, expect_fail=True)
|
|
with alloc_fail(dev[1], 1, "dpp_gen_uri;dpp_autogen_bootstrap_key"):
|
|
dev[1].dpp_auth_init(peer=id1, expect_fail=True)
|
|
with fail_test(dev[1], 1, "dpp_keygen;dpp_autogen_bootstrap_key"):
|
|
dev[1].dpp_auth_init(peer=id1, expect_fail=True)
|
|
dev[0].request("DPP_STOP_LISTEN")
|
|
|
|
def test_dpp_auth_resp_status_failure(dev, apdev):
|
|
"""DPP and Auth Resp(status) build failure"""
|
|
with alloc_fail(dev[0], 1, "dpp_auth_build_resp"):
|
|
run_dpp_proto_auth_resp_missing(dev, 99999, None,
|
|
incompatible_roles=True)
|
|
|
|
def test_dpp_auth_resp_aes_siv_issue(dev, apdev):
|
|
"""DPP Auth Resp AES-SIV issue"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
logger.info("dev0 displays QR Code")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
logger.info("dev1 scans QR Code and initiates DPP Authentication")
|
|
dev[0].dpp_listen(2412)
|
|
with fail_test(dev[1], 1, "aes_siv_decrypt;dpp_auth_resp_rx"):
|
|
dev[1].dpp_auth_init(uri=uri0)
|
|
wait_dpp_fail(dev[1], "AES-SIV decryption failed")
|
|
dev[0].request("DPP_STOP_LISTEN")
|
|
|
|
def test_dpp_invalid_legacy_params(dev, apdev):
|
|
"""DPP invalid legacy parameters"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
# No pass/psk
|
|
dev[1].dpp_auth_init(uri=uri0, conf="sta-psk", ssid="dpp-legacy",
|
|
expect_fail=True)
|
|
|
|
def test_dpp_invalid_legacy_params2(dev, apdev):
|
|
"""DPP invalid legacy parameters 2"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].set("dpp_configurator_params",
|
|
" conf=sta-psk ssid=%s" % (binascii.hexlify(b"dpp-legacy").decode()))
|
|
dev[0].dpp_listen(2412, role="configurator")
|
|
dev[1].dpp_auth_init(uri=uri0, role="enrollee")
|
|
# No pass/psk
|
|
ev = dev[0].wait_event(["DPP: Failed to set configurator parameters"],
|
|
timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP configuration failure not reported")
|
|
|
|
def test_dpp_legacy_params_failure(dev, apdev):
|
|
"""DPP legacy parameters local failure"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].dpp_listen(2412)
|
|
with alloc_fail(dev[1], 1, "dpp_build_conf_obj_legacy"):
|
|
dev[1].dpp_auth_init(uri=uri0, conf="sta-psk", passphrase="passphrase",
|
|
ssid="dpp-legacy")
|
|
ev = dev[0].wait_event(["DPP-CONF-FAILED"], timeout=5)
|
|
if ev is None:
|
|
raise Exception("DPP configuration failure not reported")
|
|
|
|
def test_dpp_invalid_configurator_key(dev, apdev):
|
|
"""DPP invalid configurator key"""
|
|
check_dpp_capab(dev[0])
|
|
|
|
if "FAIL" not in dev[0].request("DPP_CONFIGURATOR_ADD key=aa"):
|
|
raise Exception("Invalid key accepted")
|
|
|
|
with alloc_fail(dev[0], 1, "dpp_keygen_configurator"):
|
|
if "FAIL" not in dev[0].request("DPP_CONFIGURATOR_ADD key=" + dpp_key_p256):
|
|
raise Exception("Error not reported")
|
|
|
|
with alloc_fail(dev[0], 1, "dpp_get_pubkey_point;dpp_keygen_configurator"):
|
|
if "FAIL" not in dev[0].request("DPP_CONFIGURATOR_ADD key=" + dpp_key_p256):
|
|
raise Exception("Error not reported")
|
|
|
|
with alloc_fail(dev[0], 1, "base64_gen_encode;dpp_keygen_configurator"):
|
|
if "FAIL" not in dev[0].request("DPP_CONFIGURATOR_ADD key=" + dpp_key_p256):
|
|
raise Exception("Error not reported")
|
|
|
|
with fail_test(dev[0], 1, "dpp_keygen_configurator"):
|
|
if "FAIL" not in dev[0].request("DPP_CONFIGURATOR_ADD key=" + dpp_key_p256):
|
|
raise Exception("Error not reported")
|
|
|
|
def test_dpp_own_config_sign_fail(dev, apdev):
|
|
"""DPP own config signing failure"""
|
|
check_dpp_capab(dev[0])
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
tests = ["",
|
|
" ",
|
|
" conf=sta-dpp",
|
|
" configurator=%d" % conf_id,
|
|
" conf=sta-dpp configurator=%d curve=unsupported" % conf_id]
|
|
for t in tests:
|
|
if "FAIL" not in dev[0].request("DPP_CONFIGURATOR_SIGN " + t):
|
|
raise Exception("Invalid command accepted: " + t)
|
|
|
|
def test_dpp_peer_intro_failures(dev, apdev):
|
|
"""DPP peer introduction failures"""
|
|
try:
|
|
run_dpp_peer_intro_failures(dev, apdev)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def run_dpp_peer_intro_failures(dev, apdev):
|
|
check_dpp_capab(dev[0])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"})
|
|
check_dpp_capab(hapd)
|
|
|
|
conf_id = hapd.dpp_configurator_add(key=dpp_key_p256)
|
|
csign = hapd.request("DPP_CONFIGURATOR_GET_KEY %d" % conf_id)
|
|
if "FAIL" in csign or len(csign) == 0:
|
|
raise Exception("DPP_CONFIGURATOR_GET_KEY failed")
|
|
|
|
conf_id2 = dev[0].dpp_configurator_add(key=csign)
|
|
csign2 = dev[0].request("DPP_CONFIGURATOR_GET_KEY %d" % conf_id2)
|
|
|
|
if csign != csign2:
|
|
raise Exception("Unexpected difference in configurator key")
|
|
|
|
cmd = "DPP_CONFIGURATOR_SIGN conf=ap-dpp configurator=%d" % conf_id
|
|
res = hapd.request(cmd)
|
|
if "FAIL" in res:
|
|
raise Exception("Failed to generate own configuration")
|
|
update_hapd_config(hapd)
|
|
|
|
dev[0].set("dpp_config_processing", "1")
|
|
cmd = "DPP_CONFIGURATOR_SIGN conf=sta-dpp configurator=%d" % conf_id
|
|
res = dev[0].request(cmd)
|
|
if "FAIL" in res:
|
|
raise Exception("Failed to generate own configuration")
|
|
ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("DPP network profile not generated")
|
|
id = ev.split(' ')[1]
|
|
dev[0].select_network(id, freq=2412)
|
|
dev[0].wait_connected()
|
|
dev[0].request("DISCONNECT")
|
|
dev[0].wait_disconnected()
|
|
dev[0].dump_monitor()
|
|
|
|
tests = ["eyJ0eXAiOiJkcHBDb24iLCJraWQiOiIwTlNSNTlxRTc0alFfZTFLVGVPV1lYY1pTWnFUaDdNXzU0aHJPcFRpaFJnIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOltdLCJuZXRBY2Nlc3NLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiJiVmFMRGlBT09OQmFjcVFVN1pYamFBVEtEMVhhbDVlUExqOUZFZUl3VkN3IiwieSI6Il95c25JR1hTYjBvNEsyMWg0anZmSkZxMHdVNnlPNWp1VUFPd3FuM0dHVHMifX0.WgzZBOJaisWBRxvtXPbVYPXU7OIZxs6sZD-cPOLmJVTIYZKdMkSOMvP5b6si_j61FIrjhm43tmGq1P6cpoxB_g",
|
|
"eyJ0eXAiOiJkcHBDb24iLCJraWQiOiIwTlNSNTlxRTc0alFfZTFLVGVPV1lYY1pTWnFUaDdNXzU0aHJPcFRpaFJnIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7fV0sIm5ldEFjY2Vzc0tleSI6eyJrdHkiOiJFQyIsImNydiI6IlAtMjU2IiwieCI6IkJhY3BWSDNpNDBrZklNS0RHa1FFRzhCODBCaEk4cEFmTWpLbzM5NlFZT2ciLCJ5IjoiMjBDYjhDNjRsSjFzQzV2NXlKMnBFZXRRempxMjI4YVV2cHMxNmQ0M3EwQSJ9fQ.dG2y8VvZQJ5hfob8E5F2FAeR7Nd700qstYkxDgA2QfARaNMZ0_SfKfoG-yKXsIZNM-TvGBfACgfhagG9Oaw_Xw",
|
|
"eyJ0eXAiOiJkcHBDb24iLCJraWQiOiIwTlNSNTlxRTc0alFfZTFLVGVPV1lYY1pTWnFUaDdNXzU0aHJPcFRpaFJnIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIn1dLCJuZXRBY2Nlc3NLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiJkc2VmcmJWWlhad0RMWHRpLWlObDBBYkFIOXpqeFFKd0R1SUd5NzNuZGU0IiwieSI6IjZFQnExN3cwYW1fZlh1OUQ4UGxWYk9XZ2I3b19DcTUxWHlmSG8wcHJyeDQifX0.caBvdDUtXrhnS61-juVZ_2FQdprepv0yZjC04G4ERvLUpeX7cgu0Hp-A1aFDogP1PEFGpkaEdcAWRQnSSRiIKQ"]
|
|
for t in tests:
|
|
dev[0].set_network_quoted(id, "dpp_connector", t)
|
|
dev[0].select_network(id, freq=2412)
|
|
ev = dev[0].wait_event(["DPP-INTRO"], timeout=5)
|
|
if ev is None or "status=8" not in ev:
|
|
raise Exception("Introduction failure not reported")
|
|
dev[0].request("DISCONNECT")
|
|
dev[0].dump_monitor()
|
|
|
|
def test_dpp_peer_intro_local_failures(dev, apdev):
|
|
"""DPP peer introduction local failures"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
params = {"ssid": "dpp",
|
|
"wpa": "2",
|
|
"wpa_key_mgmt": "DPP",
|
|
"ieee80211w": "2",
|
|
"rsn_pairwise": "CCMP",
|
|
"dpp_connector": params1_ap_connector,
|
|
"dpp_csign": params1_csign,
|
|
"dpp_netaccesskey": params1_ap_netaccesskey}
|
|
try:
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
except:
|
|
raise HwsimSkip("DPP not supported")
|
|
|
|
tests = ["dpp_derive_pmk",
|
|
"dpp_hkdf_expand;dpp_derive_pmk",
|
|
"dpp_derive_pmkid"]
|
|
for func in tests:
|
|
with fail_test(dev[0], 1, func):
|
|
dev[0].connect("dpp", key_mgmt="DPP", scan_freq="2412",
|
|
ieee80211w="2",
|
|
dpp_csign=params1_csign,
|
|
dpp_connector=params1_sta_connector,
|
|
dpp_netaccesskey=params1_sta_netaccesskey,
|
|
wait_connect=False)
|
|
ev = dev[0].wait_event(["DPP-INTRO"], timeout=10)
|
|
if ev is None or "fail=peer_connector_validation_failed" not in ev:
|
|
raise Exception("Introduction failure not reported")
|
|
dev[0].request("REMOVE_NETWORK all")
|
|
dev[0].dump_monitor()
|
|
|
|
tests = [(1, "base64_gen_decode;dpp_peer_intro"),
|
|
(1, "json_parse;dpp_peer_intro"),
|
|
(50, "json_parse;dpp_peer_intro"),
|
|
(1, "=dpp_peer_intro"),
|
|
(1, "dpp_parse_jwk")]
|
|
for count, func in tests:
|
|
with alloc_fail(dev[0], count, func):
|
|
dev[0].connect("dpp", key_mgmt="DPP", scan_freq="2412",
|
|
ieee80211w="2",
|
|
dpp_csign=params1_csign,
|
|
dpp_connector=params1_sta_connector,
|
|
dpp_netaccesskey=params1_sta_netaccesskey,
|
|
wait_connect=False)
|
|
ev = dev[0].wait_event(["DPP-INTRO"], timeout=10)
|
|
if ev is None or "fail=peer_connector_validation_failed" not in ev:
|
|
raise Exception("Introduction failure not reported")
|
|
dev[0].request("REMOVE_NETWORK all")
|
|
dev[0].dump_monitor()
|
|
|
|
parts = params1_ap_connector.split('.')
|
|
for ap_connector in ['.'.join(parts[0:2]), '.'.join(parts[0:1])]:
|
|
hapd.set("dpp_connector", ap_connector)
|
|
dev[0].connect("dpp", key_mgmt="DPP", scan_freq="2412",
|
|
ieee80211w="2",
|
|
dpp_csign=params1_csign,
|
|
dpp_connector=params1_sta_connector,
|
|
dpp_netaccesskey=params1_sta_netaccesskey,
|
|
wait_connect=False)
|
|
ev = dev[0].wait_event(["DPP-TX-STATUS"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("No TX status reported")
|
|
dev[0].request("REMOVE_NETWORK all")
|
|
dev[0].dump_monitor()
|
|
|
|
hapd.set("dpp_netaccesskey", "00")
|
|
dev[0].connect("dpp", key_mgmt="DPP", scan_freq="2412",
|
|
ieee80211w="2",
|
|
dpp_csign=params1_csign,
|
|
dpp_connector=params1_sta_connector,
|
|
dpp_netaccesskey=params1_sta_netaccesskey,
|
|
wait_connect=False)
|
|
ev = dev[0].wait_event(["DPP-TX-STATUS"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("No TX status reported")
|
|
dev[0].request("REMOVE_NETWORK all")
|
|
dev[0].dump_monitor()
|
|
|
|
hapd.set("dpp_csign", "00")
|
|
dev[0].connect("dpp", key_mgmt="DPP", scan_freq="2412",
|
|
ieee80211w="2",
|
|
dpp_csign=params1_csign,
|
|
dpp_connector=params1_sta_connector,
|
|
dpp_netaccesskey=params1_sta_netaccesskey,
|
|
wait_connect=False)
|
|
ev = dev[0].wait_event(["DPP-TX-STATUS"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("No TX status reported")
|
|
dev[0].request("REMOVE_NETWORK all")
|
|
|
|
def run_dpp_configurator_id_unknown(dev):
|
|
check_dpp_capab(dev)
|
|
conf_id = dev.dpp_configurator_add()
|
|
if "FAIL" not in dev.request("DPP_CONFIGURATOR_GET_KEY %d" % (conf_id + 1)):
|
|
raise Exception("DPP_CONFIGURATOR_GET_KEY with incorrect id accepted")
|
|
|
|
cmd = "DPP_CONFIGURATOR_SIGN conf=sta-dpp configurator=%d" % (conf_id + 1)
|
|
if "FAIL" not in dev.request(cmd):
|
|
raise Exception("DPP_CONFIGURATOR_SIGN with incorrect id accepted")
|
|
|
|
def test_dpp_configurator_id_unknown(dev, apdev):
|
|
"""DPP and unknown configurator id"""
|
|
run_dpp_configurator_id_unknown(dev[0])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"})
|
|
run_dpp_configurator_id_unknown(hapd)
|
|
|
|
def run_dpp_bootstrap_gen_failures(dev):
|
|
check_dpp_capab(dev)
|
|
|
|
tests = ["type=unsupported",
|
|
"type=qrcode chan=-1",
|
|
"type=qrcode mac=a",
|
|
"type=qrcode key=qq",
|
|
"type=qrcode key=",
|
|
"type=qrcode info=abc\tdef"]
|
|
for t in tests:
|
|
if "FAIL" not in dev.request("DPP_BOOTSTRAP_GEN " + t):
|
|
raise Exception("Command accepted unexpectedly")
|
|
|
|
id = dev.dpp_bootstrap_gen()
|
|
uri = dev.request("DPP_BOOTSTRAP_GET_URI %d" % id)
|
|
if not uri.startswith("DPP:"):
|
|
raise Exception("Could not get URI")
|
|
if "FAIL" not in dev.request("DPP_BOOTSTRAP_GET_URI 0"):
|
|
raise Exception("Failure not reported")
|
|
info = dev.request("DPP_BOOTSTRAP_INFO %d" % id)
|
|
if not info.startswith("type=QRCODE"):
|
|
raise Exception("Could not get info")
|
|
if "FAIL" not in dev.request("DPP_BOOTSTRAP_REMOVE 0"):
|
|
raise Exception("Failure not reported")
|
|
if "FAIL" in dev.request("DPP_BOOTSTRAP_REMOVE *"):
|
|
raise Exception("Failed to remove bootstrap info")
|
|
if "FAIL" not in dev.request("DPP_BOOTSTRAP_GET_URI %d" % id):
|
|
raise Exception("Failure not reported")
|
|
if "FAIL" not in dev.request("DPP_BOOTSTRAP_INFO %d" % id):
|
|
raise Exception("Failure not reported")
|
|
|
|
func = "dpp_bootstrap_gen"
|
|
with alloc_fail(dev, 1, "=" + func):
|
|
if "FAIL" not in dev.request("DPP_BOOTSTRAP_GEN type=qrcode"):
|
|
raise Exception("Command accepted unexpectedly")
|
|
|
|
with alloc_fail(dev, 1, "dpp_gen_uri;dpp_bootstrap_gen"):
|
|
if "FAIL" not in dev.request("DPP_BOOTSTRAP_GEN type=qrcode"):
|
|
raise Exception("Command accepted unexpectedly")
|
|
|
|
with alloc_fail(dev, 1, "get_param"):
|
|
dev.request("DPP_BOOTSTRAP_GEN type=qrcode curve=foo")
|
|
|
|
def test_dpp_bootstrap_gen_failures(dev, apdev):
|
|
"""DPP_BOOTSTRAP_GEN/REMOVE/GET_URI/INFO error cases"""
|
|
run_dpp_bootstrap_gen_failures(dev[0])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"})
|
|
run_dpp_bootstrap_gen_failures(hapd)
|
|
|
|
def test_dpp_listen_continue(dev, apdev):
|
|
"""DPP and continue listen state"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
id = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id)
|
|
dev[0].dpp_listen(2412)
|
|
time.sleep(5.1)
|
|
dev[1].dpp_auth_init(uri=uri)
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0],
|
|
allow_enrollee_failure=True, stop_responder=True,
|
|
stop_initiator=True)
|
|
|
|
def test_dpp_network_addition_failure(dev, apdev):
|
|
"""DPP network addition failure"""
|
|
try:
|
|
run_dpp_network_addition_failure(dev, apdev)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def run_dpp_network_addition_failure(dev, apdev):
|
|
check_dpp_capab(dev[0])
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
dev[0].set("dpp_config_processing", "1")
|
|
cmd = "DPP_CONFIGURATOR_SIGN conf=sta-dpp configurator=%d" % conf_id
|
|
tests = [(1, "=wpas_dpp_add_network"),
|
|
(2, "=wpas_dpp_add_network"),
|
|
(3, "=wpas_dpp_add_network"),
|
|
(4, "=wpas_dpp_add_network"),
|
|
(1, "wpa_config_add_network;wpas_dpp_add_network")]
|
|
for count, func in tests:
|
|
with alloc_fail(dev[0], count, func):
|
|
res = dev[0].request(cmd)
|
|
if "OK" in res:
|
|
ev = dev[0].wait_event(["DPP-NET-ACCESS-KEY"], timeout=2)
|
|
if ev is None:
|
|
raise Exception("Config object not processed")
|
|
wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
|
|
dev[0].dump_monitor()
|
|
|
|
cmd = "DPP_CONFIGURATOR_SIGN conf=sta-psk pass=%s configurator=%d" % (binascii.hexlify(b"passphrase").decode(), conf_id)
|
|
tests = [(1, "wpa_config_set_quoted;wpas_dpp_add_network")]
|
|
for count, func in tests:
|
|
with alloc_fail(dev[0], count, func):
|
|
res = dev[0].request(cmd)
|
|
if "OK" in res:
|
|
ev = dev[0].wait_event(["DPP-NET-ACCESS-KEY"], timeout=2)
|
|
if ev is None:
|
|
raise Exception("Config object not processed")
|
|
wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
|
|
dev[0].dump_monitor()
|
|
|
|
def test_dpp_two_initiators(dev, apdev):
|
|
"""DPP and two initiators"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
check_dpp_capab(dev[2])
|
|
id = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id)
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri)
|
|
ev = dev[0].wait_event(["DPP-RX"], timeout=5)
|
|
if ev is None:
|
|
raise Exeption("No DPP Authentication Request seen")
|
|
dev[2].dpp_auth_init(uri=uri)
|
|
wait_dpp_fail(dev[0],
|
|
"DPP-FAIL Already in DPP authentication exchange - ignore new one")
|
|
|
|
ev = dev[0].wait_event(["DPP-CONF-FAILED"], timeout=2)
|
|
if ev is None:
|
|
raise Exception("DPP configuration result not seen (Enrollee)")
|
|
ev = dev[1].wait_event(["DPP-CONF-SENT"], timeout=2)
|
|
if ev is None:
|
|
raise Exception("DPP configuration result not seen (Responder)")
|
|
|
|
dev[0].request("DPP_STOP_LISTEN")
|
|
dev[1].request("DPP_STOP_LISTEN")
|
|
dev[2].request("DPP_STOP_LISTEN")
|
|
|
|
def test_dpp_conf_file_update(dev, apdev, params):
|
|
"""DPP provisioning updating wpa_supplicant configuration file"""
|
|
config = os.path.join(params['logdir'], 'dpp_conf_file_update.conf')
|
|
with open(config, "w") as f:
|
|
f.write("update_config=1\n")
|
|
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
|
|
wpas.interface_add("wlan5", config=config)
|
|
check_dpp_capab(wpas)
|
|
wpas.set("dpp_config_processing", "1")
|
|
run_dpp_qr_code_auth_unicast([wpas, dev[1]], apdev, None,
|
|
init_extra="conf=sta-dpp",
|
|
require_conf_success=True,
|
|
configurator=True)
|
|
wpas.interface_remove("wlan5")
|
|
|
|
with open(config, "r") as f:
|
|
res = f.read()
|
|
for i in ["network={", "dpp_connector=", "key_mgmt=DPP", "ieee80211w=2",
|
|
"dpp_netaccesskey=", "dpp_csign="]:
|
|
if i not in res:
|
|
raise Exception("Configuration file missing '%s'" % i)
|
|
|
|
wpas.interface_add("wlan5", config=config)
|
|
if len(wpas.list_networks()) != 1:
|
|
raise Exception("Unexpected number of networks")
|
|
|
|
def test_dpp_duplicated_auth_resp(dev, apdev):
|
|
"""DPP and duplicated Authentication Response"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].set("ext_mgmt_frame_handling", "1")
|
|
dev[1].set("ext_mgmt_frame_handling", "1")
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0)
|
|
|
|
# DPP Authentication Request
|
|
rx_process_frame(dev[0])
|
|
|
|
# DPP Authentication Response
|
|
msg = rx_process_frame(dev[1])
|
|
frame = binascii.hexlify(msg['frame']).decode()
|
|
# Duplicated frame
|
|
if "OK" not in dev[1].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], frame)):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
# Modified frame - nonzero status
|
|
if frame[2*32:2*37] != "0010010000":
|
|
raise Exception("Could not find Status attribute")
|
|
frame2 = frame[0:2*32] + "0010010001" + frame[2*37:]
|
|
if "OK" not in dev[1].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], frame2)):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
frame2 = frame[0:2*32] + "00100100ff" + frame[2*37:]
|
|
if "OK" not in dev[1].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], frame2)):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
|
|
# DPP Authentication Confirmation
|
|
rx_process_frame(dev[0])
|
|
|
|
wait_auth_success(dev[0], dev[1])
|
|
|
|
# DPP Configuration Request
|
|
rx_process_frame(dev[1])
|
|
|
|
# DPP Configuration Response
|
|
rx_process_frame(dev[0])
|
|
|
|
wait_conf_completion(dev[1], dev[0])
|
|
|
|
def test_dpp_duplicated_auth_conf(dev, apdev):
|
|
"""DPP and duplicated Authentication Confirmation"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].set("ext_mgmt_frame_handling", "1")
|
|
dev[1].set("ext_mgmt_frame_handling", "1")
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0)
|
|
|
|
# DPP Authentication Request
|
|
rx_process_frame(dev[0])
|
|
|
|
# DPP Authentication Response
|
|
rx_process_frame(dev[1])
|
|
|
|
# DPP Authentication Confirmation
|
|
msg = rx_process_frame(dev[0])
|
|
# Duplicated frame
|
|
if "OK" not in dev[0].request("MGMT_RX_PROCESS freq={} datarate={} ssi_signal={} frame={}".format(msg['freq'], msg['datarate'], msg['ssi_signal'], binascii.hexlify(msg['frame']).decode())):
|
|
raise Exception("MGMT_RX_PROCESS failed")
|
|
|
|
wait_auth_success(dev[0], dev[1])
|
|
|
|
# DPP Configuration Request
|
|
rx_process_frame(dev[1])
|
|
|
|
# DPP Configuration Response
|
|
rx_process_frame(dev[0])
|
|
|
|
wait_conf_completion(dev[1], dev[0])
|
|
|
|
def test_dpp_enrollee_reject_config(dev, apdev):
|
|
"""DPP and Enrollee rejecting Config Object"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
dev[0].set("dpp_test", "91")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0, conf="sta-sae", ssid="dpp-legacy",
|
|
passphrase="secret passphrase")
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0],
|
|
allow_enrollee_failure=True,
|
|
allow_configurator_failure=True)
|
|
|
|
def test_dpp_enrollee_ap_reject_config(dev, apdev):
|
|
"""DPP and Enrollee AP rejecting Config Object"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"})
|
|
check_dpp_capab(hapd)
|
|
hapd.set("dpp_test", "91")
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
id_h = hapd.dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri = hapd.request("DPP_BOOTSTRAP_GET_URI %d" % id_h)
|
|
dev[0].dpp_auth_init(uri=uri, conf="ap-dpp", configurator=conf_id)
|
|
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd,
|
|
allow_enrollee_failure=True,
|
|
allow_configurator_failure=True)
|
|
|
|
def test_dpp_legacy_and_dpp_akm(dev, apdev):
|
|
"""DPP and provisoning DPP and legacy AKMs"""
|
|
try:
|
|
run_dpp_legacy_and_dpp_akm(dev, apdev)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def run_dpp_legacy_and_dpp_akm(dev, apdev):
|
|
check_dpp_capab(dev[0], min_ver=2)
|
|
check_dpp_capab(dev[1], min_ver=2)
|
|
|
|
csign = "30770201010420768240a3fc89d6662d9782f120527fe7fb9edc6366ab0b9c7dde96125cfd250fa00a06082a8648ce3d030107a144034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708"
|
|
csign_pub = "3059301306072a8648ce3d020106082a8648ce3d030107034200042908e1baf7bf413cc66f9e878a03e8bb1835ba94b033dbe3d6969fc8575d5eb5dfda1cb81c95cee21d0cd7d92ba30541ffa05cb6296f5dd808b0c1c2a83c0708"
|
|
ap_connector = "eyJ0eXAiOiJkcHBDb24iLCJraWQiOiJwYWtZbXVzd1dCdWpSYTl5OEsweDViaTVrT3VNT3dzZHRlaml2UG55ZHZzIiwiYWxnIjoiRVMyNTYifQ.eyJncm91cHMiOlt7Imdyb3VwSWQiOiIqIiwibmV0Um9sZSI6ImFwIn1dLCJuZXRBY2Nlc3NLZXkiOnsia3R5IjoiRUMiLCJjcnYiOiJQLTI1NiIsIngiOiIybU5vNXZuRkI5bEw3d1VWb1hJbGVPYzBNSEE1QXZKbnpwZXZULVVTYzVNIiwieSI6IlhzS3dqVHJlLTg5WWdpU3pKaG9CN1haeUttTU05OTl3V2ZaSVl0bi01Q3MifX0.XhjFpZgcSa7G2lHy0OCYTvaZFRo5Hyx6b7g7oYyusLC7C_73AJ4_BxEZQVYJXAtDuGvb3dXSkHEKxREP9Q6Qeg"
|
|
ap_netaccesskey = "30770201010420ceba752db2ad5200fa7bc565b9c05c69b7eb006751b0b329b0279de1c19ca67ca00a06082a8648ce3d030107a14403420004da6368e6f9c507d94bef0515a1722578e73430703902f267ce97af4fe51273935ec2b08d3adefbcf588224b3261a01ed76722a630cf7df7059f64862d9fee42b"
|
|
|
|
ssid = "dpp-both"
|
|
passphrase = "secret passphrase"
|
|
params = {"ssid": ssid,
|
|
"wpa": "2",
|
|
"wpa_key_mgmt": "DPP WPA-PSK SAE",
|
|
"ieee80211w": "1",
|
|
"sae_require_mfp": '1',
|
|
"rsn_pairwise": "CCMP",
|
|
"wpa_passphrase": passphrase,
|
|
"dpp_connector": ap_connector,
|
|
"dpp_csign": csign_pub,
|
|
"dpp_netaccesskey": ap_netaccesskey}
|
|
try:
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
except:
|
|
raise HwsimSkip("DPP not supported")
|
|
|
|
dev[0].request("SET sae_groups ")
|
|
conf_id = dev[1].dpp_configurator_add(key=csign)
|
|
dev[0].set("dpp_config_processing", "1")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].dpp_listen(2412)
|
|
dev[1].dpp_auth_init(uri=uri0, conf="sta-psk-sae-dpp", ssid=ssid,
|
|
passphrase=passphrase, configurator=conf_id)
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0],
|
|
allow_enrollee_failure=True,
|
|
allow_configurator_failure=True)
|
|
ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("DPP network profile not generated")
|
|
id0 = ev.split(' ')[1]
|
|
|
|
key_mgmt = dev[0].get_network(id0, "key_mgmt").split(' ')
|
|
for m in ["SAE", "WPA-PSK", "DPP"]:
|
|
if m not in key_mgmt:
|
|
raise Exception("%s missing from key_mgmt" % m)
|
|
|
|
dev[0].scan_for_bss(hapd.own_addr(), freq=2412)
|
|
dev[0].select_network(id0, freq=2412)
|
|
dev[0].wait_connected()
|
|
|
|
dev[0].request("DISCONNECT")
|
|
dev[0].wait_disconnected()
|
|
hapd.disable()
|
|
|
|
params = {"ssid": ssid,
|
|
"wpa": "2",
|
|
"wpa_key_mgmt": "WPA-PSK SAE",
|
|
"ieee80211w": "1",
|
|
"sae_require_mfp": '1',
|
|
"rsn_pairwise": "CCMP",
|
|
"wpa_passphrase": passphrase}
|
|
hapd2 = hostapd.add_ap(apdev[1], params)
|
|
|
|
dev[0].request("BSS_FLUSH 0")
|
|
dev[0].scan_for_bss(hapd2.own_addr(), freq=2412, force_scan=True,
|
|
only_new=True)
|
|
dev[0].select_network(id0, freq=2412)
|
|
dev[0].wait_connected()
|
|
|
|
dev[0].request("DISCONNECT")
|
|
dev[0].wait_disconnected()
|
|
|
|
def test_dpp_controller_relay(dev, apdev, params):
|
|
"""DPP Controller/Relay"""
|
|
try:
|
|
run_dpp_controller_relay(dev, apdev, params)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
dev[1].request("DPP_CONTROLLER_STOP")
|
|
|
|
def test_dpp_controller_relay_chirp(dev, apdev, params):
|
|
"""DPP Controller/Relay with chirping"""
|
|
try:
|
|
run_dpp_controller_relay(dev, apdev, params, chirp=True)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
dev[1].request("DPP_CONTROLLER_STOP")
|
|
|
|
def run_dpp_controller_relay(dev, apdev, params, chirp=False):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
prefix = "dpp_controller_relay"
|
|
if chirp:
|
|
prefix += "_chirp"
|
|
cap_lo = os.path.join(params['logdir'], prefix + ".lo.pcap")
|
|
|
|
wt = WlantestCapture('lo', cap_lo)
|
|
|
|
# Controller
|
|
conf_id = dev[1].dpp_configurator_add()
|
|
if not chirp:
|
|
dev[1].set("dpp_configurator_params",
|
|
" conf=sta-dpp configurator=%d" % conf_id)
|
|
id_c = dev[1].dpp_bootstrap_gen()
|
|
uri_c = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_c)
|
|
res = dev[1].request("DPP_BOOTSTRAP_INFO %d" % id_c)
|
|
pkhash = None
|
|
for line in res.splitlines():
|
|
name, value = line.split('=')
|
|
if name == "pkhash":
|
|
pkhash = value
|
|
break
|
|
if not pkhash:
|
|
raise Exception("Could not fetch public key hash from Controller")
|
|
if "OK" not in dev[1].request("DPP_CONTROLLER_START"):
|
|
raise Exception("Failed to start Controller")
|
|
|
|
# Relay
|
|
params = {"ssid": "unconfigured",
|
|
"channel": "6",
|
|
"dpp_controller": "ipaddr=127.0.0.1 pkhash=" + pkhash}
|
|
if chirp:
|
|
params["channel"] = "11"
|
|
params["dpp_configurator_connectivity"] = "1"
|
|
relay = hostapd.add_ap(apdev[1], params)
|
|
check_dpp_capab(relay)
|
|
|
|
# Enroll Relay to the network
|
|
# TODO: Do this over TCP once direct Enrollee-over-TCP case is supported
|
|
if chirp:
|
|
id_h = relay.dpp_bootstrap_gen(chan="81/11", mac=True)
|
|
else:
|
|
id_h = relay.dpp_bootstrap_gen(chan="81/6", mac=True)
|
|
uri_r = relay.request("DPP_BOOTSTRAP_GET_URI %d" % id_h)
|
|
dev[1].dpp_auth_init(uri=uri_r, conf="ap-dpp", configurator=conf_id)
|
|
wait_auth_success(relay, dev[1], configurator=dev[1], enrollee=relay)
|
|
update_hapd_config(relay)
|
|
|
|
# Initiate from Enrollee with broadcast DPP Authentication Request or
|
|
# using chirping
|
|
dev[0].set("dpp_config_processing", "2")
|
|
if chirp:
|
|
id1 = dev[0].dpp_bootstrap_gen()
|
|
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1)
|
|
idc = dev[1].dpp_qr_code(uri)
|
|
dev[1].dpp_bootstrap_set(idc, conf="sta-dpp", configurator=conf_id)
|
|
if "OK" not in dev[0].request("DPP_CHIRP own=%d iter=5" % id1):
|
|
raise Exception("DPP_CHIRP failed")
|
|
ev = relay.wait_event(["DPP-RX"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("Presence Announcement not seen")
|
|
if "type=13" not in ev:
|
|
raise Exception("Unexpected DPP frame received: " + ev)
|
|
else:
|
|
dev[0].dpp_auth_init(uri=uri_c, role="enrollee")
|
|
wait_auth_success(dev[1], dev[0], configurator=dev[1], enrollee=dev[0],
|
|
allow_enrollee_failure=True,
|
|
allow_configurator_failure=True)
|
|
dev[0].wait_connected()
|
|
|
|
time.sleep(0.5)
|
|
wt.close()
|
|
|
|
def test_dpp_tcp(dev, apdev, params):
|
|
"""DPP over TCP"""
|
|
prefix = "dpp_tcp"
|
|
cap_lo = os.path.join(params['logdir'], prefix + ".lo.pcap")
|
|
try:
|
|
run_dpp_tcp(dev, apdev, cap_lo)
|
|
finally:
|
|
dev[1].request("DPP_CONTROLLER_STOP")
|
|
|
|
def test_dpp_tcp_port(dev, apdev, params):
|
|
"""DPP over TCP and specified port"""
|
|
prefix = "dpp_tcp_port"
|
|
cap_lo = os.path.join(params['logdir'], prefix + ".lo.pcap")
|
|
try:
|
|
run_dpp_tcp(dev, apdev, cap_lo, port="23456")
|
|
finally:
|
|
dev[1].request("DPP_CONTROLLER_STOP")
|
|
|
|
def run_dpp_tcp(dev, apdev, cap_lo, port=None):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
wt = WlantestCapture('lo', cap_lo)
|
|
time.sleep(1)
|
|
|
|
# Controller
|
|
conf_id = dev[1].dpp_configurator_add()
|
|
dev[1].set("dpp_configurator_params",
|
|
" conf=sta-dpp configurator=%d" % conf_id)
|
|
id_c = dev[1].dpp_bootstrap_gen()
|
|
uri_c = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_c)
|
|
res = dev[1].request("DPP_BOOTSTRAP_INFO %d" % id_c)
|
|
pkhash = None
|
|
for line in res.splitlines():
|
|
name, value = line.split('=')
|
|
if name == "pkhash":
|
|
pkhash = value
|
|
break
|
|
if not pkhash:
|
|
raise Exception("Could not fetch public key hash from Controller")
|
|
req = "DPP_CONTROLLER_START"
|
|
if port:
|
|
req += " tcp_port=" + port
|
|
if "OK" not in dev[1].request(req):
|
|
raise Exception("Failed to start Controller")
|
|
|
|
# Initiate from Enrollee with broadcast DPP Authentication Request
|
|
dev[0].dpp_auth_init(uri=uri_c, role="enrollee", tcp_addr="127.0.0.1",
|
|
tcp_port=port)
|
|
wait_auth_success(dev[1], dev[0], configurator=dev[1], enrollee=dev[0],
|
|
allow_enrollee_failure=True,
|
|
allow_configurator_failure=True)
|
|
time.sleep(0.5)
|
|
wt.close()
|
|
|
|
def test_dpp_tcp_controller_start_failure(dev, apdev, params):
|
|
"""DPP Controller startup failure"""
|
|
check_dpp_capab(dev[0])
|
|
|
|
try:
|
|
if "OK" not in dev[0].request("DPP_CONTROLLER_START"):
|
|
raise Exception("Could not start Controller")
|
|
if "OK" in dev[0].request("DPP_CONTROLLER_START"):
|
|
raise Exception("Second Controller start not rejected")
|
|
finally:
|
|
dev[0].request("DPP_CONTROLLER_STOP")
|
|
|
|
tests = ["dpp_controller_start",
|
|
"eloop_sock_table_add_sock;?eloop_register_sock;dpp_controller_start"]
|
|
for func in tests:
|
|
with alloc_fail(dev[0], 1, func):
|
|
if "FAIL" not in dev[0].request("DPP_CONTROLLER_START"):
|
|
raise Exception("Failure not reported during OOM")
|
|
|
|
def test_dpp_tcp_init_failure(dev, apdev, params):
|
|
"""DPP TCP init failure"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
id_c = dev[1].dpp_bootstrap_gen()
|
|
uri_c = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id_c)
|
|
peer = dev[0].dpp_qr_code(uri_c)
|
|
tests = ["dpp_tcp_init",
|
|
"eloop_sock_table_add_sock;?eloop_register_sock;dpp_tcp_init",
|
|
"dpp_tcp_encaps"]
|
|
cmd = "DPP_AUTH_INIT peer=%d tcp_addr=127.0.0.1" % peer
|
|
for func in tests:
|
|
with alloc_fail(dev[0], 1, func):
|
|
if "FAIL" not in dev[0].request(cmd):
|
|
raise Exception("DPP_AUTH_INIT accepted during OOM")
|
|
|
|
def test_dpp_controller_rx_failure(dev, apdev, params):
|
|
"""DPP Controller RX failure"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
try:
|
|
run_dpp_controller_rx_failure(dev, apdev)
|
|
finally:
|
|
dev[0].request("DPP_CONTROLLER_STOP")
|
|
|
|
def run_dpp_controller_rx_failure(dev, apdev):
|
|
if "OK" not in dev[0].request("DPP_CONTROLLER_START"):
|
|
raise Exception("Could not start Controller")
|
|
id_c = dev[0].dpp_bootstrap_gen()
|
|
uri_c = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id_c)
|
|
peer = dev[1].dpp_qr_code(uri_c)
|
|
tests = ["dpp_controller_tcp_cb",
|
|
"eloop_sock_table_add_sock;?eloop_register_sock;dpp_controller_tcp_cb",
|
|
"dpp_controller_rx",
|
|
"dpp_controller_rx_auth_req",
|
|
"wpabuf_alloc;=dpp_tcp_send_msg;dpp_controller_rx_auth_req"]
|
|
cmd = "DPP_AUTH_INIT peer=%d tcp_addr=127.0.0.1" % peer
|
|
for func in tests:
|
|
with alloc_fail(dev[0], 1, func):
|
|
if "OK" not in dev[1].request(cmd):
|
|
raise Exception("Failed to initiate TCP connection")
|
|
wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
|
|
|
|
def test_dpp_controller_rx_errors(dev, apdev, params):
|
|
"""DPP Controller RX error cases"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
try:
|
|
run_dpp_controller_rx_errors(dev, apdev)
|
|
finally:
|
|
dev[0].request("DPP_CONTROLLER_STOP")
|
|
|
|
def run_dpp_controller_rx_errors(dev, apdev):
|
|
if "OK" not in dev[0].request("DPP_CONTROLLER_START"):
|
|
raise Exception("Could not start Controller")
|
|
|
|
addr = ("127.0.0.1", 7871)
|
|
|
|
tests = [b"abc",
|
|
b"abcd",
|
|
b"\x00\x00\x00\x00",
|
|
b"\x00\x00\x00\x01",
|
|
b"\x00\x00\x00\x01\x09",
|
|
b"\x00\x00\x00\x07\x09\x50\x6f\x9a\x1a\xff\xff",
|
|
b"\x00\x00\x00\x07\x09\x50\x6f\x9a\x1a\x01\xff",
|
|
b"\x00\x00\x00\x07\x09\x50\x6f\x9a\x1a\x01\x00",
|
|
b"\x00\x00\x00\x08\x09\x50\x6f\x9a\x1a\x01\x00\xff",
|
|
b"\x00\x00\x00\x01\x0a",
|
|
b"\x00\x00\x00\x04\x0a\xff\xff\xff",
|
|
b"\x00\x00\x00\x01\x0b",
|
|
b"\x00\x00\x00\x08\x0b\xff\xff\xff\xff\xff\xff\xff",
|
|
b"\x00\x00\x00\x08\x0b\xff\x00\x00\xff\xff\xff\xff",
|
|
b"\x00\x00\x00\x08\x0b\xff\x00\x00\xff\xff\x6c\x00",
|
|
b"\x00\x00\x00\x0a\x0b\xff\x00\x00\xff\xff\x6c\x02\xff\xff",
|
|
b"\x00\x00\x00\x10\x0b\xff\x00\x00\xff\xff\x6c\x08\xff\xdd\x05\x50\x6f\x9a\x1a\x01",
|
|
b"\x00\x00\x00\x12\x0b\xff\x00\x00\xff\xff\x6c\x08\xff\xdd\x05\x50\x6f\x9a\x1a\x01\x00\x00",
|
|
b"\x00\x00\x00\x01\xff",
|
|
b"\x00\x00\x00\x01\xff\xee"]
|
|
#define WLAN_PA_GAS_INITIAL_REQ 10
|
|
#define WLAN_PA_GAS_INITIAL_RESP 11
|
|
|
|
for t in tests:
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM,
|
|
socket.IPPROTO_TCP)
|
|
sock.settimeout(0.1)
|
|
sock.connect(addr)
|
|
sock.send(t)
|
|
sock.shutdown(1)
|
|
try:
|
|
sock.recv(10)
|
|
except socket.timeout:
|
|
pass
|
|
sock.close()
|
|
|
|
def test_dpp_conn_status_success(dev, apdev):
|
|
"""DPP connection status - success"""
|
|
try:
|
|
run_dpp_conn_status(dev, apdev)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_conn_status_wrong_passphrase(dev, apdev):
|
|
"""DPP connection status - wrong passphrase"""
|
|
try:
|
|
run_dpp_conn_status(dev, apdev, result=2)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_conn_status_no_ap(dev, apdev):
|
|
"""DPP connection status - no AP"""
|
|
try:
|
|
run_dpp_conn_status(dev, apdev, result=10)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_conn_status_connector_mismatch(dev, apdev):
|
|
"""DPP connection status - invalid Connector"""
|
|
try:
|
|
run_dpp_conn_status(dev, apdev, result=8)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def test_dpp_conn_status_assoc_reject(dev, apdev):
|
|
"""DPP connection status - association rejection"""
|
|
try:
|
|
dev[0].request("TEST_ASSOC_IE 30020000")
|
|
run_dpp_conn_status(dev, apdev, assoc_reject=True)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def run_dpp_conn_status(dev, apdev, result=0, assoc_reject=False):
|
|
check_dpp_capab(dev[0], min_ver=2)
|
|
check_dpp_capab(dev[1], min_ver=2)
|
|
|
|
if result != 10:
|
|
if result == 7 or result == 8:
|
|
params = {"ssid": "dpp-status",
|
|
"wpa": "2",
|
|
"wpa_key_mgmt": "DPP",
|
|
"ieee80211w": "2",
|
|
"rsn_pairwise": "CCMP",
|
|
"dpp_connector": params1_ap_connector,
|
|
"dpp_csign": params1_csign,
|
|
"dpp_netaccesskey": params1_ap_netaccesskey}
|
|
else:
|
|
if result == 2:
|
|
passphrase = "wrong passphrase"
|
|
else:
|
|
passphrase = "secret passphrase"
|
|
params = hostapd.wpa2_params(ssid="dpp-status",
|
|
passphrase=passphrase)
|
|
try:
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
except:
|
|
raise HwsimSkip("DPP not supported")
|
|
|
|
dev[0].request("SET sae_groups ")
|
|
dev[0].set("dpp_config_processing", "2")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
|
|
dev[0].dpp_listen(2412)
|
|
if result == 7 or result == 8:
|
|
conf = 'sta-dpp'
|
|
passphrase = None
|
|
configurator = dev[1].dpp_configurator_add()
|
|
else:
|
|
conf = 'sta-psk'
|
|
passphrase = "secret passphrase"
|
|
configurator = None
|
|
dev[1].dpp_auth_init(uri=uri0, conf=conf, ssid="dpp-status",
|
|
passphrase=passphrase, configurator=configurator,
|
|
conn_status=True)
|
|
res = wait_auth_success(dev[0], dev[1], configurator=dev[1],
|
|
enrollee=dev[0])
|
|
if 'wait_conn_status' not in res:
|
|
raise Exception("Configurator did not request connection status")
|
|
|
|
if assoc_reject and result == 0:
|
|
result = 2
|
|
ev = dev[1].wait_event(["DPP-CONN-STATUS-RESULT"], timeout=20)
|
|
if ev is None:
|
|
raise Exception("No connection status reported")
|
|
if "timeout" in ev:
|
|
raise Exception("Connection status result timeout")
|
|
if "result=%d" % result not in ev:
|
|
raise Exception("Unexpected connection status result: " + ev)
|
|
if "ssid=dpp-status" not in ev:
|
|
raise Exception("SSID not reported")
|
|
|
|
if result == 0:
|
|
dev[0].wait_connected()
|
|
if result == 10 and "channel_list=" not in ev:
|
|
raise Exception("Channel list not reported for no-AP")
|
|
|
|
def test_dpp_mud_url(dev, apdev):
|
|
"""DPP MUD URL"""
|
|
check_dpp_capab(dev[0])
|
|
try:
|
|
dev[0].set("dpp_name", "Test Enrollee")
|
|
dev[0].set("dpp_mud_url", "https://example.com/mud")
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, None)
|
|
finally:
|
|
dev[0].set("dpp_mud_url", "")
|
|
dev[0].set("dpp_name", "Test")
|
|
|
|
def test_dpp_mud_url_hostapd(dev, apdev):
|
|
"""DPP MUD URL from hostapd"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
params = {"ssid": "unconfigured",
|
|
"dpp_name": "AP Enrollee",
|
|
"dpp_mud_url": "https://example.com/mud"}
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
check_dpp_capab(hapd)
|
|
|
|
id_h = hapd.dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri = hapd.request("DPP_BOOTSTRAP_GET_URI %d" % id_h)
|
|
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
dev[0].dpp_auth_init(uri=uri, conf="ap-dpp", configurator=conf_id)
|
|
wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd)
|
|
update_hapd_config(hapd)
|
|
|
|
def test_dpp_config_save(dev, apdev, params):
|
|
"""DPP configuration saving"""
|
|
config = os.path.join(params['logdir'], 'dpp_config_save.conf')
|
|
run_dpp_config_save(dev, apdev, config, "test", '"test"')
|
|
|
|
def test_dpp_config_save2(dev, apdev, params):
|
|
"""DPP configuration saving (2)"""
|
|
config = os.path.join(params['logdir'], 'dpp_config_save2.conf')
|
|
run_dpp_config_save(dev, apdev, config, "\\u0001*", '012a')
|
|
|
|
def test_dpp_config_save3(dev, apdev, params):
|
|
"""DPP configuration saving (3)"""
|
|
config = os.path.join(params['logdir'], 'dpp_config_save3.conf')
|
|
run_dpp_config_save(dev, apdev, config, "\\u0001*\\u00c2\\u00bc\\u00c3\\u009e\\u00c3\\u00bf", '012ac2bcc39ec3bf')
|
|
|
|
def run_dpp_config_save(dev, apdev, config, conf_ssid, exp_ssid):
|
|
check_dpp_capab(dev[1])
|
|
with open(config, "w") as f:
|
|
f.write("update_config=1\n" +
|
|
"dpp_config_processing=1\n")
|
|
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
|
|
wpas.interface_add("wlan5", config=config)
|
|
check_dpp_capab(wpas)
|
|
conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"' + conf_ssid + '"},"cred":{"akm":"psk","pass":"secret passphrase"}}'
|
|
dev[1].set("dpp_config_obj_override", conf)
|
|
dpp_dev = [wpas, dev[1]]
|
|
run_dpp_qr_code_auth_unicast(dpp_dev, apdev, "prime256v1",
|
|
require_conf_success=True)
|
|
if "OK" not in wpas.request("SAVE_CONFIG"):
|
|
raise Exception("Failed to save configuration file")
|
|
with open(config, "r") as f:
|
|
data = f.read()
|
|
logger.info("Saved configuration:\n" + data)
|
|
if 'ssid=' + exp_ssid + '\n' not in data:
|
|
raise Exception("SSID not saved")
|
|
if 'psk="secret passphrase"' not in data:
|
|
raise Exception("Passphtase not saved")
|
|
|
|
def test_dpp_nfc_uri(dev, apdev):
|
|
"""DPP bootstrapping via NFC URI record"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
id = dev[0].dpp_bootstrap_gen(type="nfc-uri", chan="81/1", mac=True)
|
|
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id)
|
|
logger.info("Generated URI: " + uri)
|
|
info = dev[0].request("DPP_BOOTSTRAP_INFO %d" % id)
|
|
logger.info("Bootstrapping info:\n" + info)
|
|
if "type=NFC-URI" not in info:
|
|
raise Exception("Unexpected bootstrapping info contents")
|
|
|
|
dev[0].dpp_listen(2412)
|
|
conf_id = dev[1].dpp_configurator_add()
|
|
dev[1].dpp_auth_init(nfc_uri=uri, configurator=conf_id, conf="sta-dpp")
|
|
wait_auth_success(dev[0], dev[1], configurator=dev[1], enrollee=dev[0])
|
|
|
|
def test_dpp_nfc_negotiated_handover(dev, apdev):
|
|
"""DPP bootstrapping via NFC negotiated handover"""
|
|
run_dpp_nfc_negotiated_handover(dev, apdev)
|
|
|
|
def test_dpp_nfc_negotiated_handover_diff_curve(dev, apdev):
|
|
"""DPP bootstrapping via NFC negotiated handover (different curve)"""
|
|
run_dpp_nfc_negotiated_handover(dev, apdev, curve0="prime256v1",
|
|
curve1="secp384r1")
|
|
|
|
def run_dpp_nfc_negotiated_handover(dev, apdev, curve0=None, curve1=None):
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
id0 = dev[0].dpp_bootstrap_gen(type="nfc-uri", chan="81/6,11", mac=True,
|
|
curve=curve0)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
logger.info("Generated URI[0]: " + uri0)
|
|
id1 = dev[1].dpp_bootstrap_gen(type="nfc-uri", chan="81/1,6,11", mac=True,
|
|
curve=curve1)
|
|
uri1 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1)
|
|
logger.info("Generated URI[1]: " + uri1)
|
|
|
|
# dev[0] acting as NFC Handover Requestor
|
|
# dev[1] acting as NFC Handover Selector
|
|
res = dev[1].request("DPP_NFC_HANDOVER_REQ own=%d uri=%s" % (id1, uri0))
|
|
if "FAIL" in res:
|
|
raise Exception("Failed to process NFC Handover Request")
|
|
info = dev[1].request("DPP_BOOTSTRAP_INFO %d" % id1)
|
|
logger.info("Updated local bootstrapping info:\n" + info)
|
|
freq = None
|
|
for line in info.splitlines():
|
|
if line.startswith("use_freq="):
|
|
freq = int(line.split('=')[1])
|
|
if freq is None:
|
|
raise Exception("Selected channel not indicated")
|
|
uri1 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1)
|
|
logger.info("Updated URI[1]: " + uri1)
|
|
dev[1].dpp_listen(freq)
|
|
res = dev[0].request("DPP_NFC_HANDOVER_SEL own=%d uri=%s" % (id0, uri1))
|
|
if "FAIL" in res:
|
|
raise Exception("Failed to process NFC Handover Select")
|
|
peer = int(res)
|
|
|
|
conf_id = dev[0].dpp_configurator_add()
|
|
dev[0].dpp_auth_init(peer=peer, own=id0, configurator=conf_id,
|
|
conf="sta-dpp")
|
|
wait_auth_success(dev[1], dev[0], configurator=dev[0], enrollee=dev[1])
|
|
|
|
def test_dpp_with_p2p_device(dev, apdev):
|
|
"""DPP exchange when driver uses a separate P2P Device interface"""
|
|
check_dpp_capab(dev[0])
|
|
with HWSimRadio(use_p2p_device=True) as (radio, iface):
|
|
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
|
|
wpas.interface_add(iface)
|
|
check_dpp_capab(wpas)
|
|
id1 = wpas.dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri1 = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % id1)
|
|
wpas.dpp_listen(2412)
|
|
time.sleep(7)
|
|
dev[0].dpp_auth_init(uri=uri1)
|
|
wait_auth_success(wpas, dev[0], configurator=dev[0], enrollee=wpas,
|
|
allow_enrollee_failure=True)
|
|
|
|
@long_duration_test
|
|
def test_dpp_chirp(dev, apdev):
|
|
"""DPP chirp"""
|
|
check_dpp_capab(dev[0])
|
|
dev[0].flush_scan_cache()
|
|
|
|
params = {"ssid": "dpp",
|
|
"channel": "11"}
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
check_dpp_capab(hapd)
|
|
dpp_cc = False
|
|
|
|
id1 = dev[0].dpp_bootstrap_gen(chan="81/1")
|
|
if "OK" not in dev[0].request("DPP_CHIRP own=%d iter=5" % id1):
|
|
raise Exception("DPP_CHIRP failed")
|
|
chan1 = 0
|
|
chan6 = 0
|
|
chan11 = 0
|
|
for i in range(30):
|
|
ev = dev[0].wait_event(["DPP-CHIRP-STOPPED",
|
|
"DPP-TX "], timeout=60)
|
|
if ev is None:
|
|
raise Exception("DPP chirp stop not reported")
|
|
if "DPP-CHIRP-STOPPED" in ev:
|
|
break
|
|
if "type=13" not in ev:
|
|
continue
|
|
freq = int(ev.split(' ')[2].split('=')[1])
|
|
if freq == 2412:
|
|
chan1 += 1
|
|
elif freq == 2437:
|
|
chan6 += 1
|
|
elif freq == 2462:
|
|
chan11 += 1
|
|
if not dpp_cc:
|
|
hapd.set("dpp_configurator_connectivity", "1")
|
|
if "OK" not in hapd.request("UPDATE_BEACON"):
|
|
raise Exception("UPDATE_BEACON failed")
|
|
dpp_cc = True
|
|
if chan1 != 5 or chan6 != 5 or chan11 != 1:
|
|
raise Exception("Unexpected number of presence announcements sent: %d %d %d" % (chan1, chan6, chan11))
|
|
|
|
@long_duration_test
|
|
def test_dpp_chirp_listen(dev, apdev):
|
|
"""DPP chirp with listen"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
id1 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1)
|
|
|
|
if "OK" not in dev[0].request("DPP_CHIRP own=%d iter=2 listen=2412" % id1):
|
|
raise Exception("DPP_CHIRP failed")
|
|
for i in range(30):
|
|
ev = dev[0].wait_event(["DPP-CHIRP-STOPPED",
|
|
"DPP-TX "], timeout=60)
|
|
if ev is None:
|
|
raise Exception("DPP chirp stop not reported")
|
|
if "DPP-CHIRP-STOPPED" in ev:
|
|
break
|
|
|
|
def test_dpp_chirp_configurator(dev, apdev):
|
|
"""DPP chirp with a standalone Configurator"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
id1 = dev[0].dpp_bootstrap_gen(chan="81/1")
|
|
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1)
|
|
|
|
conf_id = dev[1].dpp_configurator_add()
|
|
idc = dev[1].dpp_qr_code(uri)
|
|
dev[1].dpp_bootstrap_set(idc, conf="sta-dpp", configurator=conf_id)
|
|
dev[1].dpp_listen(2437)
|
|
|
|
if "OK" not in dev[0].request("DPP_CHIRP own=%d iter=2" % id1):
|
|
raise Exception("DPP_CHIRP failed")
|
|
|
|
ev = dev[1].wait_event(["DPP-RX"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("Presence Announcement not seen")
|
|
if "type=13" not in ev:
|
|
raise Exception("Unexpected DPP frame received: " + ev)
|
|
|
|
wait_auth_success(dev[0], dev[1], dev[1], dev[0])
|
|
|
|
def test_dpp_chirp_configurator_inits(dev, apdev):
|
|
"""DPP chirp with a standalone Configurator initiating"""
|
|
check_dpp_capab(dev[0])
|
|
check_dpp_capab(dev[1])
|
|
|
|
id1 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1)
|
|
|
|
conf_id = dev[1].dpp_configurator_add()
|
|
idc = dev[1].dpp_qr_code(uri)
|
|
|
|
if "OK" not in dev[0].request("DPP_CHIRP own=%d iter=2 listen=2412" % id1):
|
|
raise Exception("DPP_CHIRP failed")
|
|
for i in range(2):
|
|
ev = dev[0].wait_event(["DPP-TX "], timeout=10)
|
|
if ev is None or "type=13" not in ev:
|
|
raise Exception("Presence Announcement not sent")
|
|
|
|
dev[1].dpp_auth_init(uri=uri, conf="sta-dpp", configurator=conf_id)
|
|
wait_auth_success(dev[0], dev[1], dev[1], dev[0])
|
|
|
|
def start_dpp_pfs_ap(apdev, pfs):
|
|
params = {"ssid": "dpp",
|
|
"wpa": "2",
|
|
"wpa_key_mgmt": "DPP",
|
|
"dpp_pfs": str(pfs),
|
|
"ieee80211w": "2",
|
|
"rsn_pairwise": "CCMP",
|
|
"dpp_connector": params1_ap_connector,
|
|
"dpp_csign": params1_csign,
|
|
"dpp_netaccesskey": params1_ap_netaccesskey}
|
|
try:
|
|
hapd = hostapd.add_ap(apdev, params)
|
|
except:
|
|
raise HwsimSkip("DPP not supported")
|
|
return hapd
|
|
|
|
def run_dpp_pfs_sta(dev, pfs, fail=False, pfs_expected=None):
|
|
dev.connect("dpp", key_mgmt="DPP", scan_freq="2412",
|
|
ieee80211w="2", dpp_pfs=str(pfs),
|
|
dpp_csign=params1_csign,
|
|
dpp_connector=params1_sta_connector,
|
|
dpp_netaccesskey=params1_sta_netaccesskey,
|
|
wait_connect=not fail)
|
|
if fail:
|
|
for i in range(2):
|
|
ev = dev.wait_event(["CTRL-EVENT-ASSOC-REJECT",
|
|
"CTRL-EVENT-CONNECTED"], timeout=10)
|
|
if ev is None:
|
|
raise Exception("Connection result not reported")
|
|
if "CTRL-EVENT-CONNECTED" in ev:
|
|
raise Exception("Unexpected connection")
|
|
dev.request("REMOVE_NETWORK all")
|
|
else:
|
|
if pfs_expected is not None:
|
|
res = dev.get_status_field("dpp_pfs")
|
|
pfs_used = res == "1"
|
|
if pfs_expected != pfs_used:
|
|
raise Exception("Unexpected PFS negotiation result")
|
|
dev.request("REMOVE_NETWORK all")
|
|
dev.wait_disconnected()
|
|
dev.dump_monitor()
|
|
|
|
def test_dpp_pfs_ap_0(dev, apdev):
|
|
"""DPP PFS AP default"""
|
|
check_dpp_capab(dev[0])
|
|
hapd = start_dpp_pfs_ap(apdev[0], 0)
|
|
run_dpp_pfs_sta(dev[0], 0, pfs_expected=True)
|
|
run_dpp_pfs_sta(dev[0], 1, pfs_expected=True)
|
|
run_dpp_pfs_sta(dev[0], 2, pfs_expected=False)
|
|
|
|
def test_dpp_pfs_ap_1(dev, apdev):
|
|
"""DPP PFS AP required"""
|
|
check_dpp_capab(dev[0])
|
|
hapd = start_dpp_pfs_ap(apdev[0], 1)
|
|
run_dpp_pfs_sta(dev[0], 0, pfs_expected=True)
|
|
run_dpp_pfs_sta(dev[0], 1, pfs_expected=True)
|
|
run_dpp_pfs_sta(dev[0], 2, fail=True)
|
|
|
|
def test_dpp_pfs_ap_2(dev, apdev):
|
|
"""DPP PFS AP not allowed"""
|
|
check_dpp_capab(dev[0])
|
|
hapd = start_dpp_pfs_ap(apdev[0], 2)
|
|
run_dpp_pfs_sta(dev[0], 0, pfs_expected=False)
|
|
run_dpp_pfs_sta(dev[0], 1, fail=True)
|
|
run_dpp_pfs_sta(dev[0], 2, pfs_expected=False)
|
|
|
|
def test_dpp_pfs_connect_cmd(dev, apdev):
|
|
"""DPP PFS and cfg80211 connect command"""
|
|
wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
|
|
wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
|
|
check_dpp_capab(wpas)
|
|
hapd = start_dpp_pfs_ap(apdev[0], 0)
|
|
run_dpp_pfs_sta(wpas, 0, pfs_expected=True)
|
|
run_dpp_pfs_sta(wpas, 1, pfs_expected=True)
|
|
run_dpp_pfs_sta(wpas, 2, pfs_expected=False)
|
|
|
|
def test_dpp_reconfig_connector(dev, apdev):
|
|
"""DPP reconfiguration connector"""
|
|
try:
|
|
run_dpp_reconfig_connector(dev, apdev)
|
|
finally:
|
|
dev[0].set("dpp_config_processing", "0", allow_fail=True)
|
|
|
|
def run_dpp_reconfig_connector(dev, apdev):
|
|
check_dpp_capab(dev[0], min_ver=2)
|
|
check_dpp_capab(dev[1], min_ver=2)
|
|
|
|
ssid = "reconfig"
|
|
passphrase = "secret passphrase"
|
|
params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
|
|
hapd = hostapd.add_ap(apdev[0], params)
|
|
|
|
dev[0].set("dpp_config_processing", "2")
|
|
id0 = dev[0].dpp_bootstrap_gen(chan="81/1", mac=True)
|
|
uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0)
|
|
dev[0].dpp_listen(2412)
|
|
configurator = dev[1].dpp_configurator_add()
|
|
conf = 'sta-psk'
|
|
dev[1].dpp_auth_init(uri=uri0, conf=conf, ssid=ssid,
|
|
passphrase=passphrase, configurator=configurator)
|
|
res = wait_auth_success(dev[0], dev[1], configurator=dev[1],
|
|
enrollee=dev[0])
|
|
|
|
ev = dev[0].wait_event(["DPP-CONFOBJ-SSID"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("SSID not reported")
|
|
res_ssid = ev.split(' ')[1]
|
|
if res_ssid != ssid:
|
|
raise Exception("Unexpected SSID value")
|
|
|
|
ev = dev[0].wait_event(["DPP-CONNECTOR"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("Connector not reported")
|
|
connector = ev.split(' ')[1]
|
|
|
|
ev = dev[0].wait_event(["DPP-C-SIGN-KEY"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("C-sign-key not reported")
|
|
p = ev.split(' ')
|
|
csign = p[1]
|
|
|
|
ev = dev[0].wait_event(["DPP-NET-ACCESS-KEY"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("netAccessKey not reported")
|
|
p = ev.split(' ')
|
|
net_access_key = p[1]
|
|
net_access_key_expiry = p[2] if len(p) > 2 else None
|
|
|
|
ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1)
|
|
if ev is None:
|
|
raise Exception("DPP network profile not generated")
|
|
id = ev.split(' ')[1]
|
|
|
|
dev[0].wait_connected()
|
|
|
|
n_key_mgmt = dev[0].get_network(id, "key_mgmt")
|
|
if n_key_mgmt != "WPA-PSK FT-PSK WPA-PSK-SHA256":
|
|
raise Exception("Unexpected key_mgmt: " + n_key_mgmt)
|
|
n_connector = dev[0].get_network(id, "dpp_connector")
|
|
if n_connector.strip('"') != connector:
|
|
raise Exception("Connector mismatch: %s %s" % (n_connector, connector))
|
|
n_csign = dev[0].get_network(id, "dpp_csign")
|
|
if n_csign.strip('"') != csign:
|
|
raise Exception("csign mismatch: %s %s" % (n_csign, csign))
|
|
n_net_access_key = dev[0].get_network(id, "dpp_netaccesskey")
|
|
if n_net_access_key.strip('"') != net_access_key:
|
|
raise Exception("net_access_key mismatch: %s %s" % (n_net_access_key,
|
|
net_access_key))
|
|
|
|
def test_dpp_qr_code_auth_rand_mac_addr(dev, apdev):
|
|
"""DPP QR Code and authentication exchange (rand_mac_addr=1)"""
|
|
flags = int(dev[0].get_driver_status_field('capa.flags'), 16)
|
|
if flags & 0x0000400000000000 == 0:
|
|
raise HwsimSkip("Driver does not support random GAS TA")
|
|
|
|
try:
|
|
dev[0].set("gas_rand_mac_addr", "1")
|
|
run_dpp_qr_code_auth_unicast(dev, apdev, None)
|
|
finally:
|
|
dev[0].set("gas_rand_mac_addr", "0")
|