diff --git a/.gitignore b/.gitignore index 6a985a75d..b064303ce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,35 +1,8 @@ -*.a -*.o -*.d -*.gcno -*.gcda -*.gcov *.pyc *~ -.config tests/hwsim/logs tests/remote/logs wpaspy/build -wpa_supplicant/eapol_test -wpa_supplicant/nfc_pw_token -wpa_supplicant/preauth_test -wpa_supplicant/wpa_cli -wpa_supplicant/wpa_passphrase -wpa_supplicant/wpa_supplicant -wpa_supplicant/wpa_priv -wpa_supplicant/wpa_gui/Makefile -wpa_supplicant/wpa_gui/wpa_gui -wpa_supplicant/wpa_gui-qt4/Makefile -wpa_supplicant/wpa_gui-qt4/wpa_gui -wpa_supplicant/libwpa_test1 -wpa_supplicant/libwpa_test2 -hostapd/hostapd -hostapd/hostapd_cli -hostapd/hlr_auc_gw -hostapd/nt_password_hash -mac80211_hwsim/tools/hwsim_test -wlantest/libwlantest.a -wlantest/test_vectors -wlantest/wlantest -wlantest/wlantest_cli **/parallel-vm.log +tags +build/ diff --git a/doc/dbus.doxygen b/doc/dbus.doxygen index b2b4389c9..06e53b98c 100644 --- a/doc/dbus.doxygen +++ b/doc/dbus.doxygen @@ -322,6 +322,24 @@ fi.w1.wpa_supplicant1.CreateInterface. +
  • +

    Roam ( s : addr ) --> nothing

    +

    Initiate a roam to another BSS within the current ESS.

    +

    Possible errors

    +
    +
    fi.w1.wpa_supplicant1.InvalidArgs
    +
    Missing address argument.
    +
    fi.w1.wpa_supplicant1.InvalidArgs
    +
    Invalid hardware address format.
    +
    fi.w1.wpa_supplicant1.InvalidArgs
    +
    Target BSS not found.
    +
    fi.w1.wpa_supplicant1.NotConnected
    +
    Interface is not connected to any network.
    +
    fi.w1.wpa_supplicant1.UnknownError
    +
    Scan processing was not included in the build.
    +
    +
  • +
  • AddBlob ( s : name, ay : data ) --> nothing

    Adds a blob to the interface.

    @@ -651,7 +669,7 @@ fi.w1.wpa_supplicant1.CreateInterface. PairwiseasPossible array elements: "ccmp-256", "gcmp-256", "ccmp", "gcmp", "tkip", "none" GroupasPossible array elements: "ccmp-256", "gcmp-256", "ccmp", "gcmp", "tkip", "wep104", "wep40" GroupMgmtasPossible array elements: "aes-128-cmac", "bip-gmac-128", "bip-gmac-256", "bip-cmac-256" - KeyMgmtasPossible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "ieee8021x", "wpa-none", "wps", "none" + KeyMgmtasPossible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "sae", "ieee8021x", "wpa-none", "wps", "none" ProtocolasPossible array elements: "rsn", "wpa" AuthAlgasPossible array elements: "open", "shared", "leap" ScanasPossible array elements: "active", "passive", "ssid" @@ -891,7 +909,7 @@ fi.w1.wpa_supplicant1.CreateInterface.
  • Hessid - s - (read/write)

    -

    Homogenous ESS identifier

    +

    Homogeneous ESS identifier

  • @@ -2037,7 +2055,7 @@ scan results. KeyMgmtasKey management suite. Possible array elements: "wpa-psk", "wpa-ft-psk", "wpa-psk-sha256", "wpa-eap", "wpa-ft-eap", "wpa-eap-sha256", "wpa-eap-suite-b", "wpa-eap-suite-b-192", "wpa-fils-sha256", "wpa-fils-sha384", "wpa-ft-fils-sha256", "wpa-ft-fils-sha384", "sae", "ft-sae", "wpa-none" PairwiseasPairwise cipher suites. Possible array elements: "ccmp", "tkip" GroupsGroup cipher suite. Possible values are: "ccmp", "tkip", "wep104", "wep40" - MgmtGroupsMangement frames cipher suite. Possible values are: "aes128cmac" + MgmtGroupsManagement frames cipher suite. Possible values are: "aes128cmac"
  • diff --git a/doc/doxygen.conf b/doc/doxygen.conf index cf2879010..3f0117393 100644 --- a/doc/doxygen.conf +++ b/doc/doxygen.conf @@ -278,7 +278,7 @@ TYPEDEF_HIDES_STRUCT = NO # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penality. +# causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the diff --git a/doc/driver_wrapper.doxygen b/doc/driver_wrapper.doxygen index a3b470a2e..66211b3ab 100644 --- a/doc/driver_wrapper.doxygen +++ b/doc/driver_wrapper.doxygen @@ -156,7 +156,7 @@ ap_scan=1: - wpa_supplicant requests scan with SIOCSIWSCAN - driver reports scan complete with wireless event SIOCGIWSCAN - wpa_supplicant reads scan results with SIOCGIWSCAN (multiple call if - a larget buffer is needed) + a larger buffer is needed) - wpa_supplicant decides which AP to use based on scan results - wpa_supplicant configures driver to associate with the selected BSS (SIOCSIWMODE, SIOCSIWGENIE, SIOCSIWAUTH, SIOCSIWFREQ, diff --git a/doc/p2p.doxygen b/doc/p2p.doxygen index f46d1b80a..d4d86e3ed 100644 --- a/doc/p2p.doxygen +++ b/doc/p2p.doxygen @@ -283,7 +283,7 @@ service discovery. The user of the P2P module is responsible for providing P2P specific Service Request TLV(s) for queries and Service Response TLV(s) for responses. -\subsection p2p_sd_query Quering services of peers +\subsection p2p_sd_query Querying services of peers Service discovery is implemented by processing pending queries as a part of the device discovery phase. \ref p2p_sd_request() function is used diff --git a/eap_example/Makefile b/eap_example/Makefile index 0cc19bd53..691466f03 100644 --- a/eap_example/Makefile +++ b/eap_example/Makefile @@ -1,28 +1,15 @@ ALL=eap_example -all: $(ALL) - -ifndef CC -CC=gcc -endif - -ifndef RANLIB -RANLIB=ranlib -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - +include ../src/build.rules CFLAGS += -I. CFLAGS += -I../src CFLAGS += -I../src/utils -OBJS_both += ../src/utils/libutils.a -OBJS_both += ../src/crypto/libcrypto.a -OBJS_both += ../src/tls/libtls.a +EAP_LIBS += ../src/utils/libutils.a +EAP_LIBS += ../src/crypto/libcrypto.a +EAP_LIBS += ../src/tls/libtls.a OBJS_both += ../src/eap_common/eap_peap_common.o OBJS_both += ../src/eap_common/eap_psk_common.o @@ -95,41 +82,22 @@ OBJS_server += ../src/eap_server/eap_server_tls_common.o CFLAGS += -DEAP_SERVER -ifndef LDO -LDO=$(CC) -endif - -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif - -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< - - OBJS_lib=$(OBJS_both) $(OBJS_peer) $(OBJS_server) +_OBJS_VAR := OBJS_lib +include ../src/objs.mk OBJS_ex = eap_example.o eap_example_peer.o eap_example_server.o +_OBJS_VAR := OBJS_ex +include ../src/objs.mk - -../src/utils/libutils.a: - $(MAKE) -C ../src/utils - -../src/crypto/libcrypto.a: - $(MAKE) -C ../src/crypto - -../src/tls/libtls.a: - $(MAKE) -C ../src/tls +_OBJS_VAR := EAP_LIBS +include ../src/objs.mk ifneq ($(CONFIG_SOLIB), yes) LIBEAP = libeap.a -libeap.a: $(OBJS_lib) - $(AR) crT libeap.a $(OBJS_lib) +libeap.a: $(EAP_LIBS) $(OBJS_lib) + $(AR) crT libeap.a $^ $(RANLIB) libeap.a else @@ -137,16 +105,15 @@ CFLAGS += -fPIC -DPIC LDFLAGS += -shared LIBEAP = libeap.so -libeap.so: $(OBJS_lib) - $(LDO) $(LDFLAGS) $(OBJS_lib) -o $(LIBEAP) +libeap.so: $(EAP_LIBS) $(OBJS_lib) + $(LDO) $(LDFLAGS) $^ -o $(LIBEAP) endif eap_example: $(OBJS_ex) $(LIBEAP) $(LDO) $(LDFLAGS) -o eap_example $(OBJS_ex) -L. -leap $(LIBS) -clean: - $(MAKE) -C ../src clean - rm -f core *~ *.o *.d libeap.a libeap.so $(ALL) +clean: common-clean + rm -f core *~ *.o *.d libeap.a libeap.so -include $(OBJS:%.o=%.d) diff --git a/eap_example/eap_example_peer.c b/eap_example/eap_example_peer.c index fcbfb12d8..5fe0cb7fa 100644 --- a/eap_example/eap_example_peer.c +++ b/eap_example/eap_example_peer.c @@ -18,16 +18,16 @@ void eap_example_server_rx(const u8 *data, size_t data_len); struct eap_peer_ctx { - Boolean eapSuccess; - Boolean eapRestart; - Boolean eapFail; - Boolean eapResp; - Boolean eapNoResp; - Boolean eapReq; - Boolean portEnabled; - Boolean altAccept; /* for EAP */ - Boolean altReject; /* for EAP */ - Boolean eapTriggerStart; + bool eapSuccess; + bool eapRestart; + bool eapFail; + bool eapResp; + bool eapNoResp; + bool eapReq; + bool portEnabled; + bool altAccept; /* for EAP */ + bool altReject; /* for EAP */ + bool eapTriggerStart; struct wpabuf *eapReqData; /* for EAP */ @@ -48,11 +48,11 @@ static struct eap_peer_config * peer_get_config(void *ctx) } -static Boolean peer_get_bool(void *ctx, enum eapol_bool_var variable) +static bool peer_get_bool(void *ctx, enum eapol_bool_var variable) { struct eap_peer_ctx *peer = ctx; if (peer == NULL) - return FALSE; + return false; switch (variable) { case EAPOL_eapSuccess: return peer->eapSuccess; @@ -75,12 +75,11 @@ static Boolean peer_get_bool(void *ctx, enum eapol_bool_var variable) case EAPOL_eapTriggerStart: return peer->eapTriggerStart; } - return FALSE; + return false; } -static void peer_set_bool(void *ctx, enum eapol_bool_var variable, - Boolean value) +static void peer_set_bool(void *ctx, enum eapol_bool_var variable, bool value) { struct eap_peer_ctx *peer = ctx; if (peer == NULL) @@ -319,7 +318,7 @@ int eap_example_peer_init(void) return -1; /* Enable "port" to allow authentication */ - eap_ctx.portEnabled = TRUE; + eap_ctx.portEnabled = true; return 0; } @@ -344,7 +343,7 @@ int eap_example_peer_step(void) if (eap_ctx.eapResp) { struct wpabuf *resp; printf("==> Response\n"); - eap_ctx.eapResp = FALSE; + eap_ctx.eapResp = false; resp = eap_get_eapRespData(eap_ctx.eap); if (resp) { /* Send EAP response to the server */ @@ -372,7 +371,7 @@ int eap_example_peer_step(void) void eap_example_peer_rx(const u8 *data, size_t data_len) { /* Make received EAP message available to the EAP library */ - eap_ctx.eapReq = TRUE; + eap_ctx.eapReq = true; wpabuf_free(eap_ctx.eapReqData); eap_ctx.eapReqData = wpabuf_alloc_copy(data, data_len); } diff --git a/eap_example/eap_example_server.c b/eap_example/eap_example_server.c index 1e91fa8ed..3a132bb34 100644 --- a/eap_example/eap_example_server.c +++ b/eap_example/eap_example_server.c @@ -234,8 +234,8 @@ int eap_example_server_init(void) eap_ctx.eap_if = eap_get_interface(eap_ctx.eap); /* Enable "port" and request EAP to start authentication. */ - eap_ctx.eap_if->portEnabled = TRUE; - eap_ctx.eap_if->eapRestart = TRUE; + eap_ctx.eap_if->portEnabled = true; + eap_ctx.eap_if->eapRestart = true; return 0; } @@ -296,5 +296,5 @@ void eap_example_server_rx(const u8 *data, size_t data_len) wpabuf_free(eap_ctx.eap_if->eapRespData); eap_ctx.eap_if->eapRespData = wpabuf_alloc_copy(data, data_len); if (eap_ctx.eap_if->eapRespData) - eap_ctx.eap_if->eapResp = TRUE; + eap_ctx.eap_if->eapResp = true; } diff --git a/hostapd/.gitignore b/hostapd/.gitignore new file mode 100644 index 000000000..857f3dc41 --- /dev/null +++ b/hostapd/.gitignore @@ -0,0 +1,5 @@ +.config +hostapd +hostapd_cli +hlr_auc_gw +nt_password_hash diff --git a/hostapd/Android.mk b/hostapd/Android.mk index 258c5ad9c..6c9561778 100644 --- a/hostapd/Android.mk +++ b/hostapd/Android.mk @@ -250,8 +250,13 @@ endif ifdef CONFIG_SAE L_CFLAGS += -DCONFIG_SAE OBJS += src/common/sae.c +ifdef CONFIG_SAE_PK +L_CFLAGS += -DCONFIG_SAE_PK +OBJS += src/common/sae_pk.c +endif NEED_ECC=y NEED_DH_GROUPS=y +NEED_HMAC_SHA256_KDF=y NEED_DRAGONFLY=y endif @@ -281,10 +286,6 @@ L_CFLAGS += -DCONFIG_WNM -DCONFIG_WNM_AP OBJS += src/ap/wnm_ap.c endif -ifdef CONFIG_IEEE80211N -L_CFLAGS += -DCONFIG_IEEE80211N -endif - ifdef CONFIG_IEEE80211AC L_CFLAGS += -DCONFIG_IEEE80211AC endif @@ -313,6 +314,14 @@ OBJS += src/fst/fst_ctrl_iface.c endif endif +ifdef CONFIG_WEP +L_CFLAGS += -DCONFIG_WEP +endif + +ifdef CONFIG_NO_TKIP +L_CFLAGS += -DCONFIG_NO_TKIP +endif + include $(LOCAL_PATH)/src/drivers/drivers.mk @@ -405,7 +414,7 @@ endif ifdef CONFIG_EAP_SIM_COMMON OBJS += src/eap_common/eap_sim_common.c # Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be -# replaced with another file implementating the interface specified in +# replaced with another file implementing the interface specified in # eap_sim_db.h. OBJS += src/eap_server/eap_sim_db.c NEED_FIPS186_2_PRF=y @@ -532,6 +541,12 @@ endif ifdef CONFIG_DPP L_CFLAGS += -DCONFIG_DPP OBJS += src/common/dpp.c +OBJS += src/common/dpp_auth.c +OBJS += src/common/dpp_backup.c +OBJS += src/common/dpp_crypto.c +OBJS += src/common/dpp_pkex.c +OBJS += src/common/dpp_reconfig.c +OBJS += src/common/dpp_tcp.c OBJS += src/ap/dpp_hostapd.c OBJS += src/ap/gas_query_ap.c NEED_AES_SIV=y @@ -999,9 +1014,7 @@ OBJS += src/ap/hw_features.c OBJS += src/ap/dfs.c L_CFLAGS += -DNEED_AP_MLME endif -ifdef CONFIG_IEEE80211N OBJS += src/ap/ieee802_11_ht.c -endif ifdef CONFIG_IEEE80211AC OBJS += src/ap/ieee802_11_vht.c diff --git a/hostapd/ChangeLog b/hostapd/ChangeLog index 6c4410e8e..34a8a0818 100644 --- a/hostapd/ChangeLog +++ b/hostapd/ChangeLog @@ -362,7 +362,7 @@ ChangeLog for hostapd * RADIUS server functionality - add minimal RADIUS accounting server support (hostapd-as-server); this is mainly to enable testing coverage with hwsim scripts - - allow authentication log to be written into SQLite databse + - allow authentication log to be written into SQLite database - added option for TLS protocol testing of an EAP peer by simulating various misbehaviors/known attacks - MAC ACL support for testing purposes @@ -668,7 +668,7 @@ ChangeLog for hostapd * fixed HT Capabilities IE with nl80211 drivers * moved generic AP functionality code into src/ap * WPS: handle Selected Registrar as union of info from all Registrars - * remove obsolte Prism54.org driver wrapper + * remove obsolete Prism54.org driver wrapper * added internal debugging mechanism with backtrace support and memory allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y) * EAP-FAST server: piggyback Phase 2 start with the end of Phase 1 diff --git a/hostapd/Makefile b/hostapd/Makefile index 8666763a0..456fb184f 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -1,10 +1,7 @@ -ifndef CC -CC=gcc -endif +ALL=hostapd hostapd_cli +CONFIG_FILE = .config -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif +include ../src/build.rules ifdef LIBS # If LIBS is set with some global build system defaults, clone those for @@ -19,6 +16,9 @@ endif ifndef LIBS_n LIBS_n := $(LIBS) endif +ifndef LIBS_s +LIBS_s := $(LIBS) +endif endif CFLAGS += $(EXTRA_CFLAGS) @@ -27,8 +27,6 @@ CFLAGS += -I$(abspath ../src/utils) export BINDIR ?= /usr/local/bin/ --include .config - ifndef CONFIG_NO_GITVER # Add VERSION_STR postfix for builds from a git repository ifeq ($(wildcard ../.git),../.git) @@ -122,6 +120,7 @@ LIBS += -lbfd -ldl -liberty -lz LIBS_c += -lbfd -ldl -liberty -lz LIBS_h += -lbfd -ldl -liberty -lz LIBS_n += -lbfd -ldl -liberty -lz +LIBS_s += -lbfd -ldl -liberty -lz endif endif @@ -294,8 +293,13 @@ endif ifdef CONFIG_SAE CFLAGS += -DCONFIG_SAE OBJS += ../src/common/sae.o +ifdef CONFIG_SAE_PK +CFLAGS += -DCONFIG_SAE_PK +OBJS += ../src/common/sae_pk.o +endif NEED_ECC=y NEED_DH_GROUPS=y +NEED_HMAC_SHA256_KDF=y NEED_AP_MLME=y NEED_DRAGONFLY=y endif @@ -331,10 +335,6 @@ CFLAGS += -DCONFIG_WNM -DCONFIG_WNM_AP OBJS += ../src/ap/wnm_ap.o endif -ifdef CONFIG_IEEE80211N -CFLAGS += -DCONFIG_IEEE80211N -endif - ifdef CONFIG_IEEE80211AC CFLAGS += -DCONFIG_IEEE80211AC endif @@ -444,7 +444,7 @@ endif ifdef CONFIG_EAP_SIM_COMMON OBJS += ../src/eap_common/eap_sim_common.o # Example EAP-SIM/AKA interface for GSM/UMTS authentication. This can be -# replaced with another file implementating the interface specified in +# replaced with another file implementing the interface specified in # eap_sim_db.h. OBJS += ../src/eap_server/eap_sim_db.o NEED_FIPS186_2_PRF=y @@ -571,6 +571,12 @@ endif ifdef CONFIG_DPP CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o +OBJS += ../src/common/dpp_auth.o +OBJS += ../src/common/dpp_backup.o +OBJS += ../src/common/dpp_crypto.o +OBJS += ../src/common/dpp_pkex.o +OBJS += ../src/common/dpp_reconfig.o +OBJS += ../src/common/dpp_tcp.o OBJS += ../src/ap/dpp_hostapd.o OBJS += ../src/ap/gas_query_ap.o NEED_AES_SIV=y @@ -697,6 +703,7 @@ LIBS += -lssl endif OBJS += ../src/crypto/crypto_openssl.o HOBJS += ../src/crypto/crypto_openssl.o +SOBJS += ../src/crypto/crypto_openssl.o ifdef NEED_FIPS186_2_PRF OBJS += ../src/crypto/fips_prf_openssl.o endif @@ -704,9 +711,11 @@ NEED_TLS_PRF_SHA256=y LIBS += -lcrypto LIBS_h += -lcrypto LIBS_n += -lcrypto +LIBS_s += -lcrypto ifdef CONFIG_TLS_ADD_DL LIBS += -ldl LIBS_h += -ldl +LIBS_s += -ldl endif ifndef CONFIG_TLS_DEFAULT_CIPHERS CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW" @@ -1155,9 +1164,7 @@ OBJS += ../src/ap/hw_features.o OBJS += ../src/ap/dfs.o CFLAGS += -DNEED_AP_MLME endif -ifdef CONFIG_IEEE80211N OBJS += ../src/ap/ieee802_11_ht.o -endif ifdef CONFIG_IEEE80211AC OBJS += ../src/ap/ieee802_11_vht.o @@ -1244,60 +1251,33 @@ OBJS += ../src/fst/fst_ctrl_iface.o endif endif -ALL=hostapd hostapd_cli - -all: verify_config $(ALL) - -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif -ifeq ($(QUIET), 1) -Q=@ -E=true +ifdef CONFIG_WEP +CFLAGS += -DCONFIG_WEP endif -ifdef CONFIG_CODE_COVERAGE -%.o: %.c - @$(E) " CC " $< - $(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<) -else -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< +ifdef CONFIG_NO_TKIP +CFLAGS += -DCONFIG_NO_TKIP endif -verify_config: - @if [ ! -r .config ]; then \ - echo 'Building hostapd requires a configuration file'; \ - echo '(.config). See README for more instructions. You can'; \ - echo 'run "cp defconfig .config" to create an example'; \ - echo 'configuration.'; \ - exit 1; \ - fi - $(DESTDIR)$(BINDIR)/%: % install -D $(<) $(@) install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL)) -../src/drivers/build.hostapd: - @if [ -f ../src/drivers/build.wpa_supplicant ]; then \ - $(MAKE) -C ../src/drivers clean; \ - fi - @touch ../src/drivers/build.hostapd +_OBJS_VAR := OBJS +include ../src/objs.mk -BCHECK=../src/drivers/build.hostapd - -hostapd: $(BCHECK) $(OBJS) +hostapd: $(OBJS) $(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS) @$(E) " LD " $@ ifdef CONFIG_WPA_TRACE OBJS_c += ../src/utils/trace.o endif + +_OBJS_VAR := OBJS_c +include ../src/objs.mk + hostapd_cli: $(OBJS_c) $(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c) @$(E) " LD " $@ @@ -1332,6 +1312,35 @@ ifeq ($(CONFIG_TLS), linux) HOBJS += ../src/crypto/crypto_linux.o endif +SOBJS += sae_pk_gen.o +SOBJS += ../src/utils/common.o +SOBJS += ../src/utils/os_$(CONFIG_OS).o +SOBJS += ../src/utils/base64.o +SOBJS += ../src/utils/wpa_debug.o +SOBJS += ../src/utils/wpabuf.o +ifdef CONFIG_WPA_TRACE +SOBJS += ../src/utils/trace.o +endif +SOBJS += ../src/common/ieee802_11_common.o +SOBJS += ../src/common/sae.o +SOBJS += ../src/common/sae_pk.o +SOBJS += ../src/common/dragonfly.o +SOBJS += $(AESOBJS) +SOBJS += ../src/crypto/sha256-prf.o +SOBJS += ../src/crypto/sha384-prf.o +SOBJS += ../src/crypto/sha512-prf.o +SOBJS += ../src/crypto/dh_groups.o +SOBJS += ../src/crypto/sha256-kdf.o +SOBJS += ../src/crypto/sha384-kdf.o +SOBJS += ../src/crypto/sha512-kdf.o + +_OBJS_VAR := NOBJS +include ../src/objs.mk +_OBJS_VAR := HOBJS +include ../src/objs.mk +_OBJS_VAR := SOBJS +include ../src/objs.mk + nt_password_hash: $(NOBJS) $(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n) @$(E) " LD " $@ @@ -1340,15 +1349,17 @@ hlr_auc_gw: $(HOBJS) $(Q)$(CC) $(LDFLAGS) -o hlr_auc_gw $(HOBJS) $(LIBS_h) @$(E) " LD " $@ +sae_pk_gen: $(SOBJS) + $(Q)$(CC) $(LDFLAGS) -o sae_pk_gen $(SOBJS) $(LIBS_s) + @$(E) " LD " $@ + +.PHONY: lcov-html lcov-html: - lcov -c -d .. > lcov.info + lcov -c -d $(BUILDDIR) > lcov.info genhtml lcov.info --output-directory lcov-html -clean: - $(MAKE) -C ../src clean - rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw - rm -f *.d *.gcno *.gcda *.gcov +clean: common-clean + rm -f core *~ nt_password_hash hlr_auc_gw + rm -f sae_pk_gen rm -f lcov.info rm -rf lcov-html - --include $(OBJS:%.o=%.d) diff --git a/hostapd/android.config b/hostapd/android.config index e2e6c7821..7bd792efe 100644 --- a/hostapd/android.config +++ b/hostapd/android.config @@ -125,9 +125,6 @@ CONFIG_IPV6=y # the IEEE 802.11 Management capability (e.g., FreeBSD/net80211) #CONFIG_DRIVER_RADIUS_ACL=y -# IEEE 802.11n (High Throughput) support -CONFIG_IEEE80211N=y - # Remove debugging code that is printing out debug messages to stdout. # This can be used to reduce the size of the hostapd considerably if debugging # code is not needed. @@ -187,7 +184,7 @@ CONFIG_AP=y #CONFIG_FST=y # Multiband Operation support -# These extentions facilitate efficient use of multiple frequency bands +# These extensions facilitate efficient use of multiple frequency bands # available to the AP and the devices that may associate with it. #CONFIG_MBO=y @@ -204,3 +201,11 @@ CONFIG_WPA_CLI_EDIT=y # /dev/urandom earlier in boot' seeds /dev/urandom with that entropy before # either wpa_supplicant or hostapd are run. CONFIG_NO_RANDOM_POOL=y + +# Wired equivalent privacy (WEP) +# WEP is an obsolete cryptographic data confidentiality algorithm that is not +# considered secure. It should not be used for anything anymore. The +# functionality needed to use WEP is available in the current hostapd +# release under this optional build parameter. This functionality is subject to +# be completely removed in a future release. +CONFIG_WEP=y diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 0169b989d..b3dc8f81a 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -14,6 +14,7 @@ #include "utils/common.h" #include "utils/uuid.h" #include "common/ieee802_11_defs.h" +#include "common/sae.h" #include "crypto/sha256.h" #include "crypto/tls.h" #include "drivers/driver.h" @@ -340,7 +341,7 @@ static int hostapd_config_read_eap_user(const char *fname, struct hostapd_radius_attr *attr, *a; attr = hostapd_parse_radius_attr(buf + 19); if (attr == NULL) { - wpa_printf(MSG_ERROR, "Invalid radius_auth_req_attr: %s", + wpa_printf(MSG_ERROR, "Invalid radius_accept_attr: %s", buf + 19); user = NULL; /* already in the BSS list */ goto failed; @@ -793,6 +794,7 @@ static int hostapd_config_parse_cipher(int line, const char *value) } +#ifdef CONFIG_WEP static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, char *val) { @@ -843,6 +845,7 @@ static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, return 0; } +#endif /* CONFIG_WEP */ static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val) @@ -940,104 +943,6 @@ static int hostapd_config_bss(struct hostapd_config *conf, const char *ifname) } -/* convert floats with one decimal place to value*10 int, i.e., - * "1.5" will return 15 */ -static int hostapd_config_read_int10(const char *value) -{ - int i, d; - char *pos; - - i = atoi(value); - pos = os_strchr(value, '.'); - d = 0; - if (pos) { - pos++; - if (*pos >= '0' && *pos <= '9') - d = *pos - '0'; - } - - return i * 10 + d; -} - - -static int valid_cw(int cw) -{ - return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 || - cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 || - cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 || - cw == 32767); -} - - -enum { - IEEE80211_TX_QUEUE_DATA0 = 0, /* used for EDCA AC_VO data */ - IEEE80211_TX_QUEUE_DATA1 = 1, /* used for EDCA AC_VI data */ - IEEE80211_TX_QUEUE_DATA2 = 2, /* used for EDCA AC_BE data */ - IEEE80211_TX_QUEUE_DATA3 = 3 /* used for EDCA AC_BK data */ -}; - -static int hostapd_config_tx_queue(struct hostapd_config *conf, - const char *name, const char *val) -{ - int num; - const char *pos; - struct hostapd_tx_queue_params *queue; - - /* skip 'tx_queue_' prefix */ - pos = name + 9; - if (os_strncmp(pos, "data", 4) == 0 && - pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') { - num = pos[4] - '0'; - pos += 6; - } else if (os_strncmp(pos, "after_beacon_", 13) == 0 || - os_strncmp(pos, "beacon_", 7) == 0) { - wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); - return 0; - } else { - wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos); - return -1; - } - - if (num >= NUM_TX_QUEUES) { - /* for backwards compatibility, do not trigger failure */ - wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); - return 0; - } - - queue = &conf->tx_queue[num]; - - if (os_strcmp(pos, "aifs") == 0) { - queue->aifs = atoi(val); - if (queue->aifs < 0 || queue->aifs > 255) { - wpa_printf(MSG_ERROR, "Invalid AIFS value %d", - queue->aifs); - return -1; - } - } else if (os_strcmp(pos, "cwmin") == 0) { - queue->cwmin = atoi(val); - if (!valid_cw(queue->cwmin)) { - wpa_printf(MSG_ERROR, "Invalid cwMin value %d", - queue->cwmin); - return -1; - } - } else if (os_strcmp(pos, "cwmax") == 0) { - queue->cwmax = atoi(val); - if (!valid_cw(queue->cwmax)) { - wpa_printf(MSG_ERROR, "Invalid cwMax value %d", - queue->cwmax); - return -1; - } - } else if (os_strcmp(pos, "burst") == 0) { - queue->burst = hostapd_config_read_int10(val); - } else { - wpa_printf(MSG_ERROR, "Unknown tx_queue field '%s'", pos); - return -1; - } - - return 0; -} - - #ifdef CONFIG_IEEE80211R_AP static int rkh_derive_key(const char *pos, u8 *key, size_t key_len) @@ -1151,7 +1056,6 @@ static int add_r1kh(struct hostapd_bss_config *bss, char *value) #endif /* CONFIG_IEEE80211R_AP */ -#ifdef CONFIG_IEEE80211N static int hostapd_config_ht_capab(struct hostapd_config *conf, const char *capab) { @@ -1171,14 +1075,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf, } if (!os_strstr(capab, "[HT40+]") && !os_strstr(capab, "[HT40-]")) conf->secondary_channel = 0; - if (os_strstr(capab, "[SMPS-STATIC]")) { - conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; - conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC; - } - if (os_strstr(capab, "[SMPS-DYNAMIC]")) { - conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; - conf->ht_capab |= HT_CAP_INFO_SMPS_DYNAMIC; - } if (os_strstr(capab, "[GF]")) conf->ht_capab |= HT_CAP_INFO_GREEN_FIELD; if (os_strstr(capab, "[SHORT-GI-20]")) @@ -1212,7 +1108,6 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf, return 0; } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC @@ -2298,6 +2193,35 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val) pw->vlan_id = atoi(pos2); } +#ifdef CONFIG_SAE_PK + pos2 = os_strstr(pos, "|pk="); + if (pos2) { + const char *epos; + char *tmp; + + if (!end) + end = pos2; + pos2 += 4; + epos = os_strchr(pos2, '|'); + if (epos) { + tmp = os_malloc(epos - pos2 + 1); + if (!tmp) + goto fail; + os_memcpy(tmp, pos2, epos - pos2); + tmp[epos - pos2] = '\0'; + } else { + tmp = os_strdup(pos2); + if (!tmp) + goto fail; + } + + pw->pk = sae_parse_pk(tmp); + str_clear_free(tmp); + if (!pw->pk) + goto fail; + } +#endif /* CONFIG_SAE_PK */ + pos2 = os_strstr(pos, "|id="); if (pos2) { if (!end) @@ -2320,6 +2244,18 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val) pw->password[end - val] = '\0'; } +#ifdef CONFIG_SAE_PK + if (pw->pk && +#ifdef CONFIG_TESTING_OPTIONS + !bss->sae_pk_password_check_skip && +#endif /* CONFIG_TESTING_OPTIONS */ + !sae_pk_valid_password(pw->password)) { + wpa_printf(MSG_INFO, + "Invalid SAE password for a SAE-PK sae_password entry"); + goto fail; + } +#endif /* CONFIG_SAE_PK */ + pw->next = bss->sae_passwords; bss->sae_passwords = pw; @@ -2327,6 +2263,9 @@ static int parse_sae_password(struct hostapd_bss_config *bss, const char *val) fail: str_clear_free(pw->password); os_free(pw->identifier); +#ifdef CONFIG_SAE_PK + sae_deinit_pk(pw->pk); +#endif /* CONFIG_SAE_PK */ os_free(pw); return -1; } @@ -2471,6 +2410,13 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "skip_inactivity_poll") == 0) { bss->skip_inactivity_poll = atoi(pos); } else if (os_strcmp(buf, "country_code") == 0) { + if (pos[0] < 'A' || pos[0] > 'Z' || + pos[1] < 'A' || pos[1] > 'Z') { + wpa_printf(MSG_ERROR, + "Line %d: Invalid country_code '%s'", + line, pos); + return 1; + } os_memcpy(conf->country, pos, 2); } else if (os_strcmp(buf, "country3") == 0) { conf->country[2] = strtol(pos, NULL, 16); @@ -2613,7 +2559,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "eap_teap_auth") == 0) { int val = atoi(pos); - if (val < 0 || val > 1) { + if (val < 0 || val > 2) { wpa_printf(MSG_ERROR, "Line %d: Invalid eap_teap_auth value", line); @@ -2674,6 +2620,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "erp_domain") == 0) { os_free(bss->erp_domain); bss->erp_domain = os_strdup(pos); +#ifdef CONFIG_WEP } else if (os_strcmp(buf, "wep_key_len_broadcast") == 0) { int val = atoi(pos); @@ -2701,6 +2648,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, line, bss->wep_rekeying_period); return 1; } +#endif /* CONFIG_WEP */ } else if (os_strcmp(buf, "eap_reauth_period") == 0) { bss->eap_reauth_period = atoi(pos); if (bss->eap_reauth_period < 0) { @@ -2875,6 +2823,16 @@ static int hostapd_config_fill(struct hostapd_config *conf, } } else if (os_strcmp(buf, "wpa") == 0) { bss->wpa = atoi(pos); + } else if (os_strcmp(buf, "extended_key_id") == 0) { + int val = atoi(pos); + + if (val < 0 || val > 2) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid extended_key_id=%d; allowed range 0..2", + line, val); + return 1; + } + bss->extended_key_id = val; } else if (os_strcmp(buf, "wpa_group_rekey") == 0) { bss->wpa_group_rekey = atoi(pos); bss->wpa_group_rekey_set = 1; @@ -2884,6 +2842,15 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->wpa_gmk_rekey = atoi(pos); } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) { bss->wpa_ptk_rekey = atoi(pos); + } else if (os_strcmp(buf, "wpa_deny_ptk0_rekey") == 0) { + bss->wpa_deny_ptk0_rekey = atoi(pos); + if (bss->wpa_deny_ptk0_rekey < 0 || + bss->wpa_deny_ptk0_rekey > 2) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid wpa_deny_ptk0_rekey=%d; allowed range 0..2", + line, bss->wpa_deny_ptk0_rekey); + return 1; + } } else if (os_strcmp(buf, "wpa_group_update_count") == 0) { char *endp; unsigned long val = strtoul(pos, &endp, 0); @@ -3312,6 +3279,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->ignore_broadcast_ssid = atoi(pos); } else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) { bss->no_probe_resp_if_max_sta = atoi(pos); +#ifdef CONFIG_WEP } else if (os_strcmp(buf, "wep_default_key") == 0) { bss->ssid.wep.idx = atoi(pos); if (bss->ssid.wep.idx > 3) { @@ -3330,6 +3298,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, line, buf); return 1; } +#endif /* CONFIG_WEP */ #ifndef CONFIG_NO_VLAN } else if (os_strcmp(buf, "dynamic_vlan") == 0) { bss->ssid.dynamic_vlan = atoi(pos); @@ -3361,7 +3330,7 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) { conf->ap_table_expiration_time = atoi(pos); } else if (os_strncmp(buf, "tx_queue_", 9) == 0) { - if (hostapd_config_tx_queue(conf, buf, pos)) { + if (hostapd_config_tx_queue(conf->tx_queue, buf, pos)) { wpa_printf(MSG_ERROR, "Line %d: invalid TX queue item", line); return 1; @@ -3408,6 +3377,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, line, pos); return 1; } + } else if (os_strcmp(buf, "beacon_prot") == 0) { + bss->beacon_prot = atoi(pos); } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) { bss->assoc_sa_query_max_timeout = atoi(pos); if (bss->assoc_sa_query_max_timeout == 0) { @@ -3428,7 +3399,6 @@ static int hostapd_config_fill(struct hostapd_config *conf, if (bss->ocv && !bss->ieee80211w) bss->ieee80211w = 1; #endif /* CONFIG_OCV */ -#ifdef CONFIG_IEEE80211N } else if (os_strcmp(buf, "ieee80211n") == 0) { conf->ieee80211n = atoi(pos); } else if (os_strcmp(buf, "ht_capab") == 0) { @@ -3441,7 +3411,6 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->require_ht = atoi(pos); } else if (os_strcmp(buf, "obss_interval") == 0) { conf->obss_interval = atoi(pos); -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC } else if (os_strcmp(buf, "ieee80211ac") == 0) { conf->ieee80211ac = atoi(pos); @@ -3474,7 +3443,10 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "he_mu_beamformer") == 0) { conf->he_phy_capab.he_mu_beamformer = atoi(pos); } else if (os_strcmp(buf, "he_bss_color") == 0) { - conf->he_op.he_bss_color = atoi(pos); + conf->he_op.he_bss_color = atoi(pos) & 0x3f; + conf->he_op.he_bss_color_disabled = 0; + } else if (os_strcmp(buf, "he_bss_color_partial") == 0) { + conf->he_op.he_bss_color_partial = atoi(pos); } else if (os_strcmp(buf, "he_default_pe_duration") == 0) { conf->he_op.he_default_pe_duration = atoi(pos); } else if (os_strcmp(buf, "he_twt_required") == 0) { @@ -4165,18 +4137,53 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->own_ie_override = tmp; } else if (os_strcmp(buf, "sae_reflection_attack") == 0) { bss->sae_reflection_attack = atoi(pos); + } else if (os_strcmp(buf, "sae_commit_status") == 0) { + bss->sae_commit_status = atoi(pos); + } else if (os_strcmp(buf, "sae_pk_omit") == 0) { + bss->sae_pk_omit = atoi(pos); + } else if (os_strcmp(buf, "sae_pk_password_check_skip") == 0) { + bss->sae_pk_password_check_skip = atoi(pos); } else if (os_strcmp(buf, "sae_commit_override") == 0) { wpabuf_free(bss->sae_commit_override); bss->sae_commit_override = wpabuf_parse_bin(pos); + } else if (os_strcmp(buf, "rsne_override_eapol") == 0) { + wpabuf_free(bss->rsne_override_eapol); + bss->rsne_override_eapol = wpabuf_parse_bin(pos); } else if (os_strcmp(buf, "rsnxe_override_eapol") == 0) { wpabuf_free(bss->rsnxe_override_eapol); bss->rsnxe_override_eapol = wpabuf_parse_bin(pos); + } else if (os_strcmp(buf, "rsne_override_ft") == 0) { + wpabuf_free(bss->rsne_override_ft); + bss->rsne_override_ft = wpabuf_parse_bin(pos); + } else if (os_strcmp(buf, "rsnxe_override_ft") == 0) { + wpabuf_free(bss->rsnxe_override_ft); + bss->rsnxe_override_ft = wpabuf_parse_bin(pos); } else if (os_strcmp(buf, "gtk_rsc_override") == 0) { wpabuf_free(bss->gtk_rsc_override); bss->gtk_rsc_override = wpabuf_parse_bin(pos); } else if (os_strcmp(buf, "igtk_rsc_override") == 0) { wpabuf_free(bss->igtk_rsc_override); bss->igtk_rsc_override = wpabuf_parse_bin(pos); + } else if (os_strcmp(buf, "no_beacon_rsnxe") == 0) { + bss->no_beacon_rsnxe = atoi(pos); + } else if (os_strcmp(buf, "skip_prune_assoc") == 0) { + bss->skip_prune_assoc = atoi(pos); + } else if (os_strcmp(buf, "ft_rsnxe_used") == 0) { + bss->ft_rsnxe_used = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_eapol_m3") == 0) { + bss->oci_freq_override_eapol_m3 = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_eapol_g1") == 0) { + bss->oci_freq_override_eapol_g1 = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_saquery_req") == 0) { + bss->oci_freq_override_saquery_req = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_saquery_resp") == 0) { + bss->oci_freq_override_saquery_resp = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_ft_assoc") == 0) { + bss->oci_freq_override_ft_assoc = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_fils_assoc") == 0) { + bss->oci_freq_override_fils_assoc = atoi(pos); + } else if (os_strcmp(buf, "oci_freq_override_wnm_sleep") == 0) { + bss->oci_freq_override_wnm_sleep = atoi(pos); #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_SAE } else if (os_strcmp(buf, "sae_password") == 0) { @@ -4379,6 +4386,18 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "dpp_controller") == 0) { if (hostapd_dpp_controller_parse(bss, pos)) return 1; + } else if (os_strcmp(buf, "dpp_configurator_connectivity") == 0) { + bss->dpp_configurator_connectivity = atoi(pos); + } else if (os_strcmp(buf, "dpp_pfs") == 0) { + int val = atoi(pos); + + if (val < 0 || val > 2) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid dpp_pfs value '%s'", + line, pos); + return -1; + } + bss->dpp_pfs = val; #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ #ifdef CONFIG_OWE @@ -4431,8 +4450,12 @@ static int hostapd_config_fill(struct hostapd_config *conf, conf->rssi_reject_assoc_rssi = atoi(pos); } else if (os_strcmp(buf, "rssi_reject_assoc_timeout") == 0) { conf->rssi_reject_assoc_timeout = atoi(pos); + } else if (os_strcmp(buf, "rssi_ignore_probe_request") == 0) { + conf->rssi_ignore_probe_request = atoi(pos); } else if (os_strcmp(buf, "pbss") == 0) { bss->pbss = atoi(pos); + } else if (os_strcmp(buf, "transition_disable") == 0) { + bss->transition_disable = strtol(pos, NULL, 16); #ifdef CONFIG_AIRTIME_POLICY } else if (os_strcmp(buf, "airtime_mode") == 0) { int val = atoi(pos); @@ -4548,6 +4571,12 @@ static int hostapd_config_fill(struct hostapd_config *conf, } bss->mka_psk_set |= MKA_PSK_SET_CKN; #endif /* CONFIG_MACSEC */ + } else if (os_strcmp(buf, "disable_11n") == 0) { + bss->disable_11n = !!atoi(pos); + } else if (os_strcmp(buf, "disable_11ac") == 0) { + bss->disable_11ac = !!atoi(pos); + } else if (os_strcmp(buf, "disable_11ax") == 0) { + bss->disable_11ax = !!atoi(pos); } else { wpa_printf(MSG_ERROR, "Line %d: unknown configuration item '%s'", diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index cbe074a95..85c15c5c2 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -49,6 +49,7 @@ #include "ap/ieee802_1x.h" #include "ap/wpa_auth.h" #include "ap/wpa_auth_i.h" +#include "ap/pmksa_cache_auth.h" #include "ap/ieee802_11.h" #include "ap/sta_info.h" #include "ap/wps_hostapd.h" @@ -61,6 +62,7 @@ #include "ap/neighbor_db.h" #include "ap/rrm.h" #include "ap/dpp_hostapd.h" +#include "ap/dfs.h" #include "wps/wps_defs.h" #include "wps/wps.h" #include "fst/fst_ctrl_iface.h" @@ -71,9 +73,6 @@ #define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256 #ifdef CONFIG_CTRL_IFACE_UDP -#define COOKIE_LEN 8 -static unsigned char cookie[COOKIE_LEN]; -static unsigned char gcookie[COOKIE_LEN]; #define HOSTAPD_CTRL_IFACE_PORT 8877 #define HOSTAPD_CTRL_IFACE_PORT_LIMIT 50 #define HOSTAPD_GLOBAL_CTRL_IFACE_PORT 8878 @@ -1294,6 +1293,22 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, pos += ret; } + if (hapd->conf->wpa && hapd->conf->wpa_deny_ptk0_rekey) { + ret = os_snprintf(pos, end - pos, "wpa_deny_ptk0_rekey=%d\n", + hapd->conf->wpa_deny_ptk0_rekey); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + + if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->extended_key_id) { + ret = os_snprintf(pos, end - pos, "extended_key_id=%d\n", + hapd->conf->extended_key_id); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + return pos - buf; } @@ -1336,21 +1351,29 @@ static void hostapd_disassoc_deny_mac(struct hostapd_data *hapd) static int hostapd_ctrl_iface_set_band(struct hostapd_data *hapd, - const char *band) + const char *bands) { union wpa_event_data event; - enum set_band setband; + u32 setband_mask = WPA_SETBAND_AUTO; - if (os_strcmp(band, "AUTO") == 0) - setband = WPA_SETBAND_AUTO; - else if (os_strcmp(band, "5G") == 0) - setband = WPA_SETBAND_5G; - else if (os_strcmp(band, "2G") == 0) - setband = WPA_SETBAND_2G; - else - return -1; + /* + * For example: + * SET setband 2G,6G + * SET setband 5G + * SET setband AUTO + */ + if (!os_strstr(bands, "AUTO")) { + if (os_strstr(bands, "5G")) + setband_mask |= WPA_SETBAND_5G; + if (os_strstr(bands, "6G")) + setband_mask |= WPA_SETBAND_6G; + if (os_strstr(bands, "2G")) + setband_mask |= WPA_SETBAND_2G; + if (setband_mask == WPA_SETBAND_AUTO) + return -1; + } - if (hostapd_drv_set_band(hapd, setband) == 0) { + if (hostapd_drv_set_band(hapd, setband_mask) == 0) { os_memset(&event, 0, sizeof(event)); event.channel_list_changed.initiator = REGDOM_SET_BY_USER; event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN; @@ -1418,6 +1441,8 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) hapd->dpp_ignore_netaccesskey_mismatch = atoi(value); } else if (os_strcasecmp(cmd, "dpp_test") == 0) { dpp_test = atoi(value); + } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) { + dpp_version_override = atoi(value); #endif /* CONFIG_DPP */ #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_MBO @@ -1466,7 +1491,32 @@ static int hostapd_ctrl_iface_set(struct hostapd_data *hapd, char *cmd) os_strcmp(cmd, "sae_pwe") == 0) { if (hapd->started) hostapd_setup_sae_pt(hapd->conf); + } else if (os_strcasecmp(cmd, "transition_disable") == 0) { + wpa_auth_set_transition_disable(hapd->wpa_auth, + hapd->conf->transition_disable); } + +#ifdef CONFIG_TESTING_OPTIONS + if (os_strcmp(cmd, "ft_rsnxe_used") == 0) + wpa_auth_set_ft_rsnxe_used(hapd->wpa_auth, + hapd->conf->ft_rsnxe_used); + else if (os_strcmp(cmd, "oci_freq_override_eapol_m3") == 0) + wpa_auth_set_ocv_override_freq( + hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_M3, + atoi(value)); + else if (os_strcmp(cmd, "oci_freq_override_eapol_g1") == 0) + wpa_auth_set_ocv_override_freq( + hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_EAPOL_G1, + atoi(value)); + else if (os_strcmp(cmd, "oci_freq_override_ft_assoc") == 0) + wpa_auth_set_ocv_override_freq( + hapd->wpa_auth, WPA_AUTH_OCV_OVERRIDE_FT_ASSOC, + atoi(value)); + else if (os_strcmp(cmd, "oci_freq_override_fils_assoc") == 0) + wpa_auth_set_ocv_override_freq( + hapd->wpa_auth, + WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC, atoi(value)); +#endif /* CONFIG_TESTING_OPTIONS */ } return ret; @@ -1884,7 +1934,7 @@ static void hostapd_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) { wpa_printf(MSG_DEBUG, - "test data: RX - ignore unexpect IP header"); + "test data: RX - ignore unexpected IP header"); return; } @@ -2147,6 +2197,32 @@ static int hostapd_ctrl_reset_pn(struct hostapd_data *hapd, const char *cmd) if (hwaddr_aton(cmd, addr)) return -1; + if (is_broadcast_ether_addr(addr) && os_strstr(cmd, " BIGTK")) { + if (hapd->last_bigtk_alg == WPA_ALG_NONE) + return -1; + + wpa_printf(MSG_INFO, "TESTING: Reset BIPN for BIGTK"); + + /* First, use a zero key to avoid any possible duplicate key + * avoidance in the driver. */ + if (hostapd_drv_set_key(hapd->conf->iface, hapd, + hapd->last_bigtk_alg, + broadcast_ether_addr, + hapd->last_bigtk_key_idx, 0, 1, NULL, 0, + zero, hapd->last_bigtk_len, + KEY_FLAG_GROUP_TX_DEFAULT) < 0) + return -1; + + /* Set the previously configured key to reset its TSC */ + return hostapd_drv_set_key(hapd->conf->iface, hapd, + hapd->last_bigtk_alg, + broadcast_ether_addr, + hapd->last_bigtk_key_idx, 0, 1, NULL, + 0, hapd->last_bigtk, + hapd->last_bigtk_len, + KEY_FLAG_GROUP_TX_DEFAULT); + } + if (is_broadcast_ether_addr(addr) && os_strstr(cmd, "IGTK")) { if (hapd->last_igtk_alg == WPA_ALG_NONE) return -1; @@ -2412,6 +2488,19 @@ static int hostapd_ctrl_resend_group_m1(struct hostapd_data *hapd, } +static int hostapd_ctrl_get_pmksa_pmk(struct hostapd_data *hapd, const u8 *addr, + char *buf, size_t buflen) +{ + struct rsn_pmksa_cache_entry *pmksa; + + pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, addr, NULL); + if (!pmksa) + return -1; + + return wpa_snprintf_hex(buf, buflen, pmksa->pmk, pmksa->pmk_len); +} + + static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd, char *buf, size_t buflen) { @@ -2427,13 +2516,13 @@ static int hostapd_ctrl_get_pmk(struct hostapd_data *hapd, const char *cmd, if (!sta || !sta->wpa_sm) { wpa_printf(MSG_DEBUG, "No STA WPA state machine for " MACSTR, MAC2STR(addr)); - return -1; + return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen); } pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len); - if (!pmk) { + if (!pmk || !pmk_len) { wpa_printf(MSG_DEBUG, "No PMK stored for " MACSTR, MAC2STR(addr)); - return -1; + return hostapd_ctrl_get_pmksa_pmk(hapd, addr, buf, buflen); } return wpa_snprintf_hex(buf, buflen, pmk, pmk_len); @@ -2501,18 +2590,175 @@ static int hostapd_get_channel(struct hostapd_data *hapd, char *buf, size_t buf #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef NEED_AP_MLME +static int hostapd_ctrl_check_freq_params(struct hostapd_freq_params *params) +{ + switch (params->bandwidth) { + case 0: + /* bandwidth not specified: use 20 MHz by default */ + /* fall-through */ + case 20: + if (params->center_freq1 && + params->center_freq1 != params->freq) + return -1; + + if (params->center_freq2 || params->sec_channel_offset) + return -1; + break; + case 40: + if (params->center_freq2 || !params->sec_channel_offset) + return -1; + + if (!params->center_freq1) + break; + switch (params->sec_channel_offset) { + case 1: + if (params->freq + 10 != params->center_freq1) + return -1; + break; + case -1: + if (params->freq - 10 != params->center_freq1) + return -1; + break; + default: + return -1; + } + break; + case 80: + if (!params->center_freq1 || !params->sec_channel_offset) + return 1; + + switch (params->sec_channel_offset) { + case 1: + if (params->freq - 10 != params->center_freq1 && + params->freq + 30 != params->center_freq1) + return 1; + break; + case -1: + if (params->freq + 10 != params->center_freq1 && + params->freq - 30 != params->center_freq1) + return -1; + break; + default: + return -1; + } + + /* Adjacent and overlapped are not allowed for 80+80 */ + if (params->center_freq2 && + params->center_freq1 - params->center_freq2 <= 80 && + params->center_freq2 - params->center_freq1 <= 80) + return 1; + break; + case 160: + if (!params->center_freq1 || params->center_freq2 || + !params->sec_channel_offset) + return -1; + + switch (params->sec_channel_offset) { + case 1: + if (params->freq + 70 != params->center_freq1 && + params->freq + 30 != params->center_freq1 && + params->freq - 10 != params->center_freq1 && + params->freq - 50 != params->center_freq1) + return -1; + break; + case -1: + if (params->freq + 50 != params->center_freq1 && + params->freq + 10 != params->center_freq1 && + params->freq - 30 != params->center_freq1 && + params->freq - 70 != params->center_freq1) + return -1; + break; + default: + return -1; + } + break; + default: + return -1; + } + + return 0; +} +#endif /* NEED_AP_MLME */ + + static int hostapd_ctrl_iface_chan_switch(struct hostapd_iface *iface, char *pos) { #ifdef NEED_AP_MLME struct csa_settings settings; int ret; + int dfs_range = 0; unsigned int i; + int bandwidth; + u8 chan; ret = hostapd_parse_csa_settings(pos, &settings); if (ret) return ret; + ret = hostapd_ctrl_check_freq_params(&settings.freq_params); + if (ret) { + wpa_printf(MSG_INFO, + "chanswitch: invalid frequency settings provided"); + return ret; + } + + switch (settings.freq_params.bandwidth) { + case 40: + bandwidth = CHAN_WIDTH_40; + break; + case 80: + if (settings.freq_params.center_freq2) + bandwidth = CHAN_WIDTH_80P80; + else + bandwidth = CHAN_WIDTH_80; + break; + case 160: + bandwidth = CHAN_WIDTH_160; + break; + default: + bandwidth = CHAN_WIDTH_20; + break; + } + + if (settings.freq_params.center_freq1) + dfs_range += hostapd_is_dfs_overlap( + iface, bandwidth, settings.freq_params.center_freq1); + else + dfs_range += hostapd_is_dfs_overlap( + iface, bandwidth, settings.freq_params.freq); + + if (settings.freq_params.center_freq2) + dfs_range += hostapd_is_dfs_overlap( + iface, bandwidth, settings.freq_params.center_freq2); + + if (dfs_range) { + ret = ieee80211_freq_to_chan(settings.freq_params.freq, &chan); + if (ret == NUM_HOSTAPD_MODES) { + wpa_printf(MSG_ERROR, + "Failed to get channel for (freq=%d, sec_channel_offset=%d, bw=%d)", + settings.freq_params.freq, + settings.freq_params.sec_channel_offset, + settings.freq_params.bandwidth); + return -1; + } + + settings.freq_params.channel = chan; + + wpa_printf(MSG_DEBUG, + "DFS/CAC to (channel=%u, freq=%d, sec_channel_offset=%d, bw=%d, center_freq1=%d)", + settings.freq_params.channel, + settings.freq_params.freq, + settings.freq_params.sec_channel_offset, + settings.freq_params.bandwidth, + settings.freq_params.center_freq1); + + /* Perform CAC and switch channel */ + hostapd_switch_channel_fallback(iface, &settings.freq_params); + return 0; + } + for (i = 0; i < iface->num_bss; i++) { /* Save CHAN_SWITCH VHT config */ @@ -2551,13 +2797,17 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen) { int ret; - char *pos; + char *pos, *temp = NULL; u8 *data = NULL; unsigned int vendor_id, subcmd; + enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED; struct wpabuf *reply; size_t data_len = 0; - /* cmd: [] */ + /** + * cmd: [] + * [nested=<0|1>] + */ vendor_id = strtoul(cmd, &pos, 16); if (!isblank((unsigned char) *pos)) return -EINVAL; @@ -2567,7 +2817,9 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, if (*pos != '\0') { if (!isblank((unsigned char) *pos++)) return -EINVAL; - data_len = os_strlen(pos); + + temp = os_strchr(pos, ' '); + data_len = temp ? (size_t) (temp - pos) : os_strlen(pos); } if (data_len) { @@ -2584,6 +2836,11 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, } } + pos = os_strstr(cmd, "nested="); + if (pos) + nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED : + NESTED_ATTR_NOT_USED; + reply = wpabuf_alloc((buflen - 1) / 2); if (!reply) { os_free(data); @@ -2591,7 +2848,7 @@ static int hostapd_ctrl_iface_vendor(struct hostapd_data *hapd, char *cmd, } ret = hostapd_drv_vendor_cmd(hapd, vendor_id, subcmd, data, data_len, - reply); + nested_attr_flag, reply); if (ret == 0) ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), @@ -3012,6 +3269,34 @@ static int hostapd_ctrl_driver_flags(struct hostapd_iface *iface, char *buf, } +static int hostapd_ctrl_driver_flags2(struct hostapd_iface *iface, char *buf, + size_t buflen) +{ + int ret, i; + char *pos, *end; + + ret = os_snprintf(buf, buflen, "%016llX:\n", + (long long unsigned) iface->drv_flags2); + if (os_snprintf_error(buflen, ret)) + return -1; + + pos = buf + ret; + end = buf + buflen; + + for (i = 0; i < 64; i++) { + if (iface->drv_flags2 & (1LLU << i)) { + ret = os_snprintf(pos, end - pos, "%s\n", + driver_flag2_to_string(1LLU << i)); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + } + + return pos - buf; +} + + static int hostapd_ctrl_iface_acl_del_mac(struct mac_acl_entry **acl, int *num, const char *txtaddr) { @@ -3443,6 +3728,9 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { reply_len = hostapd_ctrl_driver_flags(hapd->iface, reply, reply_size); + } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) { + reply_len = hostapd_ctrl_driver_flags2(hapd->iface, reply, + reply_size); } else if (os_strcmp(buf, "TERMINATE") == 0) { eloop_terminate(); } else if (os_strncmp(buf, "ACCEPT_ACL ", 11) == 0) { @@ -3551,6 +3839,11 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, reply_len = dpp_bootstrap_info(hapd->iface->interfaces->dpp, atoi(buf + 19), reply, reply_size); + } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) { + if (dpp_bootstrap_set(hapd->iface->interfaces->dpp, + atoi(buf + 18), + os_strchr(buf + 18, ' ')) < 0) + reply_len = -1; } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { if (hostapd_dpp_auth_init(hapd, buf + 13) < 0) reply_len = -1; @@ -3594,6 +3887,21 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd, } else if (os_strncmp(buf, "DPP_PKEX_REMOVE ", 16) == 0) { if (hostapd_dpp_pkex_remove(hapd, buf + 16) < 0) reply_len = -1; +#ifdef CONFIG_DPP2 + } else if (os_strncmp(buf, "DPP_CONTROLLER_START ", 21) == 0) { + if (hostapd_dpp_controller_start(hapd, buf + 20) < 0) + reply_len = -1; + } else if (os_strcmp(buf, "DPP_CONTROLLER_START") == 0) { + if (hostapd_dpp_controller_start(hapd, NULL) < 0) + reply_len = -1; + } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) { + dpp_controller_stop(hapd->iface->interfaces->dpp); + } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) { + if (hostapd_dpp_chirp(hapd, buf + 9) < 0) + reply_len = -1; + } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) { + hostapd_dpp_chirp_stop(hapd); +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ #ifdef RADIUS_SERVER } else if (os_strncmp(buf, "DAC_REQUEST ", 12) == 0) { @@ -3642,7 +3950,7 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, int reply_len; int level = MSG_DEBUG; #ifdef CONFIG_CTRL_IFACE_UDP - unsigned char lcookie[COOKIE_LEN]; + unsigned char lcookie[CTRL_IFACE_COOKIE_LEN]; #endif /* CONFIG_CTRL_IFACE_UDP */ res = recvfrom(sock, buf, sizeof(buf) - 1, 0, @@ -3667,28 +3975,30 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, #ifdef CONFIG_CTRL_IFACE_UDP if (os_strcmp(buf, "GET_COOKIE") == 0) { os_memcpy(reply, "COOKIE=", 7); - wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, - cookie, COOKIE_LEN); - reply_len = 7 + 2 * COOKIE_LEN; + wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1, + hapd->ctrl_iface_cookie, + CTRL_IFACE_COOKIE_LEN); + reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN; goto done; } if (os_strncmp(buf, "COOKIE=", 7) != 0 || - hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) { + hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) { wpa_printf(MSG_DEBUG, "CTRL: No cookie in the request - drop request"); os_free(reply); return; } - if (os_memcmp(cookie, lcookie, COOKIE_LEN) != 0) { + if (os_memcmp(hapd->ctrl_iface_cookie, lcookie, + CTRL_IFACE_COOKIE_LEN) != 0) { wpa_printf(MSG_DEBUG, "CTRL: Invalid cookie in the request - drop request"); os_free(reply); return; } - pos = buf + 7 + 2 * COOKIE_LEN; + pos = buf + 7 + 2 * CTRL_IFACE_COOKIE_LEN; while (*pos == ' ') pos++; #endif /* CONFIG_CTRL_IFACE_UDP */ @@ -3777,7 +4087,7 @@ int hostapd_ctrl_iface_init(struct hostapd_data *hapd) dl_list_init(&hapd->ctrl_dst); hapd->ctrl_sock = -1; - os_get_random(cookie, COOKIE_LEN); + os_get_random(hapd->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN); #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE hints.ai_flags = AI_PASSIVE; @@ -4091,6 +4401,11 @@ static void hostapd_ctrl_iface_flush(struct hapd_interfaces *interfaces) #ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_DPP dpp_test = DPP_TEST_DISABLED; +#ifdef CONFIG_DPP2 + dpp_version_override = 2; +#else /* CONFIG_DPP2 */ + dpp_version_override = 1; +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ #endif /* CONFIG_TESTING_OPTIONS */ @@ -4356,7 +4671,7 @@ static int hostapd_global_ctrl_iface_ifname(struct hapd_interfaces *interfaces, static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, void *sock_ctx) { - void *interfaces = eloop_ctx; + struct hapd_interfaces *interfaces = eloop_ctx; char buffer[256], *buf = buffer; int res; struct sockaddr_storage from; @@ -4365,7 +4680,7 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, int reply_len; const int reply_size = 4096; #ifdef CONFIG_CTRL_IFACE_UDP - unsigned char lcookie[COOKIE_LEN]; + unsigned char lcookie[CTRL_IFACE_COOKIE_LEN]; #endif /* CONFIG_CTRL_IFACE_UDP */ res = recvfrom(sock, buffer, sizeof(buffer) - 1, 0, @@ -4394,28 +4709,30 @@ static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx, #ifdef CONFIG_CTRL_IFACE_UDP if (os_strcmp(buf, "GET_COOKIE") == 0) { os_memcpy(reply, "COOKIE=", 7); - wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1, - gcookie, COOKIE_LEN); - reply_len = 7 + 2 * COOKIE_LEN; + wpa_snprintf_hex(reply + 7, 2 * CTRL_IFACE_COOKIE_LEN + 1, + interfaces->ctrl_iface_cookie, + CTRL_IFACE_COOKIE_LEN); + reply_len = 7 + 2 * CTRL_IFACE_COOKIE_LEN; goto send_reply; } if (os_strncmp(buf, "COOKIE=", 7) != 0 || - hexstr2bin(buf + 7, lcookie, COOKIE_LEN) < 0) { + hexstr2bin(buf + 7, lcookie, CTRL_IFACE_COOKIE_LEN) < 0) { wpa_printf(MSG_DEBUG, "CTRL: No cookie in the request - drop request"); os_free(reply); return; } - if (os_memcmp(gcookie, lcookie, COOKIE_LEN) != 0) { + if (os_memcmp(interfaces->ctrl_iface_cookie, lcookie, + CTRL_IFACE_COOKIE_LEN) != 0) { wpa_printf(MSG_DEBUG, "CTRL: Invalid cookie in the request - drop request"); os_free(reply); return; } - buf += 7 + 2 * COOKIE_LEN; + buf += 7 + 2 * CTRL_IFACE_COOKIE_LEN; while (*buf == ' ') buf++; #endif /* CONFIG_CTRL_IFACE_UDP */ @@ -4559,7 +4876,7 @@ int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface) } } - os_get_random(gcookie, COOKIE_LEN); + os_get_random(interface->ctrl_iface_cookie, CTRL_IFACE_COOKIE_LEN); #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE hints.ai_flags = AI_PASSIVE; @@ -4802,13 +5119,8 @@ static void hostapd_ctrl_iface_send_internal(int sock, struct dl_list *ctrl_dst, return; idx = 0; if (ifname) { -#ifdef CONFIG_CTRL_IFACE_UDP - io[idx].iov_base = "IFACE="; - io[idx].iov_len = 6; -#else /* CONFIG_CTRL_IFACE_UDP */ io[idx].iov_base = "IFNAME="; io[idx].iov_len = 7; -#endif /* CONFIG_CTRL_IFACE_UDP */ idx++; io[idx].iov_base = (char *) ifname; io[idx].iov_len = os_strlen(ifname); diff --git a/hostapd/defconfig b/hostapd/defconfig index 57121d47c..9095223ca 100644 --- a/hostapd/defconfig +++ b/hostapd/defconfig @@ -148,9 +148,6 @@ CONFIG_IEEE80211R=y # the IEEE 802.11 Management capability (e.g., FreeBSD/net80211) #CONFIG_DRIVER_RADIUS_ACL=y -# IEEE 802.11n (High Throughput) support -CONFIG_IEEE80211N=y - # Wireless Network Management (IEEE Std 802.11v-2011) # Note: This is experimental and not complete implementation. #CONFIG_WNM=y @@ -354,7 +351,7 @@ CONFIG_INTERWORKING=y #CONFIG_ACS=y # Multiband Operation support -# These extentions facilitate efficient use of multiple frequency bands +# These extensions facilitate efficient use of multiple frequency bands # available to the AP and the devices that may associate with it. #CONFIG_MBO=y @@ -384,6 +381,19 @@ CONFIG_INTERWORKING=y # parameter. See that parameter in hostapd.conf for more details. #CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1 -CONFIG_TESTING_OPTIONS=y +# Wired equivalent privacy (WEP) +# WEP is an obsolete cryptographic data confidentiality algorithm that is not +# considered secure. It should not be used for anything anymore. The +# functionality needed to use WEP is available in the current hostapd +# release under this optional build parameter. This functionality is subject to +# be completely removed in a future release. +CONFIG_WEP=y -CONFIG_SAE=y +# Remove all TKIP functionality +# TKIP is an old cryptographic data confidentiality algorithm that is not +# considered secure. It should not be used anymore. For now, the default hostapd +# build includes this to allow mixed mode WPA+WPA2 networks to be enabled, but +# that functionality is subject to be removed in the future. +#CONFIG_NO_TKIP=y + +CONFIG_TESTING_OPTIONS=y diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 4643657cd..13e7fc666 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -210,7 +210,7 @@ channel=1 # Frequency list can be provided as range using hyphen ('-') or individual # frequencies can be specified by comma (',') separated values # Default: all frequencies allowed in selected hw_mode -#freqlist=2437,5945,5965 +#freqlist=2437,5955,5975 #freqlist=2437,5985-6105 # Exclude DFS channels from ACS @@ -580,6 +580,9 @@ wmm_ac_vo_acm=0 # Note: hw_mode=g (2.4 GHz) and hw_mode=a (5 GHz) is used to specify the band. ieee80211n=1 +# disable_11n: Boolean (0/1) to disable HT for a specific BSS +#disable_11n=0 + # ht_capab: HT capabilities (list of flags) # LDPC coding capability: [LDPC] = supported # Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary @@ -598,8 +601,6 @@ ieee80211n=1 # channels if needed or creation of 40 MHz channel maybe rejected based # on overlapping BSSes. These changes are done automatically when hostapd # is setting up the 40 MHz channel. -# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC] -# (SMPS disabled if neither is set) # HT-greenfield: [GF] (disabled if not set) # Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set) # Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set) @@ -634,6 +635,9 @@ ieee80211n=1 # Note: hw_mode=a is used to specify that 5 GHz band is used with VHT. #ieee80211ac=1 +# disable_11ac: Boolean (0/1) to disable VHT for a specific BSS +#disable_11ac=0 + # vht_capab: VHT capabilities (list of flags) # # vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454] @@ -788,6 +792,9 @@ ieee80211n=1 # 1 = enabled #ieee80211ax=1 +# disable_11ax: Boolean (0/1) to disable HE for a specific BSS +#disable_11ax=0 + #he_su_beamformer: HE single user beamformer support # 0 = not supported (default) # 1 = supported @@ -806,6 +813,9 @@ ieee80211n=1 # he_bss_color: BSS color (1-63) #he_bss_color=1 +# he_bss_color_partial: BSS color AID equation +#he_bss_color_partial=0 + #he_default_pe_duration: The duration of PE field in an HE PPDU in us # Possible values are 0 us (default), 4 us, 8 us, 12 us, and 16 us #he_default_pe_duration=0 @@ -821,11 +831,11 @@ ieee80211n=1 #he_rts_threshold=0 # HE operating channel information; see matching vht_* parameters for details. -# On the 6 GHz band the center freq calculation starts from 5.940 GHz offset. -# For example idx=3 would result in 5955 MHz center frequency. In addition, +# On the 6 GHz band the center freq calculation starts from 5.950 GHz offset. +# For example idx=3 would result in 5965 MHz center frequency. In addition, # he_oper_chwidth is ignored, and the channel width is derived from the # configured operating class or center frequency indexes (see -# IEEE P802.11ax/D4.3 Annex E, Table E-4). +# IEEE P802.11ax/D6.1 Annex E, Table E-4). #he_oper_chwidth #he_oper_centr_freq_seg0_idx #he_oper_centr_freq_seg1_idx @@ -903,6 +913,8 @@ eapol_key_index_workaround=0 # EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable # reauthentication). +# Note: Reauthentications may enforce a disconnection, check the related +# parameter wpa_deny_ptk0_rekey for details. #eap_reauth_period=3600 # Use PAE group address (01:80:c2:00:00:03) instead of individual target @@ -1199,7 +1211,7 @@ eap_server=0 # should be unique across all issuing servers. In theory, this is a variable # length field, but due to some existing implementations requiring A-ID to be # 16 octets in length, it is strongly recommended to use that length for the -# field to provid interoperability with deployed peer implementations. This +# field to provide interoperability with deployed peer implementations. This # field is configured in hex format. #eap_fast_a_id=101112131415161718191a1b1c1d1e1f @@ -1226,6 +1238,8 @@ eap_server=0 # EAP-TEAP authentication type # 0 = inner EAP (default) # 1 = Basic-Password-Auth +# 2 = Do not require Phase 2 authentication if client can be authenticated +# during Phase 1 #eap_teap_auth=0 # EAP-TEAP authentication behavior when using PAC @@ -1507,6 +1521,17 @@ own_ip_addr=127.0.0.1 # wpa_key_mgmt=SAE for WPA3-Personal instead of wpa_key_mgmt=WPA-PSK). wpa=2 +# Extended Key ID support for Individually Addressed frames +# +# Extended Key ID allows to rekey PTK keys without the impacts the "normal" +# PTK rekeying with only a single Key ID 0 has. It can only be used when the +# driver supports it and RSN/WPA2 is used with a CCMP/GCMP pairwise cipher. +# +# 0 = force off, i.e., use only Key ID 0 (default) +# 1 = enable and use Extended Key ID support when possible +# 2 = identical to 1 but start with Key ID 1 when possible +#extended_key_id=0 + # WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit # secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase # (8..63 characters) that will be converted to PSK. This conversion uses SSID @@ -1607,8 +1632,26 @@ group_cipher=CCMP # Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of # PTK to mitigate some attacks against TKIP deficiencies. +# Warning: PTK rekeying is buggy with many drivers/devices and with such +# devices, the only secure method to rekey the PTK without Extended Key ID +# support requires a disconnection. Check the related parameter +# wpa_deny_ptk0_rekey for details. #wpa_ptk_rekey=600 +# Workaround for PTK rekey issues +# +# PTK0 rekeys (rekeying the PTK without "Extended Key ID for Individually +# Addressed Frames") can degrade the security and stability with some cards. +# To avoid such issues hostapd can replace those PTK rekeys (including EAP +# reauthentications) with disconnects. +# +# Available options: +# 0 = always rekey when configured/instructed (default) +# 1 = only rekey when the local driver is explicitly indicating it can perform +# this operation without issues +# 2 = never allow PTK0 rekeys +#wpa_deny_ptk0_rekey=0 + # The number of times EAPOL-Key Message 1/4 and Message 3/4 in the RSN 4-Way # Handshake are retried per 4-Way Handshake attempt. # (dot11RSNAConfigPairwiseUpdateCount) @@ -1677,6 +1720,12 @@ wpa_pairwise_update_count=100 # available in deployed devices. #group_mgmt_cipher=AES-128-CMAC +# Beacon Protection (management frame protection for Beacon frames) +# This depends on management frame protection being enabled (ieee80211w != 0). +# 0 = disabled (default) +# 1 = enabled +#beacon_prot=0 + # Association SA Query maximum timeout (in TU = 1.024 ms; for MFP) # (maximum time to wait for a SA Query response) # dot11AssociationSAQueryMaximumTimeout, 1...4294967295 @@ -1692,6 +1741,19 @@ wpa_pairwise_update_count=100 # Enabling this automatically also enables ieee80211w, if not yet enabled. # 0 = disabled (default) # 1 = enabled +# 2 = enabled in workaround mode - Allow STA that claims OCV capability to +# connect even if the STA doesn't send OCI or negotiate PMF. This +# workaround is to improve interoperability with legacy STAs which are +# wrongly copying reserved bits of RSN capabilities from the AP's +# RSNE into (Re)Association Request frames. When this configuration is +# enabled, the AP considers STA is OCV capable only when the STA indicates +# MFP capability in (Re)Association Request frames and sends OCI in +# EAPOL-Key msg 2/4/FT Reassociation Request frame/FILS (Re)Association +# Request frame; otherwise, the AP disables OCV for the current connection +# with the STA. Enabling this workaround mode reduced OCV protection to +# some extend since it allows misbehavior to go through. As such, this +# should be enabled only if interoperability with misbehaving STAs is +# needed. #ocv=1 # disable_pmksa_caching: Disable PMKSA caching @@ -1723,7 +1785,7 @@ wpa_pairwise_update_count=100 # be followed by optional peer MAC address (dot11RSNAConfigPasswordPeerMac) and # by optional password identifier (dot11RSNAConfigPasswordIdentifier). In # addition, an optional VLAN ID specification can be used to bind the station -# to the specified VLAN whenver the specific SAE password entry is used. +# to the specified VLAN whenever the specific SAE password entry is used. # # If the peer MAC address is not included or is set to the wildcard address # (ff:ff:ff:ff:ff:ff), the entry is available for any station to use. If a @@ -1738,7 +1800,8 @@ wpa_pairwise_update_count=100 # special meaning of removing all previously added entries. # # sae_password uses the following encoding: -#[|mac=][|vlanid=][|id=] +#[|mac=][|vlanid=] +#[|pk=][|id=] # Examples: #sae_password=secret #sae_password=really secret|mac=ff:ff:ff:ff:ff:ff @@ -1867,6 +1930,23 @@ wpa_pairwise_update_count=100 # default: 30 TUs (= 30.72 milliseconds) #fils_hlp_wait_time=30 +# Transition Disable indication +# The AP can notify authenticated stations to disable transition mode in their +# network profiles when the network has completed transition steps, i.e., once +# sufficiently large number of APs in the ESS have been updated to support the +# more secure alternative. When this indication is used, the stations are +# expected to automatically disable transition mode and less secure security +# options. This includes use of WEP, TKIP (including use of TKIP as the group +# cipher), and connections without PMF. +# Bitmap bits: +# bit 0 (0x01): WPA3-Personal (i.e., disable WPA2-Personal = WPA-PSK and only +# allow SAE to be used) +# bit 1 (0x02): SAE-PK (disable SAE without use of SAE-PK) +# bit 2 (0x04): WPA3-Enterprise (move to requiring PMF) +# bit 3 (0x08): Enhanced Open (disable use of open network; require OWE) +# (default: 0 = do not include Transition Disable KDE) +#transition_disable=0x01 + ##### IEEE 802.11r configuration ############################################## # Mobility Domain identifier (dot11FTMobilityDomainID, MDID) @@ -1910,7 +1990,7 @@ wpa_pairwise_update_count=100 # Wildcard entry: # Upon receiving a response from R0KH, it will be added to this list, so # subsequent requests won't be broadcast. If R0KH does not reply, it will be -# blacklisted. +# temporarily blocked (see rkh_neg_timeout). #r0kh=ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff # List of R1KHs in the same Mobility Domain @@ -1966,7 +2046,7 @@ wpa_pairwise_update_count=100 #ft_psk_generate_local=0 ##### Neighbor table ########################################################## -# Maximum number of entries kept in AP table (either for neigbor table or for +# Maximum number of entries kept in AP table (either for neighbor table or for # detecting Overlapping Legacy BSS Condition). The oldest entry will be # removed when adding a new entry that would make the list grow over this # limit. Note! WFA certification for IEEE 802.11g requires that OLBC is @@ -2249,6 +2329,17 @@ wpa_pairwise_update_count=100 #dpp_csign #dpp_controller +# Configurator Connectivity indication +# 0: no Configurator is currently connected (default) +# 1: advertise that a Configurator is available +#dpp_configurator_connectivity=0 + +# DPP PFS +# 0: allow PFS to be used or not used (default) +# 1: require PFS to be used (note: not compatible with DPP R1) +# 2: do not allow PFS to be used +#dpp_pfs=0 + #### TDLS (IEEE 802.11z-2010) ################################################# # Prohibit use of TDLS in this BSS @@ -2644,6 +2735,10 @@ wpa_pairwise_update_count=100 # threshold (range: 0..255, default=30). #rssi_reject_assoc_timeout=30 +# Ignore Probe Request frames if RSSI is below given threshold (in dBm) +# Allowed range: -60 to -90 dBm; default = 0 (rejection disabled) +#rssi_ignore_probe_request=-75 + ##### Fast Session Transfer (FST) support ##################################### # # The options in this section are only available when the build configuration diff --git a/hostapd/hostapd_cli.c b/hostapd/hostapd_cli.c index 440664e9b..249e46699 100644 --- a/hostapd/hostapd_cli.c +++ b/hostapd/hostapd_cli.c @@ -975,7 +975,7 @@ static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl) dir = opendir(ctrl_iface_dir); if (dir == NULL) { printf("Control interface directory '%s' could not be " - "openned.\n", ctrl_iface_dir); + "opened.\n", ctrl_iface_dir); return; } @@ -1227,14 +1227,15 @@ static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[]) char cmd[256]; int res; - if (argc < 2 || argc > 3) { + if (argc < 2 || argc > 4) { printf("Invalid vendor command\n" - "usage: []\n"); + "usage: [] [nested=<0|1>]\n"); return -1; } - res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1], - argc == 3 ? argv[2] : ""); + res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s%s%s", argv[0], + argv[1], argc >= 3 ? argv[2] : "", + argc == 4 ? " " : "", argc == 4 ? argv[3] : ""); if (os_snprintf_error(sizeof(cmd), res)) { printf("Too long VENDOR command.\n"); return -1; @@ -1402,6 +1403,13 @@ static int hostapd_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc, } +static int hostapd_cli_cmd_dpp_bootstrap_set(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_SET", 1, argc, argv); +} + + static int hostapd_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -1464,6 +1472,37 @@ static int hostapd_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc, return hostapd_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv); } + +#ifdef CONFIG_DPP2 + +static int hostapd_cli_cmd_dpp_controller_start(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return hostapd_cli_cmd(ctrl, "DPP_CONTROLLER_START", 1, argc, argv); +} + + +static int hostapd_cli_cmd_dpp_controller_stop(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DPP_CONTROLLER_STOP"); +} + + +static int hostapd_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return hostapd_cli_cmd(ctrl, "DPP_CHIRP", 1, argc, argv); +} + + +static int hostapd_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DPP_STOP_CHIRP"); +} + +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ @@ -1650,6 +1689,8 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = { " = get DPP bootstrap URI" }, { "dpp_bootstrap_info", hostapd_cli_cmd_dpp_bootstrap_info, NULL, " = show DPP bootstrap information" }, + { "dpp_bootstrap_set", hostapd_cli_cmd_dpp_bootstrap_set, NULL, + " [conf=..] [ssid=] [ssid_charset=#] [psk=] [pass=] [configurator=] [conn_status=#] [akm_use_selector=<0|1>] [group_id=..] [expiry=#] [csrattrs=..] = set DPP configurator parameters" }, { "dpp_auth_init", hostapd_cli_cmd_dpp_auth_init, NULL, "peer= [own=] = initiate DPP bootstrapping" }, { "dpp_listen", hostapd_cli_cmd_dpp_listen, NULL, @@ -1670,6 +1711,16 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = { "add PKEX code" }, { "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL, "*| = remove DPP pkex information" }, +#ifdef CONFIG_DPP2 + { "dpp_controller_start", hostapd_cli_cmd_dpp_controller_start, NULL, + "[tcp_port=] [role=..] = start DPP controller" }, + { "dpp_controller_stop", hostapd_cli_cmd_dpp_controller_stop, NULL, + "= stop DPP controller" }, + { "dpp_chirp", hostapd_cli_cmd_dpp_chirp, NULL, + "own= iter= = start DPP chirp" }, + { "dpp_stop_chirp", hostapd_cli_cmd_dpp_stop_chirp, NULL, + "= stop DPP chirp" }, +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ { "accept_acl", hostapd_cli_cmd_accept_macacl, NULL, "=Add/Delete/Show/Clear accept MAC ACL" }, diff --git a/hostapd/main.c b/hostapd/main.c index 9bca26e35..4f2d1f216 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -218,7 +218,7 @@ static int hostapd_driver_init(struct hostapd_iface *iface) struct wowlan_triggers *triggs; iface->drv_flags = capa.flags; - iface->smps_modes = capa.smps_modes; + iface->drv_flags2 = capa.flags2; iface->probe_resp_offloads = capa.probe_resp_offloads; /* * Use default extended capa values from per-radio information @@ -451,11 +451,12 @@ static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize, static void show_version(void) { fprintf(stderr, - "hostapd v" VERSION_STR "\n" + "hostapd v%s\n" "User space daemon for IEEE 802.11 AP management,\n" "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" "Copyright (c) 2002-2019, Jouni Malinen " - "and contributors\n"); + "and contributors\n", + VERSION_STR); } @@ -673,7 +674,10 @@ int main(int argc, char *argv[]) #endif /* CONFIG_ETH_P_OUI */ #ifdef CONFIG_DPP os_memset(&dpp_conf, 0, sizeof(dpp_conf)); - /* TODO: dpp_conf.msg_ctx? */ + dpp_conf.cb_ctx = &interfaces; +#ifdef CONFIG_DPP2 + dpp_conf.remove_bi = hostapd_dpp_remove_bi; +#endif /* CONFIG_DPP2 */ interfaces.dpp = dpp_global_init(&dpp_conf); if (!interfaces.dpp) return -1; @@ -902,8 +906,11 @@ int main(int argc, char *argv[]) !!(interfaces.iface[i]->drv_flags & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); hostapd_interface_deinit_free(interfaces.iface[i]); + interfaces.iface[i] = NULL; } os_free(interfaces.iface); + interfaces.iface = NULL; + interfaces.count = 0; #ifdef CONFIG_DPP dpp_global_deinit(interfaces.dpp); diff --git a/hostapd/sae_pk_gen.c b/hostapd/sae_pk_gen.c new file mode 100644 index 000000000..c31eff75b --- /dev/null +++ b/hostapd/sae_pk_gen.c @@ -0,0 +1,196 @@ +/* + * SAE-PK password/modifier generator + * Copyright (c) 2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/base64.h" +#include "crypto/crypto.h" +#include "common/sae.h" + + +int main(int argc, char *argv[]) +{ + char *der = NULL; + size_t der_len; + struct crypto_ec_key *key = NULL; + struct wpabuf *pub = NULL; + u8 *data = NULL, *m; + size_t data_len; + char *b64 = NULL, *pw = NULL, *pos, *src; + int sec, j; + int ret = -1; + u8 hash[SAE_MAX_HASH_LEN]; + char hash_hex[2 * SAE_MAX_HASH_LEN + 1]; + u8 pw_base_bin[SAE_MAX_HASH_LEN]; + u8 *dst; + int group; + size_t hash_len; + unsigned long long i, expected; + char m_hex[2 * SAE_PK_M_LEN + 1]; + u32 sec_1b, val20; + + wpa_debug_level = MSG_INFO; + if (os_program_init() < 0) + goto fail; + + if (argc != 4) { + fprintf(stderr, + "usage: sae_pk_gen \n"); + goto fail; + } + + sec = atoi(argv[2]); + if (sec != 3 && sec != 5) { + fprintf(stderr, + "Invalid Sec value (allowed values: 3 and 5)\n"); + goto fail; + } + sec_1b = sec == 3; + expected = 1; + for (j = 0; j < sec; j++) + expected *= 256; + + der = os_readfile(argv[1], &der_len); + if (!der) { + fprintf(stderr, "Could not read %s: %s\n", + argv[1], strerror(errno)); + goto fail; + } + + key = crypto_ec_key_parse_priv((u8 *) der, der_len); + if (!key) { + fprintf(stderr, "Could not parse ECPrivateKey\n"); + goto fail; + } + + pub = crypto_ec_key_get_subject_public_key(key); + if (!pub) { + fprintf(stderr, "Failed to build SubjectPublicKey\n"); + goto fail; + } + + group = crypto_ec_key_group(key); + switch (group) { + case 19: + hash_len = 32; + break; + case 20: + hash_len = 48; + break; + case 21: + hash_len = 64; + break; + default: + fprintf(stderr, "Unsupported private key group\n"); + goto fail; + } + + data_len = os_strlen(argv[3]) + SAE_PK_M_LEN + wpabuf_len(pub); + data = os_malloc(data_len); + if (!data) { + fprintf(stderr, "No memory for data buffer\n"); + goto fail; + } + os_memcpy(data, argv[3], os_strlen(argv[3])); + m = data + os_strlen(argv[3]); + if (os_get_random(m, SAE_PK_M_LEN) < 0) { + fprintf(stderr, "Could not generate random Modifier M\n"); + goto fail; + } + os_memcpy(m + SAE_PK_M_LEN, wpabuf_head(pub), wpabuf_len(pub)); + + fprintf(stderr, "Searching for a suitable Modifier M value\n"); + for (i = 0;; i++) { + if (sae_hash(hash_len, data, data_len, hash) < 0) { + fprintf(stderr, "Hash failed\n"); + goto fail; + } + if (hash[0] == 0 && hash[1] == 0) { + if ((hash[2] & 0xf0) == 0) + fprintf(stderr, "\r%3.2f%%", + 100.0 * (double) i / (double) expected); + for (j = 2; j < sec; j++) { + if (hash[j]) + break; + } + if (j == sec) + break; + } + inc_byte_array(m, SAE_PK_M_LEN); + } + + if (wpa_snprintf_hex(m_hex, sizeof(m_hex), m, SAE_PK_M_LEN) < 0 || + wpa_snprintf_hex(hash_hex, sizeof(hash_hex), hash, hash_len) < 0) + goto fail; + fprintf(stderr, "\nFound a valid hash in %llu iterations: %s\n", + i + 1, hash_hex); + + b64 = base64_encode(der, der_len, NULL); + if (!b64) + goto fail; + src = pos = b64; + while (*src) { + if (*src != '\n') + *pos++ = *src; + src++; + } + *pos = '\0'; + + /* Skip 8*Sec bits and add Sec_1b as the every 20th bit starting with + * one. */ + os_memset(pw_base_bin, 0, sizeof(pw_base_bin)); + dst = pw_base_bin; + for (j = 0; j < 8 * (int) hash_len / 20; j++) { + val20 = sae_pk_get_be19(hash + sec); + val20 |= sec_1b << 19; + sae_pk_buf_shift_left_19(hash + sec, hash_len - sec); + + if (j & 1) { + *dst |= (val20 >> 16) & 0x0f; + dst++; + *dst++ = (val20 >> 8) & 0xff; + *dst++ = val20 & 0xff; + } else { + *dst++ = (val20 >> 12) & 0xff; + *dst++ = (val20 >> 4) & 0xff; + *dst = (val20 << 4) & 0xf0; + } + } + if (wpa_snprintf_hex(hash_hex, sizeof(hash_hex), + pw_base_bin, hash_len - sec) >= 0) + fprintf(stderr, "PasswordBase binary data for base32: %s", + hash_hex); + + pw = sae_pk_base32_encode(pw_base_bin, 20 * 3 - 5); + if (!pw) + goto fail; + + printf("# SAE-PK password/M/private key for Sec=%d.\n", sec); + printf("sae_password=%s|pk=%s:%s\n", pw, m_hex, b64); + printf("# Longer passwords can be used for improved security at the cost of usability:\n"); + for (j = 4; j <= ((int) hash_len * 8 + 5 - 8 * sec) / 19; j++) { + os_free(pw); + pw = sae_pk_base32_encode(pw_base_bin, 20 * j - 5); + if (pw) + printf("# %s\n", pw); + } + + ret = 0; +fail: + os_free(der); + wpabuf_free(pub); + crypto_ec_key_deinit(key); + os_free(data); + os_free(b64); + os_free(pw); + + os_program_deinit(); + + return ret; +} diff --git a/hs20/client/Makefile b/hs20/client/Makefile index 67f6f55c5..4dcfe2d3b 100644 --- a/hs20/client/Makefile +++ b/hs20/client/Makefile @@ -1,28 +1,6 @@ -all: hs20-osu-client +ALL=hs20-osu-client -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifeq ($(QUIET), 1) -Q=@ -E=true -else -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif +include ../../src/build.rules CFLAGS += -I../../src/utils CFLAGS += -I../../src/common @@ -30,8 +8,17 @@ CFLAGS += -I../../src ifndef CONFIG_NO_BROWSER ifndef CONFIG_BROWSER_SYSTEM +TEST_WK := $(shell pkg-config --silence-errors --cflags webkitgtk-3.0) +ifeq ($(TEST_WK),) +# Try webkit2 +GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkit2gtk-4.0) +GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkit2gtk-4.0) +CFLAGS += -DUSE_WEBKIT2 +else GTKCFLAGS := $(shell pkg-config --cflags gtk+-3.0 webkitgtk-3.0) GTKLIBS := $(shell pkg-config --libs gtk+-3.0 webkitgtk-3.0) +endif + CFLAGS += $(GTKCFLAGS) LIBS += $(GTKLIBS) endif @@ -84,23 +71,11 @@ CFLAGS += -DEAP_TLS_OPENSSL OBJS += ../../src/crypto/tls_openssl_ocsp.o LIBS += -lssl -lcrypto +_OBJS_VAR := OBJS +include ../../src/objs.mk hs20-osu-client: $(OBJS) $(Q)$(LDO) $(LDFLAGS) -o hs20-osu-client $(OBJS) $(LIBS) @$(E) " LD " $@ -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< - -clean: - rm -f core *~ *.o *.d hs20-osu-client - rm -f ../../src/utils/*.o - rm -f ../../src/utils/*.d - rm -f ../../src/common/*.o - rm -f ../../src/common/*.d - rm -f ../../src/crypto/*.o - rm -f ../../src/crypto/*.d - rm -f ../../src/wps/*.o - rm -f ../../src/wps/*.d - --include $(OBJS:%.o=%.d) +clean: common-clean + rm -f core *~ diff --git a/hs20/client/oma_dm_client.c b/hs20/client/oma_dm_client.c index d75c84562..bcd68b877 100644 --- a/hs20/client/oma_dm_client.c +++ b/hs20/client/oma_dm_client.c @@ -407,7 +407,7 @@ static int oma_dm_exec_browser(struct hs20_osu_client *ctx, xml_node_t *exec) wpa_printf(MSG_INFO, "Data: %s", data); wpa_printf(MSG_INFO, "Launch browser to URI '%s'", data); write_summary(ctx, "Launch browser to URI '%s'", data); - res = hs20_web_browser(data); + res = hs20_web_browser(data, 1); xml_node_get_text_free(ctx->xml, data); if (res > 0) { wpa_printf(MSG_INFO, "User response in browser completed successfully"); diff --git a/hs20/client/osu_client.c b/hs20/client/osu_client.c index a94f40c51..11bf0db35 100644 --- a/hs20/client/osu_client.c +++ b/hs20/client/osu_client.c @@ -2233,7 +2233,7 @@ static int osu_connect(struct hs20_osu_client *ctx, const char *bssid, wpa_ctrl_close(mon); if (res < 0) { - wpa_printf(MSG_INFO, "Could not connect"); + wpa_printf(MSG_INFO, "Could not connect to OSU network"); write_summary(ctx, "Could not connect to OSU network"); wpa_printf(MSG_INFO, "Remove OSU network connection"); snprintf(buf, sizeof(buf), "REMOVE_NETWORK %d", id); @@ -2406,7 +2406,7 @@ static int cmd_osu_select(struct hs20_osu_client *ctx, const char *dir, snprintf(fname, sizeof(fname), "file://%s/osu-providers.html", dir); write_summary(ctx, "Start web browser with OSU provider selection page"); - ret = hs20_web_browser(fname); + ret = hs20_web_browser(fname, 0); selected: if (ret > 0 && (size_t) ret <= osu_count) { @@ -2907,7 +2907,7 @@ static char * get_hostname(const char *url) static int osu_cert_cb(void *_ctx, struct http_cert *cert) { struct hs20_osu_client *ctx = _ctx; - unsigned int i, j; + size_t i, j; int found; char *host = NULL; @@ -3002,7 +3002,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert) size_t name_len = os_strlen(name); wpa_printf(MSG_INFO, - "[%i] Looking for icon file name '%s' match", + "[%zu] Looking for icon file name '%s' match", j, name); for (i = 0; i < cert->num_logo; i++) { struct http_logo *logo = &cert->logo[i]; @@ -3010,7 +3010,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert) char *pos; wpa_printf(MSG_INFO, - "[%i] Comparing to '%s' uri_len=%d name_len=%d", + "[%zu] Comparing to '%s' uri_len=%d name_len=%d", i, logo->uri, (int) uri_len, (int) name_len); if (uri_len < 1 + name_len) { wpa_printf(MSG_INFO, "URI Length is too short"); @@ -3044,7 +3044,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert) if (logo->hash_len != 32) { wpa_printf(MSG_INFO, - "[%i][%i] Icon hash length invalid (should be 32): %d", + "[%zu][%zu] Icon hash length invalid (should be 32): %d", j, i, (int) logo->hash_len); continue; } @@ -3054,7 +3054,7 @@ static int osu_cert_cb(void *_ctx, struct http_cert *cert) } wpa_printf(MSG_DEBUG, - "[%u][%u] Icon hash did not match", j, i); + "[%zu][%zu] Icon hash did not match", j, i); wpa_hexdump_ascii(MSG_DEBUG, "logo->hash", logo->hash, 32); wpa_hexdump_ascii(MSG_DEBUG, "ctx->icon_hash[j]", @@ -3152,7 +3152,7 @@ static void check_workarounds(struct hs20_osu_client *ctx) static void usage(void) { - printf("usage: hs20-osu-client [-dddqqKt] [-S] \\\n" + printf("usage: hs20-osu-client [-dddqqKtT] [-S] \\\n" " [-w] " "[-r] [-f] \\\n" " [-s] \\\n" @@ -3198,7 +3198,7 @@ int main(int argc, char *argv[]) return -1; for (;;) { - c = getopt(argc, argv, "df:hKNo:O:qr:s:S:tw:x:"); + c = getopt(argc, argv, "df:hKNo:O:qr:s:S:tTw:x:"); if (c < 0) break; switch (c) { @@ -3236,6 +3236,9 @@ int main(int argc, char *argv[]) case 't': wpa_debug_timestamp++; break; + case 'T': + ctx.ignore_tls = 1; + break; case 'w': wpas_ctrl_path = optarg; break; @@ -3403,7 +3406,7 @@ int main(int argc, char *argv[]) wpa_printf(MSG_INFO, "Launch web browser to URL %s", argv[optind + 1]); - ret = hs20_web_browser(argv[optind + 1]); + ret = hs20_web_browser(argv[optind + 1], ctx.ignore_tls); wpa_printf(MSG_INFO, "Web browser result: %d", ret); } else if (strcmp(argv[optind], "parse_cert") == 0) { if (argc - optind < 2) { diff --git a/hs20/client/osu_client.h b/hs20/client/osu_client.h index 5c8e6d00b..9b45b03fe 100644 --- a/hs20/client/osu_client.h +++ b/hs20/client/osu_client.h @@ -50,6 +50,8 @@ struct hs20_osu_client { const char *osu_ssid; /* Enforced OSU_SSID for testing purposes */ #define WORKAROUND_OCSP_OPTIONAL 0x00000001 unsigned long int workarounds; + int ignore_tls; /* whether to ignore TLS validation issues with HTTPS + * server certificate */ }; diff --git a/hs20/client/spp_client.c b/hs20/client/spp_client.c index c619541ae..39d10e036 100644 --- a/hs20/client/spp_client.c +++ b/hs20/client/spp_client.c @@ -547,7 +547,7 @@ static int hs20_spp_exec(struct hs20_osu_client *ctx, xml_node_t *exec, } wpa_printf(MSG_INFO, "Launch browser to URI '%s'", uri); write_summary(ctx, "Launch browser to URI '%s'", uri); - res = hs20_web_browser(uri); + res = hs20_web_browser(uri, 1); xml_node_get_text_free(ctx->xml, uri); if (res > 0) { wpa_printf(MSG_INFO, "User response in browser completed successfully - sessionid='%s'", diff --git a/hs20/server/.gitignore b/hs20/server/.gitignore new file mode 100644 index 000000000..fecb096c1 --- /dev/null +++ b/hs20/server/.gitignore @@ -0,0 +1 @@ +hs20_spp_server diff --git a/hs20/server/Makefile b/hs20/server/Makefile index 9b7372796..0cab6d6b0 100644 --- a/hs20/server/Makefile +++ b/hs20/server/Makefile @@ -1,16 +1,6 @@ -all: hs20_spp_server +ALL=hs20_spp_server -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif +include ../../src/build.rules CFLAGS += -I../../src CFLAGS += -I../../src/utils @@ -43,14 +33,10 @@ CFLAGS += $(shell xml2-config --cflags) LIBS += $(shell xml2-config --libs) OBJS += ../../src/utils/xml_libxml2.o +_OBJS_VAR := OBJS +include ../../src/objs.mk hs20_spp_server: $(OBJS) $(LDO) $(LDFLAGS) -o hs20_spp_server $(OBJS) $(LIBS) -clean: - rm -f core *~ *.o *.d hs20_spp_server - rm -f ../../src/utils/*.o - rm -f ../../src/utils/*.d - rm -f ../../src/crypto/*.o - rm -f ../../src/crypto/*.d - --include $(OBJS:%.o=%.d) +clean: common-clean + rm -f core *~ diff --git a/hs20/server/ca/ocsp-responder.sh b/hs20/server/ca/ocsp-responder.sh index 8cebd7453..620947d01 100755 --- a/hs20/server/ca/ocsp-responder.sh +++ b/hs20/server/ca/ocsp-responder.sh @@ -1,3 +1,3 @@ #!/bin/sh -openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner ocsp.pem -rkey ocsp.key -CA demoCA/cacert.pem -text +openssl ocsp -index demoCA/index.txt -port 8888 -nmin 5 -rsigner ocsp.pem -rkey ocsp.key -CA demoCA/cacert.pem -text -ignore_err diff --git a/hs20/server/ca/ocsp-update-cache.sh b/hs20/server/ca/ocsp-update-cache.sh index 8ddef9b9c..f2b23250c 100755 --- a/hs20/server/ca/ocsp-update-cache.sh +++ b/hs20/server/ca/ocsp-update-cache.sh @@ -1,5 +1,6 @@ #!/bin/sh +# NOTE: You may need to replace 'localhost' with your OCSP server hostname. openssl ocsp \ -no_nonce \ -CAfile ca.pem \ diff --git a/hs20/server/hs20_spp_server.c b/hs20/server/hs20_spp_server.c index 6c74f541d..347c40a73 100644 --- a/hs20/server/hs20_spp_server.c +++ b/hs20/server/hs20_spp_server.c @@ -176,7 +176,7 @@ int main(int argc, char *argv[]) ctx.root_dir = optarg; break; case 'v': - printf("hs20_spp_server v" VERSION_STR "\n"); + printf("hs20_spp_server v%s\n", VERSION_STR); return 0; default: usage(); diff --git a/radius_example/Makefile b/radius_example/Makefile index 883e2f2da..d58a82c34 100644 --- a/radius_example/Makefile +++ b/radius_example/Makefile @@ -1,18 +1,6 @@ ALL=radius_example -all: $(ALL) - -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif +include ../src/build.rules CFLAGS += -I. CFLAGS += -I../src @@ -23,24 +11,18 @@ LIBS += ../src/crypto/libcrypto.a LIBS += ../src/utils/libutils.a LLIBS = -lrt -../src/utils/libutils.a: - $(MAKE) -C ../src/utils - -../src/crypto/libcrypto.a: - $(MAKE) -C ../src/crypto - -../src/radius/libradius.a: - $(MAKE) -C ../src/radius - #CLAGS += -DCONFIG_IPV6 OBJS_ex = radius_example.o +_OBJS_VAR := OBJS_ex +include ../src/objs.mk + +_OBJS_VAR := LIBS +include ../src/objs.mk + radius_example: $(OBJS_ex) $(LIBS) $(LDO) $(LDFLAGS) -o radius_example $(OBJS_ex) $(LIBS) $(LLIBS) -clean: - $(MAKE) -C ../src clean - rm -f core *~ *.o *.d $(ALL) - --include $(OBJS:%.o=%.d) +clean: common-clean + rm -f core *~ *.o *.d diff --git a/src/Makefile b/src/Makefile index c9e84c11d..6eb7f2acb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -5,8 +5,8 @@ all: for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done clean: - for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done - rm -f *~ + $(Q)for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d clean; done + $(Q)rm -f *~ install: for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d install; done diff --git a/src/ap/Makefile b/src/ap/Makefile index 54e48a0dd..a1e9b7c44 100644 --- a/src/ap/Makefile +++ b/src/ap/Makefile @@ -1,13 +1,3 @@ -all: libap.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libap.a - -install: - @echo Nothing to be made. - -include ../lib.rules - CFLAGS += -DHOSTAPD CFLAGS += -DNEED_AP_MLME CFLAGS += -DCONFIG_ETH_P_OUI @@ -67,7 +57,4 @@ LIB_OBJS= \ wps_hostapd.o \ x_snoop.o -libap.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/ap/acs.c b/src/ap/acs.c index 232afa890..aa2ceb0d1 100644 --- a/src/ap/acs.c +++ b/src/ap/acs.c @@ -261,13 +261,13 @@ static void acs_clean_chan_surveys(struct hostapd_channel_data *chan) } -void acs_cleanup(struct hostapd_iface *iface) +static void acs_cleanup_mode(struct hostapd_hw_modes *mode) { int i; struct hostapd_channel_data *chan; - for (i = 0; i < iface->current_mode->num_channels; i++) { - chan = &iface->current_mode->channels[i]; + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; if (chan->flag & HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED) acs_clean_chan_surveys(chan); @@ -276,6 +276,15 @@ void acs_cleanup(struct hostapd_iface *iface) chan->flag |= HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED; chan->min_nf = 0; } +} + + +void acs_cleanup(struct hostapd_iface *iface) +{ + int i; + + for (i = 0; i < iface->num_hw_features; i++) + acs_cleanup_mode(&iface->hw_features[i]); iface->chans_surveyed = 0; iface->acs_num_completed_scans = 0; @@ -453,21 +462,35 @@ static int acs_survey_list_is_sufficient(struct hostapd_channel_data *chan) } -static int acs_surveys_are_sufficient(struct hostapd_iface *iface) +static int acs_surveys_are_sufficient_mode(struct hostapd_hw_modes *mode) { int i; struct hostapd_channel_data *chan; - int valid = 0; - for (i = 0; i < iface->current_mode->num_channels; i++) { - chan = &iface->current_mode->channels[i]; + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && acs_survey_list_is_sufficient(chan)) - valid++; + return 1; } - /* We need at least survey data for one channel */ - return !!valid; + return 0; +} + + +static int acs_surveys_are_sufficient(struct hostapd_iface *iface) +{ + int i; + struct hostapd_hw_modes *mode; + + for (i = 0; i < iface->num_hw_features; i++) { + mode = &iface->hw_features[i]; + if (!hostapd_hw_skip_mode(iface, mode) && + acs_surveys_are_sufficient_mode(mode)) + return 1; + } + + return 0; } @@ -489,14 +512,25 @@ static int is_in_chanlist(struct hostapd_iface *iface, } -static void acs_survey_all_chans_intereference_factor( - struct hostapd_iface *iface) +static int is_in_freqlist(struct hostapd_iface *iface, + struct hostapd_channel_data *chan) +{ + if (!iface->conf->acs_freq_list.num) + return 1; + + return freq_range_list_includes(&iface->conf->acs_freq_list, + chan->freq); +} + + +static void acs_survey_mode_interference_factor( + struct hostapd_iface *iface, struct hostapd_hw_modes *mode) { int i; struct hostapd_channel_data *chan; - for (i = 0; i < iface->current_mode->num_channels; i++) { - chan = &iface->current_mode->channels[i]; + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; if (!acs_usable_chan(chan)) continue; @@ -504,6 +538,9 @@ static void acs_survey_all_chans_intereference_factor( if (!is_in_chanlist(iface, chan)) continue; + if (!is_in_freqlist(iface, chan)) + continue; + wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)", chan->chan, chan->freq); @@ -515,14 +552,28 @@ static void acs_survey_all_chans_intereference_factor( } -static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface, - int freq) +static void acs_survey_all_chans_interference_factor( + struct hostapd_iface *iface) +{ + int i; + struct hostapd_hw_modes *mode; + + for (i = 0; i < iface->num_hw_features; i++) { + mode = &iface->hw_features[i]; + if (!hostapd_hw_skip_mode(iface, mode)) + acs_survey_mode_interference_factor(iface, mode); + } +} + + +static struct hostapd_channel_data * +acs_find_chan_mode(struct hostapd_hw_modes *mode, int freq) { struct hostapd_channel_data *chan; int i; - for (i = 0; i < iface->current_mode->num_channels; i++) { - chan = &iface->current_mode->channels[i]; + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; if (chan->flag & HOSTAPD_CHAN_DISABLED) continue; @@ -535,6 +586,26 @@ static struct hostapd_channel_data *acs_find_chan(struct hostapd_iface *iface, } +static struct hostapd_channel_data * +acs_find_chan(struct hostapd_iface *iface, int freq) +{ + int i; + struct hostapd_hw_modes *mode; + struct hostapd_channel_data *chan; + + for (i = 0; i < iface->num_hw_features; i++) { + mode = &iface->hw_features[i]; + if (!hostapd_hw_skip_mode(iface, mode)) { + chan = acs_find_chan_mode(mode, freq); + if (chan) + return chan; + } + } + + return NULL; +} + + static int is_24ghz_mode(enum hostapd_hw_mode mode) { return mode == HOSTAPD_MODE_IEEE80211B || @@ -565,58 +636,24 @@ static int is_common_24ghz_chan(int chan) #define ACS_24GHZ_PREFER_1_6_11 0.8 #endif /* ACS_24GHZ_PREFER_1_6_11 */ -/* - * At this point it's assumed chan->interface_factor has been computed. - * This function should be reusable regardless of interference computation - * option (survey, BSS, spectral, ...). chan->interference factor must be - * summable (i.e., must be always greater than zero). - */ -static struct hostapd_channel_data * -acs_find_ideal_chan(struct hostapd_iface *iface) +static void +acs_find_ideal_chan_mode(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode, + int n_chans, u32 bw, + struct hostapd_channel_data **rand_chan, + struct hostapd_channel_data **ideal_chan, + long double *ideal_factor) { - struct hostapd_channel_data *chan, *adj_chan, *ideal_chan = NULL, - *rand_chan = NULL; - long double factor, ideal_factor = 0; + struct hostapd_channel_data *chan, *adj_chan = NULL; + long double factor; int i, j; - int n_chans = 1; - u32 bw; unsigned int k; - /* TODO: HT40- support */ - - if (iface->conf->ieee80211n && - iface->conf->secondary_channel == -1) { - wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+"); - return NULL; - } - - if (iface->conf->ieee80211n && - iface->conf->secondary_channel) - n_chans = 2; - - if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) { - switch (hostapd_get_oper_chwidth(iface->conf)) { - case CHANWIDTH_80MHZ: - n_chans = 4; - break; - case CHANWIDTH_160MHZ: - n_chans = 8; - break; - } - } - - bw = num_chan_to_bw(n_chans); - - /* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */ - - wpa_printf(MSG_DEBUG, - "ACS: Survey analysis for selected bandwidth %d MHz", bw); - - for (i = 0; i < iface->current_mode->num_channels; i++) { + for (i = 0; i < mode->num_channels; i++) { double total_weight; struct acs_bias *bias, tmp_bias; - chan = &iface->current_mode->channels[i]; + chan = &mode->channels[i]; /* Since in the current ACS implementation the first channel is * always a primary channel, skip channels not available as @@ -628,6 +665,9 @@ acs_find_ideal_chan(struct hostapd_iface *iface) if (!is_in_chanlist(iface, chan)) continue; + if (!is_in_freqlist(iface, chan)) + continue; + if (!chan_bw_allowed(chan, bw, 1, 1)) { wpa_printf(MSG_DEBUG, "ACS: Channel %d: BW %u is not supported", @@ -637,7 +677,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface) /* HT40 on 5 GHz has a limited set of primary channels as per * 11n Annex J */ - if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && + if (mode->mode == HOSTAPD_MODE_IEEE80211A && iface->conf->ieee80211n && iface->conf->secondary_channel && !acs_usable_ht40_chan(chan)) { @@ -646,7 +686,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface) continue; } - if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && + if (mode->mode == HOSTAPD_MODE_IEEE80211A && (iface->conf->ieee80211ac || iface->conf->ieee80211ax)) { if (hostapd_get_oper_chwidth(iface->conf) == CHANWIDTH_80MHZ && @@ -698,7 +738,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface) /* 2.4 GHz has overlapping 20 MHz channels. Include adjacent * channel interference factor. */ - if (is_24ghz_mode(iface->current_mode->mode)) { + if (is_24ghz_mode(mode->mode)) { for (j = 0; j < n_chans; j++) { adj_chan = acs_find_chan(iface, chan->freq + (j * 20) - 5); @@ -744,7 +784,7 @@ acs_find_ideal_chan(struct hostapd_iface *iface) break; bias = NULL; } - } else if (is_24ghz_mode(iface->current_mode->mode) && + } else if (is_24ghz_mode(mode->mode) && is_common_24ghz_chan(chan->chan)) { tmp_bias.channel = chan->chan; tmp_bias.bias = ACS_24GHZ_PREFER_1_6_11; @@ -763,14 +803,71 @@ acs_find_ideal_chan(struct hostapd_iface *iface) } if (acs_usable_chan(chan) && - (!ideal_chan || factor < ideal_factor)) { - ideal_factor = factor; - ideal_chan = chan; + (!*ideal_chan || factor < *ideal_factor)) { + *ideal_factor = factor; + *ideal_chan = chan; } /* This channel would at least be usable */ - if (!rand_chan) - rand_chan = chan; + if (!(*rand_chan)) + *rand_chan = chan; + } +} + + +/* + * At this point it's assumed chan->interference_factor has been computed. + * This function should be reusable regardless of interference computation + * option (survey, BSS, spectral, ...). chan->interference factor must be + * summable (i.e., must be always greater than zero). + */ +static struct hostapd_channel_data * +acs_find_ideal_chan(struct hostapd_iface *iface) +{ + struct hostapd_channel_data *ideal_chan = NULL, + *rand_chan = NULL; + long double ideal_factor = 0; + int i; + int n_chans = 1; + u32 bw; + struct hostapd_hw_modes *mode; + + /* TODO: HT40- support */ + + if (iface->conf->ieee80211n && + iface->conf->secondary_channel == -1) { + wpa_printf(MSG_ERROR, "ACS: HT40- is not supported yet. Please try HT40+"); + return NULL; + } + + if (iface->conf->ieee80211n && + iface->conf->secondary_channel) + n_chans = 2; + + if (iface->conf->ieee80211ac || iface->conf->ieee80211ax) { + switch (hostapd_get_oper_chwidth(iface->conf)) { + case CHANWIDTH_80MHZ: + n_chans = 4; + break; + case CHANWIDTH_160MHZ: + n_chans = 8; + break; + } + } + + bw = num_chan_to_bw(n_chans); + + /* TODO: VHT/HE80+80. Update acs_adjust_center_freq() too. */ + + wpa_printf(MSG_DEBUG, + "ACS: Survey analysis for selected bandwidth %d MHz", bw); + + for (i = 0; i < iface->num_hw_features; i++) { + mode = &iface->hw_features[i]; + if (!hostapd_hw_skip_mode(iface, mode)) + acs_find_ideal_chan_mode(iface, mode, n_chans, bw, + &rand_chan, &ideal_chan, + &ideal_factor); } if (ideal_chan) { @@ -826,7 +923,7 @@ static int acs_study_survey_based(struct hostapd_iface *iface) return -1; } - acs_survey_all_chans_intereference_factor(iface); + acs_survey_all_chans_interference_factor(iface); return 0; } @@ -918,29 +1015,59 @@ fail: } -static int acs_request_scan(struct hostapd_iface *iface) +static int * acs_request_scan_add_freqs(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode, + int *freq) { - struct wpa_driver_scan_params params; struct hostapd_channel_data *chan; - int i, *freq; + int i; - os_memset(¶ms, 0, sizeof(params)); - params.freqs = os_calloc(iface->current_mode->num_channels + 1, - sizeof(params.freqs[0])); - if (params.freqs == NULL) - return -1; - - freq = params.freqs; - for (i = 0; i < iface->current_mode->num_channels; i++) { - chan = &iface->current_mode->channels[i]; + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; if (chan->flag & HOSTAPD_CHAN_DISABLED) continue; if (!is_in_chanlist(iface, chan)) continue; + if (!is_in_freqlist(iface, chan)) + continue; + *freq++ = chan->freq; } + + return freq; +} + + +static int acs_request_scan(struct hostapd_iface *iface) +{ + struct wpa_driver_scan_params params; + int i, *freq; + int num_channels; + struct hostapd_hw_modes *mode; + + os_memset(¶ms, 0, sizeof(params)); + + num_channels = 0; + for (i = 0; i < iface->num_hw_features; i++) { + mode = &iface->hw_features[i]; + if (!hostapd_hw_skip_mode(iface, mode)) + num_channels += mode->num_channels; + } + + params.freqs = os_calloc(num_channels + 1, sizeof(params.freqs[0])); + if (params.freqs == NULL) + return -1; + + freq = params.freqs; + + for (i = 0; i < iface->num_hw_features; i++) { + mode = &iface->hw_features[i]; + if (!hostapd_hw_skip_mode(iface, mode)) + freq = acs_request_scan_add_freqs(iface, mode, freq); + } + *freq = 0; if (params.freqs == freq) { @@ -978,7 +1105,8 @@ enum hostapd_chan_status acs_init(struct hostapd_iface *iface) return HOSTAPD_CHAN_ACS; } - if (!iface->current_mode) + if (!iface->current_mode && + iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY) return HOSTAPD_CHAN_INVALID; acs_cleanup(iface); diff --git a/src/ap/airtime_policy.c b/src/ap/airtime_policy.c index f56ca5bdd..1e67f0d59 100644 --- a/src/ap/airtime_policy.c +++ b/src/ap/airtime_policy.c @@ -134,8 +134,8 @@ static void update_airtime_weights(void *eloop_data, void *user_data) unsigned int num_sta_min = 0, num_sta_prod = 1, num_sta_sum = 0, wt_sum = 0; unsigned int quantum; - Boolean all_div_min = TRUE; - Boolean apply_limit = iface->conf->airtime_mode == AIRTIME_MODE_DYNAMIC; + bool all_div_min = true; + bool apply_limit = iface->conf->airtime_mode == AIRTIME_MODE_DYNAMIC; int wt, num_bss = 0, max_wt = 0; size_t i; @@ -169,7 +169,7 @@ static void update_airtime_weights(void *eloop_data, void *user_data) * integers. */ if (bss->num_backlogged_sta && bss->num_backlogged_sta % num_sta_min > 0) - all_div_min = FALSE; + all_div_min = false; /* If we're in LIMIT mode, we only apply the weight * scaling when the BSS(es) marked as limited would a @@ -178,7 +178,7 @@ static void update_airtime_weights(void *eloop_data, void *user_data) if (!apply_limit && bss->conf->airtime_limit) { if (bss->num_backlogged_sta * wt_sum > bss->conf->airtime_weight * num_sta_sum) - apply_limit = TRUE; + apply_limit = true; } } if (all_div_min) diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index d4d098b38..f82468ac8 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -54,23 +54,33 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) bss->logger_syslog = (unsigned int) -1; bss->logger_stdout = (unsigned int) -1; +#ifdef CONFIG_WEP bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED; bss->wep_rekeying_period = 300; /* use key0 in individual key and key1 in broadcast key */ bss->broadcast_key_idx_min = 1; bss->broadcast_key_idx_max = 2; +#else /* CONFIG_WEP */ + bss->auth_algs = WPA_AUTH_ALG_OPEN; +#endif /* CONFIG_WEP */ bss->eap_reauth_period = 3600; bss->wpa_group_rekey = 600; bss->wpa_gmk_rekey = 86400; + bss->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS; bss->wpa_group_update_count = 4; bss->wpa_pairwise_update_count = 4; bss->wpa_disable_eapol_key_retries = DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES; bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; +#ifdef CONFIG_NO_TKIP + bss->wpa_pairwise = WPA_CIPHER_CCMP; + bss->wpa_group = WPA_CIPHER_CCMP; +#else /* CONFIG_NO_TKIP */ bss->wpa_pairwise = WPA_CIPHER_TKIP; bss->wpa_group = WPA_CIPHER_TKIP; +#endif /* CONFIG_NO_TKIP */ bss->rsn_pairwise = 0; bss->max_num_sta = MAX_STA_COUNT; @@ -150,6 +160,10 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) /* Default to strict CRL checking. */ bss->check_crl_strict = 1; + +#ifdef CONFIG_TESTING_OPTIONS + bss->sae_commit_status = -1; +#endif /* CONFIG_TESTING_OPTIONS */ } @@ -251,6 +265,9 @@ struct hostapd_config * hostapd_config_defaults(void) HE_OPERATION_RTS_THRESHOLD_OFFSET; /* Set default basic MCS/NSS set to single stream MCS 0-7 */ conf->he_op.he_basic_mcs_nss_set = 0xfffc; + conf->he_op.he_bss_color_disabled = 1; + conf->he_op.he_bss_color_partial = 0; + conf->he_op.he_bss_color = 1; #endif /* CONFIG_IEEE80211AX */ /* The third octet of the country string uses an ASCII space character @@ -448,7 +465,8 @@ int hostapd_setup_sae_pt(struct hostapd_bss_config *conf) struct hostapd_ssid *ssid = &conf->ssid; struct sae_password_entry *pw; - if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf)) || + if ((conf->sae_pwe == 0 && !hostapd_sae_pw_id_in_use(conf) && + !hostapd_sae_pk_in_use(conf)) || conf->sae_pwe == 3 || !wpa_key_mgmt_sae(conf->wpa_key_mgmt)) return 0; /* PT not needed */ @@ -632,6 +650,7 @@ void hostapd_config_free_eap_users(struct hostapd_eap_user *user) } +#ifdef CONFIG_WEP static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) { int i; @@ -640,6 +659,7 @@ static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) keys->key[i] = NULL; } } +#endif /* CONFIG_WEP */ void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l) @@ -696,6 +716,9 @@ static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf) #ifdef CONFIG_SAE sae_deinit_pt(tmp->pt); #endif /* CONFIG_SAE */ +#ifdef CONFIG_SAE_PK + sae_deinit_pk(tmp->pk); +#endif /* CONFIG_SAE_PK */ os_free(tmp); } } @@ -728,7 +751,9 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) str_clear_free(conf->ssid.wpa_passphrase); os_free(conf->ssid.wpa_psk_file); +#ifdef CONFIG_WEP hostapd_config_free_wep(&conf->ssid.wep); +#endif /* CONFIG_WEP */ #ifdef CONFIG_FULL_DYNAMIC_VLAN os_free(conf->ssid.vlan_tagged_interface); #endif /* CONFIG_FULL_DYNAMIC_VLAN */ @@ -890,7 +915,10 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) #ifdef CONFIG_TESTING_OPTIONS wpabuf_free(conf->own_ie_override); wpabuf_free(conf->sae_commit_override); + wpabuf_free(conf->rsne_override_eapol); wpabuf_free(conf->rsnxe_override_eapol); + wpabuf_free(conf->rsne_override_ft); + wpabuf_free(conf->rsnxe_override_ft); wpabuf_free(conf->gtk_rsc_override); wpabuf_free(conf->igtk_rsc_override); #endif /* CONFIG_TESTING_OPTIONS */ @@ -1091,6 +1119,37 @@ const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, } +#ifdef CONFIG_SAE_PK +static bool hostapd_sae_pk_password_without_pk(struct hostapd_bss_config *bss) +{ + struct sae_password_entry *pw; + bool res = false; + + if (bss->ssid.wpa_passphrase && +#ifdef CONFIG_TESTING_OPTIONS + !bss->sae_pk_password_check_skip && +#endif /* CONFIG_TESTING_OPTIONS */ + sae_pk_valid_password(bss->ssid.wpa_passphrase)) + res = true; + + for (pw = bss->sae_passwords; pw; pw = pw->next) { + if (!pw->pk && +#ifdef CONFIG_TESTING_OPTIONS + !bss->sae_pk_password_check_skip && +#endif /* CONFIG_TESTING_OPTIONS */ + sae_pk_valid_password(pw->password)) + return true; + + if (bss->ssid.wpa_passphrase && res && pw->pk && + os_strcmp(bss->ssid.wpa_passphrase, pw->password) == 0) + res = false; + } + + return res; +} +#endif /* CONFIG_SAE_PK */ + + static int hostapd_config_check_bss(struct hostapd_bss_config *bss, struct hostapd_config *conf, int full_config) @@ -1102,6 +1161,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, return -1; } +#ifdef CONFIG_WEP if (bss->wpa) { int wep, i; @@ -1119,6 +1179,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, return -1; } } +#endif /* CONFIG_WEP */ if (full_config && bss->wpa && bss->wpa_psk_radius != PSK_RADIUS_IGNORED && @@ -1166,47 +1227,49 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, } #endif /* CONFIG_IEEE80211R_AP */ -#ifdef CONFIG_IEEE80211N if (full_config && conf->ieee80211n && conf->hw_mode == HOSTAPD_MODE_IEEE80211B) { - bss->disable_11n = 1; + bss->disable_11n = true; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not " "allowed, disabling HT capabilities"); } +#ifdef CONFIG_WEP if (full_config && conf->ieee80211n && bss->ssid.security_policy == SECURITY_STATIC_WEP) { - bss->disable_11n = 1; + bss->disable_11n = true; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not " "allowed, disabling HT capabilities"); } +#endif /* CONFIG_WEP */ if (full_config && conf->ieee80211n && bss->wpa && !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) { - bss->disable_11n = 1; + bss->disable_11n = true; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " "requires CCMP/GCMP to be enabled, disabling HT " "capabilities"); } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC +#ifdef CONFIG_WEP if (full_config && conf->ieee80211ac && bss->ssid.security_policy == SECURITY_STATIC_WEP) { - bss->disable_11ac = 1; + bss->disable_11ac = true; wpa_printf(MSG_ERROR, "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities"); } +#endif /* CONFIG_WEP */ if (full_config && conf->ieee80211ac && bss->wpa && !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) { - bss->disable_11ac = 1; + bss->disable_11ac = true; wpa_printf(MSG_ERROR, "VHT (IEEE 802.11ac) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling VHT capabilities"); } @@ -1219,12 +1282,14 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, bss->wps_state = 0; } +#ifdef CONFIG_WEP if (full_config && bss->wps_state && bss->ssid.wep.keys_set && bss->wpa == 0) { wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be " "disabled"); bss->wps_state = 0; } +#endif /* CONFIG_WEP */ if (full_config && bss->wps_state && bss->wpa && (!(bss->wpa & 2) || @@ -1268,6 +1333,15 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, } #endif /* CONFIG_OCV */ +#ifdef CONFIG_SAE_PK + if (full_config && hostapd_sae_pk_in_use(bss) && + hostapd_sae_pk_password_without_pk(bss)) { + wpa_printf(MSG_ERROR, + "SAE-PK: SAE password uses SAE-PK style, but does not have PK configured"); + return -1; + } +#endif /* CONFIG_SAE_PK */ + return 0; } @@ -1348,11 +1422,13 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config) void hostapd_set_security_params(struct hostapd_bss_config *bss, int full_config) { +#ifdef CONFIG_WEP if (bss->individual_wep_key_len == 0) { /* individual keys are not use; can use key idx0 for * broadcast keys */ bss->broadcast_key_idx_min = 0; } +#endif /* CONFIG_WEP */ if ((bss->wpa & 2) && bss->rsn_pairwise == 0) bss->rsn_pairwise = bss->wpa_pairwise; @@ -1378,6 +1454,7 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss, } else if (bss->ieee802_1x) { int cipher = WPA_CIPHER_NONE; bss->ssid.security_policy = SECURITY_IEEE_802_1X; +#ifdef CONFIG_WEP bss->ssid.wep.default_len = bss->default_wep_key_len; if (full_config && bss->default_wep_key_len) { cipher = bss->default_wep_key_len >= 13 ? @@ -1388,11 +1465,13 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss, else cipher = WPA_CIPHER_WEP40; } +#endif /* CONFIG_WEP */ bss->wpa_group = cipher; bss->wpa_pairwise = cipher; bss->rsn_pairwise = cipher; if (full_config) bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA; +#ifdef CONFIG_WEP } else if (bss->ssid.wep.keys_set) { int cipher = WPA_CIPHER_WEP40; if (bss->ssid.wep.len[0] >= 13) @@ -1403,6 +1482,7 @@ void hostapd_set_security_params(struct hostapd_bss_config *bss, bss->rsn_pairwise = cipher; if (full_config) bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE; +#endif /* CONFIG_WEP */ } else if (bss->osen) { bss->ssid.security_policy = SECURITY_OSEN; bss->wpa_group = WPA_CIPHER_CCMP; @@ -1441,3 +1521,38 @@ int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf) return 2; return with_id; } + + +bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf) +{ +#ifdef CONFIG_SAE_PK + struct sae_password_entry *pw; + + for (pw = conf->sae_passwords; pw; pw = pw->next) { + if (pw->pk) + return true; + } +#endif /* CONFIG_SAE_PK */ + + return false; +} + + +#ifdef CONFIG_SAE_PK +bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf) +{ + bool with_pk = false; + struct sae_password_entry *pw; + + if (conf->ssid.wpa_passphrase) + return false; + + for (pw = conf->sae_passwords; pw; pw = pw->next) { + if (!pw->pk) + return false; + with_pk = true; + } + + return with_pk; +} +#endif /* CONFIG_SAE_PK */ diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index f321017e8..f7a344e0e 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -67,6 +67,7 @@ struct hostapd_radius_servers; struct ft_remote_r0kh; struct ft_remote_r1kh; +#ifdef CONFIG_WEP #define NUM_WEP_KEYS 4 struct hostapd_wep_keys { u8 idx; @@ -75,10 +76,13 @@ struct hostapd_wep_keys { int keys_set; size_t default_len; /* key length used for dynamic key generation */ }; +#endif /* CONFIG_WEP */ typedef enum hostap_security_policy { SECURITY_PLAINTEXT = 0, +#ifdef CONFIG_WEP SECURITY_STATIC_WEP = 1, +#endif /* CONFIG_WEP */ SECURITY_IEEE_802_1X = 2, SECURITY_WPA_PSK = 3, SECURITY_WPA = 4, @@ -102,7 +106,9 @@ struct hostapd_ssid { char *wpa_psk_file; struct sae_pt *pt; +#ifdef CONFIG_WEP struct hostapd_wep_keys wep; +#endif /* CONFIG_WEP */ #define DYNAMIC_VLAN_DISABLED 0 #define DYNAMIC_VLAN_OPTIONAL 1 @@ -191,15 +197,6 @@ struct hostapd_radius_attr { #define NUM_TX_QUEUES 4 - -struct hostapd_tx_queue_params { - int aifs; - int cwmin; - int cwmax; - int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */ -}; - - #define MAX_ROAMING_CONSORTIUM_LEN 15 struct hostapd_roaming_consortium { @@ -255,6 +252,7 @@ struct sae_password_entry { u8 peer_addr[ETH_ALEN]; int vlan_id; struct sae_pt *pt; + struct sae_pk *pk; }; struct dpp_controller_conf { @@ -321,10 +319,12 @@ struct hostapd_bss_config { size_t eap_req_id_text_len; int eapol_key_index_workaround; +#ifdef CONFIG_WEP size_t default_wep_key_len; int individual_wep_key_len; int wep_rekeying_period; int broadcast_key_idx_min, broadcast_key_idx_max; +#endif /* CONFIG_WEP */ int eap_reauth_period; int erp_send_reauth_start; char *erp_domain; @@ -346,9 +346,11 @@ struct hostapd_bss_config { * algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */ int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */ + int extended_key_id; int wpa_key_mgmt; enum mfp_options ieee80211w; int group_mgmt_cipher; + int beacon_prot; /* dot11AssociationSAQueryMaximumTimeout (in TUs) */ unsigned int assoc_sa_query_max_timeout; /* dot11AssociationSAQueryRetryTimeout (in TUs) */ @@ -369,6 +371,7 @@ struct hostapd_bss_config { int wpa_strict_rekey; int wpa_gmk_rekey; int wpa_ptk_rekey; + enum ptk0_rekey_handling wpa_deny_ptk0_rekey; u32 wpa_group_update_count; u32 wpa_pairwise_update_count; int wpa_disable_eapol_key_retries; @@ -528,8 +531,9 @@ struct hostapd_bss_config { #define TDLS_PROHIBIT BIT(0) #define TDLS_PROHIBIT_CHAN_SWITCH BIT(1) int tdls; - int disable_11n; - int disable_11ac; + bool disable_11n; + bool disable_11ac; + bool disable_11ax; /* IEEE 802.11v */ int time_advertisement; @@ -666,10 +670,26 @@ struct hostapd_bss_config { u8 bss_load_test_set; struct wpabuf *own_ie_override; int sae_reflection_attack; + int sae_commit_status; + int sae_pk_omit; + int sae_pk_password_check_skip; struct wpabuf *sae_commit_override; + struct wpabuf *rsne_override_eapol; struct wpabuf *rsnxe_override_eapol; + struct wpabuf *rsne_override_ft; + struct wpabuf *rsnxe_override_ft; struct wpabuf *gtk_rsc_override; struct wpabuf *igtk_rsc_override; + int no_beacon_rsnxe; + int skip_prune_assoc; + int ft_rsnxe_used; + unsigned int oci_freq_override_eapol_m3; + unsigned int oci_freq_override_eapol_g1; + unsigned int oci_freq_override_saquery_req; + unsigned int oci_freq_override_saquery_resp; + unsigned int oci_freq_override_ft_assoc; + unsigned int oci_freq_override_fils_assoc; + unsigned int oci_freq_override_wnm_sleep; #endif /* CONFIG_TESTING_OPTIONS */ #define MESH_ENABLED BIT(0) @@ -725,6 +745,8 @@ struct hostapd_bss_config { struct wpabuf *dpp_csign; #ifdef CONFIG_DPP2 struct dpp_controller_conf *dpp_controller; + int dpp_configurator_connectivity; + int dpp_pfs; #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ @@ -741,6 +763,8 @@ struct hostapd_bss_config { u8 send_probe_response; + u8 transition_disable; + #define BACKHAUL_BSS 1 #define FRONTHAUL_BSS 2 int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */ @@ -844,9 +868,9 @@ struct hostapd_bss_config { * struct he_phy_capabilities_info - HE PHY capabilities */ struct he_phy_capabilities_info { - Boolean he_su_beamformer; - Boolean he_su_beamformee; - Boolean he_mu_beamformer; + bool he_su_beamformer; + bool he_su_beamformee; + bool he_mu_beamformer; }; /** @@ -854,6 +878,8 @@ struct he_phy_capabilities_info { */ struct he_operation { u8 he_bss_color; + u8 he_bss_color_disabled; + u8 he_bss_color_partial; u8 he_default_pe_duration; u8 he_twt_required; u16 he_rts_threshold; @@ -1013,6 +1039,7 @@ struct hostapd_config { int rssi_reject_assoc_rssi; int rssi_reject_assoc_timeout; + int rssi_ignore_probe_request; #ifdef CONFIG_AIRTIME_POLICY enum { @@ -1117,6 +1144,8 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config); void hostapd_set_security_params(struct hostapd_bss_config *bss, int full_config); int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf); +bool hostapd_sae_pk_in_use(struct hostapd_bss_config *conf); +bool hostapd_sae_pk_exclusively(struct hostapd_bss_config *conf); int hostapd_setup_sae_pt(struct hostapd_bss_config *conf); #endif /* HOSTAPD_CONFIG_H */ diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index c217d9b24..f15765945 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -418,6 +418,7 @@ int hostapd_sta_add(struct hostapd_data *hapd, const struct ieee80211_vht_capabilities *vht_capab, const struct ieee80211_he_capabilities *he_capab, size_t he_capab_len, + const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, int set) { @@ -439,6 +440,7 @@ int hostapd_sta_add(struct hostapd_data *hapd, params.vht_capabilities = vht_capab; params.he_capab = he_capab; params.he_capab_len = he_capab_len; + params.he_6ghz_capab = he_6ghz_capab; params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED); params.vht_opmode = vht_opmode; params.flags = hostapd_sta_flags_to_drv(flags); @@ -588,7 +590,7 @@ int hostapd_set_frag(struct hostapd_data *hapd, int frag) int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, int total_flags, int flags_or, int flags_and) { - if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL) + if (!hapd->driver || !hapd->drv_priv || !hapd->driver->sta_set_flags) return 0; return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags, flags_or, flags_and); @@ -650,6 +652,12 @@ int hostapd_drv_none(struct hostapd_data *hapd) } +bool hostapd_drv_nl80211(struct hostapd_data *hapd) +{ + return hapd->driver && os_strcmp(hapd->driver->name, "nl80211") == 0; +} + + int hostapd_driver_scan(struct hostapd_data *hapd, struct wpa_driver_scan_params *params) { @@ -714,7 +722,7 @@ int hostapd_drv_send_mlme(struct hostapd_data *hapd, if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv) return 0; return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0, - csa_offs, csa_offs_len, no_encrypt); + csa_offs, csa_offs_len, no_encrypt, 0); } @@ -938,6 +946,7 @@ int hostapd_drv_do_acs(struct hostapd_data *hapd) } params.freq_list = freq_list; + params.edmg_enabled = hapd->iface->conf->enable_edmg; params.ht_enabled = !!(hapd->iface->conf->ieee80211n); params.ht40_enabled = !!(hapd->iface->conf->ht_capab & diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index 56d1ad862..0257c3a65 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -43,6 +43,7 @@ int hostapd_sta_add(struct hostapd_data *hapd, const struct ieee80211_vht_capabilities *vht_capab, const struct ieee80211_he_capabilities *he_capab, size_t he_capab_len, + const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab, u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, int set); int hostapd_set_privacy(struct hostapd_data *hapd, int enabled); @@ -80,6 +81,7 @@ hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, u16 *flags, u8 *dfs_domain); int hostapd_driver_commit(struct hostapd_data *hapd); int hostapd_drv_none(struct hostapd_data *hapd); +bool hostapd_drv_nl80211(struct hostapd_data *hapd); int hostapd_driver_scan(struct hostapd_data *hapd, struct wpa_driver_scan_params *params); struct wpa_scan_results * hostapd_driver_get_scan_results( @@ -348,12 +350,13 @@ static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd, static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd, int vendor_id, int subcmd, const u8 *data, size_t data_len, + enum nested_attr nested_attr_flag, struct wpabuf *buf) { if (hapd->driver == NULL || hapd->driver->vendor_cmd == NULL) return -1; return hapd->driver->vendor_cmd(hapd->drv_priv, vendor_id, subcmd, data, - data_len, buf); + data_len, nested_attr_flag, buf); } static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd) @@ -382,11 +385,11 @@ hostapd_drv_send_external_auth_status(struct hostapd_data *hapd, } static inline int -hostapd_drv_set_band(struct hostapd_data *hapd, enum set_band band) +hostapd_drv_set_band(struct hostapd_data *hapd, u32 band_mask) { if (!hapd->driver || !hapd->drv_priv || !hapd->driver->set_band) return -1; - return hapd->driver->set_band(hapd->drv_priv, band); + return hapd->driver->set_band(hapd->drv_priv, band_mask); } #endif /* AP_DRV_OPS */ diff --git a/src/ap/ap_list.c b/src/ap/ap_list.c index 8bf6ddec8..20be7f8f8 100644 --- a/src/ap/ap_list.c +++ b/src/ap/ap_list.c @@ -228,7 +228,6 @@ void ap_list_process_beacon(struct hostapd_iface *iface, set_beacon++; } -#ifdef CONFIG_IEEE80211N if (!iface->olbc_ht && !ap->ht_support && (ap->channel == 0 || ap->channel == iface->conf->channel || @@ -241,7 +240,6 @@ void ap_list_process_beacon(struct hostapd_iface *iface, MAC2STR(ap->addr), ap->channel); set_beacon++; } -#endif /* CONFIG_IEEE80211N */ if (set_beacon) ieee802_11_update_beacons(iface); @@ -285,14 +283,12 @@ void ap_list_timer(struct hostapd_iface *iface) iface->olbc = 0; set_beacon++; } -#ifdef CONFIG_IEEE80211N if (!olbc_ht && iface->olbc_ht) { wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore"); iface->olbc_ht = 0; hostapd_ht_operation_update(iface); set_beacon++; } -#endif /* CONFIG_IEEE80211N */ } if (set_beacon) diff --git a/src/ap/beacon.c b/src/ap/beacon.c index ecee27aa6..47b260e81 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -266,17 +266,101 @@ static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid, } -static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len) +static const u8 * hostapd_wpa_ie(struct hostapd_data *hapd, u8 eid) +{ + const u8 *ies; + size_t ies_len; + + ies = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ies_len); + if (!ies) + return NULL; + + return get_ie(ies, ies_len, eid); +} + + +static const u8 * hostapd_vendor_wpa_ie(struct hostapd_data *hapd, + u32 vendor_type) +{ + const u8 *ies; + size_t ies_len; + + ies = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ies_len); + if (!ies) + return NULL; + + return get_vendor_ie(ies, ies_len, vendor_type); +} + + +static u8 * hostapd_get_rsne(struct hostapd_data *hapd, u8 *pos, size_t len) { const u8 *ie; - size_t ielen; - ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen); - if (ie == NULL || ielen > len) - return eid; + ie = hostapd_wpa_ie(hapd, WLAN_EID_RSN); + if (!ie || 2U + ie[1] > len) + return pos; - os_memcpy(eid, ie, ielen); - return eid + ielen; + os_memcpy(pos, ie, 2 + ie[1]); + return pos + 2 + ie[1]; +} + + +static u8 * hostapd_get_mde(struct hostapd_data *hapd, u8 *pos, size_t len) +{ + const u8 *ie; + + ie = hostapd_wpa_ie(hapd, WLAN_EID_MOBILITY_DOMAIN); + if (!ie || 2U + ie[1] > len) + return pos; + + os_memcpy(pos, ie, 2 + ie[1]); + return pos + 2 + ie[1]; +} + + +static u8 * hostapd_get_rsnxe(struct hostapd_data *hapd, u8 *pos, size_t len) +{ + const u8 *ie; + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->no_beacon_rsnxe) { + wpa_printf(MSG_INFO, "TESTING: Do not add RSNXE into Beacon"); + return pos; + } +#endif /* CONFIG_TESTING_OPTIONS */ + ie = hostapd_wpa_ie(hapd, WLAN_EID_RSNX); + if (!ie || 2U + ie[1] > len) + return pos; + + os_memcpy(pos, ie, 2 + ie[1]); + return pos + 2 + ie[1]; +} + + +static u8 * hostapd_get_wpa_ie(struct hostapd_data *hapd, u8 *pos, size_t len) +{ + const u8 *ie; + + ie = hostapd_vendor_wpa_ie(hapd, WPA_IE_VENDOR_TYPE); + if (!ie || 2U + ie[1] > len) + return pos; + + os_memcpy(pos, ie, 2 + ie[1]); + return pos + 2 + ie[1]; +} + + +static u8 * hostapd_get_osen_ie(struct hostapd_data *hapd, u8 *pos, size_t len) +{ + const u8 *ie; + + ie = hostapd_vendor_wpa_ie(hapd, OSEN_IE_VENDOR_TYPE); + if (!ie || 2U + ie[1] > len) + return pos; + + os_memcpy(pos, ie, 2 + ie[1]); + return pos + 2 + ie[1]; } @@ -374,16 +458,20 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, } #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { buflen += 3 + sizeof(struct ieee80211_he_capabilities) + 3 + sizeof(struct ieee80211_he_operation) + 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + 3 + sizeof(struct ieee80211_spatial_reuse); + if (is_6ghz_op_class(hapd->iconf->op_class)) + buflen += sizeof(struct ieee80211_he_6ghz_oper_info) + + 3 + sizeof(struct ieee80211_he_6ghz_band_cap); } #endif /* CONFIG_IEEE80211AX */ buflen += hostapd_mbo_ie_len(hapd); buflen += hostapd_eid_owe_trans_len(hapd); + buflen += hostapd_eid_dpp_cc_len(hapd); resp = os_zalloc(buflen); if (resp == NULL) @@ -434,14 +522,10 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, /* Extended supported rates */ pos = hostapd_eid_ext_supp_rates(hapd, pos); - /* RSN, MDIE */ - if (!(hapd->conf->wpa == WPA_PROTO_WPA || - (hapd->conf->osen && !hapd->conf->wpa))) - pos = hostapd_eid_wpa(hapd, pos, epos - pos); - + pos = hostapd_get_rsne(hapd, pos, epos - pos); pos = hostapd_eid_bss_load(hapd, pos, epos - pos); - pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos); + pos = hostapd_get_mde(hapd, pos, epos - pos); /* eCSA IE */ csa_pos = hostapd_eid_ecsa(hapd, pos); @@ -450,15 +534,8 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = csa_pos; pos = hostapd_eid_supported_op_classes(hapd, pos); - -#ifdef CONFIG_IEEE80211N - /* Secondary Channel Offset element */ - /* TODO: The standard doesn't specify a position for this element. */ - pos = hostapd_eid_secondary_channel(hapd, pos); - pos = hostapd_eid_ht_capabilities(hapd, pos); pos = hostapd_eid_ht_operation(hapd, pos); -#endif /* CONFIG_IEEE80211N */ pos = hostapd_eid_ext_capab(hapd, pos); @@ -483,18 +560,23 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_vht_capabilities(hapd, pos, 0); pos = hostapd_eid_vht_operation(hapd, pos); pos = hostapd_eid_txpower_envelope(hapd, pos); - pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); } #endif /* CONFIG_IEEE80211AC */ + if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) || + (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax)) + pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); + pos = hostapd_eid_fils_indic(hapd, pos, 0); + pos = hostapd_get_rsnxe(hapd, pos, epos - pos); #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP); pos = hostapd_eid_he_operation(hapd, pos); - pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos); pos = hostapd_eid_spatial_reuse(hapd, pos); + pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos); + pos = hostapd_eid_he_6ghz_band_cap(hapd, pos); } #endif /* CONFIG_IEEE80211AX */ @@ -503,10 +585,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_vendor_vht(hapd, pos); #endif /* CONFIG_IEEE80211AC */ - /* WPA */ - if (hapd->conf->wpa == WPA_PROTO_WPA || - (hapd->conf->osen && !hapd->conf->wpa)) - pos = hostapd_eid_wpa(hapd, pos, epos - pos); + /* WPA / OSEN */ + pos = hostapd_get_wpa_ie(hapd, pos, epos - pos); + pos = hostapd_get_osen_ie(hapd, pos, epos - pos); /* Wi-Fi Alliance WMM */ pos = hostapd_eid_wmm(hapd, pos); @@ -539,6 +620,7 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos); pos = hostapd_eid_owe_trans(hapd, pos, (u8 *) resp + buflen - pos); + pos = hostapd_eid_dpp_cc(hapd, pos, (u8 *) resp + buflen - pos); if (hapd->conf->vendor_elements) { os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements), @@ -736,6 +818,10 @@ void handle_probe_req(struct hostapd_data *hapd, size_t csa_offs_len; struct radius_sta rad_info; + if (hapd->iconf->rssi_ignore_probe_request && ssi_signal && + ssi_signal < hapd->iconf->rssi_ignore_probe_request) + return; + if (len < IEEE80211_HDRLEN) return; ie = ((const u8 *) mgmt) + IEEE80211_HDRLEN; @@ -1052,7 +1138,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, size_t resp_len = 0; #ifdef NEED_AP_MLME u16 capab_info; - u8 *pos, *tailpos, *csa_pos; + u8 *pos, *tailpos, *tailend, *csa_pos; #define BEACON_HEAD_BUF_SIZE 256 #define BEACON_TAIL_BUF_SIZE 512 @@ -1081,16 +1167,20 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, #endif /* CONFIG_IEEE80211AC */ #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { tail_len += 3 + sizeof(struct ieee80211_he_capabilities) + 3 + sizeof(struct ieee80211_he_operation) + 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + 3 + sizeof(struct ieee80211_spatial_reuse); + if (is_6ghz_op_class(hapd->iconf->op_class)) + tail_len += sizeof(struct ieee80211_he_6ghz_oper_info) + + 3 + sizeof(struct ieee80211_he_6ghz_band_cap); } #endif /* CONFIG_IEEE80211AX */ tail_len += hostapd_mbo_ie_len(hapd); tail_len += hostapd_eid_owe_trans_len(hapd); + tail_len += hostapd_eid_dpp_cc_len(hapd); tailpos = tail = os_malloc(tail_len); if (head == NULL || tail == NULL) { @@ -1099,6 +1189,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, os_free(tail); return -1; } + tailend = tail + tail_len; head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_BEACON); @@ -1139,8 +1230,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, head_len = pos - (u8 *) head; - tailpos = hostapd_eid_country(hapd, tailpos, - tail + BEACON_TAIL_BUF_SIZE - tailpos); + tailpos = hostapd_eid_country(hapd, tailpos, tailend - tailpos); /* Power Constraint element */ tailpos = hostapd_eid_pwr_constraint(hapd, tailpos); @@ -1157,19 +1247,11 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, /* Extended supported rates */ tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); - /* RSN, MDIE */ - if (!(hapd->conf->wpa == WPA_PROTO_WPA || - (hapd->conf->osen && !hapd->conf->wpa))) - tailpos = hostapd_eid_wpa(hapd, tailpos, - tail + BEACON_TAIL_BUF_SIZE - - tailpos); - + tailpos = hostapd_get_rsne(hapd, tailpos, tailend - tailpos); + tailpos = hostapd_eid_bss_load(hapd, tailpos, tailend - tailpos); tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos, - tail + BEACON_TAIL_BUF_SIZE - - tailpos); - - tailpos = hostapd_eid_bss_load(hapd, tailpos, - tail + BEACON_TAIL_BUF_SIZE - tailpos); + tailend - tailpos); + tailpos = hostapd_get_mde(hapd, tailpos, tailend - tailpos); /* eCSA IE */ csa_pos = hostapd_eid_ecsa(hapd, tailpos); @@ -1178,15 +1260,8 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = csa_pos; tailpos = hostapd_eid_supported_op_classes(hapd, tailpos); - -#ifdef CONFIG_IEEE80211N - /* Secondary Channel Offset element */ - /* TODO: The standard doesn't specify a position for this element. */ - tailpos = hostapd_eid_secondary_channel(hapd, tailpos); - tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); tailpos = hostapd_eid_ht_operation(hapd, tailpos); -#endif /* CONFIG_IEEE80211N */ tailpos = hostapd_eid_ext_capab(hapd, tailpos); @@ -1213,19 +1288,24 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_vht_capabilities(hapd, tailpos, 0); tailpos = hostapd_eid_vht_operation(hapd, tailpos); tailpos = hostapd_eid_txpower_envelope(hapd, tailpos); - tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos); } #endif /* CONFIG_IEEE80211AC */ + if ((hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) || + (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax)) + tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos); + tailpos = hostapd_eid_fils_indic(hapd, tailpos, 0); + tailpos = hostapd_get_rsnxe(hapd, tailpos, tailend - tailpos); #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { tailpos = hostapd_eid_he_capab(hapd, tailpos, IEEE80211_MODE_AP); tailpos = hostapd_eid_he_operation(hapd, tailpos); - tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos); tailpos = hostapd_eid_spatial_reuse(hapd, tailpos); + tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos); + tailpos = hostapd_eid_he_6ghz_band_cap(hapd, tailpos); } #endif /* CONFIG_IEEE80211AX */ @@ -1234,12 +1314,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_vendor_vht(hapd, tailpos); #endif /* CONFIG_IEEE80211AC */ - /* WPA */ - if (hapd->conf->wpa == WPA_PROTO_WPA || - (hapd->conf->osen && !hapd->conf->wpa)) - tailpos = hostapd_eid_wpa(hapd, tailpos, - tail + BEACON_TAIL_BUF_SIZE - - tailpos); + /* WPA / OSEN */ + tailpos = hostapd_get_wpa_ie(hapd, tailpos, tailend - tailpos); + tailpos = hostapd_get_osen_ie(hapd, tailpos, tailend - tailpos); /* Wi-Fi Alliance WMM */ tailpos = hostapd_eid_wmm(hapd, tailpos); @@ -1272,6 +1349,7 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos); tailpos = hostapd_eid_owe_trans(hapd, tailpos, tail + tail_len - tailpos); + tailpos = hostapd_eid_dpp_cc(hapd, tailpos, tail + tail_len - tailpos); if (hapd->conf->vendor_elements) { os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements), @@ -1310,10 +1388,13 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, params->key_mgmt_suites = hapd->conf->wpa_key_mgmt; params->auth_algs = hapd->conf->auth_algs; params->wpa_version = hapd->conf->wpa; - params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa || + params->privacy = hapd->conf->wpa; +#ifdef CONFIG_WEP + params->privacy |= hapd->conf->ssid.wep.keys_set || (hapd->conf->ieee802_1x && (hapd->conf->default_wep_key_len || hapd->conf->individual_wep_key_len)); +#endif /* CONFIG_WEP */ switch (hapd->conf->ignore_broadcast_ssid) { case 0: params->hide_ssid = NO_SSID_HIDING; @@ -1326,7 +1407,6 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, break; } params->isolate = hapd->conf->isolate; - params->smps_mode = hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_MASK; #ifdef NEED_AP_MLME params->cts_protect = !!(ieee802_11_erp_info(hapd) & ERP_INFO_USE_PROTECTION); @@ -1422,8 +1502,18 @@ int ieee802_11_set_beacon(struct hostapd_data *hapd) hapd->iface->conf->spr.srg_obss_pd_min_offset; params.he_spr_srg_obss_pd_max_offset = hapd->iface->conf->spr.srg_obss_pd_max_offset; + params.he_bss_color_disabled = + hapd->iface->conf->he_op.he_bss_color_disabled; + params.he_bss_color_partial = + hapd->iface->conf->he_op.he_bss_color_partial; + params.he_bss_color = hapd->iface->conf->he_op.he_bss_color; + params.twt_responder = hostapd_get_he_twt_responder(hapd, + IEEE80211_MODE_AP); #endif /* CONFIG_IEEE80211AX */ hapd->reenable_beacon = 0; +#ifdef CONFIG_SAE + params.sae_pwe = hapd->conf->sae_pwe; +#endif /* CONFIG_SAE */ if (cmode && hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq, diff --git a/src/ap/ctrl_iface_ap.c b/src/ap/ctrl_iface_ap.c index a54b0ca2c..b3d6d62e4 100644 --- a/src/ap/ctrl_iface_ap.c +++ b/src/ap/ctrl_iface_ap.c @@ -345,7 +345,6 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, } #endif /* CONFIG_IEEE80211AC */ -#ifdef CONFIG_IEEE80211N if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) { res = os_snprintf(buf + len, buflen - len, "ht_caps_info=0x%04x\n", @@ -354,7 +353,6 @@ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd, if (!os_snprintf_error(buflen - len, res)) len += res; } -#endif /* CONFIG_IEEE80211N */ if (sta->ext_capability && buflen - len > (unsigned) (11 + 2 * sta->ext_capability[0])) { @@ -750,7 +748,8 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, iface->conf->ieee80211n && !hapd->conf->disable_11n, iface->conf->ieee80211ac && !hapd->conf->disable_11ac, - iface->conf->ieee80211ax, + iface->conf->ieee80211ax && + !hapd->conf->disable_11ax, iface->conf->beacon_int, hapd->conf->dtim_period); if (os_snprintf_error(buflen - len, ret)) @@ -758,7 +757,7 @@ int hostapd_ctrl_iface_status(struct hostapd_data *hapd, char *buf, len += ret; #ifdef CONFIG_IEEE80211AX - if (iface->conf->ieee80211ax) { + if (iface->conf->ieee80211ax && !hapd->conf->disable_11ax) { ret = os_snprintf(buf + len, buflen - len, "he_oper_chwidth=%d\n" "he_oper_centr_freq_seg0_idx=%d\n" diff --git a/src/ap/dfs.c b/src/ap/dfs.c index f70ecc946..84db7f28d 100644 --- a/src/ap/dfs.c +++ b/src/ap/dfs.c @@ -144,30 +144,44 @@ static int dfs_chan_range_available(struct hostapd_hw_modes *mode, int i; u32 bw = num_chan_to_bw(num_chans); - if (first_chan_idx + num_chans > mode->num_channels) + if (first_chan_idx + num_chans > mode->num_channels) { + wpa_printf(MSG_DEBUG, + "DFS: some channels in range not defined"); return 0; + } first_chan = &mode->channels[first_chan_idx]; /* hostapd DFS implementation assumes the first channel as primary. * If it's not allowed to use the first channel as primary, decline the * whole channel range. */ - if (!chan_pri_allowed(first_chan)) + if (!chan_pri_allowed(first_chan)) { + wpa_printf(MSG_DEBUG, "DFS: primary chanenl not allowed"); return 0; + } for (i = 0; i < num_chans; i++) { chan = dfs_get_chan_data(mode, first_chan->freq + i * 20, first_chan_idx); - if (!chan) + if (!chan) { + wpa_printf(MSG_DEBUG, "DFS: no channel data for %d", + first_chan->freq + i * 20); return 0; + } /* HT 40 MHz secondary channel availability checked only for * primary channel */ - if (!chan_bw_allowed(chan, bw, 1, !i)) + if (!chan_bw_allowed(chan, bw, 1, !i)) { + wpa_printf(MSG_DEBUG, "DFS: bw now allowed for %d", + first_chan->freq + i * 20); return 0; + } - if (!dfs_channel_available(chan, skip_radar)) + if (!dfs_channel_available(chan, skip_radar)) { + wpa_printf(MSG_DEBUG, "DFS: channel not available %d", + first_chan->freq + i * 20); return 0; + } } return 1; @@ -210,22 +224,36 @@ static int dfs_find_channel(struct hostapd_iface *iface, if (iface->conf->ieee80211n && iface->conf->secondary_channel && (!dfs_is_chan_allowed(chan, n_chans) || - !(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))) + !(chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P))) { + wpa_printf(MSG_DEBUG, + "DFS: channel %d (%d) is incompatible", + chan->freq, chan->chan); continue; + } /* Skip incompatible chandefs */ - if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) + if (!dfs_chan_range_available(mode, i, n_chans, skip_radar)) { + wpa_printf(MSG_DEBUG, + "DFS: range not available for %d (%d)", + chan->freq, chan->chan); continue; + } - if (!is_in_chanlist(iface, chan)) + if (!is_in_chanlist(iface, chan)) { + wpa_printf(MSG_DEBUG, + "DFS: channel %d (%d) not in chanlist", + chan->freq, chan->chan); continue; + } if (ret_chan && idx == channel_idx) { - wpa_printf(MSG_DEBUG, "Selected ch. #%d", chan->chan); + wpa_printf(MSG_DEBUG, "Selected channel %d (%d)", + chan->freq, chan->chan); *ret_chan = chan; return idx; } - wpa_printf(MSG_DEBUG, "Adding channel: %d", chan->chan); + wpa_printf(MSG_DEBUG, "Adding channel %d (%d)", + chan->freq, chan->chan); channel_idx++; } return channel_idx; @@ -235,6 +263,7 @@ static int dfs_find_channel(struct hostapd_iface *iface, static void dfs_adjust_center_freq(struct hostapd_iface *iface, struct hostapd_channel_data *chan, int secondary_channel, + int sec_chan_idx_80p80, u8 *oper_centr_freq_seg0_idx, u8 *oper_centr_freq_seg1_idx) { @@ -261,8 +290,14 @@ static void dfs_adjust_center_freq(struct hostapd_iface *iface, case CHANWIDTH_160MHZ: *oper_centr_freq_seg0_idx = chan->chan + 14; break; + case CHANWIDTH_80P80MHZ: + *oper_centr_freq_seg0_idx = chan->chan + 6; + *oper_centr_freq_seg1_idx = sec_chan_idx_80p80 + 6; + break; + default: - wpa_printf(MSG_INFO, "DFS only VHT20/40/80/160 is supported now"); + wpa_printf(MSG_INFO, + "DFS: Unsupported channel width configuration"); *oper_centr_freq_seg0_idx = 0; break; } @@ -441,8 +476,11 @@ dfs_get_valid_channel(struct hostapd_iface *iface, { struct hostapd_hw_modes *mode; struct hostapd_channel_data *chan = NULL; + struct hostapd_channel_data *chan2 = NULL; int num_available_chandefs; - int chan_idx; + int chan_idx, chan_idx2; + int sec_chan_idx_80p80 = -1; + int i; u32 _rand; wpa_printf(MSG_DEBUG, "DFS: Selecting random channel"); @@ -459,6 +497,8 @@ dfs_get_valid_channel(struct hostapd_iface *iface, /* Get the count first */ num_available_chandefs = dfs_find_channel(iface, NULL, 0, skip_radar); + wpa_printf(MSG_DEBUG, "DFS: num_available_chandefs=%d", + num_available_chandefs); if (num_available_chandefs == 0) return NULL; @@ -466,6 +506,12 @@ dfs_get_valid_channel(struct hostapd_iface *iface, return NULL; chan_idx = _rand % num_available_chandefs; dfs_find_channel(iface, &chan, chan_idx, skip_radar); + if (!chan) { + wpa_printf(MSG_DEBUG, "DFS: no random channel found"); + return NULL; + } + wpa_printf(MSG_DEBUG, "DFS: got random channel %d (%d)", + chan->freq, chan->chan); /* dfs_find_channel() calculations assume HT40+ */ if (iface->conf->secondary_channel) @@ -473,8 +519,45 @@ dfs_get_valid_channel(struct hostapd_iface *iface, else *secondary_channel = 0; + /* Get secondary channel for HT80P80 */ + if (hostapd_get_oper_chwidth(iface->conf) == CHANWIDTH_80P80MHZ) { + if (num_available_chandefs <= 1) { + wpa_printf(MSG_ERROR, + "only 1 valid chan, can't support 80+80"); + return NULL; + } + + /* + * Loop all channels except channel1 to find a valid channel2 + * that is not adjacent to channel1. + */ + for (i = 0; i < num_available_chandefs - 1; i++) { + /* start from chan_idx + 1, end when chan_idx - 1 */ + chan_idx2 = (chan_idx + 1 + i) % num_available_chandefs; + dfs_find_channel(iface, &chan2, chan_idx2, skip_radar); + if (chan2 && abs(chan2->chan - chan->chan) > 12) { + /* two channels are not adjacent */ + sec_chan_idx_80p80 = chan2->chan; + wpa_printf(MSG_DEBUG, + "DFS: got second chan: %d (%d)", + chan2->freq, chan2->chan); + break; + } + } + + /* Check if we got a valid secondary channel which is not + * adjacent to the first channel. + */ + if (sec_chan_idx_80p80 == -1) { + wpa_printf(MSG_INFO, + "DFS: failed to get chan2 for 80+80"); + return NULL; + } + } + dfs_adjust_center_freq(iface, chan, *secondary_channel, + sec_chan_idx_80p80, oper_centr_freq_seg0_idx, oper_centr_freq_seg1_idx); @@ -773,7 +856,7 @@ int hostapd_handle_dfs(struct hostapd_iface *iface) } -static int hostapd_config_dfs_chan_available(struct hostapd_iface *iface) +int hostapd_is_dfs_chan_available(struct hostapd_iface *iface) { int n_chans, n_chans1, start_chan_idx, start_chan_idx1; @@ -821,7 +904,7 @@ int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq, * another radio. */ if (iface->state != HAPD_IFACE_ENABLED && - hostapd_config_dfs_chan_available(iface)) { + hostapd_is_dfs_chan_available(iface)) { hostapd_setup_interface_complete(iface, 0); iface->cac_started = 0; } @@ -851,6 +934,44 @@ int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq, } +static struct hostapd_channel_data * +dfs_downgrade_bandwidth(struct hostapd_iface *iface, int *secondary_channel, + u8 *oper_centr_freq_seg0_idx, + u8 *oper_centr_freq_seg1_idx, int *skip_radar) +{ + struct hostapd_channel_data *channel; + + for (;;) { + channel = dfs_get_valid_channel(iface, secondary_channel, + oper_centr_freq_seg0_idx, + oper_centr_freq_seg1_idx, + *skip_radar); + if (channel) { + wpa_printf(MSG_DEBUG, "DFS: Selected channel: %d", + channel->chan); + return channel; + } + + if (*skip_radar) { + *skip_radar = 0; + } else { + int oper_chwidth; + + oper_chwidth = hostapd_get_oper_chwidth(iface->conf); + if (oper_chwidth == CHANWIDTH_USE_HT) + break; + *skip_radar = 1; + hostapd_set_oper_chwidth(iface->conf, oper_chwidth - 1); + } + } + + wpa_printf(MSG_INFO, + "%s: no DFS channels left, waiting for NOP to finish", + __func__); + return NULL; +} + + static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface) { struct hostapd_channel_data *channel; @@ -868,8 +989,14 @@ static int hostapd_dfs_start_channel_switch_cac(struct hostapd_iface *iface) skip_radar); if (!channel) { - wpa_printf(MSG_ERROR, "No valid channel available"); - return err; + channel = dfs_downgrade_bandwidth(iface, &secondary_channel, + &oper_centr_freq_seg0_idx, + &oper_centr_freq_seg1_idx, + &skip_radar); + if (!channel) { + wpa_printf(MSG_ERROR, "No valid channel available"); + return err; + } } wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", @@ -898,11 +1025,14 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) int secondary_channel; u8 oper_centr_freq_seg0_idx; u8 oper_centr_freq_seg1_idx; + u8 new_vht_oper_chwidth; int skip_radar = 1; struct csa_settings csa_settings; unsigned int i; int err = 1; struct hostapd_hw_modes *cmode = iface->current_mode; + u8 current_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); + int ieee80211_mode = IEEE80211_MODE_AP; wpa_printf(MSG_DEBUG, "%s called (CAC active: %s, CSA active: %s)", __func__, iface->cac_started ? "yes" : "no", @@ -936,28 +1066,33 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) * requires to perform a CAC first. */ skip_radar = 0; - channel = dfs_get_valid_channel(iface, &secondary_channel, - &oper_centr_freq_seg0_idx, - &oper_centr_freq_seg1_idx, - skip_radar); + channel = dfs_downgrade_bandwidth(iface, &secondary_channel, + &oper_centr_freq_seg0_idx, + &oper_centr_freq_seg1_idx, + &skip_radar); if (!channel) { - wpa_printf(MSG_INFO, - "%s: no DFS channels left, waiting for NOP to finish", - __func__); - return err; + /* + * Toggle interface state to enter DFS state + * until NOP is finished. + */ + hostapd_disable_iface(iface); + hostapd_enable_iface(iface); + return 0; } - iface->freq = channel->freq; - iface->conf->channel = channel->chan; - iface->conf->secondary_channel = secondary_channel; - hostapd_set_oper_centr_freq_seg0_idx(iface->conf, - oper_centr_freq_seg0_idx); - hostapd_set_oper_centr_freq_seg1_idx(iface->conf, - oper_centr_freq_seg1_idx); + if (!skip_radar) { + iface->freq = channel->freq; + iface->conf->channel = channel->chan; + iface->conf->secondary_channel = secondary_channel; + hostapd_set_oper_centr_freq_seg0_idx( + iface->conf, oper_centr_freq_seg0_idx); + hostapd_set_oper_centr_freq_seg1_idx( + iface->conf, oper_centr_freq_seg1_idx); - hostapd_disable_iface(iface); - hostapd_enable_iface(iface); - return 0; + hostapd_disable_iface(iface); + hostapd_enable_iface(iface); + return 0; + } } wpa_printf(MSG_DEBUG, "DFS will switch to a new channel %d", @@ -966,10 +1101,17 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) "freq=%d chan=%d sec_chan=%d", channel->freq, channel->chan, secondary_channel); + new_vht_oper_chwidth = hostapd_get_oper_chwidth(iface->conf); + hostapd_set_oper_chwidth(iface->conf, current_vht_oper_chwidth); + /* Setup CSA request */ os_memset(&csa_settings, 0, sizeof(csa_settings)); csa_settings.cs_count = 5; csa_settings.block_tx = 1; +#ifdef CONFIG_MESH + if (iface->mconf) + ieee80211_mode = IEEE80211_MODE_MESH; +#endif /* CONFIG_MESH */ err = hostapd_set_freq_params(&csa_settings.freq_params, iface->conf->hw_mode, channel->freq, @@ -980,11 +1122,11 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) iface->conf->ieee80211ac, iface->conf->ieee80211ax, secondary_channel, - hostapd_get_oper_chwidth(iface->conf), + new_vht_oper_chwidth, oper_centr_freq_seg0_idx, oper_centr_freq_seg1_idx, cmode->vht_capab, - &cmode->he_capab[IEEE80211_MODE_AP]); + &cmode->he_capab[ieee80211_mode]); if (err) { wpa_printf(MSG_ERROR, "DFS failed to calculate CSA freq params"); @@ -1004,6 +1146,7 @@ static int hostapd_dfs_start_channel_switch(struct hostapd_iface *iface) iface->freq = channel->freq; iface->conf->channel = channel->chan; iface->conf->secondary_channel = secondary_channel; + hostapd_set_oper_chwidth(iface->conf, new_vht_oper_chwidth); hostapd_set_oper_centr_freq_seg0_idx(iface->conf, oper_centr_freq_seg0_idx); hostapd_set_oper_centr_freq_seg1_idx(iface->conf, @@ -1040,8 +1183,10 @@ int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq, return 0; /* mark radar frequency as invalid */ - set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, - cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE); + res = set_dfs_state(iface, freq, ht_enabled, chan_offset, chan_width, + cf1, cf2, HOSTAPD_CHAN_DFS_UNAVAILABLE); + if (!res) + return 0; /* Skip if reported radar event not overlapped our channels */ res = dfs_are_channels_overlapped(iface, freq, chan_width, cf1, cf2); @@ -1161,3 +1306,56 @@ int hostapd_handle_dfs_offload(struct hostapd_iface *iface) __func__, iface->freq); return 2; } + + +int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width, + int center_freq) +{ + struct hostapd_channel_data *chan; + struct hostapd_hw_modes *mode = iface->current_mode; + int half_width; + int res = 0; + int i; + + if (!iface->conf->ieee80211h || !mode || + mode->mode != HOSTAPD_MODE_IEEE80211A) + return 0; + + switch (width) { + case CHAN_WIDTH_20_NOHT: + case CHAN_WIDTH_20: + half_width = 10; + break; + case CHAN_WIDTH_40: + half_width = 20; + break; + case CHAN_WIDTH_80: + case CHAN_WIDTH_80P80: + half_width = 40; + break; + case CHAN_WIDTH_160: + half_width = 80; + break; + default: + wpa_printf(MSG_WARNING, "DFS chanwidth %d not supported", + width); + return 0; + } + + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; + + if (!(chan->flag & HOSTAPD_CHAN_RADAR)) + continue; + + if (center_freq - chan->freq < half_width && + chan->freq - center_freq < half_width) + res++; + } + + wpa_printf(MSG_DEBUG, "DFS: (%d, %d): in range: %s", + center_freq - half_width, center_freq + half_width, + res ? "yes" : "no"); + + return res; +} diff --git a/src/ap/dfs.h b/src/ap/dfs.h index f0fa6f688..606c1b393 100644 --- a/src/ap/dfs.h +++ b/src/ap/dfs.h @@ -25,9 +25,12 @@ int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq, int ht_enabled, int chan_offset, int chan_width, int cf1, int cf2); int hostapd_is_dfs_required(struct hostapd_iface *iface); +int hostapd_is_dfs_chan_available(struct hostapd_iface *iface); int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq, int ht_enabled, int chan_offset, int chan_width, int cf1, int cf2); int hostapd_handle_dfs_offload(struct hostapd_iface *iface); +int hostapd_is_dfs_overlap(struct hostapd_iface *iface, enum chan_width width, + int center_freq); #endif /* DFS_H */ diff --git a/src/ap/dpp_hostapd.c b/src/ap/dpp_hostapd.c index 8e22c8ba6..6772a8748 100644 --- a/src/ap/dpp_hostapd.c +++ b/src/ap/dpp_hostapd.c @@ -26,6 +26,13 @@ static void hostapd_dpp_reply_wait_timeout(void *eloop_ctx, void *timeout_ctx); static void hostapd_dpp_auth_success(struct hostapd_data *hapd, int initiator); static void hostapd_dpp_init_timeout(void *eloop_ctx, void *timeout_ctx); static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd); +#ifdef CONFIG_DPP2 +static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, + void *timeout_ctx); +static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd, + struct dpp_authentication *auth, + struct dpp_config_obj *conf); +#endif /* CONFIG_DPP2 */ static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -59,6 +66,10 @@ int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd) wpabuf_len(hapd->dpp_auth->resp_msg)); } +#ifdef CONFIG_DPP2 + dpp_controller_new_qr_code(hapd->iface->interfaces->dpp, bi); +#endif /* CONFIG_DPP2 */ + return bi->id; } @@ -237,6 +248,10 @@ void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst, hapd, NULL); eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL); +#ifdef CONFIG_DPP2 + eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); +#endif /* CONFIG_DPP2 */ hostapd_drv_send_action_cancel_wait(hapd); dpp_auth_deinit(hapd->dpp_auth); hapd->dpp_auth = NULL; @@ -478,12 +493,35 @@ static int hostapd_dpp_auth_init_next(struct hostapd_data *hapd) } +#ifdef CONFIG_DPP2 +static int hostapd_dpp_process_conf_obj(void *ctx, + struct dpp_authentication *auth) +{ + struct hostapd_data *hapd = ctx; + unsigned int i; + + for (i = 0; i < auth->num_conf_obj; i++) + hostapd_dpp_handle_config_obj(hapd, auth, + &auth->conf_obj[i]); + + return 0; +} +#endif /* CONFIG_DPP2 */ + + int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) { const char *pos; struct dpp_bootstrap_info *peer_bi, *own_bi = NULL; + struct dpp_authentication *auth; u8 allowed_roles = DPP_CAPAB_CONFIGURATOR; unsigned int neg_freq = 0; + int tcp = 0; +#ifdef CONFIG_DPP2 + int tcp_port = DPP_TCP_PORT; + struct hostapd_ip_addr ipaddr; + char *addr; +#endif /* CONFIG_DPP2 */ pos = os_strstr(cmd, " peer="); if (!pos) @@ -496,6 +534,25 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) return -1; } +#ifdef CONFIG_DPP2 + pos = os_strstr(cmd, " tcp_port="); + if (pos) { + pos += 10; + tcp_port = atoi(pos); + } + + addr = get_param(cmd, " tcp_addr="); + if (addr) { + int res; + + res = hostapd_parse_ip_addr(addr, &ipaddr); + os_free(addr); + if (res) + return -1; + tcp = 1; + } +#endif /* CONFIG_DPP2 */ + pos = os_strstr(cmd, " own="); if (pos) { pos += 5; @@ -533,36 +590,46 @@ int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd) if (pos) neg_freq = atoi(pos + 10); - if (hapd->dpp_auth) { + if (!tcp && hapd->dpp_auth) { eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL); eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL); eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL); +#ifdef CONFIG_DPP2 + eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); +#endif /* CONFIG_DPP2 */ hostapd_drv_send_action_cancel_wait(hapd); dpp_auth_deinit(hapd->dpp_auth); } - hapd->dpp_auth = dpp_auth_init(hapd->msg_ctx, peer_bi, own_bi, - allowed_roles, neg_freq, - hapd->iface->hw_features, - hapd->iface->num_hw_features); - if (!hapd->dpp_auth) + auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx, + peer_bi, own_bi, allowed_roles, neg_freq, + hapd->iface->hw_features, + hapd->iface->num_hw_features); + if (!auth) goto fail; - hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth); - if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx, - hapd->dpp_auth, cmd) < 0) { - dpp_auth_deinit(hapd->dpp_auth); - hapd->dpp_auth = NULL; + hostapd_dpp_set_testing_options(hapd, auth); + if (dpp_set_configurator(auth, cmd) < 0) { + dpp_auth_deinit(auth); goto fail; } - hapd->dpp_auth->neg_freq = neg_freq; + auth->neg_freq = neg_freq; if (!is_zero_ether_addr(peer_bi->mac_addr)) - os_memcpy(hapd->dpp_auth->peer_mac_addr, peer_bi->mac_addr, - ETH_ALEN); + os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN); +#ifdef CONFIG_DPP2 + if (tcp) + return dpp_tcp_init(hapd->iface->interfaces->dpp, auth, + &ipaddr, tcp_port, hapd->conf->dpp_name, + DPP_NETROLE_AP, hapd->msg_ctx, hapd, + hostapd_dpp_process_conf_obj); +#endif /* CONFIG_DPP2 */ + + hapd->dpp_auth = auth; return hostapd_dpp_auth_init_next(hapd); fail: return -1; @@ -618,6 +685,10 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src, wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR, MAC2STR(src)); +#ifdef CONFIG_DPP2 + hostapd_dpp_chirp_stop(hapd); +#endif /* CONFIG_DPP2 */ + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, &r_bootstrap_len); if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { @@ -663,7 +734,8 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src, } hapd->dpp_auth_ok_on_ack = 0; - hapd->dpp_auth = dpp_auth_req_rx(hapd->msg_ctx, hapd->dpp_allowed_roles, + hapd->dpp_auth = dpp_auth_req_rx(hapd->iface->interfaces->dpp, + hapd->msg_ctx, hapd->dpp_allowed_roles, hapd->dpp_qr_mutual, peer_bi, own_bi, freq, hdr, buf, len); if (!hapd->dpp_auth) { @@ -671,8 +743,7 @@ static void hostapd_dpp_rx_auth_req(struct hostapd_data *hapd, const u8 *src, return; } hostapd_dpp_set_testing_options(hapd, hapd->dpp_auth); - if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx, - hapd->dpp_auth, + if (dpp_set_configurator(hapd->dpp_auth, hapd->dpp_configurator_params) < 0) { dpp_auth_deinit(hapd->dpp_auth); hapd->dpp_auth = NULL; @@ -708,7 +779,8 @@ static void hostapd_dpp_handle_config_obj(struct hostapd_data *hapd, * message. */ wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CONNECTOR "%s", conf->connector); - } else if (conf->passphrase[0]) { + } + if (conf->passphrase[0]) { char hex[64 * 2 + 1]; wpa_snprintf_hex(hex, sizeof(hex), @@ -1132,6 +1204,227 @@ static void hostapd_dpp_rx_conn_status_result(struct hostapd_data *hapd, } +static void +hostapd_dpp_rx_presence_announcement(struct hostapd_data *hapd, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + const u8 *r_bootstrap; + u16 r_bootstrap_len; + struct dpp_bootstrap_info *peer_bi; + struct dpp_authentication *auth; + + wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR, + MAC2STR(src)); + + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + peer_bi = dpp_bootstrap_find_chirp(hapd->iface->interfaces->dpp, + r_bootstrap); + dpp_notify_chirp_received(hapd->msg_ctx, + peer_bi ? (int) peer_bi->id : -1, + src, freq, r_bootstrap); + if (!peer_bi) { + if (dpp_relay_rx_action(hapd->iface->interfaces->dpp, + src, hdr, buf, len, freq, NULL, + r_bootstrap) == 0) + return; + wpa_printf(MSG_DEBUG, + "DPP: No matching bootstrapping information found"); + return; + } + + if (hapd->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Presence Announcement during ongoing Authentication"); + return; + } + + auth = dpp_auth_init(hapd->iface->interfaces->dpp, hapd->msg_ctx, + peer_bi, NULL, DPP_CAPAB_CONFIGURATOR, freq, NULL, + 0); + if (!auth) + return; + hostapd_dpp_set_testing_options(hapd, auth); + if (dpp_set_configurator(auth, + hapd->dpp_configurator_params) < 0) { + dpp_auth_deinit(auth); + return; + } + + auth->neg_freq = freq; + + if (!is_zero_ether_addr(peer_bi->mac_addr)) + os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN); + + hapd->dpp_auth = auth; + if (hostapd_dpp_auth_init_next(hapd) < 0) { + dpp_auth_deinit(hapd->dpp_auth); + hapd->dpp_auth = NULL; + } +} + + +static void hostapd_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, + void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct dpp_authentication *auth = hapd->dpp_auth; + + if (!auth) + return; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout"); + hostapd_dpp_listen_stop(hapd); + dpp_auth_deinit(auth); + hapd->dpp_auth = NULL; +} + + +static void +hostapd_dpp_rx_reconfig_announcement(struct hostapd_data *hapd, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + const u8 *csign_hash, *fcgroup, *a_nonce, *e_id; + u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len; + struct dpp_configurator *conf; + struct dpp_authentication *auth; + unsigned int wait_time, max_wait_time; + u16 group; + + if (hapd->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Reconfig Announcement during ongoing Authentication"); + return; + } + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR, + MAC2STR(src)); + + csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH, + &csign_hash_len); + if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) { + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Configurator C-sign key Hash attribute"); + return; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)", + csign_hash, csign_hash_len); + conf = dpp_configurator_find_kid(hapd->iface->interfaces->dpp, + csign_hash); + if (!conf) { + if (dpp_relay_rx_action(hapd->iface->interfaces->dpp, + src, hdr, buf, len, freq, NULL, + NULL) == 0) + return; + wpa_printf(MSG_DEBUG, + "DPP: No matching Configurator information found"); + return; + } + + fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, + &fcgroup_len); + if (!fcgroup || fcgroup_len != 2) { + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Finite Cyclic Group attribute"); + return; + } + group = WPA_GET_LE16(fcgroup); + wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); + + a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len); + e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len); + + auth = dpp_reconfig_init(hapd->iface->interfaces->dpp, hapd->msg_ctx, + conf, freq, group, a_nonce, a_nonce_len, + e_id, e_id_len); + if (!auth) + return; + hostapd_dpp_set_testing_options(hapd, auth); + if (dpp_set_configurator(auth, hapd->dpp_configurator_params) < 0) { + dpp_auth_deinit(auth); + return; + } + + os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); + hapd->dpp_auth = auth; + + hapd->dpp_in_response_listen = 0; + hapd->dpp_auth_ok_on_ack = 0; + wait_time = 2000; /* TODO: hapd->max_remain_on_chan; */ + max_wait_time = hapd->dpp_resp_wait_time ? + hapd->dpp_resp_wait_time : 2000; + if (wait_time > max_wait_time) + wait_time = max_wait_time; + wait_time += 10; /* give the driver some extra time to complete */ + eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000, + hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); + wait_time -= 10; + + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR + " freq=%u type=%d", + MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ); + if (hostapd_drv_send_action(hapd, freq, wait_time, src, + wpabuf_head(auth->reconfig_req_msg), + wpabuf_len(auth->reconfig_req_msg)) < 0) { + dpp_auth_deinit(hapd->dpp_auth); + hapd->dpp_auth = NULL; + } +} + + +static void +hostapd_dpp_rx_reconfig_auth_resp(struct hostapd_data *hapd, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + struct dpp_authentication *auth = hapd->dpp_auth; + struct wpabuf *conf; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from " + MACSTR, MAC2STR(src)); + + if (!auth || !auth->reconfig || !auth->configurator) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Reconfig Authentication in progress - drop"); + return; + } + + if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " + MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); + return; + } + + conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len); + if (!conf) + return; + + eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); + + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR + " freq=%u type=%d", + MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF); + if (hostapd_drv_send_action(hapd, freq, 500, src, + wpabuf_head(conf), wpabuf_len(conf)) < 0) { + wpabuf_free(conf); + dpp_auth_deinit(hapd->dpp_auth); + hapd->dpp_auth = NULL; + return; + } + wpabuf_free(conf); +} + #endif /* CONFIG_DPP2 */ @@ -1141,9 +1434,13 @@ static void hostapd_dpp_send_peer_disc_resp(struct hostapd_data *hapd, enum dpp_status_error status) { struct wpabuf *msg; + size_t len; - msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, - 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector)); + len = 5 + 5 + 4 + os_strlen(hapd->conf->dpp_connector); +#ifdef CONFIG_DPP2 + len += 5; +#endif /* CONFIG_DPP2 */ + msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_RESP, len); if (!msg) return; @@ -1216,6 +1513,15 @@ skip_status: skip_connector: #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_DPP2 + if (DPP_VERSION > 1) { + /* Protocol Version */ + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + } +#endif /* CONFIG_DPP2 */ + wpa_printf(MSG_DEBUG, "DPP: Send Peer Discovery Response to " MACSTR " status=%d", MAC2STR(src), status); wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR @@ -1581,6 +1887,18 @@ void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src, case DPP_PA_CONNECTION_STATUS_RESULT: hostapd_dpp_rx_conn_status_result(hapd, src, hdr, buf, len); break; + case DPP_PA_PRESENCE_ANNOUNCEMENT: + hostapd_dpp_rx_presence_announcement(hapd, src, hdr, buf, len, + freq); + break; + case DPP_PA_RECONFIG_ANNOUNCEMENT: + hostapd_dpp_rx_reconfig_announcement(hapd, src, hdr, buf, len, + freq); + break; + case DPP_PA_RECONFIG_AUTH_RESP: + hostapd_dpp_rx_reconfig_auth_resp(hapd, src, hdr, buf, len, + freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG, @@ -1610,7 +1928,7 @@ hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa, struct wpabuf *resp; wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa)); - if (!auth || !auth->auth_success || + if (!auth || (!auth->auth_success && !auth->reconfig_success) || os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) { #ifdef CONFIG_DPP2 if (dpp_relay_rx_gas_req(hapd->iface->interfaces->dpp, sa, data, @@ -1646,6 +1964,8 @@ void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok) eloop_cancel_timeout(hostapd_dpp_reply_wait_timeout, hapd, NULL); eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL); #ifdef CONFIG_DPP2 + eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); if (ok && auth->peer_version >= 2 && auth->conf_resp_status == DPP_STATUS_OK) { wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result"); @@ -1675,14 +1995,13 @@ int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd) int ret = -1; char *curve = NULL; - auth = os_zalloc(sizeof(*auth)); + auth = dpp_alloc_auth(hapd->iface->interfaces->dpp, hapd->msg_ctx); if (!auth) return -1; curve = get_param(cmd, " curve="); hostapd_dpp_set_testing_options(hapd, auth); - if (dpp_set_configurator(hapd->iface->interfaces->dpp, hapd->msg_ctx, - auth, cmd) == 0 && + if (dpp_set_configurator(auth, cmd) == 0 && dpp_configurator_own_config(auth, curve, 1) == 0) { hostapd_dpp_handle_config_obj(hapd, auth, &auth->conf_obj[0]); ret = 0; @@ -1891,10 +2210,13 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd) eloop_cancel_timeout(hostapd_dpp_init_timeout, hapd, NULL); eloop_cancel_timeout(hostapd_dpp_auth_resp_retry_timeout, hapd, NULL); #ifdef CONFIG_DPP2 + eloop_cancel_timeout(hostapd_dpp_reconfig_reply_wait_timeout, + hapd, NULL); eloop_cancel_timeout(hostapd_dpp_config_result_wait_timeout, hapd, NULL); eloop_cancel_timeout(hostapd_dpp_conn_status_result_wait_timeout, hapd, NULL); + hostapd_dpp_chirp_stop(hapd); #endif /* CONFIG_DPP2 */ dpp_auth_deinit(hapd->dpp_auth); hapd->dpp_auth = NULL; @@ -1903,3 +2225,359 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd) os_free(hapd->dpp_configurator_params); hapd->dpp_configurator_params = NULL; } + + +#ifdef CONFIG_DPP2 + +int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd) +{ + struct dpp_controller_config config; + const char *pos; + + os_memset(&config, 0, sizeof(config)); + config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR; + config.netrole = DPP_NETROLE_AP; + config.msg_ctx = hapd->msg_ctx; + config.cb_ctx = hapd; + config.process_conf_obj = hostapd_dpp_process_conf_obj; + if (cmd) { + pos = os_strstr(cmd, " tcp_port="); + if (pos) { + pos += 10; + config.tcp_port = atoi(pos); + } + + pos = os_strstr(cmd, " role="); + if (pos) { + pos += 6; + if (os_strncmp(pos, "configurator", 12) == 0) + config.allowed_roles = DPP_CAPAB_CONFIGURATOR; + else if (os_strncmp(pos, "enrollee", 8) == 0) + config.allowed_roles = DPP_CAPAB_ENROLLEE; + else if (os_strncmp(pos, "either", 6) == 0) + config.allowed_roles = DPP_CAPAB_CONFIGURATOR | + DPP_CAPAB_ENROLLEE; + else + return -1; + } + + config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL; + } + config.configurator_params = hapd->dpp_configurator_params; + return dpp_controller_start(hapd->iface->interfaces->dpp, &config); +} + + +static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx); + +static void hostapd_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + + wpa_printf(MSG_DEBUG, "DPP: No chirp response received"); + hostapd_drv_send_action_cancel_wait(hapd); + hostapd_dpp_chirp_next(hapd, NULL); +} + + +static void hostapd_dpp_chirp_start(struct hostapd_data *hapd) +{ + struct wpabuf *msg; + int type; + + msg = hapd->dpp_presence_announcement; + type = DPP_PA_PRESENCE_ANNOUNCEMENT; + wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", hapd->dpp_chirp_freq); + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR + " freq=%u type=%d", + MAC2STR(broadcast), hapd->dpp_chirp_freq, type); + if (hostapd_drv_send_action( + hapd, hapd->dpp_chirp_freq, 2000, broadcast, + wpabuf_head(msg), wpabuf_len(msg)) < 0 || + eloop_register_timeout(2, 0, hostapd_dpp_chirp_timeout, + hapd, NULL) < 0) + hostapd_dpp_chirp_stop(hapd); +} + + +static struct hostapd_hw_modes * +dpp_get_mode(struct hostapd_data *hapd, + enum hostapd_hw_mode mode) +{ + struct hostapd_hw_modes *modes = hapd->iface->hw_features; + u16 num_modes = hapd->iface->num_hw_features; + u16 i; + + for (i = 0; i < num_modes; i++) { + if (modes[i].mode != mode || + !modes[i].num_channels || !modes[i].channels) + continue; + return &modes[i]; + } + + return NULL; +} + + +static void +hostapd_dpp_chirp_scan_res_handler(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + struct wpa_scan_results *scan_res; + struct dpp_bootstrap_info *bi = hapd->dpp_chirp_bi; + unsigned int i; + struct hostapd_hw_modes *mode; + int c; + + if (!bi) + return; + + hapd->dpp_chirp_scan_done = 1; + + scan_res = hostapd_driver_get_scan_results(hapd); + + os_free(hapd->dpp_chirp_freqs); + hapd->dpp_chirp_freqs = NULL; + + /* Channels from own bootstrapping info */ + if (bi) { + for (i = 0; i < bi->num_freq; i++) + int_array_add_unique(&hapd->dpp_chirp_freqs, + bi->freq[i]); + } + + /* Preferred chirping channels */ + int_array_add_unique(&hapd->dpp_chirp_freqs, 2437); + + mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211A); + if (mode) { + int chan44 = 0, chan149 = 0; + + for (c = 0; c < mode->num_channels; c++) { + struct hostapd_channel_data *chan = &mode->channels[c]; + + if (chan->flag & (HOSTAPD_CHAN_DISABLED | + HOSTAPD_CHAN_RADAR)) + continue; + if (chan->freq == 5220) + chan44 = 1; + if (chan->freq == 5745) + chan149 = 1; + } + if (chan149) + int_array_add_unique(&hapd->dpp_chirp_freqs, 5745); + else if (chan44) + int_array_add_unique(&hapd->dpp_chirp_freqs, 5220); + } + + mode = dpp_get_mode(hapd, HOSTAPD_MODE_IEEE80211AD); + if (mode) { + for (c = 0; c < mode->num_channels; c++) { + struct hostapd_channel_data *chan = &mode->channels[c]; + + if ((chan->flag & (HOSTAPD_CHAN_DISABLED | + HOSTAPD_CHAN_RADAR)) || + chan->freq != 60480) + continue; + int_array_add_unique(&hapd->dpp_chirp_freqs, 60480); + break; + } + } + + /* Add channels from scan results for APs that advertise Configurator + * Connectivity element */ + for (i = 0; scan_res && i < scan_res->num; i++) { + struct wpa_scan_res *bss = scan_res->res[i]; + size_t ie_len = bss->ie_len; + + if (!ie_len) + ie_len = bss->beacon_ie_len; + if (get_vendor_ie((const u8 *) (bss + 1), ie_len, + DPP_CC_IE_VENDOR_TYPE)) + int_array_add_unique(&hapd->dpp_chirp_freqs, + bss->freq); + } + + if (!hapd->dpp_chirp_freqs || + eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, + hapd, NULL) < 0) + hostapd_dpp_chirp_stop(hapd); + + wpa_scan_results_free(scan_res); +} + + +static void hostapd_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + int i; + + if (hapd->dpp_chirp_listen) + hostapd_dpp_listen_stop(hapd); + + if (hapd->dpp_chirp_freq == 0) { + if (hapd->dpp_chirp_round % 4 == 0 && + !hapd->dpp_chirp_scan_done) { + struct wpa_driver_scan_params params; + int ret; + + wpa_printf(MSG_DEBUG, + "DPP: Update channel list for chirping"); + os_memset(¶ms, 0, sizeof(params)); + ret = hostapd_driver_scan(hapd, ¶ms); + if (ret < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to request a scan ret=%d (%s)", + ret, strerror(-ret)); + hostapd_dpp_chirp_scan_res_handler(hapd->iface); + } else { + hapd->iface->scan_cb = + hostapd_dpp_chirp_scan_res_handler; + } + return; + } + hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[0]; + hapd->dpp_chirp_round++; + wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d", + hapd->dpp_chirp_round); + } else { + for (i = 0; hapd->dpp_chirp_freqs[i]; i++) + if (hapd->dpp_chirp_freqs[i] == hapd->dpp_chirp_freq) + break; + if (!hapd->dpp_chirp_freqs[i]) { + wpa_printf(MSG_DEBUG, + "DPP: Previous chirp freq %d not found", + hapd->dpp_chirp_freq); + return; + } + i++; + if (hapd->dpp_chirp_freqs[i]) { + hapd->dpp_chirp_freq = hapd->dpp_chirp_freqs[i]; + } else { + hapd->dpp_chirp_iter--; + if (hapd->dpp_chirp_iter <= 0) { + wpa_printf(MSG_DEBUG, + "DPP: Chirping iterations completed"); + hostapd_dpp_chirp_stop(hapd); + return; + } + hapd->dpp_chirp_freq = 0; + hapd->dpp_chirp_scan_done = 0; + if (eloop_register_timeout(30, 0, + hostapd_dpp_chirp_next, + hapd, NULL) < 0) { + hostapd_dpp_chirp_stop(hapd); + return; + } + if (hapd->dpp_chirp_listen) { + wpa_printf(MSG_DEBUG, + "DPP: Listen on %d MHz during chirp 30 second wait", + hapd->dpp_chirp_listen); + /* TODO: start listen on the channel */ + } else { + wpa_printf(MSG_DEBUG, + "DPP: Wait 30 seconds before starting the next chirping round"); + } + return; + } + } + + hostapd_dpp_chirp_start(hapd); +} + + +int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd) +{ + const char *pos; + int iter = 1, listen_freq = 0; + struct dpp_bootstrap_info *bi; + + pos = os_strstr(cmd, " own="); + if (!pos) + return -1; + pos += 5; + bi = dpp_bootstrap_get_id(hapd->iface->interfaces->dpp, atoi(pos)); + if (!bi) { + wpa_printf(MSG_DEBUG, + "DPP: Identified bootstrap info not found"); + return -1; + } + + pos = os_strstr(cmd, " iter="); + if (pos) { + iter = atoi(pos + 6); + if (iter <= 0) + return -1; + } + + pos = os_strstr(cmd, " listen="); + if (pos) { + listen_freq = atoi(pos + 8); + if (listen_freq <= 0) + return -1; + } + + hostapd_dpp_chirp_stop(hapd); + hapd->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; + hapd->dpp_qr_mutual = 0; + hapd->dpp_chirp_bi = bi; + hapd->dpp_presence_announcement = dpp_build_presence_announcement(bi); + if (!hapd->dpp_presence_announcement) + return -1; + hapd->dpp_chirp_iter = iter; + hapd->dpp_chirp_round = 0; + hapd->dpp_chirp_scan_done = 0; + hapd->dpp_chirp_listen = listen_freq; + + return eloop_register_timeout(0, 0, hostapd_dpp_chirp_next, hapd, NULL); +} + + +void hostapd_dpp_chirp_stop(struct hostapd_data *hapd) +{ + if (hapd->dpp_presence_announcement) { + hostapd_drv_send_action_cancel_wait(hapd); + wpa_msg(hapd->msg_ctx, MSG_INFO, DPP_EVENT_CHIRP_STOPPED); + } + hapd->dpp_chirp_bi = NULL; + wpabuf_free(hapd->dpp_presence_announcement); + hapd->dpp_presence_announcement = NULL; + if (hapd->dpp_chirp_listen) + hostapd_dpp_listen_stop(hapd); + hapd->dpp_chirp_listen = 0; + hapd->dpp_chirp_freq = 0; + os_free(hapd->dpp_chirp_freqs); + hapd->dpp_chirp_freqs = NULL; + eloop_cancel_timeout(hostapd_dpp_chirp_next, hapd, NULL); + eloop_cancel_timeout(hostapd_dpp_chirp_timeout, hapd, NULL); + if (hapd->iface->scan_cb == hostapd_dpp_chirp_scan_res_handler) { + /* TODO: abort ongoing scan */ + hapd->iface->scan_cb = NULL; + } +} + + +static int handle_dpp_remove_bi(struct hostapd_iface *iface, void *ctx) +{ + struct dpp_bootstrap_info *bi = ctx; + size_t i; + + for (i = 0; i < iface->num_bss; i++) { + struct hostapd_data *hapd = iface->bss[i]; + + if (bi == hapd->dpp_chirp_bi) + hostapd_dpp_chirp_stop(hapd); + } + + return 0; +} + + +void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi) +{ + struct hapd_interfaces *interfaces = ctx; + + hostapd_for_each_interface(interfaces, handle_dpp_remove_bi, bi); +} + +#endif /* CONFIG_DPP2 */ diff --git a/src/ap/dpp_hostapd.h b/src/ap/dpp_hostapd.h index b1fa99ed0..264d3e4c0 100644 --- a/src/ap/dpp_hostapd.h +++ b/src/ap/dpp_hostapd.h @@ -10,6 +10,8 @@ #ifndef DPP_HOSTAPD_H #define DPP_HOSTAPD_H +struct dpp_bootstrap_info; + int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd); int hostapd_dpp_nfc_uri(struct hostapd_data *hapd, const char *cmd); int hostapd_dpp_nfc_handover_req(struct hostapd_data *hapd, const char *cmd); @@ -39,4 +41,9 @@ void hostapd_dpp_deinit(struct hostapd_data *hapd); void hostapd_dpp_init_global(struct hapd_interfaces *ifaces); void hostapd_dpp_deinit_global(struct hapd_interfaces *ifaces); +int hostapd_dpp_controller_start(struct hostapd_data *hapd, const char *cmd); +int hostapd_dpp_chirp(struct hostapd_data *hapd, const char *cmd); +void hostapd_dpp_chirp_stop(struct hostapd_data *hapd); +void hostapd_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi); + #endif /* DPP_HOSTAPD_H */ diff --git a/src/ap/drv_callbacks.c b/src/ap/drv_callbacks.c index beaaada79..866b9d32c 100644 --- a/src/ap/drv_callbacks.c +++ b/src/ap/drv_callbacks.c @@ -106,18 +106,45 @@ void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd, #endif /* CONFIG_FILS */ +static bool check_sa_query_need(struct hostapd_data *hapd, struct sta_info *sta) +{ + if ((sta->flags & + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) != + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) + return false; + + if (!sta->sa_query_timed_out && sta->sa_query_count > 0) + ap_check_sa_query_timeout(hapd, sta); + + if (!sta->sa_query_timed_out && (sta->auth_alg != WLAN_AUTH_FT)) { + /* + * STA has already been associated with MFP and SA Query timeout + * has not been reached. Reject the association attempt + * temporarily and start SA Query, if one is not pending. + */ + if (sta->sa_query_count == 0) + ap_sta_start_sa_query(hapd, sta); + + return true; + } + + return false; +} + + int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, const u8 *req_ies, size_t req_ies_len, int reassoc) { struct sta_info *sta; - int new_assoc, res; + int new_assoc; + enum wpa_validate_result res; struct ieee802_11_elems elems; const u8 *ie; size_t ielen; u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; u8 *p = buf; u16 reason = WLAN_REASON_UNSPECIFIED; - u16 status = WLAN_STATUS_SUCCESS; + int status = WLAN_STATUS_SUCCESS; const u8 *p2p_dev_addr = NULL; if (addr == NULL) { @@ -226,7 +253,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, } #endif /* CONFIG_P2P */ -#ifdef CONFIG_IEEE80211N #ifdef NEED_AP_MLME if (elems.ht_capabilities && (hapd->iface->conf->ht_capab & @@ -240,7 +266,6 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, ht40_intolerant_add(hapd->iface, sta); } #endif /* NEED_AP_MLME */ -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_INTERWORKING if (elems.ext_capab && elems.ext_capab_len > 4) { @@ -300,6 +325,17 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { struct wpabuf *wps; + if (check_sa_query_need(hapd, sta)) { + status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; + + p = hostapd_eid_assoc_comeback_time(hapd, sta, + p); + + hostapd_sta_assoc(hapd, addr, reassoc, status, + buf, p - buf); + return 0; + } + sta->flags |= WLAN_STA_WPS; wps = ieee802_11_vendor_ie_concat(ie, ielen, WPS_IE_VENDOR_TYPE); @@ -331,55 +367,71 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, elems.rsnxe ? elems.rsnxe_len + 2 : 0, elems.mdie, elems.mdie_len, elems.owe_dh, elems.owe_dh_len); - if (res != WPA_IE_OK) { + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + switch (res) { + case WPA_IE_OK: + reason = WLAN_REASON_UNSPECIFIED; + status = WLAN_STATUS_SUCCESS; + break; + case WPA_INVALID_IE: + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + break; + case WPA_INVALID_GROUP: + reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID; + status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; + break; + case WPA_INVALID_PAIRWISE: + reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; + status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; + break; + case WPA_INVALID_AKMP: + reason = WLAN_REASON_AKMP_NOT_VALID; + status = WLAN_STATUS_AKMP_NOT_VALID; + break; + case WPA_NOT_ENABLED: + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + break; + case WPA_ALLOC_FAIL: + reason = WLAN_REASON_UNSPECIFIED; + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + break; + case WPA_MGMT_FRAME_PROTECTION_VIOLATION: + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + break; + case WPA_INVALID_MGMT_GROUP_CIPHER: + reason = WLAN_REASON_CIPHER_SUITE_REJECTED; + status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; + break; + case WPA_INVALID_MDIE: + reason = WLAN_REASON_INVALID_MDE; + status = WLAN_STATUS_INVALID_MDIE; + break; + case WPA_INVALID_PROTO: + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + break; + case WPA_INVALID_PMKID: + reason = WLAN_REASON_INVALID_PMKID; + status = WLAN_STATUS_INVALID_PMKID; + break; + case WPA_DENIED_OTHER_REASON: + reason = WLAN_REASON_UNSPECIFIED; + status = WLAN_STATUS_ASSOC_DENIED_UNSPEC; + break; + } + if (status != WLAN_STATUS_SUCCESS) { wpa_printf(MSG_DEBUG, "WPA/RSN information element rejected? (res %u)", res); wpa_hexdump(MSG_DEBUG, "IE", ie, ielen); - if (res == WPA_INVALID_GROUP) { - reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID; - status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; - } else if (res == WPA_INVALID_PAIRWISE) { - reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; - status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - } else if (res == WPA_INVALID_AKMP) { - reason = WLAN_REASON_AKMP_NOT_VALID; - status = WLAN_STATUS_AKMP_NOT_VALID; - } else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) { - reason = WLAN_REASON_INVALID_IE; - status = WLAN_STATUS_INVALID_IE; - } else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) { - reason = WLAN_REASON_CIPHER_SUITE_REJECTED; - status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; - } else if (res == WPA_INVALID_PMKID) { - reason = WLAN_REASON_INVALID_PMKID; - status = WLAN_STATUS_INVALID_PMKID; - } else { - reason = WLAN_REASON_INVALID_IE; - status = WLAN_STATUS_INVALID_IE; - } goto fail; } - if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == - (WLAN_STA_ASSOC | WLAN_STA_MFP) && - !sta->sa_query_timed_out && - sta->sa_query_count > 0) - ap_check_sa_query_timeout(hapd, sta); - if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == - (WLAN_STA_ASSOC | WLAN_STA_MFP) && - !sta->sa_query_timed_out && - (sta->auth_alg != WLAN_AUTH_FT)) { - /* - * STA has already been associated with MFP and SA - * Query timeout has not been reached. Reject the - * association attempt temporarily and start SA Query, - * if one is not pending. - */ - - if (sta->sa_query_count == 0) - ap_sta_start_sa_query(hapd, sta); - + if (check_sa_query_need(hapd, sta)) { status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; p = hostapd_eid_assoc_comeback_time(hapd, sta, p); @@ -412,7 +464,7 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, #ifdef CONFIG_SAE if (hapd->conf->sae_pwe == 2 && sta->auth_alg == WLAN_AUTH_SAE && - sta->sae && sta->sae->tmp && !sta->sae->tmp->h2e && + sta->sae && !sta->sae->h2e && elems.rsnxe && elems.rsnxe_len >= 1 && (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { wpa_printf(MSG_INFO, "SAE: " MACSTR @@ -475,6 +527,9 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, return WLAN_STATUS_INVALID_IE; #endif /* CONFIG_HS20 */ } +#ifdef CONFIG_WPS +skip_wpa_check: +#endif /* CONFIG_WPS */ #ifdef CONFIG_MBO if (hapd->conf->mbo_enabled && (hapd->conf->wpa & 2) && @@ -486,13 +541,10 @@ int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, } #endif /* CONFIG_MBO */ -#ifdef CONFIG_WPS -skip_wpa_check: -#endif /* CONFIG_WPS */ - #ifdef CONFIG_IEEE80211R_AP p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf), - sta->auth_alg, req_ies, req_ies_len); + sta->auth_alg, req_ies, req_ies_len, + !elems.rsnxe); if (!p) { wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs"); return WLAN_STATUS_UNSPECIFIED_FAILURE; @@ -579,17 +631,19 @@ skip_wpa_check: wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE && elems.owe_dh) { u8 *npos; + u16 ret_status; npos = owe_assoc_req_process(hapd, sta, elems.owe_dh, elems.owe_dh_len, p, sizeof(buf) - (p - buf), - &status); + &ret_status); + status = ret_status; if (npos) p = npos; if (!npos && status == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) { - hostapd_sta_assoc(hapd, addr, reassoc, status, buf, + hostapd_sta_assoc(hapd, addr, reassoc, ret_status, buf, p - buf); return 0; } @@ -631,6 +685,11 @@ skip_wpa_check: pfs_fail: #endif /* CONFIG_DPP2 */ + if (elems.rrm_enabled && + elems.rrm_enabled_len >= sizeof(sta->rrm_enabled_capa)) + os_memcpy(sta->rrm_enabled_capa, elems.rrm_enabled, + sizeof(sta->rrm_enabled_capa)); + #if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS) || defined(CONFIG_OWE) hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); @@ -677,7 +736,8 @@ skip_wpa_check: fail: #ifdef CONFIG_IEEE80211R_AP - hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); + if (status >= 0) + hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); #endif /* CONFIG_IEEE80211R_AP */ hostapd_drv_sta_disassoc(hapd, sta->addr, reason); ap_free_sta(hapd, sta); @@ -715,6 +775,7 @@ void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) ap_sta_set_authorized(hapd, sta, 0); sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); + hostapd_set_sta_flags(hapd, sta); wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); @@ -808,8 +869,6 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, int offset, int width, int cf1, int cf2, int finished) { - /* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */ - #ifdef NEED_AP_MLME int channel, chwidth, is_dfs; u8 seg0_idx = 0, seg1_idx = 0; @@ -859,9 +918,18 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, switch (hapd->iface->current_mode->mode) { case HOSTAPD_MODE_IEEE80211A: - if (cf1 > 5000) + if (cf1 == 5935) + seg0_idx = (cf1 - 5925) / 5; + else if (cf1 > 5950) + seg0_idx = (cf1 - 5950) / 5; + else if (cf1 > 5000) seg0_idx = (cf1 - 5000) / 5; - if (cf2 > 5000) + + if (cf2 == 5935) + seg1_idx = (cf2 - 5925) / 5; + else if (cf2 > 5950) + seg1_idx = (cf2 - 5950) / 5; + else if (cf2 > 5000) seg1_idx = (cf2 - 5000) / 5; break; default: @@ -912,10 +980,39 @@ void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, } else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED "freq=%d dfs=%d", freq, is_dfs); + } else if (is_dfs && + hostapd_is_dfs_required(hapd->iface) && + !hostapd_is_dfs_chan_available(hapd->iface) && + !hapd->iface->cac_started) { + hostapd_disable_iface(hapd->iface); + hostapd_enable_iface(hapd->iface); } for (i = 0; i < hapd->iface->num_bss; i++) hostapd_neighbor_set_own_report(hapd->iface->bss[i]); + +#ifdef CONFIG_OCV + if (hapd->conf->ocv) { + struct sta_info *sta; + bool check_sa_query = false; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (wpa_auth_uses_ocv(sta->wpa_sm) && + !(sta->flags & WLAN_STA_WNM_SLEEP_MODE)) { + sta->post_csa_sa_query = 1; + check_sa_query = true; + } + } + + if (check_sa_query) { + wpa_printf(MSG_DEBUG, + "OCV: Check post-CSA SA Query initiation in 15 seconds"); + eloop_register_timeout(15, 0, + hostapd_ocv_check_csa_sa_query, + hapd, NULL); + } + } +#endif /* CONFIG_OCV */ #endif /* NEED_AP_MLME */ } @@ -1011,6 +1108,8 @@ void hostapd_acs_channel_selected(struct hostapd_data *hapd, goto out; } + hapd->iconf->edmg_channel = acs_res->edmg_channel; + if (hapd->iface->conf->ieee80211ac || hapd->iface->conf->ieee80211ax) { /* set defaults for backwards compatibility */ hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0); @@ -1433,15 +1532,33 @@ static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src, #endif /* HOSTAPD */ +static struct hostapd_channel_data * +hostapd_get_mode_chan(struct hostapd_hw_modes *mode, unsigned int freq) +{ + int i; + struct hostapd_channel_data *chan; + + for (i = 0; i < mode->num_channels; i++) { + chan = &mode->channels[i]; + if ((unsigned int) chan->freq == freq) + return chan; + } + + return NULL; +} + + static struct hostapd_channel_data * hostapd_get_mode_channel( struct hostapd_iface *iface, unsigned int freq) { int i; struct hostapd_channel_data *chan; - for (i = 0; i < iface->current_mode->num_channels; i++) { - chan = &iface->current_mode->channels[i]; - if ((unsigned int) chan->freq == freq) + for (i = 0; i < iface->num_hw_features; i++) { + if (hostapd_hw_skip_mode(iface, &iface->hw_features[i])) + continue; + chan = hostapd_get_mode_chan(&iface->hw_features[i], freq); + if (chan) return chan; } diff --git a/src/ap/gas_serv.c b/src/ap/gas_serv.c index 9567e202a..90f15778b 100644 --- a/src/ap/gas_serv.c +++ b/src/ap/gas_serv.c @@ -1555,11 +1555,14 @@ void gas_serv_req_dpp_processing(struct hostapd_data *hapd, di->prot = prot; di->sd_resp = buf; di->sd_resp_pos = 0; + di->dpp = 1; tx_buf = gas_build_initial_resp( dialog_token, WLAN_STATUS_SUCCESS, - comeback_delay, 10); - if (tx_buf) + comeback_delay, 10 + 2); + if (tx_buf) { gas_serv_write_dpp_adv_proto(tx_buf); + wpabuf_put_le16(tx_buf, 0); + } } } else { wpa_printf(MSG_DEBUG, @@ -1782,9 +1785,10 @@ static void gas_serv_rx_gas_comeback_req(struct hostapd_data *hapd, tx_buf = gas_build_comeback_resp(dialog_token, WLAN_STATUS_SUCCESS, dialog->sd_frag_id, more, 0, - 10 + frag_len); + 10 + 2 + frag_len); if (tx_buf) { gas_serv_write_dpp_adv_proto(tx_buf); + wpabuf_put_le16(tx_buf, frag_len); wpabuf_put_buf(tx_buf, buf); } } else diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c index b87663fe9..1de032930 100644 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c @@ -58,8 +58,10 @@ static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason); +#ifdef CONFIG_WEP static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd); static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd); +#endif /* CONFIG_WEP */ static int setup_interface2(struct hostapd_iface *iface); static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx); static void hostapd_interface_setup_failure_handler(void *eloop_ctx, @@ -74,6 +76,8 @@ int hostapd_for_each_interface(struct hapd_interfaces *interfaces, int ret; for (i = 0; i < interfaces->count; i++) { + if (!interfaces->iface[i]) + continue; ret = cb(interfaces->iface[i], ctx); if (ret) return ret; @@ -89,7 +93,9 @@ void hostapd_reconfig_encryption(struct hostapd_data *hapd) return; hostapd_set_privacy(hapd, 0); +#ifdef CONFIG_WEP hostapd_setup_encryption(hapd->conf->iface, hapd); +#endif /* CONFIG_WEP */ } @@ -142,7 +148,9 @@ static void hostapd_reload_bss(struct hostapd_data *hapd) wpa_deinit(hapd->wpa_auth); hapd->wpa_auth = NULL; hostapd_set_privacy(hapd, 0); +#ifdef CONFIG_WEP hostapd_setup_encryption(hapd->conf->iface, hapd); +#endif /* CONFIG_WEP */ hostapd_set_generic_elem(hapd, (u8 *) "", 0); } @@ -170,7 +178,9 @@ static void hostapd_clear_old(struct hostapd_iface *iface) for (j = 0; j < iface->num_bss; j++) { hostapd_flush_old_stations(iface->bss[j], WLAN_REASON_PREV_AUTH_NOT_VALID); +#ifdef CONFIG_WEP hostapd_broadcast_wep_clear(iface->bss[j]); +#endif /* CONFIG_WEP */ #ifndef CONFIG_NO_RADIUS /* TODO: update dynamic data based on changed configuration @@ -284,6 +294,8 @@ int hostapd_reload_config(struct hostapd_iface *iface) } +#ifdef CONFIG_WEP + static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd, const char *ifname) { @@ -326,7 +338,7 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd) struct hostapd_ssid *ssid = &hapd->conf->ssid; idx = ssid->wep.idx; - if (ssid->wep.default_len && + if (ssid->wep.default_len && ssid->wep.key[idx] && hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_WEP, broadcast_ether_addr, idx, 0, 1, NULL, 0, ssid->wep.key[idx], @@ -339,8 +351,10 @@ static int hostapd_broadcast_wep_set(struct hostapd_data *hapd) return errors; } +#endif /* CONFIG_WEP */ -static void hostapd_free_hapd_data(struct hostapd_data *hapd) + +void hostapd_free_hapd_data(struct hostapd_data *hapd) { os_free(hapd->probereq_cb); hapd->probereq_cb = NULL; @@ -420,11 +434,17 @@ static void hostapd_free_hapd_data(struct hostapd_data *hapd) #ifdef CONFIG_MESH wpabuf_free(hapd->mesh_pending_auth); hapd->mesh_pending_auth = NULL; + /* handling setup failure is already done */ + hapd->setup_complete_cb = NULL; #endif /* CONFIG_MESH */ hostapd_clean_rrm(hapd); fils_hlp_deinit(hapd); +#ifdef CONFIG_OCV + eloop_cancel_timeout(hostapd_ocv_check_csa_sa_query, hapd, NULL); +#endif /* CONFIG_OCV */ + #ifdef CONFIG_SAE { struct hostapd_sae_commit_queue *q; @@ -478,14 +498,12 @@ static void sta_track_deinit(struct hostapd_iface *iface) } -static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface) +void hostapd_cleanup_iface_partial(struct hostapd_iface *iface) { wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); -#ifdef CONFIG_IEEE80211N #ifdef NEED_AP_MLME hostapd_stop_setup_timers(iface); #endif /* NEED_AP_MLME */ -#endif /* CONFIG_IEEE80211N */ if (iface->current_mode) acs_cleanup(iface); hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); @@ -526,6 +544,8 @@ static void hostapd_cleanup_iface(struct hostapd_iface *iface) } +#ifdef CONFIG_WEP + static void hostapd_clear_wep(struct hostapd_data *hapd) { if (hapd->drv_priv && !hapd->iface->driver_ap_teardown && hapd->conf) { @@ -573,6 +593,8 @@ static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd) return 0; } +#endif /* CONFIG_WEP */ + static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason) { @@ -604,11 +626,13 @@ static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason) } -static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd) +void hostapd_bss_deinit_no_free(struct hostapd_data *hapd) { hostapd_free_stas(hapd); hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING); +#ifdef CONFIG_WEP hostapd_clear_wep(hapd); +#endif /* CONFIG_WEP */ } @@ -1159,13 +1183,15 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) #endif /* CONFIG_MESH */ if (flush_old_stations) - hostapd_flush_old_stations(hapd, - WLAN_REASON_PREV_AUTH_NOT_VALID); + hostapd_flush(hapd); hostapd_set_privacy(hapd, 0); - hostapd_broadcast_wep_clear(hapd); +#ifdef CONFIG_WEP + if (!hostapd_drv_nl80211(hapd)) + hostapd_broadcast_wep_clear(hapd); if (hostapd_setup_encryption(conf->iface, hapd)) return -1; +#endif /* CONFIG_WEP */ /* * Fetch the SSID from the system and use it or, @@ -1351,6 +1377,21 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first) if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0) return -1; + if (flush_old_stations && !conf->start_disabled && + conf->broadcast_deauth) { + u8 addr[ETH_ALEN]; + + /* Should any previously associated STA not have noticed that + * the AP had stopped and restarted, send one more + * deauthentication notification now that the AP is ready to + * operate. */ + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, + "Deauthenticate all stations at BSS start"); + os_memset(addr, 0xff, ETH_ALEN); + hostapd_drv_sta_deauth(hapd, addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + } + if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0) return -1; @@ -1754,7 +1795,7 @@ static void fst_hostapd_update_mb_ie_cb(void *ctx, const u8 *addr, static const u8 * fst_hostapd_get_sta(struct fst_get_peer_ctx **get_ctx, - Boolean mb_only) + bool mb_only) { struct sta_info *s = (struct sta_info *) *get_ctx; @@ -1776,7 +1817,7 @@ static const u8 * fst_hostapd_get_sta(struct fst_get_peer_ctx **get_ctx, static const u8 * fst_hostapd_get_peer_first(void *ctx, struct fst_get_peer_ctx **get_ctx, - Boolean mb_only) + bool mb_only) { struct hostapd_data *hapd = ctx; @@ -1788,7 +1829,7 @@ static const u8 * fst_hostapd_get_peer_first(void *ctx, static const u8 * fst_hostapd_get_peer_next(void *ctx, struct fst_get_peer_ctx **get_ctx, - Boolean mb_only) + bool mb_only) { return fst_hostapd_get_sta(get_ctx, mb_only); } @@ -1876,6 +1917,13 @@ static int hostapd_owe_iface_iter2(struct hostapd_iface *iface, void *ctx) if (!bss->conf->owe_transition_ifname[0]) continue; + if (bss->iface->state != HAPD_IFACE_ENABLED) { + wpa_printf(MSG_DEBUG, + "OWE: Interface %s state %s - defer beacon update", + bss->conf->iface, + hostapd_state_text(bss->iface->state)); + continue; + } res = hostapd_owe_trans_get_info(bss); if (res == 0) continue; @@ -2110,6 +2158,13 @@ dfs_offload: if (hapd->setup_complete_cb) hapd->setup_complete_cb(hapd->setup_complete_cb_ctx); +#ifdef CONFIG_MESH + if (delay_apply_cfg && !iface->mconf) { + wpa_printf(MSG_ERROR, "Error while completing mesh init"); + goto fail; + } +#endif /* CONFIG_MESH */ + wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", iface->bss[0]->conf->iface); if (iface->interfaces && iface->interfaces->terminate_on_error > 0) @@ -2253,7 +2308,7 @@ int hostapd_setup_interface(struct hostapd_iface *iface) ret = setup_interface(iface); if (ret) { wpa_printf(MSG_ERROR, "%s: Unable to setup interface.", - iface->bss[0]->conf->iface); + iface->conf ? iface->conf->bss[0]->iface : "N/A"); return -1; } @@ -2349,12 +2404,10 @@ void hostapd_interface_deinit(struct hostapd_iface *iface) hostapd_bss_deinit(iface->bss[j]); } -#ifdef CONFIG_IEEE80211N #ifdef NEED_AP_MLME hostapd_stop_setup_timers(iface); eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL); #endif /* NEED_AP_MLME */ -#endif /* CONFIG_IEEE80211N */ } @@ -2637,6 +2690,12 @@ int hostapd_enable_iface(struct hostapd_iface *hapd_iface) { size_t j; + if (!hapd_iface) + return -1; + + if (hapd_iface->enable_iface_cb) + return hapd_iface->enable_iface_cb(hapd_iface); + if (hapd_iface->bss[0]->drv_priv != NULL) { wpa_printf(MSG_ERROR, "Interface %s already enabled", hapd_iface->conf->bss[0]->iface); @@ -2698,6 +2757,9 @@ int hostapd_disable_iface(struct hostapd_iface *hapd_iface) if (hapd_iface == NULL) return -1; + if (hapd_iface->disable_iface_cb) + return hapd_iface->disable_iface_cb(hapd_iface); + if (hapd_iface->bss[0]->drv_priv == NULL) { wpa_printf(MSG_INFO, "Interface %s already disabled", hapd_iface->conf->bss[0]->iface); @@ -3118,6 +3180,7 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, hostapd_prune_associations(hapd, sta->addr); ap_sta_clear_disconnect_timeouts(hapd, sta); + sta->post_csa_sa_query = 0; #ifdef CONFIG_P2P if (sta->p2p_ie == NULL && !sta->no_p2p_set) { @@ -3629,3 +3692,25 @@ void hostapd_periodic_iface(struct hostapd_iface *iface) #endif /* CONFIG_NO_RADIUS */ } } + + +#ifdef CONFIG_OCV +void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta; + + wpa_printf(MSG_DEBUG, "OCV: Post-CSA SA Query initiation check"); + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (!sta->post_csa_sa_query) + continue; + + wpa_printf(MSG_DEBUG, "OCV: OCVC STA " MACSTR + " did not start SA Query after CSA - disconnect", + MAC2STR(sta->addr)); + ap_sta_disconnect(hapd, sta, sta->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + } +} +#endif /* CONFIG_OCV */ diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 2358d1664..4ce31416d 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -38,6 +38,10 @@ union wps_event_data; struct mesh_conf; #endif /* CONFIG_MESH */ +#ifdef CONFIG_CTRL_IFACE_UDP +#define CTRL_IFACE_COOKIE_LEN 8 +#endif /* CONFIG_CTRL_IFACE_UDP */ + struct hostapd_iface; struct hapd_interfaces { @@ -72,6 +76,11 @@ struct hapd_interfaces { #ifdef CONFIG_DPP struct dpp_global *dpp; #endif /* CONFIG_DPP */ + +#ifdef CONFIG_CTRL_IFACE_UDP + unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN]; +#endif /* CONFIG_CTRL_IFACE_UDP */ + }; enum hostapd_chan_status { @@ -340,6 +349,11 @@ struct hostapd_data { int last_igtk_key_idx; u8 last_igtk[WPA_IGTK_MAX_LEN]; size_t last_igtk_len; + + enum wpa_alg last_bigtk_alg; + int last_bigtk_key_idx; + u8 last_bigtk[WPA_BIGTK_MAX_LEN]; + size_t last_bigtk_len; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_MBO @@ -377,6 +391,16 @@ struct hostapd_data { unsigned int dpp_resp_wait_time; unsigned int dpp_resp_max_tries; unsigned int dpp_resp_retry_time; +#ifdef CONFIG_DPP2 + struct wpabuf *dpp_presence_announcement; + struct dpp_bootstrap_info *dpp_chirp_bi; + int dpp_chirp_freq; + int *dpp_chirp_freqs; + int dpp_chirp_iter; + int dpp_chirp_round; + int dpp_chirp_scan_done; + int dpp_chirp_listen; +#endif /* CONFIG_DPP2 */ #ifdef CONFIG_TESTING_OPTIONS char *dpp_config_obj_override; char *dpp_discovery_override; @@ -395,6 +419,10 @@ struct hostapd_data { #ifdef CONFIG_SQLITE sqlite3 *rad_attr_db; #endif /* CONFIG_SQLITE */ + +#ifdef CONFIG_CTRL_IFACE_UDP + unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN]; +#endif /* CONFIG_CTRL_IFACE_UDP */ }; @@ -462,9 +490,7 @@ struct hostapd_iface { struct ap_info *ap_hash[STA_HASH_SIZE]; u64 drv_flags; - - /* SMPS modes supported by the driver (WPA_DRIVER_SMPS_MODE_*) */ - unsigned int smps_modes; + u64 drv_flags2; /* * A bitmap of supported protocols for probe response offload. See @@ -563,6 +589,9 @@ struct hostapd_iface { /* Previous WMM element information */ struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM]; + + int (*enable_iface_cb)(struct hostapd_iface *iface); + int (*disable_iface_cb)(struct hostapd_iface *iface); }; /* hostapd.c */ @@ -591,6 +620,9 @@ void hostapd_interface_deinit_free(struct hostapd_iface *iface); int hostapd_enable_iface(struct hostapd_iface *hapd_iface); int hostapd_reload_iface(struct hostapd_iface *hapd_iface); int hostapd_disable_iface(struct hostapd_iface *hapd_iface); +void hostapd_bss_deinit_no_free(struct hostapd_data *hapd); +void hostapd_free_hapd_data(struct hostapd_data *hapd); +void hostapd_cleanup_iface_partial(struct hostapd_iface *iface); int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf); int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf); void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator); @@ -606,6 +638,7 @@ hostapd_switch_channel_fallback(struct hostapd_iface *iface, void hostapd_cleanup_cs_params(struct hostapd_data *hapd); void hostapd_periodic_iface(struct hostapd_iface *iface); int hostapd_owe_trans_get_info(struct hostapd_data *hapd); +void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx); /* utils.c */ int hostapd_register_probereq_cb(struct hostapd_data *hapd, diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 0d856d572..f6e69030d 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -224,7 +224,6 @@ int hostapd_prepare_rates(struct hostapd_iface *iface, } -#ifdef CONFIG_IEEE80211N static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) { int pri_freq, sec_freq; @@ -561,26 +560,6 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) return 0; } - switch (conf & HT_CAP_INFO_SMPS_MASK) { - case HT_CAP_INFO_SMPS_STATIC: - if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_STATIC)) { - wpa_printf(MSG_ERROR, - "Driver does not support configured HT capability [SMPS-STATIC]"); - return 0; - } - break; - case HT_CAP_INFO_SMPS_DYNAMIC: - if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_DYNAMIC)) { - wpa_printf(MSG_ERROR, - "Driver does not support configured HT capability [SMPS-DYNAMIC]"); - return 0; - } - break; - case HT_CAP_INFO_SMPS_DISABLED: - default: - break; - } - if ((conf & HT_CAP_INFO_GREEN_FIELD) && !(hw & HT_CAP_INFO_GREEN_FIELD)) { wpa_printf(MSG_ERROR, "Driver does not support configured " @@ -687,12 +666,9 @@ static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface) } #endif /* CONFIG_IEEE80211AX */ -#endif /* CONFIG_IEEE80211N */ - int hostapd_check_ht_capab(struct hostapd_iface *iface) { -#ifdef CONFIG_IEEE80211N int ret; if (is_6ghz_freq(iface->freq)) @@ -725,7 +701,6 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface) return ret; if (!ieee80211n_allowed_ht40_channel_pair(iface)) return -1; -#endif /* CONFIG_IEEE80211N */ return 0; } @@ -810,7 +785,7 @@ static int hostapd_is_usable_edmg(struct hostapd_iface *iface) /* 60 GHz channels 1..6 */ for (i = 0; i < 6; i++) { - int freq = 56160 + 2160 * i; + int freq = 56160 + 2160 * (i + 1); if (edmg.channels & BIT(i)) { contiguous++; @@ -904,10 +879,43 @@ static int hostapd_is_usable_chans(struct hostapd_iface *iface) } +static void hostapd_determine_mode(struct hostapd_iface *iface) +{ + int i; + enum hostapd_hw_mode target_mode; + + if (iface->current_mode || + iface->conf->hw_mode != HOSTAPD_MODE_IEEE80211ANY) + return; + + if (iface->freq < 4000) + target_mode = HOSTAPD_MODE_IEEE80211G; + else if (iface->freq > 50000) + target_mode = HOSTAPD_MODE_IEEE80211AD; + else + target_mode = HOSTAPD_MODE_IEEE80211A; + + for (i = 0; i < iface->num_hw_features; i++) { + struct hostapd_hw_modes *mode; + + mode = &iface->hw_features[i]; + if (mode->mode == target_mode) { + iface->current_mode = mode; + iface->conf->hw_mode = mode->mode; + break; + } + } + + if (!iface->current_mode) + wpa_printf(MSG_ERROR, "ACS: Cannot decide mode"); +} + + static enum hostapd_chan_status hostapd_check_chans(struct hostapd_iface *iface) { if (iface->freq) { + hostapd_determine_mode(iface); if (hostapd_is_usable_chans(iface)) return HOSTAPD_CHAN_VALID; else @@ -1033,9 +1041,15 @@ int hostapd_select_hw_mode(struct hostapd_iface *iface) } if (iface->current_mode == NULL) { - if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) || - !(iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY)) - { + if ((iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) && + (iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY)) { + wpa_printf(MSG_DEBUG, + "Using offloaded hw_mode=any ACS"); + } else if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) && + iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211ANY) { + wpa_printf(MSG_DEBUG, + "Using internal ACS for hw_mode=any"); + } else { wpa_printf(MSG_ERROR, "Hardware does not support configured mode"); hostapd_logger(iface->bss[0], NULL, @@ -1110,3 +1124,20 @@ int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) } return 0; } + + +int hostapd_hw_skip_mode(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode) +{ + int i; + + if (iface->current_mode) + return mode != iface->current_mode; + if (mode->mode != HOSTAPD_MODE_IEEE80211B) + return 0; + for (i = 0; i < iface->num_hw_features; i++) { + if (iface->hw_features[i].mode == HOSTAPD_MODE_IEEE80211G) + return 1; + } + return 0; +} diff --git a/src/ap/hw_features.h b/src/ap/hw_features.h index 67493193a..dd24f95b2 100644 --- a/src/ap/hw_features.h +++ b/src/ap/hw_features.h @@ -25,6 +25,8 @@ int hostapd_check_edmg_capab(struct hostapd_iface *iface); int hostapd_prepare_rates(struct hostapd_iface *iface, struct hostapd_hw_modes *mode); void hostapd_stop_setup_timers(struct hostapd_iface *iface); +int hostapd_hw_skip_mode(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode); #else /* NEED_AP_MLME */ static inline void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, @@ -77,6 +79,12 @@ static inline void hostapd_stop_setup_timers(struct hostapd_iface *iface) { } +static inline int hostapd_hw_skip_mode(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode) +{ + return 0; +} + #endif /* NEED_AP_MLME */ #endif /* HW_FEATURES_H */ diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index d411e9246..7dc7ec78c 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -25,6 +25,7 @@ #include "common/dpp.h" #include "common/ocv.h" #include "common/wpa_common.h" +#include "common/wpa_ctrl.h" #include "radius/radius.h" #include "radius/radius_client.h" #include "p2p/p2p.h" @@ -224,7 +225,7 @@ u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid, u16 hostapd_own_capab_info(struct hostapd_data *hapd) { int capab = WLAN_CAPABILITY_ESS; - int privacy; + int privacy = 0; int dfs; int i; @@ -240,12 +241,14 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd) hapd->iconf->preamble == SHORT_PREAMBLE) capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; +#ifdef CONFIG_WEP privacy = hapd->conf->ssid.wep.keys_set; if (hapd->conf->ieee802_1x && (hapd->conf->default_wep_key_len || hapd->conf->individual_wep_key_len)) privacy = 1; +#endif /* CONFIG_WEP */ if (hapd->conf->wpa) privacy = 1; @@ -285,6 +288,7 @@ u16 hostapd_own_capab_info(struct hostapd_data *hapd) } +#ifdef CONFIG_WEP #ifndef CONFIG_NO_RC4 static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta, u16 auth_transaction, const u8 *challenge, @@ -341,6 +345,7 @@ static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta, return 0; } #endif /* CONFIG_NO_RC4 */ +#endif /* CONFIG_WEP */ static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta, @@ -380,9 +385,10 @@ static int send_auth_reply(struct hostapd_data *hapd, struct sta_info *sta, #ifdef CONFIG_SAE if (hapd->conf->sae_confirm_immediate == 2 && auth_alg == WLAN_AUTH_SAE) { - if (auth_transaction == 1 && + if (auth_transaction == 1 && sta && (resp == WLAN_STATUS_SUCCESS || - resp == WLAN_STATUS_SAE_HASH_TO_ELEMENT)) { + resp == WLAN_STATUS_SAE_HASH_TO_ELEMENT || + resp == WLAN_STATUS_SAE_PK)) { wpa_printf(MSG_DEBUG, "TESTING: Postpone SAE Commit transmission until Confirm is ready"); os_free(sta->sae_postponed_commit); @@ -474,17 +480,23 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, const char *rx_id = NULL; int use_pt = 0; struct sae_pt *pt = NULL; + const struct sae_pk *pk = NULL; if (sta->sae->tmp) { rx_id = sta->sae->tmp->pw_id; - use_pt = sta->sae->tmp->h2e; + use_pt = sta->sae->h2e; +#ifdef CONFIG_SAE_PK + os_memcpy(sta->sae->tmp->own_addr, hapd->own_addr, ETH_ALEN); + os_memcpy(sta->sae->tmp->peer_addr, sta->addr, ETH_ALEN); +#endif /* CONFIG_SAE_PK */ } if (rx_id && hapd->conf->sae_pwe != 3) use_pt = 1; else if (status_code == WLAN_STATUS_SUCCESS) use_pt = 0; - else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) + else if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || + status_code == WLAN_STATUS_SAE_PK) use_pt = 1; for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) { @@ -498,6 +510,8 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, continue; password = pw->password; pt = pw->pt; + if (!(hapd->conf->mesh & MESH_ENABLED)) + pk = pw->pk; break; } if (!password) { @@ -511,7 +525,7 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, if (update && use_pt && sae_prepare_commit_pt(sta->sae, pt, hapd->own_addr, sta->addr, - NULL) < 0) + NULL, pk) < 0) return NULL; if (update && !use_pt && @@ -533,10 +547,13 @@ static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN + (rx_id ? 3 + os_strlen(rx_id) : 0)); - if (buf == NULL) - return NULL; - sae_write_commit(sta->sae, buf, sta->sae->tmp ? - sta->sae->tmp->anti_clogging_token : NULL, rx_id); + if (buf && + sae_write_commit(sta->sae, buf, sta->sae->tmp ? + sta->sae->tmp->anti_clogging_token : NULL, + rx_id) < 0) { + wpabuf_free(buf); + buf = NULL; + } return buf; } @@ -551,7 +568,17 @@ static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd, if (buf == NULL) return NULL; - sae_write_confirm(sta->sae, buf); +#ifdef CONFIG_SAE_PK +#ifdef CONFIG_TESTING_OPTIONS + if (sta->sae->tmp) + sta->sae->tmp->omit_pk_elem = hapd->conf->sae_pk_omit; +#endif /* CONFIG_TESTING_OPTIONS */ +#endif /* CONFIG_SAE_PK */ + + if (sae_write_confirm(sta->sae, buf) < 0) { + wpabuf_free(buf); + return NULL; + } return buf; } @@ -571,8 +598,21 @@ static int auth_sae_send_commit(struct hostapd_data *hapd, if (data == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; - status = (sta->sae->tmp && sta->sae->tmp->h2e) ? - WLAN_STATUS_SAE_HASH_TO_ELEMENT : WLAN_STATUS_SUCCESS; + if (sta->sae->tmp && sta->sae->pk) + status = WLAN_STATUS_SAE_PK; + else if (sta->sae->tmp && sta->sae->h2e) + status = WLAN_STATUS_SAE_HASH_TO_ELEMENT; + else + status = WLAN_STATUS_SUCCESS; +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->sae_commit_status >= 0 && + hapd->conf->sae_commit_status != status) { + wpa_printf(MSG_INFO, + "TESTING: Override SAE commit status code %u --> %d", + status, hapd->conf->sae_commit_status); + status = hapd->conf->sae_commit_status; + } +#endif /* CONFIG_TESTING_OPTIONS */ reply_res = send_auth_reply(hapd, sta, sta->addr, bssid, WLAN_AUTH_SAE, 1, status, wpabuf_head(data), @@ -636,13 +676,15 @@ static int use_sae_anti_clogging(struct hostapd_data *hapd) } -static u8 sae_token_hash(struct hostapd_data *hapd, const u8 *addr) +static int sae_token_hash(struct hostapd_data *hapd, const u8 *addr, u8 *idx) { u8 hash[SHA256_MAC_LEN]; - hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key), - addr, ETH_ALEN, hash); - return hash[0]; + if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key), + addr, ETH_ALEN, hash) < 0) + return -1; + *idx = hash[0]; + return 0; } @@ -655,9 +697,8 @@ static int check_sae_token(struct hostapd_data *hapd, const u8 *addr, u16 token_idx; u8 idx; - if (token_len != SHA256_MAC_LEN) + if (token_len != SHA256_MAC_LEN || sae_token_hash(hapd, addr, &idx) < 0) return -1; - idx = sae_token_hash(hapd, addr); token_idx = hapd->sae_pending_token_idx[idx]; if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) { wpa_printf(MSG_DEBUG, "SAE: Invalid anti-clogging token from " @@ -721,7 +762,10 @@ static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd, wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN); } - p_idx = sae_token_hash(hapd, addr); + if (sae_token_hash(hapd, addr, &p_idx) < 0) { + wpabuf_free(buf); + return NULL; + } token_idx = hapd->sae_pending_token_idx[p_idx]; if (!token_idx) { hapd->sae_token_idx++; @@ -889,9 +933,14 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta, switch (sta->sae->state) { case SAE_NOTHING: if (auth_transaction == 1) { - if (sta->sae->tmp) - sta->sae->tmp->h2e = status_code == - WLAN_STATUS_SAE_HASH_TO_ELEMENT; + if (sta->sae->tmp) { + sta->sae->h2e = + (status_code == + WLAN_STATUS_SAE_HASH_TO_ELEMENT || + status_code == WLAN_STATUS_SAE_PK); + sta->sae->pk = + status_code == WLAN_STATUS_SAE_PK; + } ret = auth_sae_send_commit(hapd, sta, bssid, !allow_reuse, status_code); if (ret) @@ -1101,20 +1150,28 @@ static int sae_status_success(struct hostapd_data *hapd, u16 status_code) { int sae_pwe = hapd->conf->sae_pwe; int id_in_use; + bool sae_pk = false; id_in_use = hostapd_sae_pw_id_in_use(hapd->conf); if (id_in_use == 2 && sae_pwe != 3) sae_pwe = 1; else if (id_in_use == 1 && sae_pwe == 0) sae_pwe = 2; +#ifdef CONFIG_SAE_PK + sae_pk = hostapd_sae_pk_in_use(hapd->conf); + if (sae_pwe == 0 && sae_pk) + sae_pwe = 2; +#endif /* CONFIG_SAE_PK */ return ((sae_pwe == 0 || sae_pwe == 3) && status_code == WLAN_STATUS_SUCCESS) || (sae_pwe == 1 && - status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) || + (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || + (sae_pk && status_code == WLAN_STATUS_SAE_PK))) || (sae_pwe == 2 && (status_code == WLAN_STATUS_SUCCESS || - status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT)); + status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || + (sae_pk && status_code == WLAN_STATUS_SAE_PK))); } @@ -1137,11 +1194,15 @@ static int sae_is_group_enabled(struct hostapd_data *hapd, int group) static int check_sae_rejected_groups(struct hostapd_data *hapd, - const struct wpabuf *groups) + struct sae_data *sae) { + const struct wpabuf *groups; size_t i, count; const u8 *pos; + if (!sae->tmp) + return 0; + groups = sae->tmp->peer_rejected_groups; if (!groups) return 0; @@ -1183,6 +1244,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, wpa_printf(MSG_DEBUG, "SAE: TESTING - reflection attack"); pos = mgmt->u.auth.variable; end = ((const u8 *) mgmt) + len; + resp = status_code; send_auth_reply(hapd, sta, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE, auth_transaction, resp, pos, end - pos, "auth-sae-reflection-attack"); @@ -1328,7 +1390,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, ((const u8 *) mgmt) + len - mgmt->u.auth.variable, &token, &token_len, groups, status_code == - WLAN_STATUS_SAE_HASH_TO_ELEMENT); + WLAN_STATUS_SAE_HASH_TO_ELEMENT || + status_code == WLAN_STATUS_SAE_PK); if (resp == SAE_SILENTLY_DISCARD) { wpa_printf(MSG_DEBUG, "SAE: Drop commit message from " MACSTR " due to reflection attack", @@ -1358,9 +1421,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, if (resp != WLAN_STATUS_SUCCESS) goto reply; - if (sta->sae->tmp && - check_sae_rejected_groups( - hapd, sta->sae->tmp->peer_rejected_groups)) { + if (check_sae_rejected_groups(hapd, sta->sae)) { resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto reply; } @@ -1372,8 +1433,9 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, "SAE: Request anti-clogging token from " MACSTR, MAC2STR(sta->addr)); if (sta->sae->tmp) - h2e = sta->sae->tmp->h2e; - if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) + h2e = sta->sae->h2e; + if (status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT || + status_code == WLAN_STATUS_SAE_PK) h2e = 1; data = auth_build_token_req(hapd, sta->sae->group, sta->addr, h2e); @@ -1601,27 +1663,37 @@ static int auth_sae_queued_addr(struct hostapd_data *hapd, const u8 *addr) #endif /* CONFIG_SAE */ -static u16 wpa_res_to_status_code(int res) +static u16 wpa_res_to_status_code(enum wpa_validate_result res) { - if (res == WPA_INVALID_GROUP) - return WLAN_STATUS_GROUP_CIPHER_NOT_VALID; - if (res == WPA_INVALID_PAIRWISE) - return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; - if (res == WPA_INVALID_AKMP) - return WLAN_STATUS_AKMP_NOT_VALID; - if (res == WPA_ALLOC_FAIL) - return WLAN_STATUS_UNSPECIFIED_FAILURE; - if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) - return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; - if (res == WPA_INVALID_MGMT_GROUP_CIPHER) - return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; - if (res == WPA_INVALID_MDIE) - return WLAN_STATUS_INVALID_MDIE; - if (res == WPA_INVALID_PMKID) - return WLAN_STATUS_INVALID_PMKID; - if (res != WPA_IE_OK) + switch (res) { + case WPA_IE_OK: + return WLAN_STATUS_SUCCESS; + case WPA_INVALID_IE: return WLAN_STATUS_INVALID_IE; - return WLAN_STATUS_SUCCESS; + case WPA_INVALID_GROUP: + return WLAN_STATUS_GROUP_CIPHER_NOT_VALID; + case WPA_INVALID_PAIRWISE: + return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; + case WPA_INVALID_AKMP: + return WLAN_STATUS_AKMP_NOT_VALID; + case WPA_NOT_ENABLED: + return WLAN_STATUS_INVALID_IE; + case WPA_ALLOC_FAIL: + return WLAN_STATUS_UNSPECIFIED_FAILURE; + case WPA_MGMT_FRAME_PROTECTION_VIOLATION: + return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + case WPA_INVALID_MGMT_GROUP_CIPHER: + return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; + case WPA_INVALID_MDIE: + return WLAN_STATUS_INVALID_MDIE; + case WPA_INVALID_PROTO: + return WLAN_STATUS_INVALID_IE; + case WPA_INVALID_PMKID: + return WLAN_STATUS_INVALID_PMKID; + case WPA_DENIED_OTHER_REASON: + return WLAN_STATUS_ASSOC_DENIED_UNSPEC; + } + return WLAN_STATUS_INVALID_IE; } @@ -1641,7 +1713,7 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, u16 resp = WLAN_STATUS_SUCCESS; const u8 *end; struct ieee802_11_elems elems; - int res; + enum wpa_validate_result res; struct wpa_ie_data rsn; struct rsn_pmksa_cache_entry *pmksa = NULL; @@ -1817,11 +1889,11 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, FILS_SESSION_LEN); os_memcpy(sta->fils_session, elems.fils_session, FILS_SESSION_LEN); - /* FILS Wrapped Data */ - if (elems.fils_wrapped_data) { + /* Wrapped Data */ + if (elems.wrapped_data) { wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data", - elems.fils_wrapped_data, - elems.fils_wrapped_data_len); + elems.wrapped_data, + elems.wrapped_data_len); if (!pmksa) { #ifndef CONFIG_NO_RADIUS if (!sta->eapol_sm) { @@ -1831,8 +1903,8 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, wpa_printf(MSG_DEBUG, "FILS: Forward EAP-Initiate/Re-auth to authentication server"); ieee802_1x_encapsulate_radius( - hapd, sta, elems.fils_wrapped_data, - elems.fils_wrapped_data_len); + hapd, sta, elems.wrapped_data, + elems.wrapped_data_len); sta->fils_pending_cb = cb; wpa_printf(MSG_DEBUG, "FILS: Will send Authentication frame once the response from authentication server is available"); @@ -1841,8 +1913,8 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, * to maintain a copy of the EAP-Initiate/Reauth * message. */ if (fils_pmkid_erp(wpa_auth_sta_key_mgmt(sta->wpa_sm), - elems.fils_wrapped_data, - elems.fils_wrapped_data_len, + elems.wrapped_data, + elems.wrapped_data_len, sta->fils_erp_pmkid) == 0) sta->fils_erp_pmkid_set = 1; return; @@ -1985,12 +2057,12 @@ prepare_auth_resp_fils(struct hostapd_data *hapd, wpabuf_put_u8(data, WLAN_EID_EXT_FILS_SESSION); wpabuf_put_data(data, sta->fils_session, FILS_SESSION_LEN); - /* FILS Wrapped Data */ + /* Wrapped Data */ if (!pmksa && erp_resp) { wpabuf_put_u8(data, WLAN_EID_EXTENSION); /* Element ID */ wpabuf_put_u8(data, 1 + wpabuf_len(erp_resp)); /* Length */ /* Element ID Extension */ - wpabuf_put_u8(data, WLAN_EID_EXT_FILS_WRAPPED_DATA); + wpabuf_put_u8(data, WLAN_EID_EXT_WRAPPED_DATA); wpabuf_put_buf(data, erp_resp); if (fils_rmsk_to_pmk(wpa_auth_sta_key_mgmt(sta->wpa_sm), @@ -2506,32 +2578,10 @@ static void handle_auth(struct hostapd_data *hapd, (!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) && !(hapd->conf->mesh & MESH_ENABLED) && !(sta->added_unassoc)) { - /* - * If a station that is already associated to the AP, is trying - * to authenticate again, remove the STA entry, in order to make - * sure the STA PS state gets cleared and configuration gets - * updated. To handle this, station's added_unassoc flag is - * cleared once the station has completed association. - */ - ap_sta_set_authorized(hapd, sta, 0); - hostapd_drv_sta_remove(hapd, sta->addr); - sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH | - WLAN_STA_AUTHORIZED); - - if (hostapd_sta_add(hapd, sta->addr, 0, 0, - sta->supported_rates, - sta->supported_rates_len, - 0, NULL, NULL, NULL, 0, - sta->flags, 0, 0, 0, 0)) { - hostapd_logger(hapd, sta->addr, - HOSTAPD_MODULE_IEEE80211, - HOSTAPD_LEVEL_NOTICE, - "Could not add STA to kernel driver"); + if (ap_sta_re_add(hapd, sta) < 0) { resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; goto fail; } - - sta->added_unassoc = 1; } switch (auth_alg) { @@ -2544,6 +2594,7 @@ static void handle_auth(struct hostapd_data *hapd, sta->auth_alg = WLAN_AUTH_OPEN; mlme_authenticate_indication(hapd, sta); break; +#ifdef CONFIG_WEP #ifndef CONFIG_NO_RC4 case WLAN_AUTH_SHARED_KEY: resp = auth_shared_key(hapd, sta, auth_transaction, challenge, @@ -2562,6 +2613,7 @@ static void handle_auth(struct hostapd_data *hapd, } break; #endif /* CONFIG_NO_RC4 */ +#endif /* CONFIG_WEP */ #ifdef CONFIG_IEEE80211R_AP case WLAN_AUTH_FT: sta->auth_alg = WLAN_AUTH_FT; @@ -3032,7 +3084,7 @@ u16 owe_process_rsn_ie(struct hostapd_data *hapd, u16 status; u8 *owe_buf, ie[256 * 2]; size_t ie_len = 0; - int res; + enum wpa_validate_result res; if (!rsn_ie || rsn_ie_len < 2) { wpa_printf(MSG_DEBUG, "OWE: No RSNE in (Re)AssocReq"); @@ -3104,11 +3156,39 @@ end: #endif /* CONFIG_OWE */ -static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, +static bool check_sa_query(struct hostapd_data *hapd, struct sta_info *sta, + int reassoc) +{ + if ((sta->flags & + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) != + (WLAN_STA_ASSOC | WLAN_STA_MFP | WLAN_STA_AUTHORIZED)) + return false; + + if (!sta->sa_query_timed_out && sta->sa_query_count > 0) + ap_check_sa_query_timeout(hapd, sta); + + if (!sta->sa_query_timed_out && + (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) { + /* + * STA has already been associated with MFP and SA Query timeout + * has not been reached. Reject the association attempt + * temporarily and start SA Query, if one is not pending. + */ + if (sta->sa_query_count == 0) + ap_sta_start_sa_query(hapd, sta); + + return true; + } + + return false; +} + + +static int check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, const u8 *ies, size_t ies_len, int reassoc) { struct ieee802_11_elems elems; - u16 resp; + int resp; const u8 *wpa_ie; size_t wpa_ie_len; const u8 *p2p_dev_addr = NULL; @@ -3137,7 +3217,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, if (resp != WLAN_STATUS_SUCCESS) return resp; -#ifdef CONFIG_IEEE80211N resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities); if (resp != WLAN_STATUS_SUCCESS) return resp; @@ -3148,7 +3227,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, "mandatory HT PHY - reject association"); return WLAN_STATUS_ASSOC_DENIED_NO_HT; } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC if (hapd->iconf->ieee80211ac) { @@ -3177,12 +3255,25 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, } #endif /* CONFIG_IEEE80211AC */ #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { resp = copy_sta_he_capab(hapd, sta, IEEE80211_MODE_AP, elems.he_capabilities, elems.he_capabilities_len); if (resp != WLAN_STATUS_SUCCESS) return resp; + if (is_6ghz_op_class(hapd->iconf->op_class)) { + if (!(sta->flags & WLAN_STA_HE)) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Station does not support mandatory HE PHY - reject association"); + return WLAN_STATUS_DENIED_HE_NOT_SUPPORTED; + } + resp = copy_sta_he_6ghz_capab(hapd, sta, + elems.he_6ghz_band_cap); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + } } #endif /* CONFIG_IEEE80211AX */ @@ -3216,6 +3307,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, if (hapd->conf->wps_state && elems.wps_ie) { wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association " "Request - assume WPS is used"); + if (check_sa_query(hapd, sta, reassoc)) + return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; sta->flags |= WLAN_STA_WPS; wpabuf_free(sta->wps_ie); sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, @@ -3245,7 +3338,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, } if (hapd->conf->wpa && wpa_ie) { - int res; + enum wpa_validate_result res; + wpa_ie -= 2; wpa_ie_len += 2; if (sta->wpa_sm == NULL) @@ -3268,27 +3362,9 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, resp = wpa_res_to_status_code(res); if (resp != WLAN_STATUS_SUCCESS) return resp; - if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == - (WLAN_STA_ASSOC | WLAN_STA_MFP) && - !sta->sa_query_timed_out && - sta->sa_query_count > 0) - ap_check_sa_query_timeout(hapd, sta); - if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == - (WLAN_STA_ASSOC | WLAN_STA_MFP) && - !sta->sa_query_timed_out && - (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) { - /* - * STA has already been associated with MFP and SA - * Query timeout has not been reached. Reject the - * association attempt temporarily and start SA Query, - * if one is not pending. - */ - - if (sta->sa_query_count == 0) - ap_sta_start_sa_query(hapd, sta); + if (check_sa_query(hapd, sta, reassoc)) return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; - } if (wpa_auth_uses_mfp(sta->wpa_sm)) sta->flags |= WLAN_STA_MFP; @@ -3341,7 +3417,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, if (hapd->conf->sae_pwe == 2 && sta->auth_alg == WLAN_AUTH_SAE && - sta->sae && sta->sae->tmp && !sta->sae->tmp->h2e && + sta->sae && !sta->sae->h2e && elems.rsnxe && elems.rsnxe_len >= 1 && (elems.rsnxe[0] & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { wpa_printf(MSG_INFO, "SAE: " MACSTR @@ -3366,7 +3442,8 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, dpp_pfs_free(sta->dpp_pfs); sta->dpp_pfs = NULL; - if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) && + if (DPP_VERSION > 1 && + (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) && hapd->conf->dpp_netaccesskey && sta->wpa_sm && wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP && elems.owe_dh) { @@ -3393,7 +3470,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, pfs_fail: #endif /* CONFIG_DPP2 */ -#ifdef CONFIG_IEEE80211N if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) && wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) { hostapd_logger(hapd, sta->addr, @@ -3403,7 +3479,6 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, "association"); return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_HS20 } else if (hapd->conf->osen) { if (elems.osen == NULL) { @@ -3490,6 +3565,7 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, struct wpa_channel_info ci; int tx_chanwidth; int tx_seg1_idx; + enum oci_verify_result res; if (hostapd_drv_channel_info(hapd, &ci) != 0) { wpa_printf(MSG_WARNING, @@ -3503,9 +3579,20 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, &tx_seg1_idx) < 0) return WLAN_STATUS_UNSPECIFIED_FAILURE; - if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "FILS: %s", ocv_errorstr); + res = ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, + tx_chanwidth, tx_seg1_idx); + if (wpa_auth_uses_ocv(sta->wpa_sm) == 2 && + res == OCI_NOT_FOUND) { + /* Work around misbehaving STAs */ + wpa_printf(MSG_INFO, + "FILS: Disable OCV with a STA that does not send OCI"); + wpa_auth_set_ocv(sta->wpa_sm, 0); + } else if (res != OCI_SUCCESS) { + wpa_printf(MSG_WARNING, "FILS: OCV failed: %s", + ocv_errorstr); + wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr=" + MACSTR " frame=fils-reassoc-req error=%s", + MAC2STR(sta->addr), ocv_errorstr); return WLAN_STATUS_UNSPECIFIED_FAILURE; } } @@ -3604,10 +3691,8 @@ static int add_associated_sta(struct hostapd_data *hapd, sta->ft_over_ds = 0; } -#ifdef CONFIG_IEEE80211N if (sta->flags & WLAN_STA_HT) hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap); -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC if (sta->flags & WLAN_STA_VHT) hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap); @@ -3631,6 +3716,7 @@ static int add_associated_sta(struct hostapd_data *hapd, sta->flags & WLAN_STA_VHT ? &vht_cap : NULL, sta->flags & WLAN_STA_HE ? &he_cap : NULL, sta->flags & WLAN_STA_HE ? sta->he_capab_len : 0, + sta->he_6ghz_capab, sta->flags | WLAN_STA_ASSOC, sta->qosinfo, sta->vht_opmode, sta->p2p_ie ? 1 : 0, set)) { @@ -3655,7 +3741,8 @@ static int add_associated_sta(struct hostapd_data *hapd, static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, const u8 *addr, u16 status_code, int reassoc, - const u8 *ies, size_t ies_len, int rssi) + const u8 *ies, size_t ies_len, int rssi, + int omit_rsnxe) { int send_len; u8 *buf; @@ -3725,7 +3812,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, * Transition Information, RSN, [RIC Response] */ p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p, buf + buflen - p, - sta->auth_alg, ies, ies_len); + sta->auth_alg, ies, ies_len, + omit_rsnxe); if (!p) { wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs"); @@ -3755,10 +3843,8 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) p = hostapd_eid_assoc_comeback_time(hapd, sta, p); -#ifdef CONFIG_IEEE80211N p = hostapd_eid_ht_capabilities(hapd, p); p = hostapd_eid_ht_operation(hapd, p); -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac && @@ -3785,11 +3871,12 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, #endif /* CONFIG_IEEE80211AC */ #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax) { + if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP); p = hostapd_eid_he_operation(hapd, p); p = hostapd_eid_spatial_reuse(hapd, p); p = hostapd_eid_he_mu_edca_parameter_set(hapd, p); + p = hostapd_eid_he_6ghz_band_cap(hapd, p); } #endif /* CONFIG_IEEE80211AX */ @@ -3806,12 +3893,29 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, } #endif /* CONFIG_FST */ - p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p); +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->rsnxe_override_ft && + buf + buflen - p >= + (long int) wpabuf_len(hapd->conf->rsnxe_override_ft) && + sta && sta->auth_alg == WLAN_AUTH_FT) { + wpa_printf(MSG_DEBUG, "TESTING: RSNXE FT override"); + os_memcpy(p, wpabuf_head(hapd->conf->rsnxe_override_ft), + wpabuf_len(hapd->conf->rsnxe_override_ft)); + p += wpabuf_len(hapd->conf->rsnxe_override_ft); + goto rsnxe_done; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (!omit_rsnxe) + p = hostapd_eid_rsnxe(hapd, p, buf + buflen - p); +#ifdef CONFIG_TESTING_OPTIONS +rsnxe_done: +#endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_OWE if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS && - wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE) { + wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE && + !wpa_auth_sta_get_pmksa(sta->wpa_sm)) { struct wpabuf *pub; pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); @@ -3832,7 +3936,7 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, #endif /* CONFIG_OWE */ #ifdef CONFIG_DPP2 - if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) && + if (DPP_VERSION > 1 && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) && sta && sta->dpp_pfs && status_code == WLAN_STATUS_SUCCESS && wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP) { os_memcpy(p, wpabuf_head(sta->dpp_pfs->ie), @@ -4024,7 +4128,7 @@ void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta) reply_res = send_assoc_resp(hapd, sta, sta->addr, WLAN_STATUS_SUCCESS, sta->fils_pending_assoc_is_reassoc, sta->fils_pending_assoc_req, - sta->fils_pending_assoc_req_len, 0); + sta->fils_pending_assoc_req_len, 0, 0); os_free(sta->fils_pending_assoc_req); sta->fils_pending_assoc_req = NULL; sta->fils_pending_assoc_req_len = 0; @@ -4064,7 +4168,8 @@ static void handle_assoc(struct hostapd_data *hapd, int reassoc, int rssi) { u16 capab_info, listen_interval, seq_ctrl, fc; - u16 resp = WLAN_STATUS_SUCCESS, reply_res; + int resp = WLAN_STATUS_SUCCESS; + u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE; const u8 *pos; int left, i; struct sta_info *sta; @@ -4072,6 +4177,7 @@ static void handle_assoc(struct hostapd_data *hapd, #ifdef CONFIG_FILS int delay_assoc = 0; #endif /* CONFIG_FILS */ + int omit_rsnxe = 0; if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) : sizeof(mgmt->u.assoc_req))) { @@ -4284,6 +4390,7 @@ static void handle_assoc(struct hostapd_data *hapd, resp = check_assoc_ies(hapd, sta, pos, left, reassoc); if (resp != WLAN_STATUS_SUCCESS) goto fail; + omit_rsnxe = !get_ie(pos, left, WLAN_EID_RSNX); if (hostapd_get_aid(hapd, sta) < 0) { hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, @@ -4336,9 +4443,7 @@ static void handle_assoc(struct hostapd_data *hapd, ieee802_11_set_beacons(hapd->iface); } -#ifdef CONFIG_IEEE80211N update_ht_state(hapd, sta); -#endif /* CONFIG_IEEE80211N */ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, @@ -4443,12 +4548,13 @@ static void handle_assoc(struct hostapd_data *hapd, } #endif /* CONFIG_FILS */ - reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos, - left, rssi); + if (resp >= 0) + reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, + pos, left, rssi, omit_rsnxe); os_free(tmp); /* - * Remove the station in case tranmission of a success response fails + * Remove the station in case transmission of a success response fails * (the STA was added associated to the driver) or if the station was * previously added unassociated. */ @@ -4485,6 +4591,7 @@ static void handle_disassoc(struct hostapd_data *hapd, ap_sta_set_authorized(hapd, sta, 0); sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); + hostapd_set_sta_flags(hapd, sta); wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated"); @@ -4551,6 +4658,7 @@ static void handle_deauth(struct hostapd_data *hapd, sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); + hostapd_set_sta_flags(hapd, sta); wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "deauthenticated"); @@ -4682,14 +4790,12 @@ static int handle_action(struct hostapd_data *hapd, #endif /* CONFIG_FST */ case WLAN_ACTION_PUBLIC: case WLAN_ACTION_PROTECTED_DUAL: -#ifdef CONFIG_IEEE80211N if (len >= IEEE80211_HDRLEN + 2 && mgmt->u.action.u.public_action.action == WLAN_PA_20_40_BSS_COEX) { hostapd_2040_coex_action(hapd, mgmt, len); return 1; } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_DPP if (len >= IEEE80211_HDRLEN + 6 && mgmt->u.action.u.vs_public_action.action == @@ -4849,6 +4955,11 @@ int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, return 0; } + if (hapd->iface->state != HAPD_IFACE_ENABLED) { + wpa_printf(MSG_DEBUG, "MGMT: Ignore management frame while interface is not enabled (SA=" MACSTR " DA=" MACSTR " subtype=%u)", + MAC2STR(mgmt->sa), MAC2STR(mgmt->da), stype); + return 1; + } if (stype == WLAN_FC_STYPE_PROBE_REQ) { handle_probe_req(hapd, mgmt, len, ssi_signal); @@ -4967,6 +5078,7 @@ static void hostapd_set_wds_encryption(struct hostapd_data *hapd, struct sta_info *sta, char *ifname_wds) { +#ifdef CONFIG_WEP int i; struct hostapd_ssid *ssid = &hapd->conf->ssid; @@ -4987,6 +5099,7 @@ static void hostapd_set_wds_encryption(struct hostapd_data *hapd, break; } } +#endif /* CONFIG_WEP */ } @@ -5487,4 +5600,57 @@ void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, } +u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid) +{ + u8 bw, chan1, chan2 = 0; + int freq1; + + if (!hapd->cs_freq_params.channel || + (!hapd->cs_freq_params.vht_enabled && + !hapd->cs_freq_params.he_enabled)) + return eid; + + /* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */ + switch (hapd->cs_freq_params.bandwidth) { + case 40: + bw = 0; + break; + case 80: + /* check if it's 80+80 */ + if (!hapd->cs_freq_params.center_freq2) + bw = 1; + else + bw = 3; + break; + case 160: + bw = 2; + break; + default: + /* not valid VHT bandwidth or not in CSA */ + return eid; + } + + freq1 = hapd->cs_freq_params.center_freq1 ? + hapd->cs_freq_params.center_freq1 : + hapd->cs_freq_params.freq; + if (ieee80211_freq_to_chan(freq1, &chan1) != + HOSTAPD_MODE_IEEE80211A) + return eid; + + if (hapd->cs_freq_params.center_freq2 && + ieee80211_freq_to_chan(hapd->cs_freq_params.center_freq2, + &chan2) != HOSTAPD_MODE_IEEE80211A) + return eid; + + *eid++ = WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER; + *eid++ = 5; /* Length of Channel Switch Wrapper */ + *eid++ = WLAN_EID_VHT_WIDE_BW_CHSWITCH; + *eid++ = 3; /* Length of Wide Bandwidth Channel Switch element */ + *eid++ = bw; /* New Channel Width */ + *eid++ = chan1; /* New Channel Center Frequency Segment 0 */ + *eid++ = chan2; /* New Channel Center Frequency Segment 1 */ + + return eid; +} + #endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index 0a035c564..ea8c60846 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -53,7 +53,6 @@ u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid, size_t len); u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid); -u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts); u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid); @@ -64,6 +63,7 @@ u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid, u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid); u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid); int hostapd_ht_operation_update(struct hostapd_iface *iface); void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, @@ -96,6 +96,10 @@ u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta, u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta, enum ieee80211_op_mode opmode, const u8 *he_capab, size_t he_capab_len); +u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *he_6ghz_capab); +int hostapd_get_he_twt_responder(struct hostapd_data *hapd, + enum ieee80211_op_mode mode); void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, const u8 *buf, size_t len, int ack); void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst, @@ -182,6 +186,9 @@ void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd); u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, size_t len); +size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd); +u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len); + int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth, int ap_seg1_idx, int *bandwidth, int *seg1_idx); diff --git a/src/ap/ieee802_11_he.c b/src/ap/ieee802_11_he.c index 3e22ce412..dad68ac43 100644 --- a/src/ap/ieee802_11_he.c +++ b/src/ap/ieee802_11_he.c @@ -192,9 +192,12 @@ u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid) params |= (hapd->iface->conf->he_op.he_rts_threshold << HE_OPERATION_RTS_THRESHOLD_OFFSET); - if (hapd->iface->conf->he_op.he_bss_color) - params |= (hapd->iface->conf->he_op.he_bss_color << - HE_OPERATION_BSS_COLOR_OFFSET); + if (hapd->iface->conf->he_op.he_bss_color_disabled) + params |= HE_OPERATION_BSS_COLOR_DISABLED; + if (hapd->iface->conf->he_op.he_bss_color_partial) + params |= HE_OPERATION_BSS_COLOR_PARTIAL; + params |= hapd->iface->conf->he_op.he_bss_color << + HE_OPERATION_BSS_COLOR_OFFSET; /* HE minimum required basic MCS and NSS for STAs */ oper->he_mcs_nss_set = @@ -308,6 +311,35 @@ u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid) } +u8 * hostapd_eid_he_6ghz_band_cap(struct hostapd_data *hapd, u8 *eid) +{ + struct hostapd_hw_modes *mode = hapd->iface->current_mode; + struct he_capabilities *he_cap; + struct ieee80211_he_6ghz_band_cap *cap; + u16 capab; + u8 *pos; + + if (!mode || !is_6ghz_op_class(hapd->iconf->op_class) || + !is_6ghz_freq(hapd->iface->freq)) + return eid; + + he_cap = &mode->he_capab[IEEE80211_MODE_AP]; + capab = he_cap->he_6ghz_capa; + capab |= HE_6GHZ_BAND_CAP_SMPS_DISABLED; + + pos = eid; + *pos++ = WLAN_EID_EXTENSION; + *pos++ = 1 + sizeof(*cap); + *pos++ = WLAN_EID_EXT_HE_6GHZ_BAND_CAP; + + cap = (struct ieee80211_he_6ghz_band_cap *) pos; + cap->capab = host_to_le16(capab); + pos += sizeof(*cap); + + return pos; +} + + void hostapd_get_he_capab(struct hostapd_data *hapd, const struct ieee80211_he_capabilities *he_cap, struct ieee80211_he_capabilities *neg_he_cap, @@ -387,6 +419,7 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta, size_t he_capab_len) { if (!he_capab || !hapd->iconf->ieee80211ax || + hapd->conf->disable_11ax || !check_valid_he_mcs(hapd, he_capab, opmode) || ieee80211_invalid_he_cap_size(he_capab, he_capab_len) || he_capab_len > sizeof(struct ieee80211_he_capabilities)) { @@ -410,3 +443,45 @@ u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta, return WLAN_STATUS_SUCCESS; } + + +u16 copy_sta_he_6ghz_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *he_6ghz_capab) +{ + if (!he_6ghz_capab || !hapd->iconf->ieee80211ax || + hapd->conf->disable_11ax || + !is_6ghz_op_class(hapd->iconf->op_class)) { + sta->flags &= ~WLAN_STA_6GHZ; + os_free(sta->he_6ghz_capab); + sta->he_6ghz_capab = NULL; + return WLAN_STATUS_SUCCESS; + } + + if (!sta->he_6ghz_capab) { + sta->he_6ghz_capab = + os_zalloc(sizeof(struct ieee80211_he_6ghz_band_cap)); + if (!sta->he_6ghz_capab) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + sta->flags |= WLAN_STA_6GHZ; + os_memcpy(sta->he_6ghz_capab, he_6ghz_capab, + sizeof(struct ieee80211_he_6ghz_band_cap)); + + return WLAN_STATUS_SUCCESS; +} + + +int hostapd_get_he_twt_responder(struct hostapd_data *hapd, + enum ieee80211_op_mode mode) +{ + u8 *mac_cap; + + if (!hapd->iface->current_mode || + !hapd->iface->current_mode->he_capab[mode].he_supported) + return 0; + + mac_cap = hapd->iface->current_mode->he_capab[mode].mac_cap; + + return !!(mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER); +} diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c index 6db93658c..59ecbdce7 100644 --- a/src/ap/ieee802_11_ht.c +++ b/src/ap/ieee802_11_ht.c @@ -109,33 +109,9 @@ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) } -u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid) -{ - u8 sec_ch; - - if (!hapd->cs_freq_params.channel || - !hapd->cs_freq_params.sec_channel_offset || - is_6ghz_op_class(hapd->iconf->op_class)) - return eid; - - if (hapd->cs_freq_params.sec_channel_offset == -1) - sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW; - else if (hapd->cs_freq_params.sec_channel_offset == 1) - sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE; - else - return eid; - - *eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; - *eid++ = 1; - *eid++ = sec_ch; - - return eid; -} - - /* op_mode -Set to 0 (HT pure) under the followign conditions +Set to 0 (HT pure) under the following conditions - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or - all STAs in the BSS are 20 MHz HT in 20 MHz BSS Set to 1 (HT non-member protection) if there may be non-HT STAs diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c index a947bd9d1..17003d506 100644 --- a/src/ap/ieee802_11_shared.c +++ b/src/ap/ieee802_11_shared.c @@ -11,6 +11,7 @@ #include "utils/common.h" #include "common/ieee802_11_defs.h" #include "common/ocv.h" +#include "common/wpa_ctrl.h" #include "hostapd.h" #include "sta_info.h" #include "ap_config.h" @@ -72,6 +73,16 @@ void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, "Failed to get channel info for OCI element in SA Query Request"); return; } +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->oci_freq_override_saquery_req) { + wpa_printf(MSG_INFO, + "TEST: Override OCI frequency %d -> %u MHz", + ci.frequency, + hapd->conf->oci_freq_override_saquery_req); + ci.frequency = + hapd->conf->oci_freq_override_saquery_req; + } +#endif /* CONFIG_TESTING_OPTIONS */ oci_ie_len = OCV_OCI_EXTENDED_LEN; oci_ie = os_zalloc(oci_ie_len); @@ -151,6 +162,16 @@ static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd, "Failed to get channel info for OCI element in SA Query Response"); return; } +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->oci_freq_override_saquery_resp) { + wpa_printf(MSG_INFO, + "TEST: Override OCI frequency %d -> %u MHz", + ci.frequency, + hapd->conf->oci_freq_override_saquery_resp); + ci.frequency = + hapd->conf->oci_freq_override_saquery_resp; + } +#endif /* CONFIG_TESTING_OPTIONS */ oci_ie_len = OCV_OCI_EXTENDED_LEN; oci_ie = os_zalloc(oci_ie_len); @@ -254,14 +275,21 @@ void ieee802_11_sa_query_action(struct hostapd_data *hapd, return; if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "%s", ocv_errorstr); + tx_chanwidth, tx_seg1_idx) != + OCI_SUCCESS) { + wpa_msg(hapd->msg_ctx, MSG_INFO, OCV_FAILURE "addr=" + MACSTR " frame=saquery%s error=%s", + MAC2STR(sa), + action_type == WLAN_SA_QUERY_REQUEST ? + "req" : "resp", ocv_errorstr); return; } } #endif /* CONFIG_OCV */ if (action_type == WLAN_SA_QUERY_REQUEST) { + if (sta) + sta->post_csa_sa_query = 0; ieee802_11_send_sa_query_resp(hapd, sa, trans_id); return; } @@ -377,6 +405,11 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) *pos |= 0x01; #endif /* CONFIG_FILS */ +#ifdef CONFIG_IEEE80211AX + if (hapd->iconf->ieee80211ax && + hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP)) + *pos |= 0x40; /* Bit 78 - TWT responder */ +#endif /* CONFIG_IEEE80211AX */ break; case 10: /* Bits 80-87 */ #ifdef CONFIG_SAE @@ -392,6 +425,16 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) * Identifiers Used Exclusively */ } #endif /* CONFIG_SAE */ + if (hapd->conf->beacon_prot) + *pos |= 0x10; /* Bit 84 - Beacon Protection Enabled */ + break; + case 11: /* Bits 88-95 */ +#ifdef CONFIG_SAE_PK + if (hapd->conf->wpa && + wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && + hostapd_sae_pk_exclusively(hapd->conf)) + *pos |= 0x01; /* Bit 88 - SAE PK Exclusively */ +#endif /* CONFIG_SAE_PK */ break; } } @@ -440,12 +483,25 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10) len = 10; #endif /* CONFIG_FILS */ +#ifdef CONFIG_IEEE80211AX + if (len < 10 && hapd->iconf->ieee80211ax && + hostapd_get_he_twt_responder(hapd, IEEE80211_MODE_AP)) + len = 10; +#endif /* CONFIG_IEEE80211AX */ #ifdef CONFIG_SAE if (len < 11 && hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && hostapd_sae_pw_id_in_use(hapd->conf)) len = 11; #endif /* CONFIG_SAE */ + if (len < 11 && hapd->conf->beacon_prot) + len = 11; +#ifdef CONFIG_SAE_PK + if (len < 12 && hapd->conf->wpa && + wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && + hostapd_sae_pk_exclusively(hapd->conf)) + len = 12; +#endif /* CONFIG_SAE_PK */ if (len < hapd->iface->extended_capa_len) len = hapd->iface->extended_capa_len; if (len == 0) @@ -860,6 +916,35 @@ u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, } +size_t hostapd_eid_dpp_cc_len(struct hostapd_data *hapd) +{ +#ifdef CONFIG_DPP2 + if (hapd->conf->dpp_configurator_connectivity) + return 6; +#endif /* CONFIG_DPP2 */ + return 0; +} + + +u8 * hostapd_eid_dpp_cc(struct hostapd_data *hapd, u8 *eid, size_t len) +{ + u8 *pos = eid; + +#ifdef CONFIG_DPP2 + if (!hapd->conf->dpp_configurator_connectivity || len < 6) + return pos; + + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 4; + WPA_PUT_BE24(pos, OUI_WFA); + pos += 3; + *pos++ = DPP_CC_OUI_TYPE; +#endif /* CONFIG_DPP2 */ + + return pos; +} + + void ap_copy_sta_supp_op_classes(struct sta_info *sta, const u8 *supp_op_classes, size_t supp_op_classes_len) @@ -1011,11 +1096,16 @@ int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth, u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len) { u8 *pos = eid; + bool sae_pk = false; + +#ifdef CONFIG_SAE_PK + sae_pk = hostapd_sae_pk_in_use(hapd->conf); +#endif /* CONFIG_SAE_PK */ if (!(hapd->conf->wpa & WPA_PROTO_RSN) || !wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) || (hapd->conf->sae_pwe != 1 && hapd->conf->sae_pwe != 2 && - !hostapd_sae_pw_id_in_use(hapd->conf)) || + !hostapd_sae_pw_id_in_use(hapd->conf) && !sae_pk) || hapd->conf->sae_pwe == 3 || len < 3) return pos; @@ -1024,7 +1114,12 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len) *pos++ = 1; /* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is * used for now */ - *pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E); + *pos = BIT(WLAN_RSNX_CAPAB_SAE_H2E); +#ifdef CONFIG_SAE_PK + if (sae_pk) + *pos |= BIT(WLAN_RSNX_CAPAB_SAE_PK); +#endif /* CONFIG_SAE_PK */ + pos++; return pos; } diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c index f50f142dc..c925bf12c 100644 --- a/src/ap/ieee802_11_vht.c +++ b/src/ap/ieee802_11_vht.c @@ -167,59 +167,6 @@ static int check_valid_vht_mcs(struct hostapd_hw_modes *mode, } -u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid) -{ - u8 bw, chan1, chan2 = 0; - int freq1; - - if (!hapd->cs_freq_params.channel || - !hapd->cs_freq_params.vht_enabled) - return eid; - - /* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */ - switch (hapd->cs_freq_params.bandwidth) { - case 40: - bw = 0; - break; - case 80: - /* check if it's 80+80 */ - if (!hapd->cs_freq_params.center_freq2) - bw = 1; - else - bw = 3; - break; - case 160: - bw = 2; - break; - default: - /* not valid VHT bandwidth or not in CSA */ - return eid; - } - - freq1 = hapd->cs_freq_params.center_freq1 ? - hapd->cs_freq_params.center_freq1 : - hapd->cs_freq_params.freq; - if (ieee80211_freq_to_chan(freq1, &chan1) != - HOSTAPD_MODE_IEEE80211A) - return eid; - - if (hapd->cs_freq_params.center_freq2 && - ieee80211_freq_to_chan(hapd->cs_freq_params.center_freq2, - &chan2) != HOSTAPD_MODE_IEEE80211A) - return eid; - - *eid++ = WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER; - *eid++ = 5; /* Length of Channel Switch Wrapper */ - *eid++ = WLAN_EID_VHT_WIDE_BW_CHSWITCH; - *eid++ = 3; /* Length of Wide Bandwidth Channel Switch element */ - *eid++ = bw; /* New Channel Width */ - *eid++ = chan1; /* New Channel Center Frequency Segment 0 */ - *eid++ = chan2; /* New Channel Center Frequency Segment 1 */ - - return eid; -} - - u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid) { struct hostapd_iface *iface = hapd->iface; @@ -425,7 +372,9 @@ u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid) { u8 *pos = eid; - if (!hapd->iface->current_mode) + /* Vendor VHT is applicable only to 2.4 GHz */ + if (!hapd->iface->current_mode || + hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) return eid; *pos++ = WLAN_EID_VENDOR_SPECIFIC; diff --git a/src/ap/ieee802_1x.c b/src/ap/ieee802_1x.c index 001b26109..ee095f618 100644 --- a/src/ap/ieee802_1x.c +++ b/src/ap/ieee802_1x.c @@ -137,6 +137,7 @@ void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, } +#ifdef CONFIG_WEP #ifndef CONFIG_FIPS #ifndef CONFIG_NO_RC4 @@ -297,6 +298,7 @@ static void ieee802_1x_tx_key(struct hostapd_data *hapd, struct sta_info *sta) #endif /* CONFIG_NO_RC4 */ #endif /* CONFIG_FIPS */ +#endif /* CONFIG_WEP */ const char *radius_mode_txt(struct hostapd_data *hapd) @@ -876,7 +878,7 @@ static void handle_eap_response(struct hostapd_data *hapd, wpabuf_free(sm->eap_if->eapRespData); sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len); - sm->eapolEap = TRUE; + sm->eapolEap = true; } @@ -907,7 +909,7 @@ static void handle_eap_initiate(struct hostapd_data *hapd, wpabuf_free(sm->eap_if->eapRespData); sm->eap_if->eapRespData = wpabuf_alloc_copy(eap, len); - sm->eapolEap = TRUE; + sm->eapolEap = true; #endif /* CONFIG_ERP */ } @@ -1138,7 +1140,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, } #endif /* CONFIG_WPS */ - sta->eapol_sm->eap_if->portEnabled = TRUE; + sta->eapol_sm->eap_if->portEnabled = true; } /* since we support version 1, we can ignore version field and proceed @@ -1165,7 +1167,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, "cached PMKSA available - ignore it since STA sent EAPOL-Start"); wpa_auth_sta_clear_pmksa(sta->wpa_sm, pmksa); } - sta->eapol_sm->eapolStart = TRUE; + sta->eapol_sm->eapolStart = true; sta->eapol_sm->dot1xAuthEapolStartFramesRx++; eap_server_clear_identity(sta->eapol_sm->eap); wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH_EAPOL); @@ -1178,7 +1180,7 @@ void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; accounting_sta_stop(hapd, sta); - sta->eapol_sm->eapolLogoff = TRUE; + sta->eapol_sm->eapolLogoff = true; sta->eapol_sm->dot1xAuthEapolLogoffFramesRx++; eap_server_clear_identity(sta->eapol_sm->eap); break; @@ -1295,7 +1297,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) } #endif /* CONFIG_WPS */ - sta->eapol_sm->eap_if->portEnabled = TRUE; + sta->eapol_sm->eap_if->portEnabled = true; #ifdef CONFIG_IEEE80211R_AP if (sta->auth_alg == WLAN_AUTH_FT) { @@ -1304,13 +1306,13 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) "PMK from FT - skip IEEE 802.1X/EAP"); /* Setup EAPOL state machines to already authenticated state * because of existing FT information from R0KH. */ - sta->eapol_sm->keyRun = TRUE; - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; + sta->eapol_sm->keyRun = true; + sta->eapol_sm->eap_if->eapKeyAvailable = true; sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; - sta->eapol_sm->authSuccess = TRUE; - sta->eapol_sm->authFail = FALSE; - sta->eapol_sm->portValid = TRUE; + sta->eapol_sm->authSuccess = true; + sta->eapol_sm->authFail = false; + sta->eapol_sm->portValid = true; if (sta->eapol_sm->eap) eap_sm_notify_cached(sta->eapol_sm->eap); ap_sta_bind_vlan(hapd, sta); @@ -1327,13 +1329,13 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) "PMK from FILS - skip IEEE 802.1X/EAP"); /* Setup EAPOL state machines to already authenticated state * because of existing FILS information. */ - sta->eapol_sm->keyRun = TRUE; - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; + sta->eapol_sm->keyRun = true; + sta->eapol_sm->eap_if->eapKeyAvailable = true; sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; - sta->eapol_sm->authSuccess = TRUE; - sta->eapol_sm->authFail = FALSE; - sta->eapol_sm->portValid = TRUE; + sta->eapol_sm->authSuccess = true; + sta->eapol_sm->authFail = false; + sta->eapol_sm->portValid = true; if (sta->eapol_sm->eap) eap_sm_notify_cached(sta->eapol_sm->eap); wpa_auth_set_ptk_rekey_timer(sta->wpa_sm); @@ -1348,12 +1350,12 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) "PMK from PMKSA cache - skip IEEE 802.1X/EAP"); /* Setup EAPOL state machines to already authenticated state * because of existing PMKSA information in the cache. */ - sta->eapol_sm->keyRun = TRUE; - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; + sta->eapol_sm->keyRun = true; + sta->eapol_sm->eap_if->eapKeyAvailable = true; sta->eapol_sm->auth_pae_state = AUTH_PAE_AUTHENTICATING; sta->eapol_sm->be_auth_state = BE_AUTH_SUCCESS; - sta->eapol_sm->authSuccess = TRUE; - sta->eapol_sm->authFail = FALSE; + sta->eapol_sm->authSuccess = true; + sta->eapol_sm->authFail = false; if (sta->eapol_sm->eap) eap_sm_notify_cached(sta->eapol_sm->eap); pmksa_cache_to_eapol_data(hapd, pmksa, sta->eapol_sm); @@ -1365,7 +1367,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta) * re-authentication without having to wait for the * Supplicant to send EAPOL-Start. */ - sta->eapol_sm->reAuthenticate = TRUE; + sta->eapol_sm->reAuthenticate = true; } eapol_auth_step(sta->eapol_sm); } @@ -1413,7 +1415,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, if (!sm || !sm->last_recv_radius) { if (sm) - sm->eap_if->aaaEapNoReq = TRUE; + sm->eap_if->aaaEapNoReq = true; return; } @@ -1427,7 +1429,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_WARNING, "could not extract EAP-Message from RADIUS message"); - sm->eap_if->aaaEapNoReq = TRUE; + sm->eap_if->aaaEapNoReq = true; return; } @@ -1436,7 +1438,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, HOSTAPD_LEVEL_WARNING, "too short EAP packet received from authentication server"); wpabuf_free(eap); - sm->eap_if->aaaEapNoReq = TRUE; + sm->eap_if->aaaEapNoReq = true; return; } @@ -1471,7 +1473,7 @@ static void ieee802_1x_decapsulate_radius(struct hostapd_data *hapd, "decapsulated EAP packet (code=%d id=%d len=%d) from RADIUS server: %s", hdr->code, hdr->identifier, be_to_host16(hdr->length), buf); - sm->eap_if->aaaEapReq = TRUE; + sm->eap_if->aaaEapReq = true; wpabuf_free(sm->eap_if->aaaEapReqData); sm->eap_if->aaaEapReqData = eap; @@ -1510,7 +1512,7 @@ static void ieee802_1x_get_keys(struct hostapd_data *hapd, os_memcpy(sm->eap_if->aaaEapKeyData + keys->recv_len, keys->send, keys->send_len); sm->eap_if->aaaEapKeyDataLen = len; - sm->eap_if->aaaEapKeyAvailable = TRUE; + sm->eap_if->aaaEapKeyAvailable = true; } } else { wpa_printf(MSG_DEBUG, @@ -1878,7 +1880,7 @@ static int ieee802_1x_update_vlan(struct radius_msg *msg, if (vlan_desc.notempty && !hostapd_vlan_valid(hapd->conf->vlan, &vlan_desc)) { - sta->eapol_sm->authFail = TRUE; + sta->eapol_sm->authFail = true; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO, "Invalid VLAN %d%s received from RADIUS server", @@ -1891,7 +1893,7 @@ static int ieee802_1x_update_vlan(struct radius_msg *msg, if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED && !vlan_desc.notempty) { - sta->eapol_sm->authFail = TRUE; + sta->eapol_sm->authFail = true; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, HOSTAPD_LEVEL_INFO, "authentication server did not include required VLAN ID in Access-Accept"); @@ -2017,7 +2019,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, else ap_sta_no_session_timeout(hapd, sta); - sm->eap_if->aaaSuccess = TRUE; + sm->eap_if->aaaSuccess = true; override_eapReq = 1; ieee802_1x_get_keys(hapd, sta, msg, req, shared_secret, shared_secret_len); @@ -2029,7 +2031,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, (int) session_timeout : -1); break; case RADIUS_CODE_ACCESS_REJECT: - sm->eap_if->aaaFail = TRUE; + sm->eap_if->aaaFail = true; override_eapReq = 1; if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_WLAN_REASON_CODE, &reason_code) == 0) { @@ -2040,7 +2042,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, } break; case RADIUS_CODE_ACCESS_CHALLENGE: - sm->eap_if->aaaEapReq = TRUE; + sm->eap_if->aaaEapReq = true; if (session_timeout_set) { /* RFC 2869, Ch. 2.3.2; RFC 3580, Ch. 3.17 */ sm->eap_if->aaaMethodTimeout = session_timeout; @@ -2061,7 +2063,7 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req, ieee802_1x_decapsulate_radius(hapd, sta); if (override_eapReq) - sm->eap_if->aaaEapReq = FALSE; + sm->eap_if->aaaEapReq = false; #ifdef CONFIG_FILS #ifdef NEED_AP_MLME @@ -2107,13 +2109,15 @@ void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta) wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "EAP Timeout, STA " MACSTR, MAC2STR(sta->addr)); - sm->eap_if->portEnabled = FALSE; + sm->eap_if->portEnabled = false; ap_sta_disconnect(hapd, sta, sta->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); } } +#ifdef CONFIG_WEP + static int ieee802_1x_rekey_broadcast(struct hostapd_data *hapd) { struct eapol_authenticator *eapol = hapd->eapol_auth; @@ -2144,7 +2148,7 @@ static int ieee802_1x_sta_key_available(struct hostapd_data *hapd, struct sta_info *sta, void *ctx) { if (sta->eapol_sm) { - sta->eapol_sm->eap_if->eapKeyAvailable = TRUE; + sta->eapol_sm->eap_if->eapKeyAvailable = true; eapol_auth_step(sta->eapol_sm); } return 0; @@ -2198,6 +2202,8 @@ static void ieee802_1x_rekey(void *eloop_ctx, void *timeout_ctx) } } +#endif /* CONFIG_WEP */ + static void ieee802_1x_eapol_send(void *ctx, void *sta_ctx, u8 type, const u8 *data, size_t datalen) @@ -2361,6 +2367,7 @@ static void _ieee802_1x_abort_auth(void *ctx, void *sta_ctx) } +#ifdef CONFIG_WEP static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx) { #ifndef CONFIG_FIPS @@ -2372,6 +2379,7 @@ static void _ieee802_1x_tx_key(void *ctx, void *sta_ctx) #endif /* CONFIG_NO_RC4 */ #endif /* CONFIG_FIPS */ } +#endif /* CONFIG_WEP */ static void ieee802_1x_eapol_event(void *ctx, void *sta_ctx, @@ -2422,7 +2430,6 @@ static int ieee802_1x_erp_add_key(void *ctx, struct eap_server_erp_key *erp) int ieee802_1x_init(struct hostapd_data *hapd) { - int i; struct eapol_auth_config conf; struct eapol_auth_cb cb; @@ -2433,7 +2440,9 @@ int ieee802_1x_init(struct hostapd_data *hapd) conf.ctx = hapd; conf.eap_reauth_period = hapd->conf->eap_reauth_period; conf.wpa = hapd->conf->wpa; +#ifdef CONFIG_WEP conf.individual_wep_key_len = hapd->conf->individual_wep_key_len; +#endif /* CONFIG_WEP */ conf.eap_req_id_text = hapd->conf->eap_req_id_text; conf.eap_req_id_text_len = hapd->conf->eap_req_id_text_len; conf.erp_send_reauth_start = hapd->conf->erp_send_reauth_start; @@ -2448,7 +2457,9 @@ int ieee802_1x_init(struct hostapd_data *hapd) cb.logger = ieee802_1x_logger; cb.set_port_authorized = ieee802_1x_set_port_authorized; cb.abort_auth = _ieee802_1x_abort_auth; +#ifdef CONFIG_WEP cb.tx_key = _ieee802_1x_tx_key; +#endif /* CONFIG_WEP */ cb.eapol_event = ieee802_1x_eapol_event; #ifdef CONFIG_ERP cb.erp_get_key = ieee802_1x_erp_get_key; @@ -2469,17 +2480,21 @@ int ieee802_1x_init(struct hostapd_data *hapd) return -1; #endif /* CONFIG_NO_RADIUS */ +#ifdef CONFIG_WEP if (hapd->conf->default_wep_key_len) { + int i; + for (i = 0; i < 4; i++) hostapd_drv_set_key(hapd->conf->iface, hapd, WPA_ALG_NONE, NULL, i, 0, 0, NULL, - 0, NULL, 0, KEY_FLAG_GROUP_RX_TX); + 0, NULL, 0, KEY_FLAG_GROUP); ieee802_1x_rekey(hapd, NULL); if (!hapd->eapol_auth->default_wep_key) return -1; } +#endif /* CONFIG_WEP */ return 0; } @@ -2499,7 +2514,9 @@ void ieee802_1x_erp_flush(struct hostapd_data *hapd) void ieee802_1x_deinit(struct hostapd_data *hapd) { +#ifdef CONFIG_WEP eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL); +#endif /* CONFIG_WEP */ if (hapd->driver && hapd->drv_priv && (hapd->conf->ieee802_1x || hapd->conf->wpa)) @@ -2660,26 +2677,25 @@ const u8 * ieee802_1x_get_session_id(struct eapol_state_machine *sm, void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, - int enabled) + bool enabled) { if (!sm) return; - sm->eap_if->portEnabled = enabled ? TRUE : FALSE; + sm->eap_if->portEnabled = enabled; eapol_auth_step(sm); } -void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, - int valid) +void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, bool valid) { if (!sm) return; - sm->portValid = valid ? TRUE : FALSE; + sm->portValid = valid; eapol_auth_step(sm); } -void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth) +void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, bool pre_auth) { if (!sm) return; @@ -2690,7 +2706,7 @@ void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth) } -static const char * bool_txt(Boolean val) +static const char * bool_txt(bool val) { return val ? "TRUE" : "FALSE"; } diff --git a/src/ap/ieee802_1x.h b/src/ap/ieee802_1x.h index bb85b93d6..70dc11afe 100644 --- a/src/ap/ieee802_1x.h +++ b/src/ap/ieee802_1x.h @@ -42,10 +42,9 @@ const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len); const u8 * ieee802_1x_get_session_id(struct eapol_state_machine *sm, size_t *len); void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, - int enabled); -void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, - int valid); -void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth); + bool enabled); +void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, bool valid); +void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, bool pre_auth); int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, char *buf, size_t buflen); diff --git a/src/ap/neighbor_db.c b/src/ap/neighbor_db.c index 4012ae4c3..2bbe31859 100644 --- a/src/ap/neighbor_db.c +++ b/src/ap/neighbor_db.c @@ -220,7 +220,7 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd) u16 capab = hostapd_own_capab_info(hapd); int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n; int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac; - int he = hapd->iconf->ieee80211ax; + int he = hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax; struct wpa_ssid_value ssid; u8 channel, op_class; u8 center_freq1_idx = 0, center_freq2_idx = 0; @@ -256,6 +256,8 @@ void hostapd_neighbor_set_own_report(struct hostapd_data *hapd) /* VHT bit added in IEEE P802.11-REVmc/D4.3 */ if (vht) bssid_info |= NEI_REP_BSSID_INFO_VHT; + if (he) + bssid_info |= NEI_REP_BSSID_INFO_HE; } /* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */ diff --git a/src/ap/pmksa_cache_auth.c b/src/ap/pmksa_cache_auth.c index 15e2c4943..fe5f81717 100644 --- a/src/ap/pmksa_cache_auth.c +++ b/src/ap/pmksa_cache_auth.c @@ -516,6 +516,11 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( for (entry = pmksa->pmksa; entry; entry = entry->next) { if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0) continue; + if (wpa_key_mgmt_sae(entry->akmp)) { + if (os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) + return entry; + continue; + } rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid, entry->akmp); if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0) diff --git a/src/ap/preauth_auth.c b/src/ap/preauth_auth.c index 3e0c8000d..2ff186177 100644 --- a/src/ap/preauth_auth.c +++ b/src/ap/preauth_auth.c @@ -82,7 +82,7 @@ static void rsn_preauth_receive(void *ctx, const u8 *src_addr, sta = NULL; } else { sta->eapol_sm->radius_identifier = -1; - sta->eapol_sm->portValid = TRUE; + sta->eapol_sm->portValid = true; sta->eapol_sm->flags |= EAPOL_SM_PREAUTH; } } diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 7a959021e..8ce477263 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -165,6 +165,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) /* just in case */ ap_sta_set_authorized(hapd, sta, 0); + hostapd_set_sta_flags(hapd, sta); if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0); @@ -234,9 +235,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) sta->assoc_ie_taxonomy = NULL; #endif /* CONFIG_TAXONOMY */ -#ifdef CONFIG_IEEE80211N ht40_intolerant_remove(hapd->iface, sta); -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_P2P if (sta->no_p2p_set) { @@ -247,10 +246,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) } #endif /* CONFIG_P2P */ -#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N) +#ifdef NEED_AP_MLME if (hostapd_ht_operation_update(hapd->iface) > 0) set_beacon++; -#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ +#endif /* NEED_AP_MLME */ #ifdef CONFIG_MESH if (hapd->mesh_sta_free_cb) @@ -328,6 +327,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) os_free(sta->vht_capabilities); os_free(sta->vht_operation); os_free(sta->he_capab); + os_free(sta->he_6ghz_capab); hostapd_free_psk_list(sta->psk); os_free(sta->identity); os_free(sta->radius_cui); @@ -547,6 +547,7 @@ skip_poll: case STA_DISASSOC_FROM_CLI: ap_sta_set_authorized(hapd, sta, 0); sta->flags &= ~WLAN_STA_ASSOC; + hostapd_set_sta_flags(hapd, sta); ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); if (!sta->acct_terminate_cause) sta->acct_terminate_cause = @@ -815,6 +816,7 @@ void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, sta->timeout_next = STA_DEAUTH; } ap_sta_set_authorized(hapd, sta, 0); + hostapd_set_sta_flags(hapd, sta); wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " "for " MACSTR " (%d seconds - " "AP_MAX_INACTIVITY_AFTER_DISASSOC)", @@ -865,6 +867,7 @@ void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); ap_sta_set_authorized(hapd, sta, 0); + hostapd_set_sta_flags(hapd, sta); sta->timeout_next = STA_REMOVE; wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " "for " MACSTR " (%d seconds - " @@ -1030,6 +1033,13 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta) int ret; int old_vlanid = sta->vlan_id_bound; + if ((sta->flags & WLAN_STA_WDS) && sta->vlan_id == 0) { + wpa_printf(MSG_DEBUG, + "Do not override WDS VLAN assignment for STA " + MACSTR, MAC2STR(sta->addr)); + return 0; + } + iface = hapd->conf->iface; if (hapd->conf->ssid.vlan[0]) iface = hapd->conf->ssid.vlan; @@ -1136,6 +1146,8 @@ static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx) if (sta->sa_query_count > 0 && ap_check_sa_query_timeout(hapd, sta)) return; + if (sta->sa_query_count >= 1000) + return; nbuf = os_realloc_array(sta->sa_query_trans_id, sta->sa_query_count + 1, @@ -1330,9 +1342,10 @@ void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, if (sta == NULL) return; ap_sta_set_authorized(hapd, sta, 0); + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); + hostapd_set_sta_flags(hapd, sta); wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); wpa_printf(MSG_DEBUG, "%s: %s: reschedule ap_handle_timer timeout " "for " MACSTR " (%d seconds - " "AP_MAX_INACTIVITY_AFTER_DEAUTH)", @@ -1420,7 +1433,8 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen) int res; buf[0] = '\0'; - res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + res = os_snprintf(buf, buflen, + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", (flags & WLAN_STA_AUTH ? "[AUTH]" : ""), (flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), (flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""), @@ -1440,6 +1454,7 @@ int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen) (flags & WLAN_STA_HT ? "[HT]" : ""), (flags & WLAN_STA_VHT ? "[VHT]" : ""), (flags & WLAN_STA_HE ? "[HE]" : ""), + (flags & WLAN_STA_6GHZ ? "[6GHZ]" : ""), (flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""), (flags & WLAN_STA_WNM_SLEEP_MODE ? "[WNM_SLEEP_MODE]" : "")); @@ -1493,3 +1508,33 @@ int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd, return eloop_is_timeout_registered(ap_sta_delayed_1x_auth_fail_cb, hapd, sta); } + + +int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta) +{ + /* + * If a station that is already associated to the AP, is trying to + * authenticate again, remove the STA entry, in order to make sure the + * STA PS state gets cleared and configuration gets updated. To handle + * this, station's added_unassoc flag is cleared once the station has + * completed association. + */ + ap_sta_set_authorized(hapd, sta, 0); + hostapd_drv_sta_remove(hapd, sta->addr); + sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH | WLAN_STA_AUTHORIZED); + + if (hostapd_sta_add(hapd, sta->addr, 0, 0, + sta->supported_rates, + sta->supported_rates_len, + 0, NULL, NULL, NULL, 0, NULL, + sta->flags, 0, 0, 0, 0)) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_NOTICE, + "Could not add STA to kernel driver"); + return -1; + } + + sta->added_unassoc = 1; + return 0; +} diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h index 8ff6ac62f..ef485618a 100644 --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h @@ -38,6 +38,7 @@ #define WLAN_STA_PENDING_FILS_ERP BIT(22) #define WLAN_STA_MULTI_AP BIT(23) #define WLAN_STA_HE BIT(24) +#define WLAN_STA_6GHZ BIT(25) #define WLAN_STA_PENDING_DISASSOC_CB BIT(29) #define WLAN_STA_PENDING_DEAUTH_CB BIT(30) #define WLAN_STA_NONERP BIT(31) @@ -121,6 +122,7 @@ struct sta_info { unsigned int hs20_t_c_filtering:1; unsigned int ft_over_ds:1; unsigned int external_dh_updated:1; + unsigned int post_csa_sa_query:1; u16 auth_alg; @@ -170,6 +172,7 @@ struct sta_info { u8 vht_opmode; struct ieee80211_he_capabilities *he_capab; size_t he_capab_len; + struct ieee80211_he_6ghz_band_cap *he_6ghz_capab; int sa_query_count; /* number of pending SA Query requests; * 0 = no SA Query in progress */ @@ -358,5 +361,6 @@ void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd, struct sta_info *sta); int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd, struct sta_info *sta); +int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta); #endif /* STA_INFO_H */ diff --git a/src/ap/utils.c b/src/ap/utils.c index fcb371bec..bedad6eb0 100644 --- a/src/ap/utils.c +++ b/src/ap/utils.c @@ -56,6 +56,10 @@ static int prune_associations(struct hostapd_iface *iface, void *ctx) ohapd = iface->bss[j]; if (ohapd == data->hapd) continue; +#ifdef CONFIG_TESTING_OPTIONS + if (ohapd->conf->skip_prune_assoc) + continue; +#endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_FST /* Don't prune STAs belong to same FST */ if (ohapd->iface->fst && diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c index e293a0033..53eacfb45 100644 --- a/src/ap/vlan_init.c +++ b/src/ap/vlan_init.c @@ -22,7 +22,9 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan, int existsok) { - int ret, i; + int ret; +#ifdef CONFIG_WEP + int i; for (i = 0; i < NUM_WEP_KEYS; i++) { if (!hapd->conf->ssid.wep.key[i]) @@ -32,6 +34,7 @@ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan, vlan->ifname); return -1; } +#endif /* CONFIG_WEP */ if (!iface_exists(vlan->ifname)) ret = hostapd_vlan_if_add(hapd, vlan->ifname); diff --git a/src/ap/wnm_ap.c b/src/ap/wnm_ap.c index 29ca95092..be817978e 100644 --- a/src/ap/wnm_ap.c +++ b/src/ap/wnm_ap.c @@ -54,6 +54,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, size_t len; size_t gtk_elem_len = 0; size_t igtk_elem_len = 0; + size_t bigtk_elem_len = 0; struct wnm_sleep_element wnmsleep_ie; u8 *wnmtfs_ie, *oci_ie; u8 wnmsleep_ie_len, oci_ie_len; @@ -102,6 +103,15 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, os_free(wnmtfs_ie); return -1; } +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->oci_freq_override_wnm_sleep) { + wpa_printf(MSG_INFO, + "TEST: Override OCI frequency %d -> %u MHz", + ci.frequency, + hapd->conf->oci_freq_override_wnm_sleep); + ci.frequency = hapd->conf->oci_freq_override_wnm_sleep; + } +#endif /* CONFIG_TESTING_OPTIONS */ oci_ie_len = OCV_OCI_EXTENDED_LEN; oci_ie = os_zalloc(oci_ie_len); @@ -122,8 +132,10 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, #define MAX_GTK_SUBELEM_LEN 45 #define MAX_IGTK_SUBELEM_LEN 26 +#define MAX_BIGTK_SUBELEM_LEN 26 mgmt = os_zalloc(sizeof(*mgmt) + wnmsleep_ie_len + MAX_GTK_SUBELEM_LEN + MAX_IGTK_SUBELEM_LEN + + MAX_BIGTK_SUBELEM_LEN + oci_ie_len); if (mgmt == NULL) { wpa_printf(MSG_DEBUG, "MLME: Failed to allocate buffer for " @@ -157,10 +169,19 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, pos += igtk_elem_len; wpa_printf(MSG_DEBUG, "Pass 4 igtk_len = %d", (int) igtk_elem_len); + if (hapd->conf->beacon_prot) { + res = wpa_wnmsleep_bigtk_subelem(sta->wpa_sm, pos); + if (res < 0) + goto fail; + bigtk_elem_len = res; + pos += bigtk_elem_len; + wpa_printf(MSG_DEBUG, "Pass 4 bigtk_len = %d", + (int) bigtk_elem_len); + } WPA_PUT_LE16((u8 *) &mgmt->u.action.u.wnm_sleep_resp.keydata_len, - gtk_elem_len + igtk_elem_len); + gtk_elem_len + igtk_elem_len + bigtk_elem_len); } os_memcpy(pos, &wnmsleep_ie, wnmsleep_ie_len); /* copy TFS IE here */ @@ -176,7 +197,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, #endif /* CONFIG_OCV */ len = 1 + sizeof(mgmt->u.action.u.wnm_sleep_resp) + gtk_elem_len + - igtk_elem_len + wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len; + igtk_elem_len + bigtk_elem_len + + wnmsleep_ie_len + wnmtfs_ie_len + oci_ie_len; /* In driver, response frame should be forced to sent when STA is in * PS mode */ @@ -189,8 +211,8 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, /* when entering wnmsleep * 1. pause the node in driver - * 2. mark the node so that AP won't update GTK/IGTK during - * WNM Sleep + * 2. mark the node so that AP won't update GTK/IGTK/BIGTK + * during WNM Sleep */ if (wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT && wnmsleep_ie.action_type == WNM_SLEEP_MODE_ENTER) { @@ -201,7 +223,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, } /* when exiting wnmsleep * 1. unmark the node - * 2. start GTK/IGTK update if MFP is not used + * 2. start GTK/IGTK/BIGTK update if MFP is not used * 3. unpause the node in driver */ if ((wnmsleep_ie.status == WNM_STATUS_SLEEP_ACCEPT || @@ -221,6 +243,7 @@ static int ieee802_11_send_wnmsleep_resp(struct hostapd_data *hapd, #undef MAX_GTK_SUBELEM_LEN #undef MAX_IGTK_SUBELEM_LEN +#undef MAX_BIGTK_SUBELEM_LEN fail: os_free(wnmtfs_ie); os_free(oci_ie); @@ -303,8 +326,9 @@ static void ieee802_11_rx_wnmsleep_req(struct hostapd_data *hapd, if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { - wpa_msg(hapd, MSG_WARNING, "WNM: %s", ocv_errorstr); + ci.seg1_idx) != OCI_SUCCESS) { + wpa_msg(hapd, MSG_WARNING, "WNM: OCV failed: %s", + ocv_errorstr); return; } } @@ -508,6 +532,30 @@ static void ieee802_11_rx_bss_trans_mgmt_resp(struct hostapd_data *hapd, } +static void wnm_beacon_protection_failure(struct hostapd_data *hapd, + const u8 *addr) +{ + struct sta_info *sta; + + if (!hapd->conf->beacon_prot) + return; + + sta = ap_get_sta(hapd, addr); + if (!sta || !(sta->flags & WLAN_STA_AUTHORIZED)) { + wpa_printf(MSG_DEBUG, "Station " MACSTR + " not found for received WNM-Notification Request", + MAC2STR(addr)); + return; + } + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Beacon protection failure reported"); + wpa_msg(hapd->msg_ctx, MSG_INFO, WPA_EVENT_UNPROT_BEACON "reporter=" + MACSTR, MAC2STR(addr)); +} + + static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd, const u8 *addr, const u8 *buf, size_t len) @@ -526,8 +574,14 @@ static void ieee802_11_rx_wnm_notification_req(struct hostapd_data *hapd, MAC2STR(addr), dialog_token, type); wpa_hexdump(MSG_MSGDUMP, "WNM: Notification Request subelements", buf, len); - if (type == WLAN_EID_VENDOR_SPECIFIC) + switch (type) { + case WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE: + wnm_beacon_protection_failure(hapd, addr); + break; + case WNM_NOTIF_TYPE_VENDOR_SPECIFIC: mbo_ap_wnm_notification_req(hapd, addr, buf, len); + break; + } } diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index bdf779360..fd75cb237 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -1,6 +1,5 @@ /* * IEEE 802.11 RSN / WPA Authenticator - * Copyright (c) 2020, Mathy Vanhoef * Copyright (c) 2004-2019, Jouni Malinen * * This software may be distributed under the terms of the BSD license. @@ -15,6 +14,8 @@ #include "utils/bitfield.h" #include "common/ieee802_11_defs.h" #include "common/ocv.h" +#include "common/dpp.h" +#include "common/wpa_ctrl.h" #include "crypto/aes.h" #include "crypto/aes_wrap.h" #include "crypto/aes_siv.h" @@ -64,6 +65,7 @@ static void wpa_group_get(struct wpa_authenticator *wpa_auth, struct wpa_group *group); static void wpa_group_put(struct wpa_authenticator *wpa_auth, struct wpa_group *group); +static int ieee80211w_kde_len(struct wpa_state_machine *sm); static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos); static const u32 eapol_key_timeout_first = 100; /* ms */ @@ -106,7 +108,7 @@ static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth, static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, wpa_eapol_variable var) { - if (wpa_auth->cb->get_eapol == NULL) + if (!wpa_auth->cb->get_eapol) return -1; return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var); } @@ -118,7 +120,7 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, const u8 *prev_psk, size_t *psk_len, int *vlan_id) { - if (wpa_auth->cb->get_psk == NULL) + if (!wpa_auth->cb->get_psk) return NULL; return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr, prev_psk, psk_len, vlan_id); @@ -128,7 +130,7 @@ static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth, const u8 *addr, u8 *msk, size_t *len) { - if (wpa_auth->cb->get_msk == NULL) + if (!wpa_auth->cb->get_msk) return -1; return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len); } @@ -140,7 +142,7 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, u8 *key, size_t key_len, enum key_flag key_flag) { - if (wpa_auth->cb->set_key == NULL) + if (!wpa_auth->cb->set_key) return -1; return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx, key, key_len, key_flag); @@ -152,7 +154,7 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, { int res; - if (wpa_auth->cb->get_seqnum == NULL) + if (!wpa_auth->cb->get_seqnum) return -1; res = wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq); #ifdef CONFIG_TESTING_OPTIONS @@ -184,7 +186,7 @@ static inline int wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, const u8 *data, size_t data_len, int encrypt) { - if (wpa_auth->cb->send_eapol == NULL) + if (!wpa_auth->cb->send_eapol) return -1; return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len, encrypt); @@ -195,7 +197,7 @@ wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth, const u8 *addr) { - if (wpa_auth->cb->start_ampe == NULL) + if (!wpa_auth->cb->start_ampe) return -1; return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr); } @@ -206,7 +208,7 @@ int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, int (*cb)(struct wpa_state_machine *sm, void *ctx), void *cb_ctx) { - if (wpa_auth->cb->for_each_sta == NULL) + if (!wpa_auth->cb->for_each_sta) return 0; return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx); } @@ -216,7 +218,7 @@ int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, int (*cb)(struct wpa_authenticator *a, void *ctx), void *cb_ctx) { - if (wpa_auth->cb->for_each_auth == NULL) + if (!wpa_auth->cb->for_each_auth) return 0; return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx); } @@ -225,7 +227,7 @@ int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, logger_level level, const char *txt) { - if (wpa_auth->cb->logger == NULL) + if (!wpa_auth->cb->logger) return; wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt); } @@ -238,7 +240,7 @@ void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, int maxlen; va_list ap; - if (wpa_auth->cb->logger == NULL) + if (!wpa_auth->cb->logger) return; maxlen = os_strlen(fmt) + 100; @@ -259,7 +261,7 @@ void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, const u8 *addr, u16 reason) { - if (wpa_auth->cb->disconnect == NULL) + if (!wpa_auth->cb->disconnect) return; wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)", MAC2STR(addr), reason); @@ -292,8 +294,8 @@ static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx) struct wpa_authenticator *wpa_auth = eloop_ctx; if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) { - wpa_printf(MSG_ERROR, "Failed to get random data for WPA " - "initialization."); + wpa_printf(MSG_ERROR, + "Failed to get random data for WPA initialization."); } else { wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd"); wpa_hexdump_key(MSG_DEBUG, "GMK", @@ -317,9 +319,9 @@ static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx) while (group) { wpa_group_get(wpa_auth, group); - group->GTKReKey = TRUE; + group->GTKReKey = true; do { - group->changed = FALSE; + group->changed = false; wpa_group_sm_step(wpa_auth, group); } while (group->changed); @@ -417,17 +419,16 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, struct wpa_group *group; group = os_zalloc(sizeof(struct wpa_group)); - if (group == NULL) + if (!group) return NULL; - group->GTKAuthenticator = TRUE; + group->GTKAuthenticator = true; group->vlan_id = vlan_id; group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); if (random_pool_ready() != 1) { - wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " - "for secure operations - update keys later when " - "the first station connects"); + wpa_printf(MSG_INFO, + "WPA: Not enough entropy in random pool for secure operations - update keys later when the first station connects"); } /* @@ -437,20 +438,20 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, * on embedded devices. */ if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) { - wpa_printf(MSG_ERROR, "Failed to get random data for WPA " - "initialization."); + wpa_printf(MSG_ERROR, + "Failed to get random data for WPA initialization."); os_free(group); return NULL; } - group->GInit = TRUE; + group->GInit = true; if (delay_init) { - wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start " - "until Beacon frames have been configured"); + wpa_printf(MSG_DEBUG, + "WPA: Delay group state machine start until Beacon frames have been configured"); /* Initialization is completed in wpa_init_keys(). */ } else { wpa_group_sm_step(wpa_auth, group); - group->GInit = FALSE; + group->GInit = false; wpa_group_sm_step(wpa_auth, group); } @@ -473,7 +474,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr, struct wpa_authenticator *wpa_auth; wpa_auth = os_zalloc(sizeof(struct wpa_authenticator)); - if (wpa_auth == NULL) + if (!wpa_auth) return NULL; os_memcpy(wpa_auth->addr, addr, ETH_ALEN); os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); @@ -487,7 +488,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr, } wpa_auth->group = wpa_group_init(wpa_auth, 0, 1); - if (wpa_auth->group == NULL) { + if (!wpa_auth->group) { os_free(wpa_auth->wpa_ie); os_free(wpa_auth); return NULL; @@ -495,7 +496,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr, wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb, wpa_auth); - if (wpa_auth->pmksa == NULL) { + if (!wpa_auth->pmksa) { wpa_printf(MSG_ERROR, "PMKSA cache initialization failed."); os_free(wpa_auth->group); os_free(wpa_auth->wpa_ie); @@ -505,7 +506,7 @@ struct wpa_authenticator * wpa_init(const u8 *addr, #ifdef CONFIG_IEEE80211R_AP wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init(); - if (wpa_auth->ft_pmk_cache == NULL) { + if (!wpa_auth->ft_pmk_cache) { wpa_printf(MSG_ERROR, "FT PMK cache initialization failed."); os_free(wpa_auth->group); os_free(wpa_auth->wpa_ie); @@ -544,10 +545,10 @@ int wpa_init_keys(struct wpa_authenticator *wpa_auth) { struct wpa_group *group = wpa_auth->group; - wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial " - "keys"); + wpa_printf(MSG_DEBUG, + "WPA: Start group state machine to set initial keys"); wpa_group_sm_step(wpa_auth, group); - group->GInit = FALSE; + group->GInit = false; wpa_group_sm_step(wpa_auth, group); if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) return -1; @@ -601,7 +602,8 @@ int wpa_reconfig(struct wpa_authenticator *wpa_auth, struct wpa_auth_config *conf) { struct wpa_group *group; - if (wpa_auth == NULL) + + if (!wpa_auth) return 0; os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); @@ -616,9 +618,9 @@ int wpa_reconfig(struct wpa_authenticator *wpa_auth, */ group = wpa_auth->group; group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); - group->GInit = TRUE; + group->GInit = true; wpa_group_sm_step(wpa_auth, group); - group->GInit = FALSE; + group->GInit = false; wpa_group_sm_step(wpa_auth, group); return 0; @@ -635,7 +637,7 @@ wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, return NULL; sm = os_zalloc(sizeof(struct wpa_state_machine)); - if (sm == NULL) + if (!sm) return NULL; os_memcpy(sm->addr, addr, ETH_ALEN); if (p2p_dev_addr) @@ -652,17 +654,16 @@ wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm) { - if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) + if (!wpa_auth || !wpa_auth->conf.wpa || !sm) return -1; #ifdef CONFIG_IEEE80211R_AP if (sm->ft_completed) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "FT authentication already completed - do not " - "start 4-way handshake"); + "FT authentication already completed - do not start 4-way handshake"); /* Go to PTKINITDONE state to allow GTK rekeying */ sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; - sm->Pair = TRUE; + sm->Pair = true; return 0; } #endif /* CONFIG_IEEE80211R_AP */ @@ -673,14 +674,14 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, "FILS authentication already completed - do not start 4-way handshake"); /* Go to PTKINITDONE state to allow GTK rekeying */ sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; - sm->Pair = TRUE; + sm->Pair = true; return 0; } #endif /* CONFIG_FILS */ if (sm->started) { os_memset(&sm->key_replay, 0, sizeof(sm->key_replay)); - sm->ReAuthenticationRequest = TRUE; + sm->ReAuthenticationRequest = true; return wpa_sm_step(sm); } @@ -688,11 +689,11 @@ int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, "start authentication"); sm->started = 1; - sm->Init = TRUE; + sm->Init = true; if (wpa_sm_step(sm) == 1) return 1; /* should not really happen */ - sm->Init = FALSE; - sm->AuthenticationRequest = TRUE; + sm->Init = false; + sm->AuthenticationRequest = true; return wpa_sm_step(sm); } @@ -702,7 +703,7 @@ void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm) /* WPA/RSN was not used - clear WPA state. This is needed if the STA * reassociates back to the same AP while the previous entry for the * STA has not yet been removed. */ - if (sm == NULL) + if (!sm) return; sm->wpa_key_mgmt = 0; @@ -714,8 +715,9 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) #ifdef CONFIG_P2P if (WPA_GET_BE32(sm->ip_addr)) { u32 start; - wpa_printf(MSG_DEBUG, "P2P: Free assigned IP " - "address %u.%u.%u.%u from " MACSTR, + wpa_printf(MSG_DEBUG, + "P2P: Free assigned IP address %u.%u.%u.%u from " + MACSTR, sm->ip_addr[0], sm->ip_addr[1], sm->ip_addr[2], sm->ip_addr[3], MAC2STR(sm->addr)); @@ -726,7 +728,7 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) #endif /* CONFIG_P2P */ if (sm->GUpdateStationKeys) { sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; + sm->GUpdateStationKeys = false; } #ifdef CONFIG_IEEE80211R_AP os_free(sm->assoc_resp_ftie); @@ -745,31 +747,34 @@ static void wpa_free_sta_sm(struct wpa_state_machine *sm) void wpa_auth_sta_deinit(struct wpa_state_machine *sm) { - if (sm == NULL) + struct wpa_authenticator *wpa_auth; + + if (!sm) return; - if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "strict rekeying - force GTK rekey since STA " - "is leaving"); + wpa_auth = sm->wpa_auth; + if (wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, + "strict rekeying - force GTK rekey since STA is leaving"); if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk, - sm->wpa_auth, NULL) == -1) - eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth, - NULL); + wpa_auth, NULL) == -1) + eloop_register_timeout(0, 500000, wpa_rekey_gtk, + wpa_auth, NULL); } - eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); + eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); sm->pending_1_of_4_timeout = 0; eloop_cancel_timeout(wpa_sm_call_step, sm, NULL); - eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); + eloop_cancel_timeout(wpa_rekey_ptk, wpa_auth, sm); #ifdef CONFIG_IEEE80211R_AP wpa_ft_sta_deinit(sm); #endif /* CONFIG_IEEE80211R_AP */ if (sm->in_step_loop) { /* Must not free state machine while wpa_sm_step() is running. * Freeing will be completed in the end of wpa_sm_step(). */ - wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state " - "machine deinit for " MACSTR, MAC2STR(sm->addr)); + wpa_printf(MSG_DEBUG, + "WPA: Registering pending STA state machine deinit for " + MACSTR, MAC2STR(sm->addr)); sm->pending_deinit = 1; } else wpa_free_sta_sm(sm); @@ -778,11 +783,23 @@ void wpa_auth_sta_deinit(struct wpa_state_machine *sm) static void wpa_request_new_ptk(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return; - sm->PTKRequest = TRUE; - sm->PTK_valid = 0; + if (!sm->use_ext_key_id && sm->wpa_auth->conf.wpa_deny_ptk0_rekey) { + wpa_printf(MSG_INFO, + "WPA: PTK0 rekey not allowed, disconnect " MACSTR, + MAC2STR(sm->addr)); + sm->Disconnect = true; + /* Try to encourage the STA to reconnect */ + sm->disconnect_reason = + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA; + } else { + if (sm->use_ext_key_id) + sm->keyidx_active ^= 1; /* flip Key ID */ + sm->PTKRequest = true; + sm->PTK_valid = 0; + } } @@ -807,10 +824,10 @@ static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr, int i; for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { if (ctr[i].valid && - (replay_counter == NULL || + (!replay_counter || os_memcmp(replay_counter, ctr[i].counter, WPA_REPLAY_COUNTER_LEN) == 0)) - ctr[i].valid = FALSE; + ctr[i].valid = false; } } @@ -824,9 +841,9 @@ static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, struct rsn_mdie *mdie; if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 || - ie.num_pmkid != 1 || ie.pmkid == NULL) { - wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " - "FT 4-way handshake message 2/4"); + ie.num_pmkid != 1 || !ie.pmkid) { + wpa_printf(MSG_DEBUG, + "FT: No PMKR1Name in FT 4-way handshake message 2/4"); return -1; } @@ -835,8 +852,9 @@ static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, sm->sup_pmk_r1_name, PMKID_LEN); if (!kde->mdie || !kde->ftie) { - wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake " - "message 2/4", kde->mdie ? "FTIE" : "MDIE"); + wpa_printf(MSG_DEBUG, + "FT: No %s in FT 4-way handshake message 2/4", + kde->mdie ? "FTIE" : "MDIE"); return -1; } @@ -870,18 +888,15 @@ static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth, { /* Supplicant reported a Michael MIC error */ wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key Error Request " - "(STA detected Michael MIC failure (group=%d))", + "received EAPOL-Key Error Request (STA detected Michael MIC failure (group=%d))", group); if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "ignore Michael MIC failure report since " - "group cipher is not TKIP"); + "ignore Michael MIC failure report since group cipher is not TKIP"); } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "ignore Michael MIC failure report since " - "pairwise cipher is not TKIP"); + "ignore Michael MIC failure report since pairwise cipher is not TKIP"); } else { if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0) return 1; /* STA entry was removed */ @@ -917,7 +932,7 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, pmk, &pmk_len, &vlan_id); - if (pmk == NULL) + if (!pmk) break; #ifdef CONFIG_IEEE80211R_AP if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) { @@ -966,7 +981,7 @@ static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN); os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); forced_memzero(&PTK, sizeof(PTK)); - sm->PTK_valid = TRUE; + sm->PTK_valid = true; return 0; } @@ -986,7 +1001,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, size_t keyhdrlen, mic_len; u8 *mic; - if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) + if (!wpa_auth || !wpa_auth->conf.wpa || !sm) return; wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len); @@ -1005,20 +1020,19 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, key_data = mic + mic_len + 2; key_data_length = WPA_GET_BE16(mic + mic_len); wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR - " key_info=0x%x type=%u mic_len=%u key_data_length=%u", + " key_info=0x%x type=%u mic_len=%zu key_data_length=%u", MAC2STR(sm->addr), key_info, key->type, - (unsigned int) mic_len, key_data_length); + mic_len, key_data_length); wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key header (ending before Key MIC)", key, sizeof(*key)); wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC", mic, mic_len); if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) { - wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " - "key_data overflow (%d > %lu)", + wpa_printf(MSG_INFO, + "WPA: Invalid EAPOL-Key frame - key_data overflow (%d > %zu)", key_data_length, - (unsigned long) (data_len - sizeof(*hdr) - - keyhdrlen)); + data_len - sizeof(*hdr) - keyhdrlen); return; } @@ -1028,18 +1042,18 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, * Some deployed station implementations seem to send * msg 4/4 with incorrect type value in WPA2 mode. */ - wpa_printf(MSG_DEBUG, "Workaround: Allow EAPOL-Key " - "with unexpected WPA type in RSN mode"); + wpa_printf(MSG_DEBUG, + "Workaround: Allow EAPOL-Key with unexpected WPA type in RSN mode"); } else if (key->type != EAPOL_KEY_TYPE_RSN) { - wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " - "unexpected type %d in RSN mode", + wpa_printf(MSG_DEBUG, + "Ignore EAPOL-Key with unexpected type %d in RSN mode", key->type); return; } } else { if (key->type != EAPOL_KEY_TYPE_WPA) { - wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " - "unexpected type %d in WPA mode", + wpa_printf(MSG_DEBUG, + "Ignore EAPOL-Key with unexpected type %d in WPA mode", key->type); return; } @@ -1084,9 +1098,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, - "advertised support for " - "AES-128-CMAC, but did not " - "use it"); + "advertised support for AES-128-CMAC, but did not use it"); return; } @@ -1095,8 +1107,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, - "did not use HMAC-SHA1-AES " - "with CCMP/GCMP"); + "did not use HMAC-SHA1-AES with CCMP/GCMP"); return; } } @@ -1114,8 +1125,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, os_memcmp(key->replay_counter, sm->req_replay_counter, WPA_REPLAY_COUNTER_LEN) <= 0) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, - "received EAPOL-Key request with " - "replayed counter"); + "received EAPOL-Key request with replayed counter"); return; } } @@ -1138,12 +1148,10 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, * even if we have already sent out EAPOL-Key 3/4. */ wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, - "Process SNonce update from STA " - "based on retransmitted EAPOL-Key " - "1/4"); + "Process SNonce update from STA based on retransmitted EAPOL-Key 1/4"); sm->update_snonce = 1; os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN); - sm->alt_snonce_valid = TRUE; + sm->alt_snonce_valid = true; os_memcpy(sm->alt_replay_counter, sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN); @@ -1169,12 +1177,12 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, key->replay_counter) && sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, - "ignore retransmitted EAPOL-Key %s - " - "SNonce did not change", msgtxt); + "ignore retransmitted EAPOL-Key %s - SNonce did not change", + msgtxt); } else { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, - "received EAPOL-Key %s with " - "unexpected replay counter", msgtxt); + "received EAPOL-Key %s with unexpected replay counter", + msgtxt); } for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { if (!sm->key_replay[i].valid) @@ -1205,8 +1213,7 @@ continue_processing: (!sm->update_snonce || sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 2/4 in " - "invalid state (%d) - dropped", + "received EAPOL-Key msg 2/4 in invalid state (%d) - dropped", sm->wpa_ptk_state); return; } @@ -1221,9 +1228,8 @@ continue_processing: * Counter update and the station will be allowed to * continue. */ - wpa_printf(MSG_DEBUG, "WPA: Reject 4-way handshake to " - "collect more entropy for random number " - "generation"); + wpa_printf(MSG_DEBUG, + "WPA: Reject 4-way handshake to collect more entropy for random number generation"); random_mark_pool_ready(); wpa_sta_disconnect(wpa_auth, sm->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); @@ -1234,8 +1240,7 @@ continue_processing: if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || !sm->PTK_valid) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 4/4 in " - "invalid state (%d) - dropped", + "received EAPOL-Key msg 4/4 in invalid state (%d) - dropped", sm->wpa_ptk_state); return; } @@ -1244,8 +1249,7 @@ continue_processing: if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING || !sm->PTK_valid) { wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key msg 2/2 in " - "invalid state (%d) - dropped", + "received EAPOL-Key msg 2/2 in invalid state (%d) - dropped", sm->wpa_ptk_group_state); return; } @@ -1279,7 +1283,7 @@ continue_processing: } #endif /* CONFIG_FILS */ - sm->MICVerified = FALSE; + sm->MICVerified = false; if (sm->PTK_valid && !sm->update_snonce) { if (mic_len && wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK, @@ -1312,7 +1316,7 @@ continue_processing: #ifdef TEST_FUZZ continue_fuzz: #endif /* TEST_FUZZ */ - sm->MICVerified = TRUE; + sm->MICVerified = true; eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); sm->pending_1_of_4_timeout = 0; } @@ -1324,8 +1328,7 @@ continue_processing: WPA_REPLAY_COUNTER_LEN); } else { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key request with " - "invalid MIC"); + "received EAPOL-Key request with invalid MIC"); return; } @@ -1341,8 +1344,7 @@ continue_processing: return; /* STA entry was removed */ } else if (key_info & WPA_KEY_INFO_KEY_TYPE) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key Request for new " - "4-Way Handshake"); + "received EAPOL-Key Request for new 4-Way Handshake"); #ifdef CONFIG_TESTING_OPTIONS sm->early_install = 0; #endif /* CONFIG_TESTING_OPTIONS */ @@ -1353,8 +1355,7 @@ continue_processing: kde.mac_addr) { } else { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "received EAPOL-Key Request for GTK " - "rekeying"); + "received EAPOL-Key Request for GTK rekeying"); eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); wpa_rekey_gtk(wpa_auth, NULL); } @@ -1387,12 +1388,12 @@ continue_processing: os_free(sm->last_rx_eapol_key); sm->last_rx_eapol_key = os_memdup(data, data_len); - if (sm->last_rx_eapol_key == NULL) + if (!sm->last_rx_eapol_key) return; sm->last_rx_eapol_key_len = data_len; sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE); - sm->EAPOLKeyReceived = TRUE; + sm->EAPOLKeyReceived = true; sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST); os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); @@ -1455,7 +1456,7 @@ static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx) sm->pending_1_of_4_timeout = 0; wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout"); - sm->TimeoutEvt = TRUE; + sm->TimeoutEvt = true; wpa_sm_step(sm); } @@ -1466,6 +1467,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *kde, size_t kde_len, int keyidx, int encr, int force_version) { + struct wpa_auth_config *conf = &wpa_auth->conf; struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; size_t len, mic_len, keyhdrlen; @@ -1494,15 +1496,14 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); - wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d " - "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d " - "encr=%d)", + wpa_printf(MSG_DEBUG, + "WPA: Send EAPOL(version=%d secure=%d mic=%d ack=%d install=%d pairwise=%d kde_len=%zu keyidx=%d encr=%d)", version, (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0, (key_info & WPA_KEY_INFO_MIC) ? 1 : 0, (key_info & WPA_KEY_INFO_ACK) ? 1 : 0, (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0, - pairwise, (unsigned long) kde_len, keyidx, encr); + pairwise, kde_len, keyidx, encr); key_data_len = kde_len; @@ -1520,9 +1521,9 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, len += AES_BLOCK_SIZE; hdr = os_zalloc(len); - if (hdr == NULL) + if (!hdr) return; - hdr->version = wpa_auth->conf.eapol_version; + hdr->version = conf->eapol_version; hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; hdr->length = host_to_be16(len - sizeof(*hdr)); key = (struct wpa_eapol_key *) (hdr + 1); @@ -1538,7 +1539,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT; WPA_PUT_BE16(key->key_info, key_info); - alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group; + alg = pairwise ? sm->pairwise : conf->wpa_group; if (sm->wpa == WPA_VERSION_WPA2 && !pairwise) WPA_PUT_BE16(key->key_length, 0); else @@ -1555,7 +1556,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, WPA_REPLAY_COUNTER_LEN); wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", key->replay_counter, WPA_REPLAY_COUNTER_LEN); - sm->key_replay[0].valid = TRUE; + sm->key_replay[0].valid = true; if (nonce) os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN); @@ -1592,7 +1593,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, #endif /* CONFIG_FILS */ } else if (encr && kde) { buf = os_zalloc(key_data_len); - if (buf == NULL) { + if (!buf) { os_free(hdr); return; } @@ -1609,8 +1610,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, wpa_use_aes_key_wrap(sm->wpa_key_mgmt) || version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { wpa_printf(MSG_DEBUG, - "WPA: Encrypt Key Data using AES-WRAP (KEK length %u)", - (unsigned int) sm->PTK.kek_len); + "WPA: Encrypt Key Data using AES-WRAP (KEK length %zu)", + sm->PTK.kek_len); if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, (key_data_len - 8) / 8, buf, key_data)) { os_free(hdr); @@ -1644,8 +1645,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, if (key_info & WPA_KEY_INFO_MIC) { if (!sm->PTK_valid || !mic_len) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, - "PTK not valid when sending EAPOL-Key " - "frame"); + "PTK not valid when sending EAPOL-Key frame"); os_free(hdr); return; } @@ -1658,9 +1658,8 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, } #ifdef CONFIG_TESTING_OPTIONS if (!pairwise && - wpa_auth->conf.corrupt_gtk_rekey_mic_probability > 0.0 && - drand48() < - wpa_auth->conf.corrupt_gtk_rekey_mic_probability) { + conf->corrupt_gtk_rekey_mic_probability > 0.0 && + drand48() < conf->corrupt_gtk_rekey_mic_probability) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, "Corrupting group EAPOL-Key Key MIC"); key_mic[0]++; @@ -1668,8 +1667,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, #endif /* CONFIG_TESTING_OPTIONS */ } - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, - 1); + wpa_auth_set_eapol(wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1); wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len, sm->pairwise_set); os_free(hdr); @@ -1686,7 +1684,7 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth, int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; u32 ctr; - if (sm == NULL) + if (!sm) return; __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len, @@ -1706,8 +1704,9 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth, #ifdef TEST_FUZZ timeout_ms = 1; #endif /* TEST_FUZZ */ - wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry " - "counter %u)", timeout_ms, ctr); + wpa_printf(MSG_DEBUG, + "WPA: Use EAPOL-Key timeout of %u ms (retry counter %u)", + timeout_ms, ctr); eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000, wpa_send_eapol_timeout, wpa_auth, sm); } @@ -1744,13 +1743,18 @@ static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK, void wpa_remove_ptk(struct wpa_state_machine *sm) { - sm->PTK_valid = FALSE; + sm->PTK_valid = false; os_memset(&sm->PTK, 0, sizeof(sm->PTK)); if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, 0, KEY_FLAG_PAIRWISE)) wpa_printf(MSG_DEBUG, "RSN: PTK removal from the driver failed"); - sm->pairwise_set = FALSE; + if (sm->use_ext_key_id && + wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 1, NULL, + 0, KEY_FLAG_PAIRWISE)) + wpa_printf(MSG_DEBUG, + "RSN: PTK Key ID 1 removal from the driver failed"); + sm->pairwise_set = false; eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); } @@ -1759,7 +1763,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) { int remove_ptk = 1; - if (sm == NULL) + if (!sm) return -1; wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, @@ -1779,7 +1783,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) break; case WPA_DEAUTH: case WPA_DISASSOC: - sm->DeauthenticationRequest = TRUE; + sm->DeauthenticationRequest = true; #ifdef CONFIG_IEEE80211R_AP os_memset(sm->PMK, 0, sizeof(sm->PMK)); sm->pmk_len = 0; @@ -1799,32 +1803,48 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) * sure that the WPA state machines gets initialized * properly at this point. */ - wpa_printf(MSG_DEBUG, "WPA state machine had not been " - "started - initialize now"); + wpa_printf(MSG_DEBUG, + "WPA state machine had not been started - initialize now"); sm->started = 1; - sm->Init = TRUE; + sm->Init = true; if (wpa_sm_step(sm) == 1) return 1; /* should not really happen */ - sm->Init = FALSE; - sm->AuthenticationRequest = TRUE; + sm->Init = false; + sm->AuthenticationRequest = true; break; } + + if (!sm->use_ext_key_id && + sm->wpa_auth->conf.wpa_deny_ptk0_rekey) { + wpa_printf(MSG_INFO, + "WPA: PTK0 rekey not allowed, disconnect " + MACSTR, MAC2STR(sm->addr)); + sm->Disconnect = true; + /* Try to encourage the STA to reconnect */ + sm->disconnect_reason = + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA; + break; + } + + if (sm->use_ext_key_id) + sm->keyidx_active ^= 1; /* flip Key ID */ + if (sm->GUpdateStationKeys) { /* * Reauthentication cancels the pending group key * update for this STA. */ sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - sm->PtkGroupInit = TRUE; + sm->GUpdateStationKeys = false; + sm->PtkGroupInit = true; } - sm->ReAuthenticationRequest = TRUE; + sm->ReAuthenticationRequest = true; break; case WPA_ASSOC_FT: #ifdef CONFIG_IEEE80211R_AP - wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration " - "after association"); - wpa_ft_install_ptk(sm); + wpa_printf(MSG_DEBUG, + "FT: Retry PTK configuration after association"); + wpa_ft_install_ptk(sm, 1); /* Using FT protocol, not WPA auth state machine */ sm->ft_completed = 1; @@ -1844,7 +1864,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) break; #endif /* CONFIG_FILS */ case WPA_DRV_STA_REMOVED: - sm->tk_already_set = FALSE; + sm->tk_already_set = false; return 0; } @@ -1861,7 +1881,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) #endif /* CONFIG_FILS */ if (remove_ptk) { - sm->PTK_valid = FALSE; + sm->PTK_valid = false; os_memset(&sm->PTK, 0, sizeof(sm->PTK)); if (event != WPA_REAUTH_EAPOL) @@ -1873,7 +1893,7 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) * wpa_sm_step() is already running - avoid recursive call to * it by making the existing loop process the new update. */ - sm->changed = TRUE; + sm->changed = true; return 0; } return wpa_sm_step(sm); @@ -1886,18 +1906,18 @@ SM_STATE(WPA_PTK, INITIALIZE) if (sm->Init) { /* Init flag is not cleared here, so avoid busy * loop by claiming nothing changed. */ - sm->changed = FALSE; + sm->changed = false; } sm->keycount = 0; if (sm->GUpdateStationKeys) sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; + sm->GUpdateStationKeys = false; if (sm->wpa == WPA_VERSION_WPA) - sm->PInitAKeys = FALSE; + sm->PInitAKeys = false; if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and * Local AA > Remote AA)) */) { - sm->Pair = TRUE; + sm->Pair = true; } wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0); wpa_remove_ptk(sm); @@ -1917,7 +1937,7 @@ SM_STATE(WPA_PTK, DISCONNECT) u16 reason = sm->disconnect_reason; SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk); - sm->Disconnect = FALSE; + sm->Disconnect = false; sm->disconnect_reason = 0; if (!reason) reason = WLAN_REASON_PREV_AUTH_NOT_VALID; @@ -1928,7 +1948,7 @@ SM_STATE(WPA_PTK, DISCONNECT) SM_STATE(WPA_PTK, DISCONNECTED) { SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk); - sm->DeauthenticationRequest = FALSE; + sm->DeauthenticationRequest = false; } @@ -1936,11 +1956,11 @@ SM_STATE(WPA_PTK, AUTHENTICATION) { SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk); os_memset(&sm->PTK, 0, sizeof(sm->PTK)); - sm->PTK_valid = FALSE; + sm->PTK_valid = false; wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto, 1); wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1); - sm->AuthenticationRequest = FALSE; + sm->AuthenticationRequest = false; } @@ -1956,23 +1976,23 @@ static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth, * GMK and Counter here to improve their strength if there was not * enough entropy available immediately after system startup. */ - wpa_printf(MSG_DEBUG, "WPA: Re-initialize GMK/Counter on first " - "station"); + wpa_printf(MSG_DEBUG, + "WPA: Re-initialize GMK/Counter on first station"); if (random_pool_ready() != 1) { - wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " - "to proceed - reject first 4-way handshake"); - group->reject_4way_hs_for_entropy = TRUE; + wpa_printf(MSG_INFO, + "WPA: Not enough entropy in random pool to proceed - reject first 4-way handshake"); + group->reject_4way_hs_for_entropy = true; } else { - group->first_sta_seen = TRUE; - group->reject_4way_hs_for_entropy = FALSE; + group->first_sta_seen = true; + group->reject_4way_hs_for_entropy = false; } if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 || wpa_gtk_update(wpa_auth, group) < 0 || wpa_group_config_group_keys(wpa_auth, group) < 0) { wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed"); - group->first_sta_seen = FALSE; - group->reject_4way_hs_for_entropy = TRUE; + group->first_sta_seen = false; + group->reject_4way_hs_for_entropy = true; } } @@ -1982,7 +2002,7 @@ SM_STATE(WPA_PTK, AUTHENTICATION2) SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk); wpa_group_ensure_init(sm->wpa_auth, sm->group); - sm->ReAuthenticationRequest = FALSE; + sm->ReAuthenticationRequest = false; /* * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat @@ -1994,9 +2014,9 @@ SM_STATE(WPA_PTK, AUTHENTICATION2) * stronger protection against potential precomputation attacks. */ if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { - wpa_printf(MSG_ERROR, "WPA: Failed to get random data for " - "ANonce."); - sm->Disconnect = TRUE; + wpa_printf(MSG_ERROR, + "WPA: Failed to get random data for ANonce."); + sm->Disconnect = true; return; } wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce, @@ -2014,7 +2034,7 @@ static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm) if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { wpa_printf(MSG_ERROR, "WPA: Failed to get random data for ANonce"); - sm->Disconnect = TRUE; + sm->Disconnect = true; return -1; } wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce, @@ -2041,7 +2061,7 @@ SM_STATE(WPA_PTK, INITPMK) } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) { wpa_printf(MSG_DEBUG, "DPP: No PMKSA cache entry for STA - reject connection"); - sm->Disconnect = TRUE; + sm->Disconnect = true; sm->disconnect_reason = WLAN_REASON_INVALID_PMKID; return; #endif /* CONFIG_DPP */ @@ -2052,14 +2072,14 @@ SM_STATE(WPA_PTK, INITPMK) pmk_len = PMK_LEN_SUITE_B_192; else pmk_len = PMK_LEN; - wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine " - "(MSK len=%lu PMK len=%u)", (unsigned long) len, - pmk_len); + wpa_printf(MSG_DEBUG, + "WPA: PMK from EAPOL state machine (MSK len=%zu PMK len=%u)", + len, pmk_len); if (len < pmk_len) { wpa_printf(MSG_DEBUG, - "WPA: MSK not long enough (%u) to create PMK (%u)", - (unsigned int) len, (unsigned int) pmk_len); - sm->Disconnect = TRUE; + "WPA: MSK not long enough (%zu) to create PMK (%u)", + len, pmk_len); + sm->Disconnect = true; return; } os_memcpy(sm->PMK, msk, pmk_len); @@ -2078,21 +2098,21 @@ SM_STATE(WPA_PTK, INITPMK) } else { wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p", sm->wpa_auth->cb->get_msk); - sm->Disconnect = TRUE; + sm->Disconnect = true; return; } forced_memzero(msk, sizeof(msk)); sm->req_replay_counter_used = 0; - /* IEEE 802.11i does not set keyRun to FALSE, but not doing this + /* IEEE 802.11i does not set keyRun to false, but not doing this * will break reauthentication since EAPOL state machines may not be * get into AUTHENTICATING state that clears keyRun before WPA state * machine enters AUTHENTICATION2 state and goes immediately to INITPMK * state and takes PMK from the previously used AAA Key. This will * eventually fail in 4-Way Handshake because Supplicant uses PMK - * derived from the new AAA Key. Setting keyRun = FALSE here seems to + * derived from the new AAA Key. Setting keyRun = false here seems to * be good workaround for this issue. */ - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0); + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, false); } @@ -2133,9 +2153,9 @@ SM_STATE(WPA_PTK, PTKSTART) size_t pmkid_len = 0; SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk); - sm->PTKRequest = FALSE; - sm->TimeoutEvt = FALSE; - sm->alt_snonce_valid = FALSE; + sm->PTKRequest = false; + sm->TimeoutEvt = false; + sm->alt_snonce_valid = false; sm->TimeoutCtr++; if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) { @@ -2273,7 +2293,7 @@ static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, akmp = sm->wpa_key_mgmt; if (force_sha256) - akmp = WPA_KEY_MGMT_PSK_SHA256; + akmp |= WPA_KEY_MGMT_PSK_SHA256; return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion", sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce, ptk, akmp, sm->pairwise, z, z_len); @@ -2300,8 +2320,8 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, fils_ft, &fils_ft_len); if (res < 0) return res; - sm->PTK_valid = TRUE; - sm->tk_already_set = FALSE; + sm->PTK_valid = true; + sm->tk_already_set = false; #ifdef CONFIG_IEEE80211R_AP if (fils_ft_len) { @@ -2309,7 +2329,6 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, struct wpa_auth_config *conf = &wpa_auth->conf; u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN]; int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); - size_t pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; if (wpa_derive_pmk_r0(fils_ft, fils_ft_len, conf->ssid, conf->ssid_len, @@ -2320,10 +2339,6 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, use_sha384) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", - pmk_r0, pmk_r0_len); - wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name", - pmk_r0_name, WPA_PMK_NAME_LEN); wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name); forced_memzero(fils_ft, sizeof(fils_ft)); @@ -2490,9 +2505,9 @@ int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies, if (elems.fils_key_confirm_len != sm->fils_key_auth_len) { wpa_printf(MSG_DEBUG, - "FILS: Unexpected Key-Auth length %d (expected %d)", + "FILS: Unexpected Key-Auth length %d (expected %zu)", elems.fils_key_confirm_len, - (int) sm->fils_key_auth_len); + sm->fils_key_auth_len); return -1; } @@ -2685,8 +2700,13 @@ static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, u8 *gtk, dummy_gtk[32]; size_t gtk_len; struct wpa_group *gsm; + size_t plain_len; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; - plain = wpabuf_alloc(1000); + plain_len = 1000 + ieee80211w_kde_len(sm); + if (conf->transition_disable) + plain_len += 2 + RSN_SELECTOR_LEN + 1; + plain = wpabuf_alloc(plain_len); if (!plain) return NULL; @@ -2715,8 +2735,7 @@ static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, /* GTK KDE */ gtk = gsm->GTK[gsm->GN - 1]; gtk_len = gsm->GTK_len; - if (sm->wpa_auth->conf.disable_gtk || - sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { /* * Provide unique random GTK to each STA to prevent use * of GTK in the BSS. @@ -2734,11 +2753,18 @@ static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, gtk, gtk_len); wpabuf_put(plain, tmp2 - tmp); - /* IGTK KDE */ + /* IGTK KDE and BIGTK KDE */ tmp = wpabuf_put(plain, 0); tmp2 = ieee80211w_kde_add(sm, tmp); wpabuf_put(plain, tmp2 - tmp); + if (conf->transition_disable) { + tmp = wpabuf_put(plain, 0); + tmp2 = wpa_add_kde(tmp, WFA_KEY_DATA_TRANSITION_DISABLE, + &conf->transition_disable, 1, NULL, 0); + wpabuf_put(plain, tmp2 - tmp); + } + *len = (u8 *) wpabuf_put(plain, 0) - len - 1; #ifdef CONFIG_OCV @@ -2752,6 +2778,15 @@ static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, wpabuf_clear_free(plain); return NULL; } +#ifdef CONFIG_TESTING_OPTIONS + if (conf->oci_freq_override_fils_assoc) { + wpa_printf(MSG_INFO, + "TEST: Override OCI frequency %d -> %u MHz", + ci.frequency, + conf->oci_freq_override_fils_assoc); + ci.frequency = conf->oci_freq_override_fils_assoc; + } +#endif /* CONFIG_TESTING_OPTIONS */ pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN); if (ocv_insert_extended_oci(&ci, pos) < 0) { @@ -2788,7 +2823,7 @@ int fils_set_tk(struct wpa_state_machine *sm) wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver"); return -1; } - sm->tk_already_set = TRUE; + sm->tk_already_set = true; return 0; } @@ -2816,8 +2851,8 @@ u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf, os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain)); pos += wpabuf_len(plain); - wpa_printf(MSG_DEBUG, "%s: plain buf_len: %u", __func__, - (unsigned int) wpabuf_len(plain)); + wpa_printf(MSG_DEBUG, "%s: plain buf_len: %zu", __func__, + wpabuf_len(plain)); wpabuf_clear_free(plain); sm->fils_completed = 1; return pos; @@ -2859,8 +2894,8 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) int owe_ptk_workaround = !!wpa_auth->conf.owe_ptk_workaround; SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); - sm->EAPOLKeyReceived = FALSE; - sm->update_snonce = FALSE; + sm->EAPOLKeyReceived = false; + sm->update_snonce = false; os_memset(&PTK, 0, sizeof(PTK)); mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); @@ -2874,7 +2909,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, pmk, &pmk_len, &vlan_id); - if (pmk == NULL) + if (!pmk) break; psk_found = 1; #ifdef CONFIG_IEEE80211R_AP @@ -2971,7 +3006,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) eapol_key_ie_len = kde.wpa_ie_len; } ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt); - if (sm->wpa_ie == NULL || + if (!sm->wpa_ie || wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len, eapol_key_ie, eapol_key_ie_len)) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, @@ -3008,6 +3043,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) struct wpa_channel_info ci; int tx_chanwidth; int tx_seg1_idx; + enum oci_verify_result res; if (wpa_channel_info(wpa_auth, &ci) != 0) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, @@ -3021,10 +3057,21 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) &tx_seg1_idx) < 0) return; - if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != 0) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - ocv_errorstr); + res = ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, + tx_chanwidth, tx_seg1_idx); + if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) { + /* Work around misbehaving STAs */ + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "Disable OCV with a STA that does not send OCI"); + wpa_auth_set_ocv(sm, 0); + } else if (res != OCI_SUCCESS) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "OCV failed: %s", ocv_errorstr); + if (wpa_auth->conf.msg_ctx) + wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO, + OCV_FAILURE "addr=" MACSTR + " frame=eapol-key-m2 error=%s", + MAC2STR(sm->addr), ocv_errorstr); return; } } @@ -3056,6 +3103,24 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) } #endif /* CONFIG_P2P */ +#ifdef CONFIG_DPP2 + if (DPP_VERSION > 1 && kde.dpp_kde) { + wpa_printf(MSG_DEBUG, + "DPP: peer Protocol Version %u Flags 0x%x", + kde.dpp_kde[0], kde.dpp_kde[1]); + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && + wpa_auth->conf.dpp_pfs != 2 && + (kde.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) && + !sm->dpp_z) { + wpa_printf(MSG_INFO, + "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association"); + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } + } +#endif /* CONFIG_DPP2 */ + #ifdef CONFIG_IEEE80211R_AP if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { /* @@ -3065,10 +3130,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name, WPA_PMK_NAME_LEN) != 0) { wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "PMKR1Name mismatch in FT 4-way " - "handshake"); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from " - "Supplicant", + "PMKR1Name mismatch in FT 4-way handshake"); + wpa_hexdump(MSG_DEBUG, + "FT: PMKR1Name from Supplicant", sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN); wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", sm->pmk_r1_name, WPA_PMK_NAME_LEN); @@ -3087,7 +3151,7 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) sm->pending_1_of_4_timeout = 0; eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); - if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && sm->PMK != pmk) { /* PSK may have changed from the previous choice, so update * state machine data based on whatever PSK was selected here. */ @@ -3095,11 +3159,11 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) sm->pmk_len = PMK_LEN; } - sm->MICVerified = TRUE; + sm->MICVerified = true; os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); forced_memzero(&PTK, sizeof(PTK)); - sm->PTK_valid = TRUE; + sm->PTK_valid = true; } @@ -3112,22 +3176,29 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2) static int ieee80211w_kde_len(struct wpa_state_machine *sm) { + size_t len = 0; + if (sm->mgmt_frame_prot) { - size_t len; - len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); - return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len; + len += 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN; + len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + } + if (sm->mgmt_frame_prot && sm->wpa_auth->conf.beacon_prot) { + len += 2 + RSN_SELECTOR_LEN + WPA_BIGTK_KDE_PREFIX_LEN; + len += wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); } - return 0; + return len; } static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) { struct wpa_igtk_kde igtk; + struct wpa_bigtk_kde bigtk; struct wpa_group *gsm = sm->group; u8 rsc[WPA_KEY_RSC_LEN]; - size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + struct wpa_auth_config *conf = &sm->wpa_auth->conf; + size_t len = wpa_cipher_key_len(conf->group_mgmt_cipher); if (!sm->mgmt_frame_prot) return pos; @@ -3140,8 +3211,7 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) else os_memcpy(igtk.pn, rsc, sizeof(igtk.pn)); os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len); - if (sm->wpa_auth->conf.disable_gtk || - sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { /* * Provide unique random IGTK to each STA to prevent use of * IGTK in the BSS. @@ -3153,6 +3223,29 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len, NULL, 0); + if (!conf->beacon_prot) + return pos; + + bigtk.keyid[0] = gsm->GN_bigtk; + bigtk.keyid[1] = 0; + if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE || + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, rsc) < 0) + os_memset(bigtk.pn, 0, sizeof(bigtk.pn)); + else + os_memcpy(bigtk.pn, rsc, sizeof(bigtk.pn)); + os_memcpy(bigtk.bigtk, gsm->BIGTK[gsm->GN_bigtk - 6], len); + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random BIGTK to each OSEN STA to prevent use + * of BIGTK in the BSS. + */ + if (random_get_bytes(bigtk.bigtk, len) < 0) + return pos; + } + pos = wpa_add_kde(pos, RSN_KEY_DATA_BIGTK, + (const u8 *) &bigtk, WPA_BIGTK_KDE_PREFIX_LEN + len, + NULL, 0); + return pos; } @@ -3166,7 +3259,9 @@ static int ocv_oci_len(struct wpa_state_machine *sm) return 0; } -static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos) + +static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos, + unsigned int freq) { #ifdef CONFIG_OCV struct wpa_channel_info ci; @@ -3179,6 +3274,14 @@ static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos) "Failed to get channel info for OCI element"); return -1; } +#ifdef CONFIG_TESTING_OPTIONS + if (freq) { + wpa_printf(MSG_INFO, + "TEST: Override OCI KDE frequency %d -> %u MHz", + ci.frequency, freq); + ci.frequency = freq; + } +#endif /* CONFIG_TESTING_OPTIONS */ return ocv_insert_oci_kde(&ci, argpos); #else /* CONFIG_OCV */ @@ -3187,41 +3290,73 @@ static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos) } +#ifdef CONFIG_TESTING_OPTIONS +static u8 * replace_ie(const char *name, const u8 *old_buf, size_t *len, u8 eid, + const u8 *ie, size_t ie_len) +{ + const u8 *elem; + u8 *buf; + + wpa_printf(MSG_DEBUG, "TESTING: %s EAPOL override", name); + wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie before override", + old_buf, *len); + buf = os_malloc(*len + ie_len); + if (!buf) + return NULL; + os_memcpy(buf, old_buf, *len); + elem = get_ie(buf, *len, eid); + if (elem) { + u8 elem_len = 2 + elem[1]; + + os_memmove((void *) elem, elem + elem_len, + *len - (elem - buf) - elem_len); + *len -= elem_len; + } + os_memcpy(buf + *len, ie, ie_len); + *len += ie_len; + wpa_hexdump(MSG_DEBUG, "TESTING: wpa_ie after EAPOL override", + buf, *len); + + return buf; +} +#endif /* CONFIG_TESTING_OPTIONS */ + + SM_STATE(WPA_PTK, PTKINITNEGOTIATING) { u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde = NULL, *pos, dummy_gtk[32]; - size_t gtk_len, kde_len; + size_t gtk_len, kde_len, wpa_ie_len; struct wpa_group *gsm = sm->group; u8 *wpa_ie; - int wpa_ie_len, secure, gtkidx, encr = 0; - u8 *wpa_ie_buf = NULL; + int secure, gtkidx, encr = 0; + u8 *wpa_ie_buf = NULL, *wpa_ie_buf2 = NULL; + u8 hdr[2]; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); - sm->TimeoutEvt = FALSE; + sm->TimeoutEvt = false; sm->TimeoutCtr++; - if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && - sm->TimeoutCtr > 1) { + if (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1) { /* Do not allow retransmission of EAPOL-Key msg 3/4 */ return; } - if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) { + if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) { /* No point in sending the EAPOL-Key - we will disconnect * immediately following this. */ return; } /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], - GTK[GN], IGTK, [FTIE], [TIE * 2]) + GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2]) */ os_memset(rsc, 0, WPA_KEY_RSC_LEN); wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ wpa_ie = sm->wpa_auth->wpa_ie; wpa_ie_len = sm->wpa_auth->wpa_ie_len; - if (sm->wpa == WPA_VERSION_WPA && - (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && - wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { + if (sm->wpa == WPA_VERSION_WPA && (conf->wpa & WPA_PROTO_RSN) && + wpa_ie_len > wpa_ie[1] + 2U && wpa_ie[0] == WLAN_EID_RSN) { /* WPA-only STA, remove RSN IE and possible MDIE */ wpa_ie = wpa_ie + wpa_ie[1] + 2; if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN) @@ -3229,42 +3364,45 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_ie_len = wpa_ie[1] + 2; } #ifdef CONFIG_TESTING_OPTIONS - if (sm->wpa_auth->conf.rsnxe_override_eapol_len) { - u8 *obuf = sm->wpa_auth->conf.rsnxe_override_eapol; - size_t olen = sm->wpa_auth->conf.rsnxe_override_eapol_len; - const u8 *rsnxe; - - wpa_hexdump(MSG_DEBUG, - "TESTING: wpa_ie before RSNXE EAPOL override", - wpa_ie, wpa_ie_len); - wpa_ie_buf = os_malloc(wpa_ie_len + olen); + if (conf->rsne_override_eapol_set) { + wpa_ie_buf2 = replace_ie( + "RSNE", wpa_ie, &wpa_ie_len, WLAN_EID_RSN, + conf->rsne_override_eapol, + conf->rsne_override_eapol_len); + if (!wpa_ie_buf2) + goto done; + wpa_ie = wpa_ie_buf2; + } + if (conf->rsnxe_override_eapol_set) { + wpa_ie_buf = replace_ie( + "RSNXE", wpa_ie, &wpa_ie_len, WLAN_EID_RSNX, + conf->rsnxe_override_eapol, + conf->rsnxe_override_eapol_len); if (!wpa_ie_buf) - return; - os_memcpy(wpa_ie_buf, wpa_ie, wpa_ie_len); + goto done; wpa_ie = wpa_ie_buf; - rsnxe = get_ie(wpa_ie, wpa_ie_len, WLAN_EID_RSNX); - if (rsnxe) { - u8 rsnxe_len = 2 + rsnxe[1]; - - os_memmove((void *) rsnxe, rsnxe + rsnxe_len, - wpa_ie_len - (rsnxe - wpa_ie) - rsnxe_len); - wpa_ie_len -= rsnxe_len; - } - os_memcpy(wpa_ie + wpa_ie_len, obuf, olen); - wpa_ie_len += olen; - wpa_hexdump(MSG_DEBUG, - "TESTING: wpa_ie after RSNXE EAPOL override", - wpa_ie, wpa_ie_len); } #endif /* CONFIG_TESTING_OPTIONS */ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "sending 3/4 msg of 4-Way Handshake"); if (sm->wpa == WPA_VERSION_WPA2) { + if (sm->use_ext_key_id && sm->TimeoutCtr == 1 && + wpa_auth_set_key(sm->wpa_auth, 0, + wpa_cipher_to_alg(sm->pairwise), + sm->addr, + sm->keyidx_active, sm->PTK.tk, + wpa_cipher_key_len(sm->pairwise), + KEY_FLAG_PAIRWISE_RX)) { + wpa_sta_disconnect(sm->wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } + /* WPA2 send GTK in the 4-way handshake */ secure = 1; gtk = gsm->GTK[gsm->GN - 1]; gtk_len = gsm->GTK_len; - if (sm->wpa_auth->conf.disable_gtk || + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { /* * Provide unique random GTK to each STA to prevent use @@ -3293,13 +3431,16 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) * WPA if the supplicant used it first. */ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "STA used Secure bit in WPA msg 2/4 - " - "set Secure for 3/4 as workaround"); + "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround"); secure = 1; } } kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); + + if (sm->use_ext_key_id) + kde_len += 2 + RSN_SELECTOR_LEN + 2; + if (gtk) kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; #ifdef CONFIG_IEEE80211R_AP @@ -3312,8 +3453,17 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) if (WPA_GET_BE32(sm->ip_addr) > 0) kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4; #endif /* CONFIG_P2P */ + + if (conf->transition_disable) + kde_len += 2 + RSN_SELECTOR_LEN + 1; + +#ifdef CONFIG_DPP2 + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) + kde_len += 2 + RSN_SELECTOR_LEN + 2; +#endif /* CONFIG_DPP2 */ + kde = os_malloc(kde_len); - if (kde == NULL) + if (!kde) goto done; pos = kde; @@ -3327,31 +3477,34 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) elen = pos - kde; res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name); if (res < 0) { - wpa_printf(MSG_ERROR, "FT: Failed to insert " - "PMKR1Name into RSN IE in EAPOL-Key data"); + wpa_printf(MSG_ERROR, + "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data"); goto done; } pos -= wpa_ie_len; pos += elen; } #endif /* CONFIG_IEEE80211R_AP */ + hdr[1] = 0; + + if (sm->use_ext_key_id) { + hdr[0] = sm->keyidx_active & 0x01; + pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0); + } + if (gtk) { - u8 hdr[2]; hdr[0] = gtkidx & 0x03; - hdr[1] = 0; pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, gtk, gtk_len); } pos = ieee80211w_kde_add(sm, pos); - if (ocv_oci_add(sm, &pos) < 0) + if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) goto done; #ifdef CONFIG_IEEE80211R_AP if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { int res; - struct wpa_auth_config *conf; - conf = &sm->wpa_auth->conf; if (sm->assoc_resp_ftie && kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) { os_memcpy(pos, sm->assoc_resp_ftie, @@ -3365,11 +3518,11 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) conf->r0_key_holder_len, NULL, NULL, pos, kde + kde_len - pos, - NULL, 0); + NULL, 0, 0); } if (res < 0) { - wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " - "into EAPOL-Key Key Data"); + wpa_printf(MSG_ERROR, + "FT: Failed to insert FTIE into EAPOL-Key Key Data"); goto done; } pos += res; @@ -3393,13 +3546,33 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) if (WPA_GET_BE32(sm->ip_addr) > 0) { u8 addr[3 * 4]; os_memcpy(addr, sm->ip_addr, 4); - os_memcpy(addr + 4, sm->wpa_auth->conf.ip_addr_mask, 4); - os_memcpy(addr + 8, sm->wpa_auth->conf.ip_addr_go, 4); + os_memcpy(addr + 4, conf->ip_addr_mask, 4); + os_memcpy(addr + 8, conf->ip_addr_go, 4); pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC, addr, sizeof(addr), NULL, 0); } #endif /* CONFIG_P2P */ + if (conf->transition_disable) + pos = wpa_add_kde(pos, WFA_KEY_DATA_TRANSITION_DISABLE, + &conf->transition_disable, 1, NULL, 0); + +#ifdef CONFIG_DPP2 + if (DPP_VERSION > 1 && sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) { + u8 payload[2]; + + payload[0] = DPP_VERSION; /* Protocol Version */ + payload[1] = 0; /* Flags */ + if (conf->dpp_pfs == 0) + payload[1] |= DPP_KDE_PFS_ALLOWED; + else if (conf->dpp_pfs == 1) + payload[1] |= DPP_KDE_PFS_ALLOWED | + DPP_KDE_PFS_REQUIRED; + pos = wpa_add_kde(pos, WFA_KEY_DATA_DPP, + payload, sizeof(payload), NULL, 0); + } +#endif /* CONFIG_DPP2 */ + wpa_send_eapol(sm->wpa_auth, sm, (secure ? WPA_KEY_INFO_SECURE : 0) | (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? @@ -3427,25 +3600,34 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) done: os_free(kde); os_free(wpa_ie_buf); + os_free(wpa_ie_buf2); } SM_STATE(WPA_PTK, PTKINITDONE) { SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); - sm->EAPOLKeyReceived = FALSE; + sm->EAPOLKeyReceived = false; if (sm->Pair) { enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise); int klen = wpa_cipher_key_len(sm->pairwise); - if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, - sm->PTK.tk, klen, - KEY_FLAG_PAIRWISE_RX_TX)) { + int res; + + if (sm->use_ext_key_id) + res = wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr, + sm->keyidx_active, NULL, 0, + KEY_FLAG_PAIRWISE_RX_TX_MODIFY); + else + res = wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, + 0, sm->PTK.tk, klen, + KEY_FLAG_PAIRWISE_RX_TX); + if (res) { wpa_sta_disconnect(sm->wpa_auth, sm->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); return; } /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ - sm->pairwise_set = TRUE; + sm->pairwise_set = true; wpa_auth_set_ptk_rekey_timer(sm); @@ -3467,12 +3649,13 @@ SM_STATE(WPA_PTK, PTKINITDONE) wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 1); } - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, 0); - wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, 1); + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, + false); + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, true); if (sm->wpa == WPA_VERSION_WPA) - sm->PInitAKeys = TRUE; + sm->PInitAKeys = true; else - sm->has_GTK = TRUE; + sm->has_GTK = true; wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, "pairwise key handshake completed (%s)", sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); @@ -3486,6 +3669,7 @@ SM_STATE(WPA_PTK, PTKINITDONE) SM_STEP(WPA_PTK) { struct wpa_authenticator *wpa_auth = sm->wpa_auth; + struct wpa_auth_config *conf = &wpa_auth->conf; if (sm->Init) SM_ENTER(WPA_PTK, INITIALIZE); @@ -3520,8 +3704,8 @@ SM_STEP(WPA_PTK) break; case WPA_PTK_AUTHENTICATION2: if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && - wpa_auth_get_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_keyRun) > 0) + wpa_auth_get_eapol(wpa_auth, sm->addr, + WPA_EAPOL_keyRun)) SM_ENTER(WPA_PTK, INITPMK); else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE @@ -3531,8 +3715,8 @@ SM_STEP(WPA_PTK) SM_ENTER(WPA_PTK, INITPMK); break; case WPA_PTK_INITPMK: - if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, - WPA_EAPOL_keyAvailable) > 0) { + if (wpa_auth_get_eapol(wpa_auth, sm->addr, + WPA_EAPOL_keyAvailable)) { SM_ENTER(WPA_PTK, PTKSTART); #ifdef CONFIG_DPP } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) { @@ -3540,13 +3724,13 @@ SM_STEP(WPA_PTK) #endif /* CONFIG_DPP */ } else { wpa_auth->dot11RSNA4WayHandshakeFailures++; - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, "INITPMK - keyAvailable = false"); SM_ENTER(WPA_PTK, DISCONNECT); } break; case WPA_PTK_INITPSK: - if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, + if (wpa_auth_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr, NULL, NULL, NULL)) { SM_ENTER(WPA_PTK, PTKSTART); #ifdef CONFIG_SAE @@ -3554,7 +3738,7 @@ SM_STEP(WPA_PTK) SM_ENTER(WPA_PTK, PTKSTART); #endif /* CONFIG_SAE */ } else { - wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, "no PSK configured for the STA"); wpa_auth->dot11RSNA4WayHandshakeFailures++; SM_ENTER(WPA_PTK, DISCONNECT); @@ -3564,13 +3748,13 @@ SM_STEP(WPA_PTK) if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && sm->EAPOLKeyPairwise) SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); - else if (sm->TimeoutCtr > - sm->wpa_auth->conf.wpa_pairwise_update_count) { + else if (sm->TimeoutCtr > conf->wpa_pairwise_update_count) { wpa_auth->dot11RSNA4WayHandshakeFailures++; - wpa_auth_vlogger( - sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "PTKSTART: Retry limit %u reached", - sm->wpa_auth->conf.wpa_pairwise_update_count); + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "PTKSTART: Retry limit %u reached", + conf->wpa_pairwise_update_count); + sm->disconnect_reason = + WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT; SM_ENTER(WPA_PTK, DISCONNECT); } else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK, PTKSTART); @@ -3594,14 +3778,15 @@ SM_STEP(WPA_PTK) sm->EAPOLKeyPairwise && sm->MICVerified) SM_ENTER(WPA_PTK, PTKINITDONE); else if (sm->TimeoutCtr > - sm->wpa_auth->conf.wpa_pairwise_update_count || - (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + conf->wpa_pairwise_update_count || + (conf->wpa_disable_eapol_key_retries && sm->TimeoutCtr > 1)) { wpa_auth->dot11RSNA4WayHandshakeFailures++; - wpa_auth_vlogger( - sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "PTKINITNEGOTIATING: Retry limit %u reached", - sm->wpa_auth->conf.wpa_pairwise_update_count); + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "PTKINITNEGOTIATING: Retry limit %u reached", + conf->wpa_pairwise_update_count); + sm->disconnect_reason = + WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT; SM_ENTER(WPA_PTK, DISCONNECT); } else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); @@ -3618,7 +3803,7 @@ SM_STATE(WPA_PTK_GROUP, IDLE) if (sm->Init) { /* Init flag is not cleared here, so avoid busy * loop by claiming nothing changed. */ - sm->changed = FALSE; + sm->changed = false; } sm->GTimeoutCtr = 0; } @@ -3632,24 +3817,24 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) u8 *kde_buf = NULL, *pos, hdr[2]; size_t kde_len; u8 *gtk, dummy_gtk[32]; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); sm->GTimeoutCtr++; - if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && - sm->GTimeoutCtr > 1) { + if (conf->wpa_disable_eapol_key_retries && sm->GTimeoutCtr > 1) { /* Do not allow retransmission of EAPOL-Key group msg 1/2 */ return; } - if (sm->GTimeoutCtr > sm->wpa_auth->conf.wpa_group_update_count) { + if (sm->GTimeoutCtr > conf->wpa_group_update_count) { /* No point in sending the EAPOL-Key - we will disconnect * immediately following this. */ return; } if (sm->wpa == WPA_VERSION_WPA) - sm->PInitAKeys = FALSE; - sm->TimeoutEvt = FALSE; + sm->PInitAKeys = false; + sm->TimeoutEvt = false; /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ os_memset(rsc, 0, WPA_KEY_RSC_LEN); if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE) @@ -3658,8 +3843,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) "sending 1/2 msg of Group Key Handshake"); gtk = gsm->GTK[gsm->GN - 1]; - if (sm->wpa_auth->conf.disable_gtk || - sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { /* * Provide unique random GTK to each STA to prevent use * of GTK in the BSS. @@ -3672,7 +3856,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); kde_buf = os_malloc(kde_len); - if (kde_buf == NULL) + if (!kde_buf) return; kde = pos = kde_buf; @@ -3681,7 +3865,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, gtk, gsm->GTK_len); pos = ieee80211w_kde_add(sm, pos); - if (ocv_oci_add(sm, &pos) < 0) { + if (ocv_oci_add(sm, &pos, + conf->oci_freq_override_eapol_g1) < 0) { os_free(kde_buf); return; } @@ -3705,8 +3890,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) { -#ifdef CONFIG_OCV struct wpa_authenticator *wpa_auth = sm->wpa_auth; +#ifdef CONFIG_OCV const u8 *key_data, *mic; struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; @@ -3716,7 +3901,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) #endif /* CONFIG_OCV */ SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); - sm->EAPOLKeyReceived = FALSE; + sm->EAPOLKeyReceived = false; #ifdef CONFIG_OCV mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); @@ -3747,7 +3932,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) if (wpa_channel_info(wpa_auth, &ci) != 0) { wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - "Failed to get channel info to validate received OCI in EAPOL-Key group 1/2"); + "Failed to get channel info to validate received OCI in EAPOL-Key group 2/2"); return; } @@ -3758,9 +3943,15 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) return; if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != 0) { - wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, - ocv_errorstr); + tx_chanwidth, tx_seg1_idx) != + OCI_SUCCESS) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "OCV failed: %s", ocv_errorstr); + if (wpa_auth->conf.msg_ctx) + wpa_msg(wpa_auth->conf.msg_ctx, MSG_INFO, + OCV_FAILURE "addr=" MACSTR + " frame=eapol-key-g2 error=%s", + MAC2STR(sm->addr), ocv_errorstr); return; } } @@ -3768,13 +3959,13 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) if (sm->GUpdateStationKeys) sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; + sm->GUpdateStationKeys = false; sm->GTimeoutCtr = 0; /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, "group key handshake completed (%s)", sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); - sm->has_GTK = TRUE; + sm->has_GTK = true; } @@ -3783,8 +3974,9 @@ SM_STATE(WPA_PTK_GROUP, KEYERROR) SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group); if (sm->GUpdateStationKeys) sm->group->GKeyDoneStations--; - sm->GUpdateStationKeys = FALSE; - sm->Disconnect = TRUE; + sm->GUpdateStationKeys = false; + sm->Disconnect = true; + sm->disconnect_reason = WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT; wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, "group key handshake failed (%s) after %u tries", sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN", @@ -3796,7 +3988,7 @@ SM_STEP(WPA_PTK_GROUP) { if (sm->Init || sm->PtkGroupInit) { SM_ENTER(WPA_PTK_GROUP, IDLE); - sm->PtkGroupInit = FALSE; + sm->PtkGroupInit = false; } else switch (sm->wpa_ptk_group_state) { case WPA_PTK_GROUP_IDLE: if (sm->GUpdateStationKeys || @@ -3828,7 +4020,9 @@ SM_STEP(WPA_PTK_GROUP) static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { + struct wpa_auth_config *conf = &wpa_auth->conf; int ret = 0; + size_t len; os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); inc_byte_array(group->Counter, WPA_NONCE_LEN); @@ -3839,9 +4033,8 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, wpa_hexdump_key(MSG_DEBUG, "GTK", group->GTK[group->GN - 1], group->GTK_len); - if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { - size_t len; - len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { + len = wpa_cipher_key_len(conf->group_mgmt_cipher); os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); inc_byte_array(group->Counter, WPA_NONCE_LEN); if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion", @@ -3852,6 +4045,19 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, group->IGTK[group->GN_igtk - 4], len); } + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION && + conf->beacon_prot) { + len = wpa_cipher_key_len(conf->group_mgmt_cipher); + os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); + inc_byte_array(group->Counter, WPA_NONCE_LEN); + if (wpa_gmk_to_gtk(group->GMK, "BIGTK key expansion", + wpa_auth->addr, group->GNonce, + group->BIGTK[group->GN_bigtk - 6], len) < 0) + ret = -1; + wpa_hexdump_key(MSG_DEBUG, "BIGTK", + group->BIGTK[group->GN_bigtk - 6], len); + } + return ret; } @@ -3859,9 +4065,10 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " - "GTK_INIT (VLAN-ID %d)", group->vlan_id); - group->changed = FALSE; /* GInit is not cleared here; avoid loop */ + wpa_printf(MSG_DEBUG, + "WPA: group state machine entering state GTK_INIT (VLAN-ID %d)", + group->vlan_id); + group->changed = false; /* GInit is not cleared here; avoid loop */ group->wpa_group_state = WPA_GROUP_GTK_INIT; /* GTK[0..N] = 0 */ @@ -3870,6 +4077,8 @@ static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, group->GM = 2; group->GN_igtk = 4; group->GM_igtk = 5; + group->GN_bigtk = 6; + group->GM_bigtk = 7; /* GTK[GN] = CalcGTK() */ wpa_gtk_update(wpa_auth, group); } @@ -3883,7 +4092,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) { wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "Not in PTKINITDONE; skip Group Key update"); - sm->GUpdateStationKeys = FALSE; + sm->GUpdateStationKeys = false; return 0; } if (sm->GUpdateStationKeys) { @@ -3893,8 +4102,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) * station needs to be counted here anyway. */ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "GUpdateStationKeys was already set when " - "marking station for GTK rekeying"); + "GUpdateStationKeys was already set when marking station for GTK rekeying"); } /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */ @@ -3902,7 +4110,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) return 0; sm->group->GKeyDoneStations++; - sm->GUpdateStationKeys = TRUE; + sm->GUpdateStationKeys = true; wpa_sm_step(sm); return 0; @@ -3913,7 +4121,7 @@ static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) /* update GTK when exiting WNM-Sleep Mode */ void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm) { - if (sm == NULL || sm->is_wnmsleep) + if (!sm || sm->is_wnmsleep) return; wpa_group_update_sta(sm, NULL); @@ -3929,6 +4137,7 @@ void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag) int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) { + struct wpa_auth_config *conf = &sm->wpa_auth->conf; struct wpa_group *gsm = sm->group; u8 *start = pos; @@ -3947,6 +4156,14 @@ int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) return 0; pos += 8; os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len); + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random GTK to each STA to prevent use + * of GTK in the BSS. + */ + if (random_get_bytes(pos, gsm->GTK_len) < 0) + return 0; + } pos += gsm->GTK_len; wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit", @@ -3960,6 +4177,7 @@ int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) { + struct wpa_auth_config *conf = &sm->wpa_auth->conf; struct wpa_group *gsm = sm->group; u8 *start = pos; size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); @@ -3977,6 +4195,14 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) pos += 6; os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len); + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random IGTK to each STA to prevent use + * of IGTK in the BSS. + */ + if (random_get_bytes(pos, len) < 0) + return 0; + } pos += len; wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit", @@ -3987,6 +4213,44 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) return pos - start; } + +int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos) +{ + struct wpa_group *gsm = sm->group; + u8 *start = pos; + size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + + /* + * BIGTK subelement: + * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16] + */ + *pos++ = WNM_SLEEP_SUBELEM_BIGTK; + *pos++ = 2 + 6 + len; + WPA_PUT_LE16(pos, gsm->GN_bigtk); + pos += 2; + if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos) != 0) + return 0; + pos += 6; + + os_memcpy(pos, gsm->BIGTK[gsm->GN_bigtk - 6], len); + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random BIGTK to each STA to prevent use + * of BIGTK in the BSS. + */ + if (random_get_bytes(pos, len) < 0) + return 0; + } + pos += len; + + wpa_printf(MSG_DEBUG, "WNM: BIGTK Key ID %u in WNM-Sleep Mode exit", + gsm->GN_bigtk); + wpa_hexdump_key(MSG_DEBUG, "WNM: BIGTK in WNM-Sleep Mode exit", + gsm->IGTK[gsm->GN_bigtk - 6], len); + + return pos - start; +} + #endif /* CONFIG_WNM_AP */ @@ -3995,25 +4259,29 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, { int tmp; - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " - "SETKEYS (VLAN-ID %d)", group->vlan_id); - group->changed = TRUE; + wpa_printf(MSG_DEBUG, + "WPA: group state machine entering state SETKEYS (VLAN-ID %d)", + group->vlan_id); + group->changed = true; group->wpa_group_state = WPA_GROUP_SETKEYS; - group->GTKReKey = FALSE; + group->GTKReKey = false; tmp = group->GM; group->GM = group->GN; group->GN = tmp; tmp = group->GM_igtk; group->GM_igtk = group->GN_igtk; group->GN_igtk = tmp; + tmp = group->GM_bigtk; + group->GM_bigtk = group->GN_bigtk; + group->GN_bigtk = tmp; /* "GKeyDoneStations = GNoStations" is done in more robust way by * counting the STAs that are marked with GUpdateStationKeys instead of * including all STAs that could be in not-yet-completed state. */ wpa_gtk_update(wpa_auth, group); if (group->GKeyDoneStations) { - wpa_printf(MSG_DEBUG, "wpa_group_setkeys: Unexpected " - "GKeyDoneStations=%d when starting new GTK rekey", + wpa_printf(MSG_DEBUG, + "wpa_group_setkeys: Unexpected GKeyDoneStations=%d when starting new GTK rekey", group->GKeyDoneStations); group->GKeyDoneStations = 0; } @@ -4026,21 +4294,22 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { + struct wpa_auth_config *conf = &wpa_auth->conf; int ret = 0; if (wpa_auth_set_key(wpa_auth, group->vlan_id, - wpa_cipher_to_alg(wpa_auth->conf.wpa_group), + wpa_cipher_to_alg(conf->wpa_group), broadcast_ether_addr, group->GN, group->GTK[group->GN - 1], group->GTK_len, KEY_FLAG_GROUP_TX_DEFAULT) < 0) ret = -1; - if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { enum wpa_alg alg; size_t len; - alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher); - len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); + alg = wpa_cipher_to_alg(conf->group_mgmt_cipher); + len = wpa_cipher_key_len(conf->group_mgmt_cipher); if (ret == 0 && wpa_auth_set_key(wpa_auth, group->vlan_id, alg, @@ -4048,6 +4317,13 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, group->IGTK[group->GN_igtk - 4], len, KEY_FLAG_GROUP_TX_DEFAULT) < 0) ret = -1; + + if (ret == 0 && conf->beacon_prot && + wpa_auth_set_key(wpa_auth, group->vlan_id, alg, + broadcast_ether_addr, group->GN_bigtk, + group->BIGTK[group->GN_bigtk - 6], len, + KEY_FLAG_GROUP_TX_DEFAULT) < 0) + ret = -1; } return ret; @@ -4058,9 +4334,9 @@ static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx) { if (sm->group == ctx) { wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR - " for discconnection due to fatal failure", + " for disconnection due to fatal failure", MAC2STR(sm->addr)); - sm->Disconnect = TRUE; + sm->Disconnect = true; } return 0; @@ -4070,8 +4346,9 @@ static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx) static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE"); - group->changed = TRUE; + wpa_printf(MSG_DEBUG, + "WPA: group state machine entering state FATAL_FAILURE"); + group->changed = true; group->wpa_group_state = WPA_GROUP_FATAL_FAILURE; wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group); } @@ -4080,9 +4357,10 @@ static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth, static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, struct wpa_group *group) { - wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " - "SETKEYSDONE (VLAN-ID %d)", group->vlan_id); - group->changed = TRUE; + wpa_printf(MSG_DEBUG, + "WPA: group state machine entering state SETKEYSDONE (VLAN-ID %d)", + group->vlan_id); + group->changed = true; group->wpa_group_state = WPA_GROUP_SETKEYSDONE; if (wpa_group_config_group_keys(wpa_auth, group) < 0) { @@ -4118,7 +4396,7 @@ static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, static int wpa_sm_step(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return 0; if (sm->in_step_loop) { @@ -4134,8 +4412,8 @@ static int wpa_sm_step(struct wpa_state_machine *sm) if (sm->pending_deinit) break; - sm->changed = FALSE; - sm->wpa_auth->group->changed = FALSE; + sm->changed = false; + sm->wpa_auth->group->changed = false; SM_STEP_RUN(WPA_PTK); if (sm->pending_deinit) @@ -4148,8 +4426,9 @@ static int wpa_sm_step(struct wpa_state_machine *sm) sm->in_step_loop = 0; if (sm->pending_deinit) { - wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state " - "machine deinit for " MACSTR, MAC2STR(sm->addr)); + wpa_printf(MSG_DEBUG, + "WPA: Completing pending STA state machine deinit for " + MACSTR, MAC2STR(sm->addr)); wpa_free_sta_sm(sm); return 1; } @@ -4166,7 +4445,7 @@ static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx) void wpa_auth_sm_notify(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return; eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL); } @@ -4177,7 +4456,7 @@ void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth) int tmp, i; struct wpa_group *group; - if (wpa_auth == NULL) + if (!wpa_auth) return; group = wpa_auth->group; @@ -4189,6 +4468,9 @@ void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth) tmp = group->GM_igtk; group->GM_igtk = group->GN_igtk; group->GN_igtk = tmp; + tmp = group->GM_bigtk; + group->GM_bigtk = group->GN_bigtk; + group->GN_bigtk = tmp; wpa_gtk_update(wpa_auth, group); wpa_group_config_group_keys(wpa_auth, group); } @@ -4207,6 +4489,7 @@ static const char * wpa_bool_txt(int val) int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) { + struct wpa_auth_config *conf; int len = 0, ret; char pmkid_txt[PMKID_LEN * 2 + 1]; #ifdef CONFIG_RSN_PREAUTH @@ -4215,8 +4498,9 @@ int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) const int preauth = 0; #endif /* CONFIG_RSN_PREAUTH */ - if (wpa_auth == NULL) + if (!wpa_auth) return len; + conf = &wpa_auth->conf; ret = os_snprintf(buf + len, buflen - len, "dot11RSNAOptionImplemented=TRUE\n" @@ -4224,8 +4508,8 @@ int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) "dot11RSNAEnabled=%s\n" "dot11RSNAPreauthenticationEnabled=%s\n", wpa_bool_txt(preauth), - wpa_bool_txt(wpa_auth->conf.wpa & WPA_PROTO_RSN), - wpa_bool_txt(wpa_auth->conf.rsn_preauth)); + wpa_bool_txt(conf->wpa & WPA_PROTO_RSN), + wpa_bool_txt(conf->rsn_preauth)); if (os_snprintf_error(buflen - len, ret)) return len; len += ret; @@ -4260,10 +4544,10 @@ int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) "dot11RSNA4WayHandshakeFailures=%u\n" "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n", RSN_VERSION, - !!wpa_auth->conf.wpa_strict_rekey, - wpa_auth->conf.wpa_group_update_count, - wpa_auth->conf.wpa_pairwise_update_count, - wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8, + !!conf->wpa_strict_rekey, + conf->wpa_group_update_count, + conf->wpa_pairwise_update_count, + wpa_cipher_key_len(conf->wpa_group) * 8, dot11RSNAConfigPMKLifetime, dot11RSNAConfigPMKReauthThreshold, dot11RSNAConfigSATimeout, @@ -4299,7 +4583,7 @@ int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen) int len = 0, ret; u32 pairwise = 0; - if (sm == NULL) + if (!sm) return 0; /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */ @@ -4380,7 +4664,7 @@ const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len) int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return -1; return sm->wpa_key_mgmt; } @@ -4388,7 +4672,7 @@ int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return 0; return sm->wpa; } @@ -4413,7 +4697,7 @@ int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm) int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, struct rsn_pmksa_cache_entry *entry) { - if (sm == NULL || sm->pmksa != entry) + if (!sm || sm->pmksa != entry) return -1; sm->pmksa = NULL; return 0; @@ -4436,7 +4720,7 @@ void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm) const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len) { - if (wpa_auth == NULL) + if (!wpa_auth) return NULL; *len = wpa_auth->wpa_ie_len; return wpa_auth->wpa_ie; @@ -4447,7 +4731,7 @@ int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, unsigned int pmk_len, int session_timeout, struct eapol_state_machine *eapol) { - if (sm == NULL || sm->wpa != WPA_VERSION_WPA2 || + if (!sm || sm->wpa != WPA_VERSION_WPA2 || sm->wpa_auth->conf.disable_pmksa_caching) return -1; @@ -4483,7 +4767,7 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, int session_timeout, struct eapol_state_machine *eapol) { - if (wpa_auth == NULL) + if (!wpa_auth) return -1; wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len); @@ -4544,7 +4828,7 @@ void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, { struct rsn_pmksa_cache_entry *pmksa; - if (wpa_auth == NULL || wpa_auth->pmksa == NULL) + if (!wpa_auth || !wpa_auth->pmksa) return; pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL); if (pmksa) { @@ -4710,13 +4994,13 @@ wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id) { struct wpa_group *group; - if (wpa_auth == NULL || wpa_auth->group == NULL) + if (!wpa_auth || !wpa_auth->group) return NULL; wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d", vlan_id); group = wpa_group_init(wpa_auth, vlan_id, 0); - if (group == NULL) + if (!group) return NULL; group->next = wpa_auth->group->next; @@ -4736,7 +5020,7 @@ int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id) { struct wpa_group *group; - if (wpa_auth == NULL) + if (!wpa_auth) return 0; group = wpa_auth->group; @@ -4746,9 +5030,9 @@ int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id) group = group->next; } - if (group == NULL) { + if (!group) { group = wpa_auth_add_group(wpa_auth, vlan_id); - if (group == NULL) + if (!group) return -1; } @@ -4777,7 +5061,7 @@ int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id) struct wpa_group *group; int ret = 0; - if (wpa_auth == NULL) + if (!wpa_auth) return 0; group = wpa_auth->group; @@ -4787,7 +5071,7 @@ int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id) group = group->next; } - if (group == NULL) + if (!group) return -1; wpa_printf(MSG_DEBUG, @@ -4822,7 +5106,7 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) { struct wpa_group *group; - if (sm == NULL || sm->wpa_auth == NULL) + if (!sm || !sm->wpa_auth) return 0; group = sm->wpa_auth->group; @@ -4832,9 +5116,9 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) group = group->next; } - if (group == NULL) { + if (!group) { group = wpa_auth_add_group(sm->wpa_auth, vlan_id); - if (group == NULL) + if (!group) return -1; } @@ -4844,8 +5128,9 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) return -1; - wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state " - "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id); + wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR + " to use group state machine for VLAN ID %d", + MAC2STR(sm->addr), vlan_id); wpa_group_get(sm->wpa_auth, group); wpa_group_put(sm->wpa_auth, sm->group); @@ -4858,7 +5143,7 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, int ack) { - if (wpa_auth == NULL || sm == NULL) + if (!wpa_auth || !sm) return; wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR " ack=%d", MAC2STR(sm->addr), ack); @@ -4874,8 +5159,8 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, * the station has received the frame. */ int timeout_ms = eapol_key_timeout_subseq; - wpa_printf(MSG_DEBUG, "WPA: Increase initial EAPOL-Key 1/4 " - "timeout by %u ms because of acknowledged frame", + wpa_printf(MSG_DEBUG, + "WPA: Increase initial EAPOL-Key 1/4 timeout by %u ms because of acknowledged frame", timeout_ms); eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); eloop_register_timeout(timeout_ms / 1000, @@ -4895,7 +5180,7 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, int wpa_auth_uses_sae(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return 0; return wpa_key_mgmt_sae(sm->wpa_key_mgmt); } @@ -4903,7 +5188,7 @@ int wpa_auth_uses_sae(struct wpa_state_machine *sm) int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm) { - if (sm == NULL) + if (!sm) return 0; return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE; } @@ -4912,7 +5197,7 @@ int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm) #ifdef CONFIG_P2P int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr) { - if (sm == NULL || WPA_GET_BE32(sm->ip_addr) == 0) + if (!sm || WPA_GET_BE32(sm->ip_addr) == 0) return -1; os_memcpy(addr, sm->ip_addr, 4); return 0; @@ -4988,7 +5273,7 @@ int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384, return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder, conf->r0_key_holder_len, - NULL, NULL, buf, len, NULL, 0); + NULL, NULL, buf, len, NULL, 0, 0); } #endif /* CONFIG_IEEE80211R_AP */ @@ -5034,6 +5319,14 @@ void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z) #endif /* CONFIG_DPP2 */ +void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth, + u8 val) +{ + if (wpa_auth) + wpa_auth->conf.transition_disable = val; +} + + #ifdef CONFIG_TESTING_OPTIONS int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce, @@ -5065,12 +5358,14 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos; u8 *opos; size_t gtk_len, kde_len; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; struct wpa_group *gsm = sm->group; u8 *wpa_ie; int wpa_ie_len, secure, gtkidx, encr = 0; + u8 hdr[2]; /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], - GTK[GN], IGTK, [FTIE], [TIE * 2]) + GTK[GN], IGTK, [BIGTK], [FTIE], [TIE * 2]) */ /* Use 0 RSC */ @@ -5113,13 +5408,16 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, * WPA if the supplicant used it first. */ wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, - "STA used Secure bit in WPA msg 2/4 - " - "set Secure for 3/4 as workaround"); + "STA used Secure bit in WPA msg 2/4 - set Secure for 3/4 as workaround"); secure = 1; } } kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); + + if (sm->use_ext_key_id) + kde_len += 2 + RSN_SELECTOR_LEN + 2; + if (gtk) kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; #ifdef CONFIG_IEEE80211R_AP @@ -5129,7 +5427,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, } #endif /* CONFIG_IEEE80211R_AP */ kde = os_malloc(kde_len); - if (kde == NULL) + if (!kde) return -1; pos = kde; @@ -5143,8 +5441,8 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, elen = pos - kde; res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name); if (res < 0) { - wpa_printf(MSG_ERROR, "FT: Failed to insert " - "PMKR1Name into RSN IE in EAPOL-Key data"); + wpa_printf(MSG_ERROR, + "FT: Failed to insert PMKR1Name into RSN IE in EAPOL-Key data"); os_free(kde); return -1; } @@ -5152,10 +5450,15 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, pos += elen; } #endif /* CONFIG_IEEE80211R_AP */ + hdr[1] = 0; + + if (sm->use_ext_key_id) { + hdr[0] = sm->keyidx_active & 0x01; + pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0); + } + if (gtk) { - u8 hdr[2]; hdr[0] = gtkidx & 0x03; - hdr[1] = 0; pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, gtk, gtk_len); } @@ -5166,7 +5469,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, opos += 2 + RSN_SELECTOR_LEN + 2; os_memset(opos, 0, 6); /* clear PN */ } - if (ocv_oci_add(sm, &pos) < 0) { + if (ocv_oci_add(sm, &pos, conf->oci_freq_override_eapol_m3) < 0) { os_free(kde); return -1; } @@ -5174,9 +5477,7 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, #ifdef CONFIG_IEEE80211R_AP if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { int res; - struct wpa_auth_config *conf; - conf = &sm->wpa_auth->conf; if (sm->assoc_resp_ftie && kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) { os_memcpy(pos, sm->assoc_resp_ftie, @@ -5190,11 +5491,11 @@ int wpa_auth_resend_m3(struct wpa_state_machine *sm, conf->r0_key_holder_len, NULL, NULL, pos, kde + kde_len - pos, - NULL, 0); + NULL, 0, 0); } if (res < 0) { - wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " - "into EAPOL-Key Key Data"); + wpa_printf(MSG_ERROR, + "FT: Failed to insert FTIE into EAPOL-Key Key Data"); os_free(kde); return -1; } @@ -5233,6 +5534,7 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm, void *ctx1, void *ctx2) { u8 rsc[WPA_KEY_RSC_LEN]; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; struct wpa_group *gsm = sm->group; const u8 *kde; u8 *kde_buf = NULL, *pos, hdr[2]; @@ -5251,7 +5553,7 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm, kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); kde_buf = os_malloc(kde_len); - if (kde_buf == NULL) + if (!kde_buf) return -1; kde = pos = kde_buf; @@ -5267,7 +5569,8 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm, opos += 2 + RSN_SELECTOR_LEN + 2; os_memset(opos, 0, 6); /* clear PN */ } - if (ocv_oci_add(sm, &pos) < 0) { + if (ocv_oci_add(sm, &pos, + conf->oci_freq_override_eapol_g1) < 0) { os_free(kde_buf); return -1; } @@ -5303,13 +5606,42 @@ int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth) } +#ifdef CONFIG_TESTING_OPTIONS int wpa_auth_rekey_ptk(struct wpa_state_machine *sm, int early_install) { eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); -#ifdef CONFIG_TESTING_OPTIONS sm->early_install = early_install; -#endif /* CONFIG_TESTING_OPTIONS */ return eloop_register_timeout(0, 0, wpa_rekey_ptk, sm->wpa_auth, sm); } +#endif /* CONFIG_TESTING_OPTIONS */ + +void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val) +{ + if (wpa_auth) + wpa_auth->conf.ft_rsnxe_used = val; +} + + +void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth, + enum wpa_auth_ocv_override_frame frame, + unsigned int freq) +{ + if (!wpa_auth) + return; + switch (frame) { + case WPA_AUTH_OCV_OVERRIDE_EAPOL_M3: + wpa_auth->conf.oci_freq_override_eapol_m3 = freq; + break; + case WPA_AUTH_OCV_OVERRIDE_EAPOL_G1: + wpa_auth->conf.oci_freq_override_eapol_g1 = freq; + break; + case WPA_AUTH_OCV_OVERRIDE_FT_ASSOC: + wpa_auth->conf.oci_freq_override_ft_assoc = freq; + break; + case WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC: + wpa_auth->conf.oci_freq_override_fils_assoc = freq; + break; + } +} #endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 19986c808..2c49380e7 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -169,7 +169,9 @@ struct ft_remote_r1kh { struct wpa_auth_config { + void *msg_ctx; int wpa; + int extended_key_id; int wpa_key_mgmt; int wpa_pairwise; int wpa_group; @@ -177,6 +179,7 @@ struct wpa_auth_config { int wpa_strict_rekey; int wpa_gmk_rekey; int wpa_ptk_rekey; + int wpa_deny_ptk0_rekey; u32 wpa_group_update_count; u32 wpa_pairwise_update_count; int wpa_disable_eapol_key_retries; @@ -189,6 +192,7 @@ struct wpa_auth_config { int okc; int tx_status; enum mfp_options ieee80211w; + int beacon_prot; int group_mgmt_cipher; int sae_require_mfp; #ifdef CONFIG_OCV @@ -220,13 +224,28 @@ struct wpa_auth_config { double corrupt_gtk_rekey_mic_probability; u8 own_ie_override[MAX_OWN_IE_OVERRIDE]; size_t own_ie_override_len; + u8 rsne_override_eapol[MAX_OWN_IE_OVERRIDE]; + size_t rsne_override_eapol_len; u8 rsnxe_override_eapol[MAX_OWN_IE_OVERRIDE]; size_t rsnxe_override_eapol_len; + u8 rsne_override_ft[MAX_OWN_IE_OVERRIDE]; + size_t rsne_override_ft_len; + u8 rsnxe_override_ft[MAX_OWN_IE_OVERRIDE]; + size_t rsnxe_override_ft_len; u8 gtk_rsc_override[WPA_KEY_RSC_LEN]; u8 igtk_rsc_override[WPA_KEY_RSC_LEN]; + unsigned int rsne_override_eapol_set:1; + unsigned int rsnxe_override_eapol_set:1; + unsigned int rsne_override_ft_set:1; + unsigned int rsnxe_override_ft_set:1; unsigned int gtk_rsc_override_set:1; unsigned int igtk_rsc_override_set:1; + int ft_rsnxe_used; #endif /* CONFIG_TESTING_OPTIONS */ + unsigned int oci_freq_override_eapol_m3; + unsigned int oci_freq_override_eapol_g1; + unsigned int oci_freq_override_ft_assoc; + unsigned int oci_freq_override_fils_assoc; #ifdef CONFIG_P2P u8 ip_addr_go[4]; u8 ip_addr_mask[4]; @@ -238,7 +257,12 @@ struct wpa_auth_config { u8 fils_cache_id[FILS_CACHE_ID_LEN]; #endif /* CONFIG_FILS */ int sae_pwe; + bool sae_pk; int owe_ptk_workaround; + u8 transition_disable; +#ifdef CONFIG_DPP2 + int dpp_pfs; +#endif /* CONFIG_DPP2 */ }; typedef enum { @@ -285,6 +309,7 @@ struct wpa_auth_callbacks { int *bandwidth, int *seg1_idx); #ifdef CONFIG_IEEE80211R_AP struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr); + int (*add_sta_ft)(void *ctx, const u8 *sta_addr); int (*set_vlan)(void *ctx, const u8 *sta_addr, struct vlan_description *vlan); int (*get_vlan)(void *ctx, const u8 *sta_addr, @@ -318,19 +343,21 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth); int wpa_reconfig(struct wpa_authenticator *wpa_auth, struct wpa_auth_config *conf); -enum { +enum wpa_validate_result { WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE, WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL, WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER, - WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID + WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID, + WPA_DENIED_OTHER_REASON }; -int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, int freq, - const u8 *wpa_ie, size_t wpa_ie_len, - const u8 *rsnxe, size_t rsnxe_len, - const u8 *mdie, size_t mdie_len, - const u8 *owe_dh, size_t owe_dh_len); +enum wpa_validate_result +wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int freq, + const u8 *wpa_ie, size_t wpa_ie_len, + const u8 *rsnxe, size_t rsnxe_len, + const u8 *mdie, size_t mdie_len, + const u8 *owe_dh, size_t owe_dh_len); int wpa_validate_osen(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, const u8 *osen_ie, size_t osen_ie_len); @@ -414,14 +441,15 @@ void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, #ifdef CONFIG_IEEE80211R_AP u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, size_t max_len, int auth_alg, - const u8 *req_ies, size_t req_ies_len); + const u8 *req_ies, size_t req_ies_len, + int omit_rsnxe); void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, u16 auth_transaction, const u8 *ies, size_t ies_len, void (*cb)(void *ctx, const u8 *dst, const u8 *bssid, u16 auth_transaction, u16 resp, const u8 *ies, size_t ies_len), void *ctx); -u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, +int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, size_t ies_len); int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len); int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, @@ -438,6 +466,7 @@ void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm); void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag); int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos); int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos); +int wpa_wnmsleep_bigtk_subelem(struct wpa_state_machine *sm, u8 *pos); int wpa_auth_uses_sae(struct wpa_state_machine *sm); int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm); @@ -489,6 +518,8 @@ u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm, const u8 *req_ies, size_t req_ies_len); void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg); void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z); +void wpa_auth_set_transition_disable(struct wpa_authenticator *wpa_auth, + u8 val); int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce, void (*cb)(void *ctx1, void *ctx2), @@ -502,5 +533,16 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm, int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth); int wpa_auth_rekey_ptk(struct wpa_state_machine *sm, int early_install); void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm); +void wpa_auth_set_ft_rsnxe_used(struct wpa_authenticator *wpa_auth, int val); + +enum wpa_auth_ocv_override_frame { + WPA_AUTH_OCV_OVERRIDE_EAPOL_M3, + WPA_AUTH_OCV_OVERRIDE_EAPOL_G1, + WPA_AUTH_OCV_OVERRIDE_FT_ASSOC, + WPA_AUTH_OCV_OVERRIDE_FILS_ASSOC, +}; +void wpa_auth_set_ocv_override_freq(struct wpa_authenticator *wpa_auth, + enum wpa_auth_ocv_override_frame frame, + unsigned int freq); #endif /* WPA_AUTH_H */ diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index 462876195..5aa363eca 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -14,6 +14,7 @@ #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/ocv.h" +#include "common/wpa_ctrl.h" #include "drivers/driver.h" #include "crypto/aes.h" #include "crypto/aes_siv.h" @@ -808,7 +809,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, const u8 *r0kh_id, size_t r0kh_id_len, const u8 *anonce, const u8 *snonce, u8 *buf, size_t len, const u8 *subelem, - size_t subelem_len) + size_t subelem_len, int rsnxe_used) { u8 *pos = buf, *ielen; size_t hdrlen = use_sha384 ? sizeof(struct rsn_ftie_sha384) : @@ -826,7 +827,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, os_memset(hdr, 0, sizeof(*hdr)); pos += sizeof(*hdr); - WPA_PUT_LE16(hdr->mic_control, 0); + WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used); if (anonce) os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); if (snonce) @@ -836,7 +837,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, os_memset(hdr, 0, sizeof(*hdr)); pos += sizeof(*hdr); - WPA_PUT_LE16(hdr->mic_control, 0); + WPA_PUT_LE16(hdr->mic_control, !!rsnxe_used); if (anonce) os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN); if (snonce) @@ -1897,7 +1898,7 @@ static void wpa_ft_block_r0kh(struct wpa_authenticator *wpa_auth, return; } - wpa_hexdump(MSG_DEBUG, "FT: Blacklist R0KH-ID", + wpa_hexdump(MSG_DEBUG, "FT: Temporarily block R0KH-ID", f_r0kh_id, f_r0kh_id_len); if (r0kh) { @@ -1985,7 +1986,7 @@ static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm, return -1; } if (is_zero_ether_addr(r0kh->addr)) { - wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID is blacklisted", + wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID is temporarily blocked", sm->r0kh_id, sm->r0kh_id_len); return -1; } @@ -2128,8 +2129,6 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk) pmk_r0, pmk_r0_name, wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN); if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len, pmk_r0_name, @@ -2140,9 +2139,6 @@ int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk) if (wpa_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name, r1kh, sm->addr, pmk_r1, sm->pmk_r1_name) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r1_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name, - WPA_PMK_NAME_LEN); if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_len, sm->pmk_r1_name, sm->pairwise, &vlan, @@ -2167,11 +2163,12 @@ static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) { u8 *subelem; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; struct wpa_group *gsm = sm->group; size_t subelem_len, pad_len; const u8 *key; size_t key_len; - u8 keybuf[32]; + u8 keybuf[WPA_GTK_MAX_LEN]; const u8 *kek; size_t kek_len; @@ -2198,12 +2195,30 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) pad_len += 8; if (pad_len && key_len < sizeof(keybuf)) { os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len); + if (conf->disable_gtk || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random GTK to each STA to prevent use + * of GTK in the BSS. + */ + if (random_get_bytes(keybuf, key_len) < 0) + return NULL; + } os_memset(keybuf + key_len, 0, pad_len); keybuf[key_len] = 0xdd; key_len += pad_len; key = keybuf; - } else + } else if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random GTK to each STA to prevent use of GTK + * in the BSS. + */ + if (random_get_bytes(keybuf, key_len) < 0) + return NULL; + key = keybuf; + } else { key = gsm->GTK[gsm->GN - 1]; + } /* * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] | @@ -2237,11 +2252,13 @@ static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len) static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) { u8 *subelem, *pos; + struct wpa_auth_config *conf = &sm->wpa_auth->conf; struct wpa_group *gsm = sm->group; size_t subelem_len; - const u8 *kek; + const u8 *kek, *igtk; size_t kek_len; size_t igtk_len; + u8 dummy_igtk[WPA_IGTK_MAX_LEN]; if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { kek = sm->PTK.kek2; @@ -2268,8 +2285,19 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos); pos += 6; *pos++ = igtk_len; - if (aes_wrap(kek, kek_len, igtk_len / 8, - gsm->IGTK[gsm->GN_igtk - 4], pos)) { + igtk = gsm->IGTK[gsm->GN_igtk - 4]; + if (conf->disable_gtk || sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random IGTK to each STA to prevent use of + * IGTK in the BSS. + */ + if (random_get_bytes(dummy_igtk, igtk_len / 8) < 0) { + os_free(subelem); + return NULL; + } + igtk = dummy_igtk; + } + if (aes_wrap(kek, kek_len, igtk_len / 8, igtk, pos)) { wpa_printf(MSG_DEBUG, "FT: IGTK subelem encryption failed: kek_len=%d", (int) kek_len); @@ -2282,6 +2310,66 @@ static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len) } +static u8 * wpa_ft_bigtk_subelem(struct wpa_state_machine *sm, size_t *len) +{ + u8 *subelem, *pos; + struct wpa_group *gsm = sm->group; + size_t subelem_len; + const u8 *kek, *bigtk; + size_t kek_len; + size_t bigtk_len; + u8 dummy_bigtk[WPA_IGTK_MAX_LEN]; + + if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { + kek = sm->PTK.kek2; + kek_len = sm->PTK.kek2_len; + } else { + kek = sm->PTK.kek; + kek_len = sm->PTK.kek_len; + } + + bigtk_len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + + /* Sub-elem ID[1] | Length[1] | KeyID[2] | BIPN[6] | Key Length[1] | + * Key[16+8] */ + subelem_len = 1 + 1 + 2 + 6 + 1 + bigtk_len + 8; + subelem = os_zalloc(subelem_len); + if (subelem == NULL) + return NULL; + + pos = subelem; + *pos++ = FTIE_SUBELEM_BIGTK; + *pos++ = subelem_len - 2; + WPA_PUT_LE16(pos, gsm->GN_bigtk); + pos += 2; + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_bigtk, pos); + pos += 6; + *pos++ = bigtk_len; + bigtk = gsm->IGTK[gsm->GN_bigtk - 6]; + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random BIGTK to each OSEN STA to prevent use + * of BIGTK in the BSS. + */ + if (random_get_bytes(dummy_bigtk, bigtk_len / 8) < 0) { + os_free(subelem); + return NULL; + } + bigtk = dummy_bigtk; + } + if (aes_wrap(kek, kek_len, bigtk_len / 8, bigtk, pos)) { + wpa_printf(MSG_DEBUG, + "FT: BIGTK subelem encryption failed: kek_len=%d", + (int) kek_len); + os_free(subelem); + return NULL; + } + + *len = subelem_len; + return subelem; +} + + static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm, u8 *pos, u8 *end, u8 id, u8 descr_count, const u8 *ies, size_t ies_len) @@ -2415,13 +2503,15 @@ static u8 * wpa_ft_process_ric(struct wpa_state_machine *sm, u8 *pos, u8 *end, u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, size_t max_len, int auth_alg, - const u8 *req_ies, size_t req_ies_len) + const u8 *req_ies, size_t req_ies_len, + int omit_rsnxe) { u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL; u8 *fte_mic, *elem_count; size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0; - u8 rsnxe[10]; + u8 rsnxe_buf[10], *rsnxe = rsnxe_buf; size_t rsnxe_len; + int rsnxe_used; int res; struct wpa_auth_config *conf; struct wpa_ft_ies parse; @@ -2442,6 +2532,32 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, end = pos + max_len; +#ifdef CONFIG_TESTING_OPTIONS + if (auth_alg == WLAN_AUTH_FT && + sm->wpa_auth->conf.rsne_override_ft_set) { + wpa_printf(MSG_DEBUG, + "TESTING: RSNE FT override for MIC calculation"); + rsnie = sm->wpa_auth->conf.rsne_override_ft; + rsnie_len = sm->wpa_auth->conf.rsne_override_ft_len; + if (end - pos < (long int) rsnie_len) + return pos; + os_memcpy(pos, rsnie, rsnie_len); + rsnie = pos; + pos += rsnie_len; + if (rsnie_len > PMKID_LEN && sm->pmk_r1_name_valid) { + int idx; + + /* Replace all 0xff PMKID with the valid PMKR1Name */ + for (idx = 0; idx < PMKID_LEN; idx++) { + if (rsnie[rsnie_len - 1 - idx] != 0xff) + break; + } + if (idx == PMKID_LEN) + os_memcpy(&rsnie[rsnie_len - PMKID_LEN], + sm->pmk_r1_name, WPA_PMK_NAME_LEN); + } + } else +#endif /* CONFIG_TESTING_OPTIONS */ if (auth_alg == WLAN_AUTH_FT || ((auth_alg == WLAN_AUTH_FILS_SK || auth_alg == WLAN_AUTH_FILS_SK_PFS || @@ -2511,6 +2627,29 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, subelem_len += igtk_len; os_free(igtk); } + if (sm->mgmt_frame_prot && conf->beacon_prot) { + u8 *bigtk; + size_t bigtk_len; + u8 *nbuf; + + bigtk = wpa_ft_bigtk_subelem(sm, &bigtk_len); + if (!bigtk) { + wpa_printf(MSG_DEBUG, + "FT: Failed to add BIGTK subelement"); + os_free(subelem); + return NULL; + } + nbuf = os_realloc(subelem, subelem_len + bigtk_len); + if (!nbuf) { + os_free(subelem); + os_free(bigtk); + return NULL; + } + subelem = nbuf; + os_memcpy(subelem + subelem_len, bigtk, bigtk_len); + subelem_len += bigtk_len; + os_free(bigtk); + } #ifdef CONFIG_OCV if (wpa_auth_uses_ocv(sm)) { struct wpa_channel_info ci; @@ -2522,6 +2661,15 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, os_free(subelem); return NULL; } +#ifdef CONFIG_TESTING_OPTIONS + if (conf->oci_freq_override_ft_assoc) { + wpa_printf(MSG_INFO, + "TEST: Override OCI frequency %d -> %u MHz", + ci.frequency, + conf->oci_freq_override_ft_assoc); + ci.frequency = conf->oci_freq_override_ft_assoc; + } +#endif /* CONFIG_TESTING_OPTIONS */ subelem_len += 2 + OCV_OCI_LEN; nbuf = os_realloc(subelem, subelem_len); @@ -2546,9 +2694,18 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, anonce = NULL; snonce = NULL; } + rsnxe_used = (auth_alg == WLAN_AUTH_FT) && + (conf->sae_pwe == 1 || conf->sae_pwe == 2); +#ifdef CONFIG_TESTING_OPTIONS + if (sm->wpa_auth->conf.ft_rsnxe_used) { + rsnxe_used = sm->wpa_auth->conf.ft_rsnxe_used == 1; + wpa_printf(MSG_DEBUG, "TESTING: FT: Force RSNXE Used %d", + rsnxe_used); + } +#endif /* CONFIG_TESTING_OPTIONS */ res = wpa_write_ftie(conf, use_sha384, r0kh_id, r0kh_id_len, anonce, snonce, pos, end - pos, - subelem, subelem_len); + subelem, subelem_len, rsnxe_used); os_free(subelem); if (res < 0) return NULL; @@ -2584,10 +2741,24 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, if (ric_start == pos) ric_start = NULL; - res = wpa_write_rsnxe(&sm->wpa_auth->conf, rsnxe, sizeof(rsnxe)); - if (res < 0) - return NULL; - rsnxe_len = res; + if (omit_rsnxe) { + rsnxe_len = 0; + } else { + res = wpa_write_rsnxe(&sm->wpa_auth->conf, rsnxe, + sizeof(rsnxe_buf)); + if (res < 0) + return NULL; + rsnxe_len = res; + } +#ifdef CONFIG_TESTING_OPTIONS + if (auth_alg == WLAN_AUTH_FT && + sm->wpa_auth->conf.rsnxe_override_ft_set) { + wpa_printf(MSG_DEBUG, + "TESTING: RSNXE FT override for MIC calculation"); + rsnxe = sm->wpa_auth->conf.rsnxe_override_ft; + rsnxe_len = sm->wpa_auth->conf.rsnxe_override_ft_len; + } +#endif /* CONFIG_TESTING_OPTIONS */ if (auth_alg == WLAN_AUTH_FT && rsnxe_len) *elem_count += 1; @@ -2632,7 +2803,16 @@ static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, } -void wpa_ft_install_ptk(struct wpa_state_machine *sm) +static inline int wpa_auth_add_sta_ft(struct wpa_authenticator *wpa_auth, + const u8 *addr) +{ + if (!wpa_auth->cb->add_sta_ft) + return -1; + return wpa_auth->cb->add_sta_ft(wpa_auth->cb_ctx, addr); +} + + +void wpa_ft_install_ptk(struct wpa_state_machine *sm, int retry) { enum wpa_alg alg; int klen; @@ -2654,19 +2834,22 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) return; } + if (!retry) + wpa_auth_add_sta_ft(sm->wpa_auth, sm->addr); + /* FIX: add STA entry to kernel/driver here? The set_key will fail * most likely without this.. At the moment, STA entry is added only * after association has been completed. This function will be called * again after association to get the PTK configured, but that could be * optimized by adding the STA entry earlier. */ - if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, + if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, sm->keyidx_active, sm->PTK.tk, klen, KEY_FLAG_PAIRWISE_RX_TX)) return; /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ - sm->pairwise_set = TRUE; - sm->tk_already_set = TRUE; + sm->pairwise_set = true; + sm->tk_already_set = true; } @@ -2827,8 +3010,6 @@ static int wpa_ft_local_derive_pmk_r1(struct wpa_authenticator *wpa_auth, conf->r1_key_holder, sm->addr, out_pmk_r1, pmk_r1_name) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", out_pmk_r1, r0->pmk_r0_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); os_get_reltime(&now); if (r0->expiration) @@ -2957,8 +3138,6 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, sm->wpa_auth->conf.r1_key_holder, sm->addr, pmk_r1_name, use_sha384) < 0) return WLAN_STATUS_UNSPECIFIED_FAILURE; - wpa_hexdump(MSG_DEBUG, "FT: Derived requested PMKR1Name", - pmk_r1_name, WPA_PMK_NAME_LEN); if (conf->ft_psk_generate_local && wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) { @@ -3023,9 +3202,9 @@ pmk_r1_derived: return WLAN_STATUS_UNSPECIFIED_FAILURE; sm->pairwise = pairwise; - sm->PTK_valid = TRUE; - sm->tk_already_set = FALSE; - wpa_ft_install_ptk(sm); + sm->PTK_valid = true; + sm->tk_already_set = false; + wpa_ft_install_ptk(sm, 0); if (wpa_ft_set_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to configure VLAN"); @@ -3060,7 +3239,8 @@ pmk_r1_derived: pos += ret; ret = wpa_write_ftie(conf, use_sha384, parse.r0kh_id, parse.r0kh_id_len, - sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0); + sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0, + 0); if (ret < 0) goto fail; pos += ret; @@ -3119,7 +3299,7 @@ void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, } -u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, +int wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, size_t ies_len) { struct wpa_ft_ies parse; @@ -3132,10 +3312,13 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, int use_sha384; const u8 *anonce, *snonce, *fte_mic; u8 fte_elem_count; + int rsnxe_used; + struct wpa_auth_config *conf; if (sm == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; + conf = &sm->wpa_auth->conf; use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len); @@ -3164,8 +3347,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, mdie = (struct rsn_mdie *) parse.mdie; if (mdie == NULL || parse.mdie_len < sizeof(*mdie) || - os_memcmp(mdie->mobility_domain, - sm->wpa_auth->conf.mobility_domain, + os_memcmp(mdie->mobility_domain, conf->mobility_domain, MOBILITY_DOMAIN_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: Invalid MDIE"); return WLAN_STATUS_INVALID_MDIE; @@ -3182,6 +3364,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, anonce = ftie->anonce; snonce = ftie->snonce; + rsnxe_used = ftie->mic_control[0] & 0x01; fte_elem_count = ftie->mic_control[1]; fte_mic = ftie->mic; } else { @@ -3195,6 +3378,7 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, anonce = ftie->anonce; snonce = ftie->snonce; + rsnxe_used = ftie->mic_control[0] & 0x01; fte_elem_count = ftie->mic_control[1]; fte_mic = ftie->mic; } @@ -3240,14 +3424,14 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, return WLAN_STATUS_INVALID_FTIE; } - if (os_memcmp_const(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder, + if (os_memcmp_const(parse.r1kh_id, conf->r1_key_holder, FT_R1KH_ID_LEN) != 0) { wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in " "ReassocReq"); wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE", parse.r1kh_id, FT_R1KH_ID_LEN); wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID", - sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN); + conf->r1_key_holder, FT_R1KH_ID_LEN); return WLAN_STATUS_INVALID_FTIE; } @@ -3309,11 +3493,19 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, return WLAN_STATUS_INVALID_FTIE; } + if (rsnxe_used && (conf->sae_pwe == 1 || conf->sae_pwe == 2) && + !parse.rsnxe) { + wpa_printf(MSG_INFO, + "FT: FTE indicated that STA uses RSNXE, but RSNXE was not included"); + return -1; /* discard request */ + } + #ifdef CONFIG_OCV if (wpa_auth_uses_ocv(sm)) { struct wpa_channel_info ci; int tx_chanwidth; int tx_seg1_idx; + enum oci_verify_result res; if (wpa_channel_info(sm->wpa_auth, &ci) != 0) { wpa_printf(MSG_WARNING, @@ -3327,10 +3519,21 @@ u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, &tx_seg1_idx) < 0) return WLAN_STATUS_UNSPECIFIED_FAILURE; - if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, - tx_chanwidth, tx_seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "%s", ocv_errorstr); - return WLAN_STATUS_UNSPECIFIED_FAILURE; + res = ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, + tx_chanwidth, tx_seg1_idx); + if (wpa_auth_uses_ocv(sm) == 2 && res == OCI_NOT_FOUND) { + /* Work around misbehaving STAs */ + wpa_printf(MSG_INFO, + "Disable OCV with a STA that does not send OCI"); + wpa_auth_set_ocv(sm, 0); + } else if (res != OCI_SUCCESS) { + wpa_printf(MSG_WARNING, "OCV failed: %s", ocv_errorstr); + if (sm->wpa_auth->conf.msg_ctx) + wpa_msg(sm->wpa_auth->conf.msg_ctx, MSG_INFO, + OCV_FAILURE "addr=" MACSTR + " frame=ft-reassoc-req error=%s", + MAC2STR(sm->addr), ocv_errorstr); + return WLAN_STATUS_INVALID_FTIE; } } #endif /* CONFIG_OCV */ @@ -3553,14 +3756,11 @@ static int wpa_ft_rrb_build_r0(const u8 *key, const size_t key_len, { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL }, }; + wpa_printf(MSG_DEBUG, "FT: Derive PMK-R1 for peer AP"); if (wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_len, pmk_r0->pmk_r0_name, r1kh_id, s1kh_id, pmk_r1, pmk_r1_name) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 (for peer AP)", - pmk_r1, pmk_r1_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name (for peer AP)", - pmk_r1_name, WPA_PMK_NAME_LEN); WPA_PUT_LE16(f_pairwise, pmk_r0->pairwise); os_get_reltime(&now); @@ -4433,7 +4633,6 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, return -1; } status_code = WPA_GET_LE16(pos); - pos += 2; wpa_printf(MSG_DEBUG, "FT: FT Packet Type - Response " "(status_code=%d)", status_code); @@ -4446,11 +4645,6 @@ int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, return -1; } - if (end > pos) { - wpa_hexdump(MSG_DEBUG, "FT: Ignore extra data in end", - pos, end - pos); - } - return 0; } diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 894c1a1b2..c01654f38 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -41,6 +41,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, os_memset(wconf, 0, sizeof(*wconf)); wconf->wpa = conf->wpa; + wconf->extended_key_id = conf->extended_key_id; wconf->wpa_key_mgmt = conf->wpa_key_mgmt; wconf->wpa_pairwise = conf->wpa_pairwise; wconf->wpa_group = conf->wpa_group; @@ -67,6 +68,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, #endif /* CONFIG_OCV */ wconf->okc = conf->okc; wconf->ieee80211w = conf->ieee80211w; + wconf->beacon_prot = conf->beacon_prot; wconf->group_mgmt_cipher = conf->group_mgmt_cipher; wconf->sae_require_mfp = conf->sae_require_mfp; #ifdef CONFIG_IEEE80211R_AP @@ -120,14 +122,42 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wpabuf_head(conf->own_ie_override), wconf->own_ie_override_len); } + if (conf->rsne_override_eapol && + wpabuf_len(conf->rsne_override_eapol) <= MAX_OWN_IE_OVERRIDE) { + wconf->rsne_override_eapol_set = 1; + wconf->rsne_override_eapol_len = + wpabuf_len(conf->rsne_override_eapol); + os_memcpy(wconf->rsne_override_eapol, + wpabuf_head(conf->rsne_override_eapol), + wconf->rsne_override_eapol_len); + } if (conf->rsnxe_override_eapol && wpabuf_len(conf->rsnxe_override_eapol) <= MAX_OWN_IE_OVERRIDE) { + wconf->rsnxe_override_eapol_set = 1; wconf->rsnxe_override_eapol_len = wpabuf_len(conf->rsnxe_override_eapol); os_memcpy(wconf->rsnxe_override_eapol, wpabuf_head(conf->rsnxe_override_eapol), wconf->rsnxe_override_eapol_len); } + if (conf->rsne_override_ft && + wpabuf_len(conf->rsne_override_ft) <= MAX_OWN_IE_OVERRIDE) { + wconf->rsne_override_ft_set = 1; + wconf->rsne_override_ft_len = + wpabuf_len(conf->rsne_override_ft); + os_memcpy(wconf->rsne_override_ft, + wpabuf_head(conf->rsne_override_ft), + wconf->rsne_override_ft_len); + } + if (conf->rsnxe_override_ft && + wpabuf_len(conf->rsnxe_override_ft) <= MAX_OWN_IE_OVERRIDE) { + wconf->rsnxe_override_ft_set = 1; + wconf->rsnxe_override_ft_len = + wpabuf_len(conf->rsnxe_override_ft); + os_memcpy(wconf->rsnxe_override_ft, + wpabuf_head(conf->rsnxe_override_ft), + wconf->rsnxe_override_ft_len); + } if (conf->gtk_rsc_override && wpabuf_len(conf->gtk_rsc_override) > 0 && wpabuf_len(conf->gtk_rsc_override) <= WPA_KEY_RSC_LEN) { @@ -144,6 +174,12 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wpabuf_len(conf->igtk_rsc_override)); wconf->igtk_rsc_override_set = 1; } + wconf->ft_rsnxe_used = conf->ft_rsnxe_used; + wconf->oci_freq_override_eapol_m3 = conf->oci_freq_override_eapol_m3; + wconf->oci_freq_override_eapol_g1 = conf->oci_freq_override_eapol_g1; + wconf->oci_freq_override_ft_assoc = conf->oci_freq_override_ft_assoc; + wconf->oci_freq_override_fils_assoc = + conf->oci_freq_override_fils_assoc; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_P2P os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4); @@ -162,9 +198,16 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wconf->sae_pwe = 1; else if (sae_pw_id == 1 && wconf->sae_pwe == 0) wconf->sae_pwe = 2; +#ifdef CONFIG_SAE_PK + wconf->sae_pk = hostapd_sae_pk_in_use(conf); +#endif /* CONFIG_SAE_PK */ #ifdef CONFIG_OWE wconf->owe_ptk_workaround = conf->owe_ptk_workaround; #endif /* CONFIG_OWE */ + wconf->transition_disable = conf->transition_disable; +#ifdef CONFIG_DPP2 + wconf->dpp_pfs = conf->dpp_pfs; +#endif /* CONFIG_DPP2 */ } @@ -242,16 +285,15 @@ static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr, break; case WPA_EAPOL_keyRun: if (sta->eapol_sm) - sta->eapol_sm->keyRun = value ? TRUE : FALSE; + sta->eapol_sm->keyRun = value; break; case WPA_EAPOL_keyAvailable: if (sta->eapol_sm) - sta->eapol_sm->eap_if->eapKeyAvailable = - value ? TRUE : FALSE; + sta->eapol_sm->eap_if->eapKeyAvailable = value; break; case WPA_EAPOL_keyDone: if (sta->eapol_sm) - sta->eapol_sm->keyDone = value ? TRUE : FALSE; + sta->eapol_sm->keyDone = value; break; case WPA_EAPOL_inc_EapolFramesTx: if (sta->eapol_sm) @@ -404,7 +446,11 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, } #ifdef CONFIG_TESTING_OPTIONS - if (addr && !is_broadcast_ether_addr(addr)) { + if (key_flag & KEY_FLAG_MODIFY) { + /* We are updating an already installed key. Don't overwrite + * the already stored key information with zeros. + */ + } else if (addr && !is_broadcast_ether_addr(addr)) { struct sta_info *sta; sta = ap_get_sta(hapd, addr); @@ -415,15 +461,23 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, os_memcpy(sta->last_tk, key, key_len); sta->last_tk_len = key_len; } - } else if (alg == WPA_ALG_IGTK || + } else if (alg == WPA_ALG_BIP_CMAC_128 || alg == WPA_ALG_BIP_GMAC_128 || alg == WPA_ALG_BIP_GMAC_256 || alg == WPA_ALG_BIP_CMAC_256) { - hapd->last_igtk_alg = alg; - hapd->last_igtk_key_idx = idx; - if (key) - os_memcpy(hapd->last_igtk, key, key_len); - hapd->last_igtk_len = key_len; + if (idx == 4 || idx == 5) { + hapd->last_igtk_alg = alg; + hapd->last_igtk_key_idx = idx; + if (key) + os_memcpy(hapd->last_igtk, key, key_len); + hapd->last_igtk_len = key_len; + } else if (idx == 6 || idx == 7) { + hapd->last_bigtk_alg = alg; + hapd->last_bigtk_key_idx = idx; + if (key) + os_memcpy(hapd->last_bigtk, key, key_len); + hapd->last_bigtk_len = key_len; + } } else { hapd->last_gtk_alg = alg; hapd->last_gtk_key_idx = idx; @@ -1000,6 +1054,34 @@ hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) } +static int hostapd_wpa_auth_add_sta_ft(void *ctx, const u8 *sta_addr) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + + sta = ap_get_sta(hapd, sta_addr); + if (!sta) + return -1; + + if (FULL_AP_CLIENT_STATE_SUPP(hapd->iface->drv_flags) && + (sta->flags & WLAN_STA_MFP) && ap_sta_is_authorized(sta) && + !(hapd->conf->mesh & MESH_ENABLED) && !(sta->added_unassoc)) { + /* We could not do this in handle_auth() since there was a + * PMF-enabled association for the STA and the new + * authentication attempt was not yet fully processed. Now that + * we are ready to configure the TK to the driver, + * authentication has succeeded and we can clean up the driver + * STA entry to avoid issues with any maintained state from the + * previous association. */ + wpa_printf(MSG_DEBUG, + "FT: Remove and re-add driver STA entry after successful FT authentication"); + return ap_sta_re_add(hapd, sta); + } + + return 0; +} + + static int hostapd_wpa_auth_set_vlan(void *ctx, const u8 *sta_addr, struct vlan_description *vlan) { @@ -1361,6 +1443,7 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) #ifdef CONFIG_IEEE80211R_AP .send_ft_action = hostapd_wpa_auth_send_ft_action, .add_sta = hostapd_wpa_auth_add_sta, + .add_sta_ft = hostapd_wpa_auth_add_sta_ft, .add_tspec = hostapd_wpa_auth_add_tspec, .set_vlan = hostapd_wpa_auth_set_vlan, .get_vlan = hostapd_wpa_auth_get_vlan, @@ -1376,10 +1459,27 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) size_t wpa_ie_len; hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf); + _conf.msg_ctx = hapd->msg_ctx; if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS) _conf.tx_status = 1; if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME) _conf.ap_mlme = 1; + + if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED) && + (hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER || + (hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK && + !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) { + wpa_msg(hapd->msg_ctx, MSG_INFO, + "Disable PTK0 rekey support - replaced with disconnect"); + _conf.wpa_deny_ptk0_rekey = 1; + } + + if (_conf.extended_key_id && + (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) + wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Extended Key ID supported"); + else + _conf.extended_key_id = 0; + hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd); if (hapd->wpa_auth == NULL) { wpa_printf(MSG_ERROR, "WPA initialization failed."); diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index 4e0548fc5..77d8077d6 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -40,20 +40,20 @@ struct wpa_state_machine { WPA_PTK_GROUP_KEYERROR } wpa_ptk_group_state; - Boolean Init; - Boolean DeauthenticationRequest; - Boolean AuthenticationRequest; - Boolean ReAuthenticationRequest; - Boolean Disconnect; + bool Init; + bool DeauthenticationRequest; + bool AuthenticationRequest; + bool ReAuthenticationRequest; + bool Disconnect; u16 disconnect_reason; /* specific reason code to use with Disconnect */ u32 TimeoutCtr; u32 GTimeoutCtr; - Boolean TimeoutEvt; - Boolean EAPOLKeyReceived; - Boolean EAPOLKeyPairwise; - Boolean EAPOLKeyRequest; - Boolean MICVerified; - Boolean GUpdateStationKeys; + bool TimeoutEvt; + bool EAPOLKeyReceived; + bool EAPOLKeyPairwise; + bool EAPOLKeyRequest; + bool MICVerified; + bool GUpdateStationKeys; u8 ANonce[WPA_NONCE_LEN]; u8 SNonce[WPA_NONCE_LEN]; u8 alt_SNonce[WPA_NONCE_LEN]; @@ -62,20 +62,22 @@ struct wpa_state_machine { unsigned int pmk_len; u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */ struct wpa_ptk PTK; - Boolean PTK_valid; - Boolean pairwise_set; - Boolean tk_already_set; + u8 keyidx_active; + bool use_ext_key_id; + bool PTK_valid; + bool pairwise_set; + bool tk_already_set; int keycount; - Boolean Pair; + bool Pair; struct wpa_key_replay_counter { u8 counter[WPA_REPLAY_COUNTER_LEN]; - Boolean valid; + bool valid; } key_replay[RSNA_MAX_EAPOL_RETRIES], prev_key_replay[RSNA_MAX_EAPOL_RETRIES]; - Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */ - Boolean PTKRequest; /* not in IEEE 802.11i state machine */ - Boolean has_GTK; - Boolean PtkGroupInit; /* init request for PTK Group state machine */ + bool PInitAKeys; /* WPA only, not in IEEE 802.11i */ + bool PTKRequest; /* not in IEEE 802.11i state machine */ + bool has_GTK; + bool PtkGroupInit; /* init request for PTK Group state machine */ u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */ size_t last_rx_eapol_key_len; @@ -94,8 +96,9 @@ struct wpa_state_machine { #endif /* CONFIG_IEEE80211R_AP */ unsigned int is_wnmsleep:1; unsigned int pmkid_set:1; + #ifdef CONFIG_OCV - unsigned int ocv_enabled:1; + int ocv_enabled; #endif /* CONFIG_OCV */ u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN]; @@ -174,12 +177,12 @@ struct wpa_group { struct wpa_group *next; int vlan_id; - Boolean GInit; + bool GInit; int GKeyDoneStations; - Boolean GTKReKey; + bool GTKReKey; int GTK_len; int GN, GM; - Boolean GTKAuthenticator; + bool GTKAuthenticator; u8 Counter[WPA_NONCE_LEN]; enum { @@ -191,11 +194,13 @@ struct wpa_group { u8 GMK[WPA_GMK_LEN]; u8 GTK[2][WPA_GTK_MAX_LEN]; u8 GNonce[WPA_NONCE_LEN]; - Boolean changed; - Boolean first_sta_seen; - Boolean reject_4way_hs_for_entropy; + bool changed; + bool first_sta_seen; + bool reject_4way_hs_for_entropy; u8 IGTK[2][WPA_IGTK_MAX_LEN]; + u8 BIGTK[2][WPA_IGTK_MAX_LEN]; int GN_igtk, GM_igtk; + int GN_bigtk, GM_bigtk; /* Number of references except those in struct wpa_group->next */ unsigned int references; unsigned int num_setup_iface; @@ -275,7 +280,8 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len); void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, logger_level level, const char *txt); void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, - logger_level level, const char *fmt, ...); + logger_level level, const char *fmt, ...) + PRINTF_FORMAT(4, 5); void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, int key_info, const u8 *key_rsc, const u8 *nonce, @@ -294,11 +300,11 @@ int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, const u8 *r0kh_id, size_t r0kh_id_len, const u8 *anonce, const u8 *snonce, u8 *buf, size_t len, const u8 *subelem, - size_t subelem_len); + size_t subelem_len, int rsnxe_used); int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk); struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void); void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); -void wpa_ft_install_ptk(struct wpa_state_machine *sm); +void wpa_ft_install_ptk(struct wpa_state_machine *sm, int retry); int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm, const u8 *pmk_r0, const u8 *pmk_r0_name); #endif /* CONFIG_IEEE80211R_AP */ diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 2e6d05910..3704fc05e 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -297,6 +297,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, if (rsn_testing) capab |= BIT(8) | BIT(15); #endif /* CONFIG_RSN_TESTING */ + if (conf->extended_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; WPA_PUT_LE16(pos, capab); pos += 2; @@ -376,7 +378,7 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len) { u8 *pos = buf; - if (conf->sae_pwe != 1 && conf->sae_pwe != 2) + if (conf->sae_pwe != 1 && conf->sae_pwe != 2 && !conf->sae_pk) return 0; /* no supported extended RSN capabilities */ if (len < 3) @@ -386,7 +388,12 @@ int wpa_write_rsnxe(struct wpa_auth_config *conf, u8 *buf, size_t len) *pos++ = 1; /* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is * used for now */ - *pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E); + *pos = BIT(WLAN_RSNX_CAPAB_SAE_H2E); +#ifdef CONFIG_SAE_PK + if (conf->sae_pk) + *pos |= BIT(WLAN_RSNX_CAPAB_SAE_PK); +#endif /* CONFIG_SAE_PK */ + pos++; return pos - buf; } @@ -546,13 +553,15 @@ static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx) } -int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, - struct wpa_state_machine *sm, int freq, - const u8 *wpa_ie, size_t wpa_ie_len, - const u8 *rsnxe, size_t rsnxe_len, - const u8 *mdie, size_t mdie_len, - const u8 *owe_dh, size_t owe_dh_len) +enum wpa_validate_result +wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int freq, + const u8 *wpa_ie, size_t wpa_ie_len, + const u8 *rsnxe, size_t rsnxe_len, + const u8 *mdie, size_t mdie_len, + const u8 *owe_dh, size_t owe_dh_len) { + struct wpa_auth_config *conf = &wpa_auth->conf; struct wpa_ie_data data; int ciphers, key_mgmt, res, version; u32 selector; @@ -799,14 +808,26 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, #endif /* CONFIG_SAE */ #ifdef CONFIG_OCV - if ((data.capabilities & WPA_CAPABILITY_OCVC) && + if (wpa_auth->conf.ocv && (data.capabilities & WPA_CAPABILITY_OCVC) && !(data.capabilities & WPA_CAPABILITY_MFPC)) { - wpa_printf(MSG_DEBUG, - "Management frame protection required with OCV, but client did not enable it"); - return WPA_MGMT_FRAME_PROTECTION_VIOLATION; + /* Some legacy MFP incapable STAs wrongly copy OCVC bit from + * AP RSN capabilities. To improve interoperability with such + * legacy STAs allow connection without enabling OCV when the + * workaround mode (ocv=2) is enabled. + */ + if (wpa_auth->conf.ocv == 2) { + wpa_printf(MSG_DEBUG, + "Allow connecting MFP incapable and OCV capable STA without enabling OCV"); + wpa_auth_set_ocv(sm, 0); + } else { + wpa_printf(MSG_DEBUG, + "Management frame protection required with OCV, but client did not enable it"); + return WPA_MGMT_FRAME_PROTECTION_VIOLATION; + } + } else { + wpa_auth_set_ocv(sm, (data.capabilities & WPA_CAPABILITY_OCVC) ? + wpa_auth->conf.ocv : 0); } - wpa_auth_set_ocv(sm, wpa_auth->conf.ocv && - (data.capabilities & WPA_CAPABILITY_OCVC)); #endif /* CONFIG_OCV */ if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || @@ -847,19 +868,18 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, "OWE: No Diffie-Hellman Parameter element"); return WPA_INVALID_AKMP; } -#ifdef CONFIG_DPP - if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && owe_dh) { - /* Diffie-Hellman Parameter element can be used with DPP as - * well, so allow this to proceed. */ - } else -#endif /* CONFIG_DPP */ - if (sm->wpa_key_mgmt != WPA_KEY_MGMT_OWE && owe_dh) { - wpa_printf(MSG_DEBUG, - "OWE: Unexpected Diffie-Hellman Parameter element with non-OWE AKM"); - return WPA_INVALID_AKMP; - } #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP2 + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && + ((conf->dpp_pfs == 1 && !owe_dh) || + (conf->dpp_pfs == 2 && owe_dh))) { + wpa_printf(MSG_DEBUG, "DPP: PFS %s", + conf->dpp_pfs == 1 ? "required" : "not allowed"); + return WPA_DENIED_OTHER_REASON; + } +#endif /* CONFIG_DPP2 */ + sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0); if (sm->pairwise < 0) return WPA_INVALID_PAIRWISE; @@ -944,6 +964,23 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, } #endif /* CONFIG_DPP */ + if (conf->extended_key_id && sm->wpa == WPA_VERSION_WPA2 && + sm->pairwise != WPA_CIPHER_TKIP && + (data.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST)) { + sm->use_ext_key_id = true; + if (conf->extended_key_id == 2 && + !wpa_key_mgmt_ft(sm->wpa_key_mgmt) && + !wpa_key_mgmt_fils(sm->wpa_key_mgmt)) + sm->keyidx_active = 1; + else + sm->keyidx_active = 0; + wpa_printf(MSG_DEBUG, + "RSN: Extended Key ID supported (start with %d)", + sm->keyidx_active); + } else { + sm->use_ext_key_id = false; + } + if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) { os_free(sm->wpa_ie); sm->wpa_ie = os_malloc(wpa_ie_len); diff --git a/src/ap/wpa_auth_kay.c b/src/ap/wpa_auth_kay.c index b6e47979b..46d94b43f 100644 --- a/src/ap/wpa_auth_kay.c +++ b/src/ap/wpa_auth_kay.c @@ -52,7 +52,7 @@ static int hapd_macsec_get_capability(void *priv, enum macsec_cap *cap) } -static int hapd_enable_protect_frames(void *priv, Boolean enabled) +static int hapd_enable_protect_frames(void *priv, bool enabled) { struct hostapd_data *hapd = priv; @@ -62,7 +62,7 @@ static int hapd_enable_protect_frames(void *priv, Boolean enabled) } -static int hapd_enable_encrypt(void *priv, Boolean enabled) +static int hapd_enable_encrypt(void *priv, bool enabled) { struct hostapd_data *hapd = priv; @@ -72,7 +72,7 @@ static int hapd_enable_encrypt(void *priv, Boolean enabled) } -static int hapd_set_replay_protect(void *priv, Boolean enabled, u32 window) +static int hapd_set_replay_protect(void *priv, bool enabled, u32 window) { struct hostapd_data *hapd = priv; @@ -93,7 +93,7 @@ static int hapd_set_current_cipher_suite(void *priv, u64 cs) } -static int hapd_enable_controlled_port(void *priv, Boolean enabled) +static int hapd_enable_controlled_port(void *priv, bool enabled) { struct hostapd_data *hapd = priv; @@ -465,7 +465,7 @@ void * ieee802_1x_notify_create_actor_hapd(struct hostapd_data *hapd, wpa_hexdump(MSG_DEBUG, "Derived CKN", ckn->name, ckn->len); res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, EAP_EXCHANGE, - TRUE); + true); fail: bin_clear_free(msk, sizeof(*msk)); @@ -507,7 +507,7 @@ void * ieee802_1x_create_preshared_mka_hapd(struct hostapd_data *hapd, ckn->len = hapd->conf->mka_ckn_len;; os_memcpy(ckn->name, hapd->conf->mka_ckn, ckn->len); - res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, PSK, TRUE); + res = ieee802_1x_kay_create_mka(hapd->kay, ckn, cak, 0, PSK, true); if (res) goto free_cak; diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index 7b143b821..dc8aa8f65 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -125,6 +125,7 @@ static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, os_memcpy(p->addr, mac_addr, ETH_ALEN); os_memcpy(p->p2p_dev_addr, p2p_dev_addr, ETH_ALEN); os_memcpy(p->psk, psk, PMK_LEN); + p->wps = 1; if (hapd->new_psk_cb) { hapd->new_psk_cb(hapd->new_psk_cb_ctx, mac_addr, p2p_dev_addr, @@ -363,6 +364,13 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd, bss->ssid.ssid_set = 1; } +#ifdef CONFIG_NO_TKIP + if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK | + WPS_AUTH_WPA | WPS_AUTH_WPAPSK)) + bss->wpa = 2; + else + bss->wpa = 0; +#else /* CONFIG_NO_TKIP */ if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) && (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))) bss->wpa = 3; @@ -372,6 +380,7 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd, bss->wpa = 1; else bss->wpa = 0; +#endif /* CONFIG_NO_TKIP */ if (bss->wpa) { if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA)) @@ -386,8 +395,10 @@ static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd, else bss->wpa_pairwise |= WPA_CIPHER_CCMP; } +#ifndef CONFIG_NO_TKIP if (cred->encr_type & WPS_ENCR_TKIP) bss->wpa_pairwise |= WPA_CIPHER_TKIP; +#endif /* CONFIG_NO_TKIP */ bss->rsn_pairwise = bss->wpa_pairwise; bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise, @@ -558,6 +569,13 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) fprintf(nconf, "\n"); } +#ifdef CONFIG_NO_TKIP + if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK | + WPS_AUTH_WPA | WPS_AUTH_WPAPSK)) + wpa = 2; + else + wpa = 0; +#else /* CONFIG_NO_TKIP */ if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) && (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))) wpa = 3; @@ -567,6 +585,7 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) wpa = 1; else wpa = 0; +#endif /* CONFIG_NO_TKIP */ if (wpa) { char *prefix; @@ -610,9 +629,11 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) prefix = " "; } +#ifndef CONFIG_NO_TKIP if (cred->encr_type & WPS_ENCR_TKIP) { fprintf(nconf, "%sTKIP", prefix); } +#endif /* CONFIG_NO_TKIP */ fprintf(nconf, "\n"); if (cred->key_len >= 8 && cred->key_len < 64) { @@ -650,8 +671,10 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) (str_starts(buf, "ssid=") || str_starts(buf, "ssid2=") || str_starts(buf, "auth_algs=") || +#ifdef CONFIG_WEP str_starts(buf, "wep_default_key=") || str_starts(buf, "wep_key") || +#endif /* CONFIG_WEP */ str_starts(buf, "wps_state=") || (pmf_changed && str_starts(buf, "ieee80211w=")) || str_starts(buf, "wpa=") || @@ -1157,12 +1180,24 @@ int hostapd_init_wps(struct hostapd_data *hapd, wps->encr_types_rsn |= WPS_ENCR_AES; } if (conf->rsn_pairwise & WPA_CIPHER_TKIP) { +#ifdef CONFIG_NO_TKIP + wpa_printf(MSG_INFO, "WPS: TKIP not supported"); + goto fail; +#else /* CONFIG_NO_TKIP */ wps->encr_types |= WPS_ENCR_TKIP; wps->encr_types_rsn |= WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ } } if (conf->wpa & WPA_PROTO_WPA) { +#ifdef CONFIG_NO_TKIP + if (!(conf->wpa & WPA_PROTO_RSN)) { + wpa_printf(MSG_INFO, "WPS: WPA(v1) not supported"); + goto fail; + } + conf->wpa &= ~WPA_PROTO_WPA; +#else /* CONFIG_NO_TKIP */ if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) wps->auth_types |= WPS_AUTH_WPAPSK; if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) @@ -1176,6 +1211,7 @@ int hostapd_init_wps(struct hostapd_data *hapd, wps->encr_types |= WPS_ENCR_TKIP; wps->encr_types_wpa |= WPS_ENCR_TKIP; } +#endif /* CONFIG_NO_TKIP */ } if (conf->ssid.security_policy == SECURITY_PLAINTEXT) { @@ -1195,6 +1231,7 @@ int hostapd_init_wps(struct hostapd_data *hapd, wpa_snprintf_hex((char *) wps->network_key, 2 * PMK_LEN + 1, conf->ssid.wpa_psk->psk, PMK_LEN); wps->network_key_len = 2 * PMK_LEN; +#ifdef CONFIG_WEP } else if (conf->ssid.wep.keys_set && conf->ssid.wep.key[0]) { wps->network_key = os_malloc(conf->ssid.wep.len[0]); if (wps->network_key == NULL) @@ -1202,6 +1239,7 @@ int hostapd_init_wps(struct hostapd_data *hapd, os_memcpy(wps->network_key, conf->ssid.wep.key[0], conf->ssid.wep.len[0]); wps->network_key_len = conf->ssid.wep.len[0]; +#endif /* CONFIG_WEP */ } if (conf->ssid.wpa_psk) { @@ -1213,10 +1251,17 @@ int hostapd_init_wps(struct hostapd_data *hapd, wps->ap_encr_type = wps->encr_types; if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) { /* Override parameters to enable security by default */ +#ifdef CONFIG_NO_TKIP + wps->auth_types = WPS_AUTH_WPA2PSK; + wps->encr_types = WPS_ENCR_AES; + wps->encr_types_rsn = WPS_ENCR_AES; + wps->encr_types_wpa = WPS_ENCR_AES; +#else /* CONFIG_NO_TKIP */ wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK; wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP; wps->encr_types_rsn = WPS_ENCR_AES | WPS_ENCR_TKIP; wps->encr_types_wpa = WPS_ENCR_AES | WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ } if ((hapd->conf->multi_ap & FRONTHAUL_BSS) && @@ -1259,8 +1304,6 @@ int hostapd_init_wps(struct hostapd_data *hapd, cfg.extra_cred_len = conf->extra_cred_len; cfg.disable_auto_conf = (hapd->conf->wps_cred_processing == 1) && conf->skip_cred_build; - if (conf->ssid.security_policy == SECURITY_STATIC_WEP) - cfg.static_wep_only = 1; cfg.dualband = interface_count(hapd->iface) > 1; if ((wps->dev.rf_bands & (WPS_RF_50GHZ | WPS_RF_24GHZ)) == (WPS_RF_50GHZ | WPS_RF_24GHZ)) @@ -1798,8 +1841,10 @@ int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid, if (os_strncmp(auth, "OPEN", 4) == 0) cred.auth_type = WPS_AUTH_OPEN; +#ifndef CONFIG_NO_TKIP else if (os_strncmp(auth, "WPAPSK", 6) == 0) cred.auth_type = WPS_AUTH_WPAPSK; +#endif /* CONFIG_NO_TKIP */ else if (os_strncmp(auth, "WPA2PSK", 7) == 0) cred.auth_type = WPS_AUTH_WPA2PSK; else @@ -1808,8 +1853,10 @@ int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid, if (encr) { if (os_strncmp(encr, "NONE", 4) == 0) cred.encr_type = WPS_ENCR_NONE; +#ifndef CONFIG_NO_TKIP else if (os_strncmp(encr, "TKIP", 4) == 0) cred.encr_type = WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ else if (os_strncmp(encr, "CCMP", 4) == 0) cred.encr_type = WPS_ENCR_AES; else diff --git a/src/build.rules b/src/build.rules new file mode 100644 index 000000000..acda88472 --- /dev/null +++ b/src/build.rules @@ -0,0 +1,109 @@ +.PHONY: all +all: _all + +# disable built-in rules +.SUFFIXES: + +# setup some variables +ROOTDIR := $(dir $(lastword $(MAKEFILE_LIST))) +ROOTDIR := $(dir $(ROOTDIR:%../src/=%))../ +BUILDDIR ?= $(abspath $(ROOTDIR)build) +BUILDDIR := $(BUILDDIR:%/=%) +ABSROOT := $(abspath $(ROOTDIR)) +ifeq ($(origin OUT),command line) +_PROJ := $(OUT:%/=%) +_PROJ := $(_PROJ:$(BUILDDIR)/%=%) +else +_PROJ := $(abspath $(dir $(firstword $(MAKEFILE_LIST)))) +_PROJ := $(_PROJ:$(ABSROOT)/%=%) +endif + +ifndef CC +CC=gcc +endif + +ifndef RANLIB +RANLIB=ranlib +endif + +ifndef LDO +LDO=$(CC) +endif + +ifndef CFLAGS +CFLAGS = -MMD -O2 -Wall -g +endif + +ifneq ($(CONFIG_FILE),) +-include $(CONFIG_FILE) + +# export for sub-makefiles +export CONFIG_CODE_COVERAGE + +.PHONY: verify_config +verify_config: + @if [ ! -r $(CONFIG_FILE) ]; then \ + echo 'Building $(firstword $(ALL)) requires a configuration file'; \ + echo '(.config). See README for more instructions. You can'; \ + echo 'run "cp defconfig .config" to create an example'; \ + echo 'configuration.'; \ + exit 1; \ + fi +VERIFY := verify_config +else +VERIFY := +endif + +# default target +.PHONY: _all +_all: $(VERIFY) $(ALL) $(EXTRA_TARGETS) + +# continue setup +COVSUFFIX := $(if $(CONFIG_CODE_COVERAGE),-cov,) +PROJ := $(_PROJ)$(COVSUFFIX) + +Q=@ +E=echo +ifeq ($(V), 1) +Q= +E=true +endif +ifeq ($(QUIET), 1) +Q=@ +E=true +endif + +ifeq ($(Q),@) +MAKEFLAGS += --no-print-directory +endif + +_DIRS := $(BUILDDIR)/$(PROJ) +.PHONY: _make_dirs +_make_dirs: + @mkdir -p $(_DIRS) + +$(BUILDDIR)/$(PROJ)/src/%.o: $(ROOTDIR)src/%.c $(CONFIG_FILE) | _make_dirs + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + @$(E) " CC " $< +$(BUILDDIR)/$(PROJ)/%.o: %.c $(CONFIG_FILE) | _make_dirs + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + @$(E) " CC " $< +# for the fuzzing tests +$(BUILDDIR)/$(PROJ)/wpa_supplicant/%.o: $(ROOTDIR)wpa_supplicant/%.c $(CONFIG_FILE) | _make_dirs + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + @$(E) " CC " $< + +# libraries - they know how to build themselves +# (lib_phony so we recurse all the time) +.PHONY: lib_phony +lib_phony: +# nothing + +$(BUILDDIR)/$(PROJ)/%.a: $(CONFIG_FILE) lib_phony + $(Q)$(MAKE) -C $(ROOTDIR)$(dir $(@:$(BUILDDIR)/$(PROJ)/%=%)) OUT=$(abspath $(dir $@))/ + +BUILDOBJ = $(patsubst %,$(BUILDDIR)/$(PROJ)/%,$(patsubst $(ROOTDIR)%,%,$(1))) + +.PHONY: common-clean +common-clean: + $(Q)rm -rf $(ALL) $(BUILDDIR)/$(PROJ) diff --git a/src/common/Makefile b/src/common/Makefile index ccb280e90..59ba6c5e2 100644 --- a/src/common/Makefile +++ b/src/common/Makefile @@ -1,13 +1,3 @@ -all: libcommon.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libcommon.a - -install: - @echo Nothing to be made. - -include ../lib.rules - CFLAGS += -DCONFIG_IEEE80211R CFLAGS += -DCONFIG_HS20 CFLAGS += -DCONFIG_SAE @@ -21,7 +11,4 @@ LIB_OBJS= \ sae.o \ wpa_common.o -libcommon.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/common/common_module_tests.c b/src/common/common_module_tests.c index 7694c96b4..00308d41e 100644 --- a/src/common/common_module_tests.c +++ b/src/common/common_module_tests.c @@ -434,7 +434,8 @@ static int sae_tests(void) goto fail; /* Check that output matches the test vector */ - sae_write_commit(&sae, buf, NULL, pwid); + if (sae_write_commit(&sae, buf, NULL, pwid) < 0) + goto fail; wpa_hexdump_buf(MSG_DEBUG, "SAE: Commit message", buf); if (wpabuf_len(buf) != sizeof(local_commit) || @@ -547,6 +548,95 @@ fail: } +static int sae_pk_tests(void) +{ +#ifdef CONFIG_SAE_PK + const char *invalid[] = { "a2bc-de3f-ghim-", "a2bcde3fghim", "", NULL }; + struct { + const char *pw; + const u8 *val; + } valid[] = { + { "a2bc-de3f-ghim", (u8 *) "\x06\x82\x21\x93\x65\x31\xd0\xc0" }, + { "aaaa-aaaa-aaaj", (u8 *) "\x00\x00\x00\x00\x00\x00\x00\x90" }, + { "7777-7777-777f", (u8 *) "\xff\xff\xff\xff\xff\xff\xfe\x50" }, + { NULL, NULL } + }; + int i; + bool failed; + + for (i = 0; invalid[i]; i++) { + if (sae_pk_valid_password(invalid[i])) { + wpa_printf(MSG_ERROR, + "SAE-PK: Invalid password '%s' not recognized", + invalid[i]); + return -1; + } + } + + failed = false; + for (i = 0; valid[i].pw; i++) { + u8 *res; + size_t res_len; + char *b32; + const char *pw = valid[i].pw; + const u8 *val = valid[i].val; + size_t pw_len = os_strlen(pw); + size_t bits = (pw_len - pw_len / 5) * 5; + size_t bytes = (bits + 7) / 8; + + if (!sae_pk_valid_password(pw)) { + wpa_printf(MSG_ERROR, + "SAE-PK: Valid password '%s' not recognized", + pw); + failed = true; + continue; + } + + res = sae_pk_base32_decode(pw, pw_len, &res_len); + if (!res) { + wpa_printf(MSG_ERROR, + "SAE-PK: Failed to decode password '%s'", + valid[i].pw); + failed = true; + continue; + } + if (res_len != bytes || os_memcmp(val, res, res_len) != 0) { + wpa_printf(MSG_ERROR, + "SAE-PK: Mismatch for decoded password '%s'", + valid[i].pw); + wpa_hexdump(MSG_INFO, "SAE-PK: Decoded value", + res, res_len); + wpa_hexdump(MSG_INFO, "SAE-PK: Expected value", + val, bytes); + failed = true; + } + os_free(res); + + b32 = sae_pk_base32_encode(val, bits - 5); + if (!b32) { + wpa_printf(MSG_ERROR, + "SAE-PK: Failed to encode password '%s'", + pw); + failed = true; + continue; + } + if (os_strcmp(b32, pw) != 0) { + wpa_printf(MSG_ERROR, + "SAE-PK: Mismatch for password '%s'", pw); + wpa_printf(MSG_INFO, "SAE-PK: Encoded value: '%s'", + b32); + failed = true; + } + os_free(b32); + } + + return failed ? -1 : 0; +#else /* CONFIG_SAE_PK */ + return 0; +#endif /* CONFIG_SAE_PK */ +} + + int common_module_tests(void) { int ret = 0; @@ -556,6 +646,7 @@ int common_module_tests(void) if (ieee802_11_parse_tests() < 0 || gas_tests() < 0 || sae_tests() < 0 || + sae_pk_tests() < 0 || rsn_ie_parse_tests() < 0) ret = -1; diff --git a/src/common/defs.h b/src/common/defs.h index 5e22278e6..b01ab03b6 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -9,15 +9,6 @@ #ifndef DEFS_H #define DEFS_H -#ifdef FALSE -#undef FALSE -#endif -#ifdef TRUE -#undef TRUE -#endif -typedef enum { FALSE = 0, TRUE = 1 } Boolean; - - #define WPA_CIPHER_NONE BIT(0) #define WPA_CIPHER_WEP40 BIT(1) #define WPA_CIPHER_WEP104 BIT(2) @@ -82,6 +73,13 @@ static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) WPA_KEY_MGMT_FT_FILS_SHA384)); } +static inline int wpa_key_mgmt_wpa_psk_no_sae(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_PSK | + WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_PSK_SHA256)); +} + static inline int wpa_key_mgmt_wpa_psk(int akm) { return !!(akm & (WPA_KEY_MGMT_PSK | @@ -192,8 +190,7 @@ enum wpa_alg { WPA_ALG_WEP, WPA_ALG_TKIP, WPA_ALG_CCMP, - WPA_ALG_IGTK, - WPA_ALG_PMK, + WPA_ALG_BIP_CMAC_128, WPA_ALG_GCMP, WPA_ALG_SMS4, WPA_ALG_KRK, @@ -204,6 +201,14 @@ enum wpa_alg { WPA_ALG_BIP_CMAC_256 }; +static inline int wpa_alg_bip(enum wpa_alg alg) +{ + return alg == WPA_ALG_BIP_CMAC_128 || + alg == WPA_ALG_BIP_GMAC_128 || + alg == WPA_ALG_BIP_GMAC_256 || + alg == WPA_ALG_BIP_CMAC_256; +} + /** * enum wpa_states - wpa_supplicant state * @@ -383,9 +388,10 @@ enum mesh_plink_state { }; enum set_band { - WPA_SETBAND_AUTO, - WPA_SETBAND_5G, - WPA_SETBAND_2G + WPA_SETBAND_AUTO = 0, + WPA_SETBAND_5G = BIT(0), + WPA_SETBAND_2G = BIT(1), + WPA_SETBAND_6G = BIT(2), }; enum wpa_radio_work_band { @@ -443,6 +449,27 @@ enum key_flag { KEY_FLAG_PAIRWISE_RX = KEY_FLAG_PAIRWISE | KEY_FLAG_RX, KEY_FLAG_PAIRWISE_RX_TX_MODIFY = KEY_FLAG_PAIRWISE_RX_TX | KEY_FLAG_MODIFY, + /* Max allowed flags for each key type */ + KEY_FLAG_PAIRWISE_MASK = KEY_FLAG_PAIRWISE_RX_TX_MODIFY, + KEY_FLAG_GROUP_MASK = KEY_FLAG_GROUP_RX_TX_DEFAULT, + KEY_FLAG_PMK_MASK = KEY_FLAG_PMK, +}; + +static inline int check_key_flag(enum key_flag key_flag) +{ + return !!(!key_flag || + ((key_flag & (KEY_FLAG_PAIRWISE | KEY_FLAG_MODIFY)) && + (key_flag & ~KEY_FLAG_PAIRWISE_MASK)) || + ((key_flag & KEY_FLAG_GROUP) && + (key_flag & ~KEY_FLAG_GROUP_MASK)) || + ((key_flag & KEY_FLAG_PMK) && + (key_flag & ~KEY_FLAG_PMK_MASK))); +} + +enum ptk0_rekey_handling { + PTK0_REKEY_ALLOW_ALWAYS, + PTK0_REKEY_ALLOW_LOCAL_OK, + PTK0_REKEY_ALLOW_NEVER }; #endif /* DEFS_H */ diff --git a/src/common/dpp.c b/src/common/dpp.c index b200d00da..3c8c7682d 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -8,47 +8,34 @@ */ #include "utils/includes.h" -#include #include #include -#include -#include #include "utils/common.h" #include "utils/base64.h" #include "utils/json.h" -#include "utils/ip_addr.h" -#include "utils/eloop.h" #include "common/ieee802_11_common.h" -#include "common/ieee802_11_defs.h" #include "common/wpa_ctrl.h" #include "common/gas.h" +#include "eap_common/eap_defs.h" #include "crypto/crypto.h" #include "crypto/random.h" #include "crypto/aes.h" #include "crypto/aes_siv.h" -#include "crypto/sha384.h" -#include "crypto/sha512.h" -#include "tls/asn1.h" #include "drivers/driver.h" #include "dpp.h" +#include "dpp_i.h" static const char * dpp_netrole_str(enum dpp_netrole netrole); #ifdef CONFIG_TESTING_OPTIONS +#ifdef CONFIG_DPP2 +int dpp_version_override = 2; +#else +int dpp_version_override = 1; +#endif enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED; -u8 dpp_pkex_own_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; -u8 dpp_pkex_peer_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; -u8 dpp_pkex_ephemeral_key_override[600]; -size_t dpp_pkex_ephemeral_key_override_len = 0; -u8 dpp_protocol_key_override[600]; -size_t dpp_protocol_key_override_len = 0; -u8 dpp_nonce_override[DPP_MAX_NONCE_LEN]; -size_t dpp_nonce_override_len = 0; - -static int dpp_test_gen_invalid_key(struct wpabuf *msg, - const struct dpp_curve_params *curve); #endif /* CONFIG_TESTING_OPTIONS */ #if OPENSSL_VERSION_NUMBER < 0x10100000L || \ @@ -56,719 +43,19 @@ static int dpp_test_gen_invalid_key(struct wpabuf *msg, LIBRESSL_VERSION_NUMBER < 0x20700000L) /* Compatibility wrappers for older versions. */ -static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +#ifdef CONFIG_DPP2 +static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) { - sig->r = r; - sig->s = s; - return 1; -} - - -static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, - const BIGNUM **ps) -{ - if (pr) - *pr = sig->r; - if (ps) - *ps = sig->s; + if (pkey->type != EVP_PKEY_EC) + return NULL; + return pkey->pkey.ec; } +#endif /* CONFIG_DPP2 */ #endif -struct dpp_connection { - struct dl_list list; - struct dpp_controller *ctrl; - struct dpp_relay_controller *relay; - struct dpp_global *global; - struct dpp_authentication *auth; - int sock; - u8 mac_addr[ETH_ALEN]; - unsigned int freq; - u8 msg_len[4]; - size_t msg_len_octets; - struct wpabuf *msg; - struct wpabuf *msg_out; - size_t msg_out_pos; - unsigned int read_eloop:1; - unsigned int write_eloop:1; - unsigned int on_tcp_tx_complete_gas_done:1; - unsigned int on_tcp_tx_complete_remove:1; - unsigned int on_tcp_tx_complete_auth_ok:1; -}; - -/* Remote Controller */ -struct dpp_relay_controller { - struct dl_list list; - struct dpp_global *global; - u8 pkhash[SHA256_MAC_LEN]; - struct hostapd_ip_addr ipaddr; - void *cb_ctx; - void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg, - size_t len); - void (*gas_resp_tx)(void *ctx, const u8 *addr, u8 dialog_token, - int prot, struct wpabuf *buf); - struct dl_list conn; /* struct dpp_connection */ -}; - -/* Local Controller */ -struct dpp_controller { - struct dpp_global *global; - u8 allowed_roles; - int qr_mutual; - int sock; - struct dl_list conn; /* struct dpp_connection */ - char *configurator_params; -}; - -struct dpp_global { - void *msg_ctx; - struct dl_list bootstrap; /* struct dpp_bootstrap_info */ - struct dl_list configurator; /* struct dpp_configurator */ -#ifdef CONFIG_DPP2 - struct dl_list controllers; /* struct dpp_relay_controller */ - struct dpp_controller *controller; - struct dl_list tcp_init; /* struct dpp_connection */ - void *cb_ctx; - int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); -#endif /* CONFIG_DPP2 */ -}; - -static const struct dpp_curve_params dpp_curves[] = { - /* The mandatory to support and the default NIST P-256 curve needs to - * be the first entry on this list. */ - { "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" }, - { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" }, - { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" }, - { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" }, - { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" }, - { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" }, - { NULL, 0, 0, 0, 0, NULL, 0, NULL } -}; - - -/* Role-specific elements for PKEX */ - -/* NIST P-256 */ -static const u8 pkex_init_x_p256[32] = { - 0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b, - 0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54, - 0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07, - 0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25 - }; -static const u8 pkex_init_y_p256[32] = { - 0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b, - 0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc, - 0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45, - 0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4 - }; -static const u8 pkex_resp_x_p256[32] = { - 0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39, - 0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f, - 0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f, - 0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76 -}; -static const u8 pkex_resp_y_p256[32] = { - 0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19, - 0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1, - 0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a, - 0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67 -}; - -/* NIST P-384 */ -static const u8 pkex_init_x_p384[48] = { - 0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa, - 0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68, - 0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53, - 0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac, - 0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12, - 0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3 -}; -static const u8 pkex_init_y_p384[48] = { - 0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29, - 0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56, - 0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7, - 0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6, - 0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94, - 0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18 -}; -static const u8 pkex_resp_x_p384[48] = { - 0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98, - 0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97, - 0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92, - 0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44, - 0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf, - 0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf -}; -static const u8 pkex_resp_y_p384[48] = { - 0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c, - 0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c, - 0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3, - 0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1, - 0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63, - 0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06 -}; - -/* NIST P-521 */ -static const u8 pkex_init_x_p521[66] = { - 0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23, - 0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0, - 0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76, - 0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5, - 0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38, - 0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01, - 0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e, - 0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d, - 0x97, 0x76 -}; -static const u8 pkex_init_y_p521[66] = { - 0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59, - 0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99, - 0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b, - 0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd, - 0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f, - 0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf, - 0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02, - 0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d, - 0x03, 0xa8 -}; -static const u8 pkex_resp_x_p521[66] = { - 0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a, - 0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44, - 0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f, - 0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb, - 0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48, - 0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e, - 0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a, - 0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97, - 0x84, 0xb4 -}; -static const u8 pkex_resp_y_p521[66] = { - 0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d, - 0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20, - 0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3, - 0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84, - 0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9, - 0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2, - 0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80, - 0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53, - 0xce, 0xe1 -}; - -/* Brainpool P-256r1 */ -static const u8 pkex_init_x_bp_p256r1[32] = { - 0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10, - 0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca, - 0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75, - 0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8 -}; -static const u8 pkex_init_y_bp_p256r1[32] = { - 0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd, - 0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30, - 0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe, - 0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b -}; -static const u8 pkex_resp_x_bp_p256r1[32] = { - 0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f, - 0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a, - 0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a, - 0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3 -}; -static const u8 pkex_resp_y_bp_p256r1[32] = { - 0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd, - 0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2, - 0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e, - 0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64 -}; - -/* Brainpool P-384r1 */ -static const u8 pkex_init_x_bp_p384r1[48] = { - 0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd, - 0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19, - 0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06, - 0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62, - 0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30, - 0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe -}; -static const u8 pkex_init_y_bp_p384r1[48] = { - 0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99, - 0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86, - 0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32, - 0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9, - 0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e, - 0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52 -}; -static const u8 pkex_resp_x_bp_p384r1[48] = { - 0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0, - 0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25, - 0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b, - 0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71, - 0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce, - 0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c -}; -static const u8 pkex_resp_y_bp_p384r1[48] = { - 0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65, - 0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04, - 0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70, - 0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c, - 0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb, - 0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1 -}; - -/* Brainpool P-512r1 */ -static const u8 pkex_init_x_bp_p512r1[64] = { - 0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c, - 0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51, - 0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc, - 0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95, - 0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d, - 0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff, - 0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc, - 0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f -}; -static const u8 pkex_init_y_bp_p512r1[64] = { - 0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94, - 0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8, - 0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3, - 0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45, - 0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e, - 0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58, - 0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71, - 0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99 -}; -static const u8 pkex_resp_x_bp_p512r1[64] = { - 0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72, - 0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76, - 0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19, - 0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e, - 0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9, - 0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88, - 0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29, - 0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e -}; -static const u8 pkex_resp_y_bp_p512r1[64] = { - 0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81, - 0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68, - 0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa, - 0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d, - 0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c, - 0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09, - 0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56, - 0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7 -}; - - -static void dpp_debug_print_point(const char *title, const EC_GROUP *group, - const EC_POINT *point) -{ - BIGNUM *x, *y; - BN_CTX *ctx; - char *x_str = NULL, *y_str = NULL; - - if (!wpa_debug_show_keys) - return; - - ctx = BN_CTX_new(); - x = BN_new(); - y = BN_new(); - if (!ctx || !x || !y || - EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx) != 1) - goto fail; - - x_str = BN_bn2hex(x); - y_str = BN_bn2hex(y); - if (!x_str || !y_str) - goto fail; - - wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str); - -fail: - OPENSSL_free(x_str); - OPENSSL_free(y_str); - BN_free(x); - BN_free(y); - BN_CTX_free(ctx); -} - - -static int dpp_hash_vector(const struct dpp_curve_params *curve, - size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac) -{ - if (curve->hash_len == 32) - return sha256_vector(num_elem, addr, len, mac); - if (curve->hash_len == 48) - return sha384_vector(num_elem, addr, len, mac); - if (curve->hash_len == 64) - return sha512_vector(num_elem, addr, len, mac); - return -1; -} - - -static int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, - const char *label, u8 *out, size_t outlen) -{ - if (hash_len == 32) - return hmac_sha256_kdf(secret, secret_len, NULL, - (const u8 *) label, os_strlen(label), - out, outlen); - if (hash_len == 48) - return hmac_sha384_kdf(secret, secret_len, NULL, - (const u8 *) label, os_strlen(label), - out, outlen); - if (hash_len == 64) - return hmac_sha512_kdf(secret, secret_len, NULL, - (const u8 *) label, os_strlen(label), - out, outlen); - return -1; -} - - -static int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], - const size_t *len, u8 *mac) -{ - if (hash_len == 32) - return hmac_sha256_vector(key, key_len, num_elem, addr, len, - mac); - if (hash_len == 48) - return hmac_sha384_vector(key, key_len, num_elem, addr, len, - mac); - if (hash_len == 64) - return hmac_sha512_vector(key, key_len, num_elem, addr, len, - mac); - return -1; -} - - -static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, - const u8 *data, size_t data_len, u8 *mac) -{ - if (hash_len == 32) - return hmac_sha256(key, key_len, data, data_len, mac); - if (hash_len == 48) - return hmac_sha384(key, key_len, data, data_len, mac); - if (hash_len == 64) - return hmac_sha512(key, key_len, data, data_len, mac); - return -1; -} - - -#ifdef CONFIG_DPP2 - -static int dpp_pbkdf2_f(size_t hash_len, - const u8 *password, size_t password_len, - const u8 *salt, size_t salt_len, - unsigned int iterations, unsigned int count, u8 *digest) -{ - unsigned char tmp[DPP_MAX_HASH_LEN], tmp2[DPP_MAX_HASH_LEN]; - unsigned int i; - size_t j; - u8 count_buf[4]; - const u8 *addr[2]; - size_t len[2]; - - addr[0] = salt; - len[0] = salt_len; - addr[1] = count_buf; - len[1] = 4; - - /* F(P, S, c, i) = U1 xor U2 xor ... Uc - * U1 = PRF(P, S || i) - * U2 = PRF(P, U1) - * Uc = PRF(P, Uc-1) - */ - - WPA_PUT_BE32(count_buf, count); - if (dpp_hmac_vector(hash_len, password, password_len, 2, addr, len, - tmp)) - return -1; - os_memcpy(digest, tmp, hash_len); - - for (i = 1; i < iterations; i++) { - if (dpp_hmac(hash_len, password, password_len, tmp, hash_len, - tmp2)) - return -1; - os_memcpy(tmp, tmp2, hash_len); - for (j = 0; j < hash_len; j++) - digest[j] ^= tmp2[j]; - } - - return 0; -} - - -static int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len, - const u8 *salt, size_t salt_len, unsigned int iterations, - u8 *buf, size_t buflen) -{ - unsigned int count = 0; - unsigned char *pos = buf; - size_t left = buflen, plen; - unsigned char digest[DPP_MAX_HASH_LEN]; - - while (left > 0) { - count++; - if (dpp_pbkdf2_f(hash_len, password, password_len, - salt, salt_len, iterations, count, digest)) - return -1; - plen = left > hash_len ? hash_len : left; - os_memcpy(pos, digest, plen); - pos += plen; - left -= plen; - } - - return 0; -} - -#endif /* CONFIG_DPP2 */ - - -static int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len) -{ - int num_bytes, offset; - - num_bytes = BN_num_bytes(bn); - if ((size_t) num_bytes > len) - return -1; - offset = len - num_bytes; - os_memset(pos, 0, offset); - BN_bn2bin(bn, pos + offset); - return 0; -} - - -static struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix) -{ - int len, res; - EC_KEY *eckey; - struct wpabuf *buf; - unsigned char *pos; - - eckey = EVP_PKEY_get1_EC_KEY(pkey); - if (!eckey) - return NULL; - EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED); - len = i2o_ECPublicKey(eckey, NULL); - if (len <= 0) { - wpa_printf(MSG_ERROR, - "DDP: Failed to determine public key encoding length"); - EC_KEY_free(eckey); - return NULL; - } - - buf = wpabuf_alloc(len); - if (!buf) { - EC_KEY_free(eckey); - return NULL; - } - - pos = wpabuf_put(buf, len); - res = i2o_ECPublicKey(eckey, &pos); - EC_KEY_free(eckey); - if (res != len) { - wpa_printf(MSG_ERROR, - "DDP: Failed to encode public key (res=%d/%d)", - res, len); - wpabuf_free(buf); - return NULL; - } - - if (!prefix) { - /* Remove 0x04 prefix to match DPP definition */ - pos = wpabuf_mhead(buf); - os_memmove(pos, pos + 1, len - 1); - buf->used--; - } - - return buf; -} - - -static EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group, - const u8 *buf_x, const u8 *buf_y, - size_t len) -{ - EC_KEY *eckey = NULL; - BN_CTX *ctx; - EC_POINT *point = NULL; - BIGNUM *x = NULL, *y = NULL; - EVP_PKEY *pkey = NULL; - - ctx = BN_CTX_new(); - if (!ctx) { - wpa_printf(MSG_ERROR, "DPP: Out of memory"); - return NULL; - } - - point = EC_POINT_new(group); - x = BN_bin2bn(buf_x, len, NULL); - y = BN_bin2bn(buf_y, len, NULL); - if (!point || !x || !y) { - wpa_printf(MSG_ERROR, "DPP: Out of memory"); - goto fail; - } - - if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { - wpa_printf(MSG_ERROR, - "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (!EC_POINT_is_on_curve(group, point, ctx) || - EC_POINT_is_at_infinity(group, point)) { - wpa_printf(MSG_ERROR, "DPP: Invalid point"); - goto fail; - } - dpp_debug_print_point("DPP: dpp_set_pubkey_point_group", group, point); - - eckey = EC_KEY_new(); - if (!eckey || - EC_KEY_set_group(eckey, group) != 1 || - EC_KEY_set_public_key(eckey, point) != 1) { - wpa_printf(MSG_ERROR, - "DPP: Failed to set EC_KEY: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); - - pkey = EVP_PKEY_new(); - if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) { - wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY"); - goto fail; - } - -out: - BN_free(x); - BN_free(y); - EC_KEY_free(eckey); - EC_POINT_free(point); - BN_CTX_free(ctx); - return pkey; -fail: - EVP_PKEY_free(pkey); - pkey = NULL; - goto out; -} - - -static EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, - const u8 *buf, size_t len) -{ - EC_KEY *eckey; - const EC_GROUP *group; - EVP_PKEY *pkey = NULL; - - if (len & 1) - return NULL; - - eckey = EVP_PKEY_get1_EC_KEY(group_key); - if (!eckey) { - wpa_printf(MSG_ERROR, - "DPP: Could not get EC_KEY from group_key"); - return NULL; - } - - group = EC_KEY_get0_group(eckey); - if (group) - pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2, - len / 2); - else - wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); - - EC_KEY_free(eckey); - return pkey; -} - - -static int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, - u8 *secret, size_t *secret_len) -{ - EVP_PKEY_CTX *ctx; - int ret = -1; - - ERR_clear_error(); - *secret_len = 0; - - ctx = EVP_PKEY_CTX_new(own, NULL); - if (!ctx) { - wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - return -1; - } - - if (EVP_PKEY_derive_init(ctx) != 1) { - wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive_init failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (EVP_PKEY_derive_set_peer(ctx, peer) != 1) { - wpa_printf(MSG_ERROR, - "DPP: EVP_PKEY_derive_set_peet failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (EVP_PKEY_derive(ctx, NULL, secret_len) != 1) { - wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive(NULL) failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { - u8 buf[200]; - int level = *secret_len > 200 ? MSG_ERROR : MSG_DEBUG; - - /* It looks like OpenSSL can return unexpectedly large buffer - * need for shared secret from EVP_PKEY_derive(NULL) in some - * cases. For example, group 19 has shown cases where secret_len - * is set to 72 even though the actual length ends up being - * updated to 32 when EVP_PKEY_derive() is called with a buffer - * for the value. Work around this by trying to fetch the value - * and continue if it is within supported range even when the - * initial buffer need is claimed to be larger. */ - wpa_printf(level, - "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()", - (int) *secret_len); - if (*secret_len > 200) - goto fail; - if (EVP_PKEY_derive(ctx, buf, secret_len) != 1) { - wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { - wpa_printf(MSG_ERROR, - "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()", - (int) *secret_len); - goto fail; - } - wpa_hexdump_key(MSG_DEBUG, "DPP: Unexpected secret_len change", - buf, *secret_len); - os_memcpy(secret, buf, *secret_len); - forced_memzero(buf, sizeof(buf)); - goto done; - } - - if (EVP_PKEY_derive(ctx, secret, secret_len) != 1) { - wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - -done: - ret = 0; - -fail: - EVP_PKEY_CTX_free(ctx); - return ret; -} - - -static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt) +void dpp_auth_fail(struct dpp_authentication *auth, const char *txt) { wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt); } @@ -894,6 +181,7 @@ void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info) os_free(info->chan); os_free(info->pk); EVP_PKEY_free(info->pubkey); + str_clear_free(info->configurator_params); os_free(info); } @@ -957,6 +245,7 @@ int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi, wpa_printf(MSG_DEBUG, "DPP: URI channel-list: opclass=%d channel=%d ==> freq=%d", opclass, channel, freq); + bi->channels_listed = true; if (freq < 0) { wpa_printf(MSG_DEBUG, "DPP: Ignore unknown URI channel-list channel (opclass=%d channel=%d)", @@ -1025,60 +314,32 @@ int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info) } -static const struct dpp_curve_params * -dpp_get_curve_oid(const ASN1_OBJECT *poid) +int dpp_parse_uri_version(struct dpp_bootstrap_info *bi, const char *version) { - ASN1_OBJECT *oid; - int i; +#ifdef CONFIG_DPP2 + if (!version || DPP_VERSION < 2) + return 0; - for (i = 0; dpp_curves[i].name; i++) { - oid = OBJ_txt2obj(dpp_curves[i].name, 0); - if (oid && OBJ_cmp(poid, oid) == 0) - return &dpp_curves[i]; - } - return NULL; -} + if (*version == '1') + bi->version = 1; + else if (*version == '2') + bi->version = 2; + else + wpa_printf(MSG_DEBUG, "DPP: Unknown URI version"); + wpa_printf(MSG_DEBUG, "DPP: URI version: %d", bi->version); +#endif /* CONFIG_DPP2 */ -static const struct dpp_curve_params * dpp_get_curve_nid(int nid) -{ - int i, tmp; - - if (!nid) - return NULL; - for (i = 0; dpp_curves[i].name; i++) { - tmp = OBJ_txt2nid(dpp_curves[i].name); - if (tmp == nid) - return &dpp_curves[i]; - } - return NULL; + return 0; } static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info) { - const char *end; u8 *data; size_t data_len; - EVP_PKEY *pkey; - const unsigned char *p; int res; - X509_PUBKEY *pub = NULL; - ASN1_OBJECT *ppkalg; - const unsigned char *pk; - int ppklen; - X509_ALGOR *pa; -#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ - (defined(LIBRESSL_VERSION_NUMBER) && \ - LIBRESSL_VERSION_NUMBER < 0x20800000L) - ASN1_OBJECT *pa_oid; -#else - const ASN1_OBJECT *pa_oid; -#endif - const void *pval; - int ptype; - const ASN1_OBJECT *poid; - char buf[100]; + const char *end; end = os_strchr(info, ';'); if (!end) @@ -1093,104 +354,9 @@ static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info) wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key", data, data_len); - if (sha256_vector(1, (const u8 **) &data, &data_len, - bi->pubkey_hash) < 0) { - wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); - os_free(data); - return -1; - } - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", - bi->pubkey_hash, SHA256_MAC_LEN); - - /* DER encoded ASN.1 SubjectPublicKeyInfo - * - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - * - * subjectPublicKey = compressed format public key per ANSI X9.63 - * algorithm = ecPublicKey (1.2.840.10045.2.1) - * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g., - * prime256v1 (1.2.840.10045.3.1.7) - */ - - p = data; - pkey = d2i_PUBKEY(NULL, &p, data_len); + res = dpp_get_subject_public_key(bi, data, data_len); os_free(data); - - if (!pkey) { - wpa_printf(MSG_DEBUG, - "DPP: Could not parse URI public-key SubjectPublicKeyInfo"); - return -1; - } - - if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) { - wpa_printf(MSG_DEBUG, - "DPP: SubjectPublicKeyInfo does not describe an EC key"); - EVP_PKEY_free(pkey); - return -1; - } - - res = X509_PUBKEY_set(&pub, pkey); - if (res != 1) { - wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey"); - goto fail; - } - - res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub); - if (res != 1) { - wpa_printf(MSG_DEBUG, - "DPP: Could not extract SubjectPublicKeyInfo parameters"); - goto fail; - } - res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0); - if (res < 0 || (size_t) res >= sizeof(buf)) { - wpa_printf(MSG_DEBUG, - "DPP: Could not extract SubjectPublicKeyInfo algorithm"); - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf); - if (os_strcmp(buf, "id-ecPublicKey") != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Unsupported SubjectPublicKeyInfo algorithm"); - goto fail; - } - - X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa); - if (ptype != V_ASN1_OBJECT) { - wpa_printf(MSG_DEBUG, - "DPP: SubjectPublicKeyInfo parameters did not contain an OID"); - goto fail; - } - poid = pval; - res = OBJ_obj2txt(buf, sizeof(buf), poid, 0); - if (res < 0 || (size_t) res >= sizeof(buf)) { - wpa_printf(MSG_DEBUG, - "DPP: Could not extract SubjectPublicKeyInfo parameters OID"); - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf); - bi->curve = dpp_get_curve_oid(poid); - if (!bi->curve) { - wpa_printf(MSG_DEBUG, - "DPP: Unsupported SubjectPublicKeyInfo curve: %s", - buf); - goto fail; - } - - wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen); - - X509_PUBKEY_free(pub); - bi->pubkey = pkey; - return 0; -fail: - X509_PUBKEY_free(pub); - EVP_PKEY_free(pkey); - return -1; + return res; } @@ -1199,6 +365,7 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) const char *pos = uri; const char *end; const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL; + const char *version = NULL; struct dpp_bootstrap_info *bi; wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri)); @@ -1229,6 +396,8 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) info = pos + 2; else if (pos[0] == 'K' && pos[1] == ':' && !pk) pk = pos + 2; + else if (pos[0] == 'V' && pos[1] == ':' && !version) + version = pos + 2; else wpa_hexdump_ascii(MSG_DEBUG, "DPP: Ignore unrecognized URI parameter", @@ -1249,6 +418,7 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) dpp_parse_uri_chan_list(bi, chan_list) < 0 || dpp_parse_uri_mac(bi, mac) < 0 || dpp_parse_uri_info(bi, info) < 0 || + dpp_parse_uri_version(bi, version) < 0 || dpp_parse_uri_pk(bi, pk) < 0) { dpp_bootstrap_info_free(bi); bi = NULL; @@ -1258,477 +428,7 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) } -static void dpp_debug_print_key(const char *title, EVP_PKEY *key) -{ - EC_KEY *eckey; - BIO *out; - size_t rlen; - char *txt; - int res; - unsigned char *der = NULL; - int der_len; - const EC_GROUP *group; - const EC_POINT *point; - - out = BIO_new(BIO_s_mem()); - if (!out) - return; - - EVP_PKEY_print_private(out, key, 0, NULL); - rlen = BIO_ctrl_pending(out); - txt = os_malloc(rlen + 1); - if (txt) { - res = BIO_read(out, txt, rlen); - if (res > 0) { - txt[res] = '\0'; - wpa_printf(MSG_DEBUG, "%s: %s", title, txt); - } - os_free(txt); - } - BIO_free(out); - - eckey = EVP_PKEY_get1_EC_KEY(key); - if (!eckey) - return; - - group = EC_KEY_get0_group(eckey); - point = EC_KEY_get0_public_key(eckey); - if (group && point) - dpp_debug_print_point(title, group, point); - - der_len = i2d_ECPrivateKey(eckey, &der); - if (der_len > 0) - wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len); - OPENSSL_free(der); - if (der_len <= 0) { - der = NULL; - der_len = i2d_EC_PUBKEY(eckey, &der); - if (der_len > 0) - wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len); - OPENSSL_free(der); - } - - EC_KEY_free(eckey); -} - - -static EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve) -{ - EVP_PKEY_CTX *kctx = NULL; - EC_KEY *ec_params = NULL; - EVP_PKEY *params = NULL, *key = NULL; - int nid; - - wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); - - nid = OBJ_txt2nid(curve->name); - if (nid == NID_undef) { - wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name); - return NULL; - } - - ec_params = EC_KEY_new_by_curve_name(nid); - if (!ec_params) { - wpa_printf(MSG_ERROR, - "DPP: Failed to generate EC_KEY parameters"); - goto fail; - } - EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE); - params = EVP_PKEY_new(); - if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) { - wpa_printf(MSG_ERROR, - "DPP: Failed to generate EVP_PKEY parameters"); - goto fail; - } - - kctx = EVP_PKEY_CTX_new(params, NULL); - if (!kctx || - EVP_PKEY_keygen_init(kctx) != 1 || - EVP_PKEY_keygen(kctx, &key) != 1) { - wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key"); - key = NULL; - goto fail; - } - - if (wpa_debug_show_keys) - dpp_debug_print_key("Own generated key", key); - -fail: - EC_KEY_free(ec_params); - EVP_PKEY_free(params); - EVP_PKEY_CTX_free(kctx); - return key; -} - - -static const struct dpp_curve_params * -dpp_get_curve_name(const char *name) -{ - int i; - - for (i = 0; dpp_curves[i].name; i++) { - if (os_strcmp(name, dpp_curves[i].name) == 0 || - (dpp_curves[i].jwk_crv && - os_strcmp(name, dpp_curves[i].jwk_crv) == 0)) - return &dpp_curves[i]; - } - return NULL; -} - - -static const struct dpp_curve_params * -dpp_get_curve_jwk_crv(const char *name) -{ - int i; - - for (i = 0; dpp_curves[i].name; i++) { - if (dpp_curves[i].jwk_crv && - os_strcmp(name, dpp_curves[i].jwk_crv) == 0) - return &dpp_curves[i]; - } - return NULL; -} - - -static EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve, - const u8 *privkey, size_t privkey_len) -{ - EVP_PKEY *pkey; - EC_KEY *eckey; - const EC_GROUP *group; - int nid; - - pkey = EVP_PKEY_new(); - if (!pkey) - return NULL; - eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len); - if (!eckey) { - wpa_printf(MSG_INFO, - "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - EVP_PKEY_free(pkey); - return NULL; - } - group = EC_KEY_get0_group(eckey); - if (!group) { - EC_KEY_free(eckey); - EVP_PKEY_free(pkey); - return NULL; - } - nid = EC_GROUP_get_curve_name(group); - *curve = dpp_get_curve_nid(nid); - if (!*curve) { - wpa_printf(MSG_INFO, - "DPP: Unsupported curve (nid=%d) in pre-assigned key", - nid); - EC_KEY_free(eckey); - EVP_PKEY_free(pkey); - return NULL; - } - - if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { - EC_KEY_free(eckey); - EVP_PKEY_free(pkey); - return NULL; - } - return pkey; -} - - -typedef struct { - /* AlgorithmIdentifier ecPublicKey with optional parameters present - * as an OID identifying the curve */ - X509_ALGOR *alg; - /* Compressed format public key per ANSI X9.63 */ - ASN1_BIT_STRING *pub_key; -} DPP_BOOTSTRAPPING_KEY; - -ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = { - ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR), - ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING) -} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY); - -IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY); - - -static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key) -{ - unsigned char *der = NULL; - int der_len; - EC_KEY *eckey; - struct wpabuf *ret = NULL; - size_t len; - const EC_GROUP *group; - const EC_POINT *point; - BN_CTX *ctx; - DPP_BOOTSTRAPPING_KEY *bootstrap = NULL; - int nid; - - ctx = BN_CTX_new(); - eckey = EVP_PKEY_get1_EC_KEY(key); - if (!ctx || !eckey) - goto fail; - - group = EC_KEY_get0_group(eckey); - point = EC_KEY_get0_public_key(eckey); - if (!group || !point) - goto fail; - dpp_debug_print_point("DPP: bootstrap public key", group, point); - nid = EC_GROUP_get_curve_name(group); - - bootstrap = DPP_BOOTSTRAPPING_KEY_new(); - if (!bootstrap || - X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC), - V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1) - goto fail; - - len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, - NULL, 0, ctx); - if (len == 0) - goto fail; - - der = OPENSSL_malloc(len); - if (!der) - goto fail; - len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, - der, len, ctx); - - OPENSSL_free(bootstrap->pub_key->data); - bootstrap->pub_key->data = der; - der = NULL; - bootstrap->pub_key->length = len; - /* No unused bits */ - bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); - bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; - - der_len = i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der); - if (der_len <= 0) { - wpa_printf(MSG_ERROR, - "DDP: Failed to build DER encoded public key"); - goto fail; - } - - ret = wpabuf_alloc_copy(der, der_len); -fail: - DPP_BOOTSTRAPPING_KEY_free(bootstrap); - OPENSSL_free(der); - EC_KEY_free(eckey); - BN_CTX_free(ctx); - return ret; -} - - -int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) -{ - struct wpabuf *der; - int res; - const u8 *addr[1]; - size_t len[1]; - - der = dpp_bootstrap_key_der(bi->pubkey); - if (!der) - return -1; - wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", - der); - - addr[0] = wpabuf_head(der); - len[0] = wpabuf_len(der); - res = sha256_vector(1, addr, len, bi->pubkey_hash); - if (res < 0) - wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); - else - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash, - SHA256_MAC_LEN); - wpabuf_free(der); - return res; -} - - -static int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, - const u8 *privkey, size_t privkey_len) -{ - char *base64 = NULL; - char *pos, *end; - size_t len; - struct wpabuf *der = NULL; - const u8 *addr[1]; - int res; - - if (!curve) { - bi->curve = &dpp_curves[0]; - } else { - bi->curve = dpp_get_curve_name(curve); - if (!bi->curve) { - wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", - curve); - return -1; - } - } - if (privkey) - bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len); - else - bi->pubkey = dpp_gen_keypair(bi->curve); - if (!bi->pubkey) - goto fail; - bi->own = 1; - - der = dpp_bootstrap_key_der(bi->pubkey); - if (!der) - goto fail; - wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", - der); - - addr[0] = wpabuf_head(der); - len = wpabuf_len(der); - res = sha256_vector(1, addr, &len, bi->pubkey_hash); - if (res < 0) { - wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash, - SHA256_MAC_LEN); - - base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len); - wpabuf_free(der); - der = NULL; - if (!base64) - goto fail; - pos = base64; - end = pos + len; - for (;;) { - pos = os_strchr(pos, '\n'); - if (!pos) - break; - os_memmove(pos, pos + 1, end - pos); - } - os_free(bi->pk); - bi->pk = base64; - return 0; -fail: - os_free(base64); - wpabuf_free(der); - return -1; -} - - -static int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, - unsigned int hash_len) -{ - u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; - const char *info = "first intermediate key"; - int res; - - /* k1 = HKDF(<>, "first intermediate key", M.x) */ - - /* HKDF-Extract(<>, M.x) */ - os_memset(salt, 0, hash_len); - if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)", - prk, hash_len); - - /* HKDF-Expand(PRK, info, L) */ - res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len); - os_memset(prk, 0, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)", - k1, hash_len); - return 0; -} - - -static int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, - unsigned int hash_len) -{ - u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; - const char *info = "second intermediate key"; - int res; - - /* k2 = HKDF(<>, "second intermediate key", N.x) */ - - /* HKDF-Extract(<>, N.x) */ - os_memset(salt, 0, hash_len); - res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk); - if (res < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", - prk, hash_len); - - /* HKDF-Expand(PRK, info, L) */ - res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len); - os_memset(prk, 0, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)", - k2, hash_len); - return 0; -} - - -static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke, - unsigned int hash_len) -{ - size_t nonce_len; - u8 nonces[2 * DPP_MAX_NONCE_LEN]; - const char *info_ke = "DPP Key"; - u8 prk[DPP_MAX_HASH_LEN]; - int res; - const u8 *addr[3]; - size_t len[3]; - size_t num_elem = 0; - - if (!auth->Mx_len || !auth->Nx_len) { - wpa_printf(MSG_DEBUG, - "DPP: Mx/Nx not available - cannot derive ke"); - return -1; - } - - /* ke = HKDF(I-nonce | R-nonce, "DPP Key", M.x | N.x [| L.x]) */ - - /* HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */ - nonce_len = auth->curve->nonce_len; - os_memcpy(nonces, auth->i_nonce, nonce_len); - os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len); - addr[num_elem] = auth->Mx; - len[num_elem] = auth->Mx_len; - num_elem++; - addr[num_elem] = auth->Nx; - len[num_elem] = auth->Nx_len; - num_elem++; - if (auth->peer_bi && auth->own_bi) { - if (!auth->Lx_len) { - wpa_printf(MSG_DEBUG, - "DPP: Lx not available - cannot derive ke"); - return -1; - } - addr[num_elem] = auth->Lx; - len[num_elem] = auth->secret_len; - num_elem++; - } - res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len, - num_elem, addr, len, prk); - if (res < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", - prk, hash_len); - - /* HKDF-Expand(PRK, info, L) */ - res = dpp_hkdf_expand(hash_len, prk, hash_len, info_ke, ke, hash_len); - os_memset(prk, 0, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ke = HKDF-Expand(PRK, info, L)", - ke, hash_len); - return 0; -} - - -static void dpp_build_attr_status(struct wpabuf *msg, - enum dpp_status_error status) +void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status) { wpa_printf(MSG_DEBUG, "DPP: Status %d", status); wpabuf_put_le16(msg, DPP_ATTR_STATUS); @@ -1737,8 +437,7 @@ static void dpp_build_attr_status(struct wpabuf *msg, } -static void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, - const u8 *hash) +void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, const u8 *hash) { if (hash) { wpa_printf(MSG_DEBUG, "DPP: R-Bootstrap Key Hash"); @@ -1749,374 +448,6 @@ static void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, } -static void dpp_build_attr_i_bootstrap_key_hash(struct wpabuf *msg, - const u8 *hash) -{ - if (hash) { - wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash"); - wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH); - wpabuf_put_le16(msg, SHA256_MAC_LEN); - wpabuf_put_data(msg, hash, SHA256_MAC_LEN); - } -} - - -static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth, - const struct wpabuf *pi, - size_t nonce_len, - const u8 *r_pubkey_hash, - const u8 *i_pubkey_hash, - unsigned int neg_freq) -{ - struct wpabuf *msg; - u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1]; - u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE]; - u8 *pos; - const u8 *addr[2]; - size_t len[2], siv_len, attr_len; - u8 *attr_start, *attr_end; - - /* Build DPP Authentication Request frame attributes */ - attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + (pi ? wpabuf_len(pi) : 0) + - 4 + sizeof(wrapped_data); - if (neg_freq > 0) - attr_len += 4 + 2; -#ifdef CONFIG_DPP2 - attr_len += 5; -#endif /* CONFIG_DPP2 */ -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) - attr_len += 5; -#endif /* CONFIG_TESTING_OPTIONS */ - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len); - if (!msg) - return NULL; - - attr_start = wpabuf_put(msg, 0); - - /* Responder Bootstrapping Key Hash */ - dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); - - /* Initiator Bootstrapping Key Hash */ - dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); - - /* Initiator Protocol Key */ - if (pi) { - wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY); - wpabuf_put_le16(msg, wpabuf_len(pi)); - wpabuf_put_buf(msg, pi); - } - - /* Channel */ - if (neg_freq > 0) { - u8 op_class, channel; - - if (ieee80211_freq_to_channel_ext(neg_freq, 0, 0, &op_class, - &channel) == - NUM_HOSTAPD_MODES) { - wpa_printf(MSG_INFO, - "DPP: Unsupported negotiation frequency request: %d", - neg_freq); - wpabuf_free(msg); - return NULL; - } - wpabuf_put_le16(msg, DPP_ATTR_CHANNEL); - wpabuf_put_le16(msg, 2); - wpabuf_put_u8(msg, op_class); - wpabuf_put_u8(msg, channel); - } - -#ifdef CONFIG_DPP2 - /* Protocol Version */ - wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); - wpabuf_put_le16(msg, 1); - wpabuf_put_u8(msg, 2); -#endif /* CONFIG_DPP2 */ - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); - goto skip_wrapped_data; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* Wrapped data ({I-nonce, I-capabilities}k1) */ - pos = clear; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); - goto skip_i_nonce; - } - if (dpp_test == DPP_TEST_INVALID_I_NONCE_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-nonce"); - WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); - pos += 2; - WPA_PUT_LE16(pos, nonce_len - 1); - pos += 2; - os_memcpy(pos, auth->i_nonce, nonce_len - 1); - pos += nonce_len - 1; - goto skip_i_nonce; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* I-nonce */ - WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); - pos += 2; - WPA_PUT_LE16(pos, nonce_len); - pos += 2; - os_memcpy(pos, auth->i_nonce, nonce_len); - pos += nonce_len; - -#ifdef CONFIG_TESTING_OPTIONS -skip_i_nonce: - if (dpp_test == DPP_TEST_NO_I_CAPAB_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-capab"); - goto skip_i_capab; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* I-capabilities */ - WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES); - pos += 2; - WPA_PUT_LE16(pos, 1); - pos += 2; - auth->i_capab = auth->allowed_roles; - *pos++ = auth->i_capab; -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_ZERO_I_CAPAB) { - wpa_printf(MSG_INFO, "DPP: TESTING - zero I-capabilities"); - pos[-1] = 0; - } -skip_i_capab: -#endif /* CONFIG_TESTING_OPTIONS */ - - attr_end = wpabuf_put(msg, 0); - - /* OUI, OUI type, Crypto Suite, DPP frame type */ - addr[0] = wpabuf_head_u8(msg) + 2; - len[0] = 3 + 1 + 1 + 1; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - - /* Attributes before Wrapped Data */ - addr[1] = attr_start; - len[1] = attr_end - attr_start; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - siv_len = pos - clear; - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); - if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len, - 2, addr, len, wrapped_data) < 0) { - wpabuf_free(msg); - return NULL; - } - siv_len += AES_BLOCK_SIZE; - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, siv_len); - - wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); - wpabuf_put_le16(msg, siv_len); - wpabuf_put_data(msg, wrapped_data, siv_len); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); - dpp_build_attr_status(msg, DPP_STATUS_OK); - } -skip_wrapped_data: -#endif /* CONFIG_TESTING_OPTIONS */ - - wpa_hexdump_buf(MSG_DEBUG, - "DPP: Authentication Request frame attributes", msg); - - return msg; -} - - -static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth, - enum dpp_status_error status, - const struct wpabuf *pr, - size_t nonce_len, - const u8 *r_pubkey_hash, - const u8 *i_pubkey_hash, - const u8 *r_nonce, const u8 *i_nonce, - const u8 *wrapped_r_auth, - size_t wrapped_r_auth_len, - const u8 *siv_key) -{ - struct wpabuf *msg; -#define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \ - 4 + 4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE - u8 clear[DPP_AUTH_RESP_CLEAR_LEN]; - u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE]; - const u8 *addr[2]; - size_t len[2], siv_len, attr_len; - u8 *attr_start, *attr_end, *pos; - - auth->waiting_auth_conf = 1; - auth->auth_resp_tries = 0; - - /* Build DPP Authentication Response frame attributes */ - attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + - 4 + (pr ? wpabuf_len(pr) : 0) + 4 + sizeof(wrapped_data); -#ifdef CONFIG_DPP2 - attr_len += 5; -#endif /* CONFIG_DPP2 */ -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) - attr_len += 5; -#endif /* CONFIG_TESTING_OPTIONS */ - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len); - if (!msg) - return NULL; - - attr_start = wpabuf_put(msg, 0); - - /* DPP Status */ - if (status != 255) - dpp_build_attr_status(msg, status); - - /* Responder Bootstrapping Key Hash */ - dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); - - /* Initiator Bootstrapping Key Hash (mutual authentication) */ - dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); - - /* Responder Protocol Key */ - if (pr) { - wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY); - wpabuf_put_le16(msg, wpabuf_len(pr)); - wpabuf_put_buf(msg, pr); - } - -#ifdef CONFIG_DPP2 - /* Protocol Version */ - if (auth->peer_version >= 2) { - wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); - wpabuf_put_le16(msg, 1); - wpabuf_put_u8(msg, 2); - } -#endif /* CONFIG_DPP2 */ - - attr_end = wpabuf_put(msg, 0); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); - goto skip_wrapped_data; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */ - pos = clear; - - if (r_nonce) { - /* R-nonce */ - WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE); - pos += 2; - WPA_PUT_LE16(pos, nonce_len); - pos += 2; - os_memcpy(pos, r_nonce, nonce_len); - pos += nonce_len; - } - - if (i_nonce) { - /* I-nonce */ - WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); - pos += 2; - WPA_PUT_LE16(pos, nonce_len); - pos += 2; - os_memcpy(pos, i_nonce, nonce_len); -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - I-nonce mismatch"); - pos[nonce_len / 2] ^= 0x01; - } -#endif /* CONFIG_TESTING_OPTIONS */ - pos += nonce_len; - } - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_R_CAPAB_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-capab"); - goto skip_r_capab; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* R-capabilities */ - WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES); - pos += 2; - WPA_PUT_LE16(pos, 1); - pos += 2; - auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR : - DPP_CAPAB_ENROLLEE; - *pos++ = auth->r_capab; -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_ZERO_R_CAPAB) { - wpa_printf(MSG_INFO, "DPP: TESTING - zero R-capabilities"); - pos[-1] = 0; - } else if (dpp_test == DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - incompatible R-capabilities"); - if ((auth->i_capab & DPP_CAPAB_ROLE_MASK) == - (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) - pos[-1] = 0; - else - pos[-1] = auth->configurator ? DPP_CAPAB_ENROLLEE : - DPP_CAPAB_CONFIGURATOR; - } -skip_r_capab: -#endif /* CONFIG_TESTING_OPTIONS */ - - if (wrapped_r_auth) { - /* {R-auth}ke */ - WPA_PUT_LE16(pos, DPP_ATTR_WRAPPED_DATA); - pos += 2; - WPA_PUT_LE16(pos, wrapped_r_auth_len); - pos += 2; - os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len); - pos += wrapped_r_auth_len; - } - - /* OUI, OUI type, Crypto Suite, DPP frame type */ - addr[0] = wpabuf_head_u8(msg) + 2; - len[0] = 3 + 1 + 1 + 1; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - - /* Attributes before Wrapped Data */ - addr[1] = attr_start; - len[1] = attr_end - attr_start; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - siv_len = pos - clear; - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); - if (aes_siv_encrypt(siv_key, auth->curve->hash_len, clear, siv_len, - 2, addr, len, wrapped_data) < 0) { - wpabuf_free(msg); - return NULL; - } - siv_len += AES_BLOCK_SIZE; - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, siv_len); - - wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); - wpabuf_put_le16(msg, siv_len); - wpabuf_put_data(msg, wrapped_data, siv_len); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); - dpp_build_attr_status(msg, DPP_STATUS_OK); - } -skip_wrapped_data: -#endif /* CONFIG_TESTING_OPTIONS */ - - wpa_hexdump_buf(MSG_DEBUG, - "DPP: Authentication Response frame attributes", msg); - return msg; -} - - static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes, u16 num_modes, unsigned int freq) { @@ -2235,14 +566,23 @@ static int dpp_channel_local_list(struct dpp_authentication *auth, } -static int dpp_prepare_channel_list(struct dpp_authentication *auth, - struct hostapd_hw_modes *own_modes, - u16 num_modes) +int dpp_prepare_channel_list(struct dpp_authentication *auth, + unsigned int neg_freq, + struct hostapd_hw_modes *own_modes, u16 num_modes) { int res; char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end; unsigned int i; + if (!own_modes) { + if (!neg_freq) + return -1; + auth->num_freq = 1; + auth->freq[0] = neg_freq; + auth->curr_freq = neg_freq; + return 0; + } + if (auth->peer_bi->num_freq > 0) res = dpp_channel_intersect(auth, own_modes, num_modes); else @@ -2275,7 +615,7 @@ static int dpp_prepare_channel_list(struct dpp_authentication *auth, } -static int dpp_gen_uri(struct dpp_bootstrap_info *bi) +int dpp_gen_uri(struct dpp_bootstrap_info *bi) { char macstr[ETH_ALEN * 2 + 10]; size_t len; @@ -2291,203 +631,42 @@ static int dpp_gen_uri(struct dpp_bootstrap_info *bi) len += os_strlen(macstr); /* M:...; */ if (bi->info) len += 3 + os_strlen(bi->info); /* I:...; */ +#ifdef CONFIG_DPP2 + len += 4; /* V:2; */ +#endif /* CONFIG_DPP2 */ len += 4 + os_strlen(bi->pk); /* K:...;; */ os_free(bi->uri); bi->uri = os_malloc(len + 1); if (!bi->uri) return -1; - os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%sK:%s;;", + os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%sK:%s;;", bi->chan ? "C:" : "", bi->chan ? bi->chan : "", bi->chan ? ";" : "", macstr, bi->info ? "I:" : "", bi->info ? bi->info : "", bi->info ? ";" : "", + DPP_VERSION == 2 ? "V:2;" : "", bi->pk); return 0; } -static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth) -{ - struct dpp_bootstrap_info *bi; - - if (auth->own_bi) - return 0; /* already generated */ - - bi = os_zalloc(sizeof(*bi)); - if (!bi) - return -1; - bi->type = DPP_BOOTSTRAP_QR_CODE; - if (dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0) < 0 || - dpp_gen_uri(bi) < 0) - goto fail; - wpa_printf(MSG_DEBUG, - "DPP: Auto-generated own bootstrapping key info: URI %s", - bi->uri); - - auth->tmp_own_bi = auth->own_bi = bi; - - return 0; -fail: - dpp_bootstrap_info_free(bi); - return -1; -} - - -static struct dpp_authentication * dpp_alloc_auth(void *msg_ctx) +struct dpp_authentication * +dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx) { struct dpp_authentication *auth; auth = os_zalloc(sizeof(*auth)); if (!auth) return NULL; + auth->global = dpp; auth->msg_ctx = msg_ctx; auth->conf_resp_status = 255; return auth; } -struct dpp_authentication * dpp_auth_init(void *msg_ctx, - struct dpp_bootstrap_info *peer_bi, - struct dpp_bootstrap_info *own_bi, - u8 dpp_allowed_roles, - unsigned int neg_freq, - struct hostapd_hw_modes *own_modes, - u16 num_modes) -{ - struct dpp_authentication *auth; - size_t nonce_len; - size_t secret_len; - struct wpabuf *pi = NULL; - const u8 *r_pubkey_hash, *i_pubkey_hash; -#ifdef CONFIG_TESTING_OPTIONS - u8 test_hash[SHA256_MAC_LEN]; -#endif /* CONFIG_TESTING_OPTIONS */ - - auth = dpp_alloc_auth(msg_ctx); - if (!auth) - return NULL; - auth->initiator = 1; - auth->waiting_auth_resp = 1; - auth->allowed_roles = dpp_allowed_roles; - auth->configurator = !!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR); - auth->peer_bi = peer_bi; - auth->own_bi = own_bi; - auth->curve = peer_bi->curve; - - if (dpp_autogen_bootstrap_key(auth) < 0 || - dpp_prepare_channel_list(auth, own_modes, num_modes) < 0) - goto fail; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_nonce_override_len > 0) { - wpa_printf(MSG_INFO, "DPP: TESTING - override I-nonce"); - nonce_len = dpp_nonce_override_len; - os_memcpy(auth->i_nonce, dpp_nonce_override, nonce_len); - } else { - nonce_len = auth->curve->nonce_len; - if (random_get_bytes(auth->i_nonce, nonce_len)) { - wpa_printf(MSG_ERROR, - "DPP: Failed to generate I-nonce"); - goto fail; - } - } -#else /* CONFIG_TESTING_OPTIONS */ - nonce_len = auth->curve->nonce_len; - if (random_get_bytes(auth->i_nonce, nonce_len)) { - wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce"); - goto fail; - } -#endif /* CONFIG_TESTING_OPTIONS */ - wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_protocol_key_override_len) { - const struct dpp_curve_params *tmp_curve; - - wpa_printf(MSG_INFO, - "DPP: TESTING - override protocol key"); - auth->own_protocol_key = dpp_set_keypair( - &tmp_curve, dpp_protocol_key_override, - dpp_protocol_key_override_len); - } else { - auth->own_protocol_key = dpp_gen_keypair(auth->curve); - } -#else /* CONFIG_TESTING_OPTIONS */ - auth->own_protocol_key = dpp_gen_keypair(auth->curve); -#endif /* CONFIG_TESTING_OPTIONS */ - if (!auth->own_protocol_key) - goto fail; - - pi = dpp_get_pubkey_point(auth->own_protocol_key, 0); - if (!pi) - goto fail; - - /* ECDH: M = pI * BR */ - if (dpp_ecdh(auth->own_protocol_key, auth->peer_bi->pubkey, - auth->Mx, &secret_len) < 0) - goto fail; - auth->secret_len = secret_len; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)", - auth->Mx, auth->secret_len); - auth->Mx_len = auth->secret_len; - - if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1, - auth->curve->hash_len) < 0) - goto fail; - - r_pubkey_hash = auth->peer_bi->pubkey_hash; - i_pubkey_hash = auth->own_bi->pubkey_hash; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); - r_pubkey_hash = NULL; - } else if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid R-Bootstrap Key Hash"); - os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - r_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); - i_pubkey_hash = NULL; - } else if (dpp_test == DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid I-Bootstrap Key Hash"); - os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - i_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-Proto Key"); - wpabuf_free(pi); - pi = NULL; - } else if (dpp_test == DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-Proto Key"); - wpabuf_free(pi); - pi = wpabuf_alloc(2 * auth->curve->prime_len); - if (!pi || dpp_test_gen_invalid_key(pi, auth->curve) < 0) - goto fail; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash, - i_pubkey_hash, neg_freq); - if (!auth->req_msg) - goto fail; - -out: - wpabuf_free(pi); - return auth; -fail: - dpp_auth_deinit(auth); - auth = NULL; - goto out; -} - - static struct wpabuf * dpp_build_conf_req_attr(struct dpp_authentication *auth, const char *json) { @@ -2593,7 +772,7 @@ fail: } -static void dpp_write_adv_proto(struct wpabuf *buf) +void dpp_write_adv_proto(struct wpabuf *buf) { /* Advertisement Protocol IE */ wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); @@ -2607,7 +786,7 @@ static void dpp_write_adv_proto(struct wpabuf *buf) } -static void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query) +void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query) { /* GAS Query */ wpabuf_put_le16(buf, wpabuf_len(query)); @@ -2651,6 +830,7 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth, const char *tech = "infra"; const char *dpp_name; struct wpabuf *buf, *json; + char *csr = NULL; #ifdef CONFIG_TESTING_OPTIONS if (dpp_test == DPP_TEST_INVALID_CONFIG_ATTR_OBJ_CONF_REQ) { @@ -2667,6 +847,17 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth, len = 100 + name_len * 6 + 1 + int_array_len(opclasses) * 4; if (mud_url && mud_url[0]) len += 10 + os_strlen(mud_url); +#ifdef CONFIG_DPP2 + if (auth->csr) { + size_t csr_len; + + csr = base64_encode_no_lf(wpabuf_head(auth->csr), + wpabuf_len(auth->csr), &csr_len); + if (!csr) + return NULL; + len += 30 + csr_len; + } +#endif /* CONFIG_DPP2 */ json = wpabuf_alloc(len); if (!json) return NULL; @@ -2693,1702 +884,20 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth, wpabuf_printf(json, "%s%u", i ? "," : "", opclasses[i]); json_end_array(json); } + if (csr) { + json_value_sep(json); + json_add_string(json, "pkcs10", csr); + } json_end_object(json); buf = dpp_build_conf_req(auth, wpabuf_head(json)); wpabuf_free(json); + os_free(csr); return buf; } -static void dpp_auth_success(struct dpp_authentication *auth) -{ - wpa_printf(MSG_DEBUG, - "DPP: Authentication success - clear temporary keys"); - os_memset(auth->Mx, 0, sizeof(auth->Mx)); - auth->Mx_len = 0; - os_memset(auth->Nx, 0, sizeof(auth->Nx)); - auth->Nx_len = 0; - os_memset(auth->Lx, 0, sizeof(auth->Lx)); - auth->Lx_len = 0; - os_memset(auth->k1, 0, sizeof(auth->k1)); - os_memset(auth->k2, 0, sizeof(auth->k2)); - - auth->auth_success = 1; -} - - -static int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth) -{ - struct wpabuf *pix, *prx, *bix, *brx; - const u8 *addr[7]; - size_t len[7]; - size_t i, num_elem = 0; - size_t nonce_len; - u8 zero = 0; - int res = -1; - - /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ - nonce_len = auth->curve->nonce_len; - - if (auth->initiator) { - pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); - prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); - if (auth->own_bi) - bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); - else - bix = NULL; - brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); - } else { - pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); - prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); - if (auth->peer_bi) - bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); - else - bix = NULL; - brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); - } - if (!pix || !prx || !brx) - goto fail; - - addr[num_elem] = auth->i_nonce; - len[num_elem] = nonce_len; - num_elem++; - - addr[num_elem] = auth->r_nonce; - len[num_elem] = nonce_len; - num_elem++; - - addr[num_elem] = wpabuf_head(pix); - len[num_elem] = wpabuf_len(pix) / 2; - num_elem++; - - addr[num_elem] = wpabuf_head(prx); - len[num_elem] = wpabuf_len(prx) / 2; - num_elem++; - - if (bix) { - addr[num_elem] = wpabuf_head(bix); - len[num_elem] = wpabuf_len(bix) / 2; - num_elem++; - } - - addr[num_elem] = wpabuf_head(brx); - len[num_elem] = wpabuf_len(brx) / 2; - num_elem++; - - addr[num_elem] = &zero; - len[num_elem] = 1; - num_elem++; - - wpa_printf(MSG_DEBUG, "DPP: R-auth hash components"); - for (i = 0; i < num_elem; i++) - wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); - res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth); - if (res == 0) - wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth, - auth->curve->hash_len); -fail: - wpabuf_free(pix); - wpabuf_free(prx); - wpabuf_free(bix); - wpabuf_free(brx); - return res; -} - - -static int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth) -{ - struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL; - const u8 *addr[7]; - size_t len[7]; - size_t i, num_elem = 0; - size_t nonce_len; - u8 one = 1; - int res = -1; - - /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ - nonce_len = auth->curve->nonce_len; - - if (auth->initiator) { - pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); - prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); - if (auth->own_bi) - bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); - else - bix = NULL; - if (!auth->peer_bi) - goto fail; - brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); - } else { - pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); - prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); - if (auth->peer_bi) - bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); - else - bix = NULL; - if (!auth->own_bi) - goto fail; - brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); - } - if (!pix || !prx || !brx) - goto fail; - - addr[num_elem] = auth->r_nonce; - len[num_elem] = nonce_len; - num_elem++; - - addr[num_elem] = auth->i_nonce; - len[num_elem] = nonce_len; - num_elem++; - - addr[num_elem] = wpabuf_head(prx); - len[num_elem] = wpabuf_len(prx) / 2; - num_elem++; - - addr[num_elem] = wpabuf_head(pix); - len[num_elem] = wpabuf_len(pix) / 2; - num_elem++; - - addr[num_elem] = wpabuf_head(brx); - len[num_elem] = wpabuf_len(brx) / 2; - num_elem++; - - if (bix) { - addr[num_elem] = wpabuf_head(bix); - len[num_elem] = wpabuf_len(bix) / 2; - num_elem++; - } - - addr[num_elem] = &one; - len[num_elem] = 1; - num_elem++; - - wpa_printf(MSG_DEBUG, "DPP: I-auth hash components"); - for (i = 0; i < num_elem; i++) - wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); - res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth); - if (res == 0) - wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth, - auth->curve->hash_len); -fail: - wpabuf_free(pix); - wpabuf_free(prx); - wpabuf_free(bix); - wpabuf_free(brx); - return res; -} - - -static int dpp_auth_derive_l_responder(struct dpp_authentication *auth) -{ - const EC_GROUP *group; - EC_POINT *l = NULL; - EC_KEY *BI = NULL, *bR = NULL, *pR = NULL; - const EC_POINT *BI_point; - BN_CTX *bnctx; - BIGNUM *lx, *sum, *q; - const BIGNUM *bR_bn, *pR_bn; - int ret = -1; - - /* L = ((bR + pR) modulo q) * BI */ - - bnctx = BN_CTX_new(); - sum = BN_new(); - q = BN_new(); - lx = BN_new(); - if (!bnctx || !sum || !q || !lx) - goto fail; - BI = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey); - if (!BI) - goto fail; - BI_point = EC_KEY_get0_public_key(BI); - group = EC_KEY_get0_group(BI); - if (!group) - goto fail; - - bR = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey); - pR = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key); - if (!bR || !pR) - goto fail; - bR_bn = EC_KEY_get0_private_key(bR); - pR_bn = EC_KEY_get0_private_key(pR); - if (!bR_bn || !pR_bn) - goto fail; - if (EC_GROUP_get_order(group, q, bnctx) != 1 || - BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1) - goto fail; - l = EC_POINT_new(group); - if (!l || - EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 || - EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL, - bnctx) != 1) { - wpa_printf(MSG_ERROR, - "OpenSSL: failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) - goto fail; - wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); - auth->Lx_len = auth->secret_len; - ret = 0; -fail: - EC_POINT_clear_free(l); - EC_KEY_free(BI); - EC_KEY_free(bR); - EC_KEY_free(pR); - BN_clear_free(lx); - BN_clear_free(sum); - BN_free(q); - BN_CTX_free(bnctx); - return ret; -} - - -static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) -{ - const EC_GROUP *group; - EC_POINT *l = NULL, *sum = NULL; - EC_KEY *bI = NULL, *BR = NULL, *PR = NULL; - const EC_POINT *BR_point, *PR_point; - BN_CTX *bnctx; - BIGNUM *lx; - const BIGNUM *bI_bn; - int ret = -1; - - /* L = bI * (BR + PR) */ - - bnctx = BN_CTX_new(); - lx = BN_new(); - if (!bnctx || !lx) - goto fail; - BR = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey); - PR = EVP_PKEY_get1_EC_KEY(auth->peer_protocol_key); - if (!BR || !PR) - goto fail; - BR_point = EC_KEY_get0_public_key(BR); - PR_point = EC_KEY_get0_public_key(PR); - - bI = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey); - if (!bI) - goto fail; - group = EC_KEY_get0_group(bI); - bI_bn = EC_KEY_get0_private_key(bI); - if (!group || !bI_bn) - goto fail; - sum = EC_POINT_new(group); - l = EC_POINT_new(group); - if (!sum || !l || - EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 || - EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 || - EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL, - bnctx) != 1) { - wpa_printf(MSG_ERROR, - "OpenSSL: failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) - goto fail; - wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); - auth->Lx_len = auth->secret_len; - ret = 0; -fail: - EC_POINT_clear_free(l); - EC_POINT_clear_free(sum); - EC_KEY_free(bI); - EC_KEY_free(BR); - EC_KEY_free(PR); - BN_clear_free(lx); - BN_CTX_free(bnctx); - return ret; -} - - -static int dpp_auth_build_resp_ok(struct dpp_authentication *auth) -{ - size_t nonce_len; - size_t secret_len; - struct wpabuf *msg, *pr = NULL; - u8 r_auth[4 + DPP_MAX_HASH_LEN]; - u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE], *w_r_auth; - size_t wrapped_r_auth_len; - int ret = -1; - const u8 *r_pubkey_hash, *i_pubkey_hash, *r_nonce, *i_nonce; - enum dpp_status_error status = DPP_STATUS_OK; -#ifdef CONFIG_TESTING_OPTIONS - u8 test_hash[SHA256_MAC_LEN]; -#endif /* CONFIG_TESTING_OPTIONS */ - - wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response"); - if (!auth->own_bi) - return -1; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_nonce_override_len > 0) { - wpa_printf(MSG_INFO, "DPP: TESTING - override R-nonce"); - nonce_len = dpp_nonce_override_len; - os_memcpy(auth->r_nonce, dpp_nonce_override, nonce_len); - } else { - nonce_len = auth->curve->nonce_len; - if (random_get_bytes(auth->r_nonce, nonce_len)) { - wpa_printf(MSG_ERROR, - "DPP: Failed to generate R-nonce"); - goto fail; - } - } -#else /* CONFIG_TESTING_OPTIONS */ - nonce_len = auth->curve->nonce_len; - if (random_get_bytes(auth->r_nonce, nonce_len)) { - wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce"); - goto fail; - } -#endif /* CONFIG_TESTING_OPTIONS */ - wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len); - - EVP_PKEY_free(auth->own_protocol_key); -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_protocol_key_override_len) { - const struct dpp_curve_params *tmp_curve; - - wpa_printf(MSG_INFO, - "DPP: TESTING - override protocol key"); - auth->own_protocol_key = dpp_set_keypair( - &tmp_curve, dpp_protocol_key_override, - dpp_protocol_key_override_len); - } else { - auth->own_protocol_key = dpp_gen_keypair(auth->curve); - } -#else /* CONFIG_TESTING_OPTIONS */ - auth->own_protocol_key = dpp_gen_keypair(auth->curve); -#endif /* CONFIG_TESTING_OPTIONS */ - if (!auth->own_protocol_key) - goto fail; - - pr = dpp_get_pubkey_point(auth->own_protocol_key, 0); - if (!pr) - goto fail; - - /* ECDH: N = pR * PI */ - if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key, - auth->Nx, &secret_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)", - auth->Nx, auth->secret_len); - auth->Nx_len = auth->secret_len; - - if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2, - auth->curve->hash_len) < 0) - goto fail; - - if (auth->own_bi && auth->peer_bi) { - /* Mutual authentication */ - if (dpp_auth_derive_l_responder(auth) < 0) - goto fail; - } - - if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0) - goto fail; - - /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ - WPA_PUT_LE16(r_auth, DPP_ATTR_R_AUTH_TAG); - WPA_PUT_LE16(&r_auth[2], auth->curve->hash_len); - if (dpp_gen_r_auth(auth, r_auth + 4) < 0) - goto fail; -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - R-auth mismatch"); - r_auth[4 + auth->curve->hash_len / 2] ^= 0x01; - } -#endif /* CONFIG_TESTING_OPTIONS */ - if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, - r_auth, 4 + auth->curve->hash_len, - 0, NULL, NULL, wrapped_r_auth) < 0) - goto fail; - wrapped_r_auth_len = 4 + auth->curve->hash_len + AES_BLOCK_SIZE; - wpa_hexdump(MSG_DEBUG, "DPP: {R-auth}ke", - wrapped_r_auth, wrapped_r_auth_len); - w_r_auth = wrapped_r_auth; - - r_pubkey_hash = auth->own_bi->pubkey_hash; - if (auth->peer_bi) - i_pubkey_hash = auth->peer_bi->pubkey_hash; - else - i_pubkey_hash = NULL; - - i_nonce = auth->i_nonce; - r_nonce = auth->r_nonce; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); - r_pubkey_hash = NULL; - } else if (dpp_test == - DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid R-Bootstrap Key Hash"); - os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - r_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); - i_pubkey_hash = NULL; - } else if (dpp_test == - DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid I-Bootstrap Key Hash"); - if (i_pubkey_hash) - os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); - else - os_memset(test_hash, 0, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - i_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Proto Key"); - wpabuf_free(pr); - pr = NULL; - } else if (dpp_test == DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid R-Proto Key"); - wpabuf_free(pr); - pr = wpabuf_alloc(2 * auth->curve->prime_len); - if (!pr || dpp_test_gen_invalid_key(pr, auth->curve) < 0) - goto fail; - } else if (dpp_test == DPP_TEST_NO_R_AUTH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth"); - w_r_auth = NULL; - wrapped_r_auth_len = 0; - } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); - status = 255; - } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); - status = 254; - } else if (dpp_test == DPP_TEST_NO_R_NONCE_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-nonce"); - r_nonce = NULL; - } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); - i_nonce = NULL; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - msg = dpp_auth_build_resp(auth, status, pr, nonce_len, - r_pubkey_hash, i_pubkey_hash, - r_nonce, i_nonce, - w_r_auth, wrapped_r_auth_len, - auth->k2); - if (!msg) - goto fail; - wpabuf_free(auth->resp_msg); - auth->resp_msg = msg; - ret = 0; -fail: - wpabuf_free(pr); - return ret; -} - - -static int dpp_auth_build_resp_status(struct dpp_authentication *auth, - enum dpp_status_error status) -{ - struct wpabuf *msg; - const u8 *r_pubkey_hash, *i_pubkey_hash, *i_nonce; -#ifdef CONFIG_TESTING_OPTIONS - u8 test_hash[SHA256_MAC_LEN]; -#endif /* CONFIG_TESTING_OPTIONS */ - - if (!auth->own_bi) - return -1; - wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response"); - - r_pubkey_hash = auth->own_bi->pubkey_hash; - if (auth->peer_bi) - i_pubkey_hash = auth->peer_bi->pubkey_hash; - else - i_pubkey_hash = NULL; - - i_nonce = auth->i_nonce; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); - r_pubkey_hash = NULL; - } else if (dpp_test == - DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid R-Bootstrap Key Hash"); - os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - r_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); - i_pubkey_hash = NULL; - } else if (dpp_test == - DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid I-Bootstrap Key Hash"); - if (i_pubkey_hash) - os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); - else - os_memset(test_hash, 0, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - i_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); - status = 255; - } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); - i_nonce = NULL; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - msg = dpp_auth_build_resp(auth, status, NULL, auth->curve->nonce_len, - r_pubkey_hash, i_pubkey_hash, - NULL, i_nonce, NULL, 0, auth->k1); - if (!msg) - return -1; - wpabuf_free(auth->resp_msg); - auth->resp_msg = msg; - return 0; -} - - -struct dpp_authentication * -dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, - struct dpp_bootstrap_info *peer_bi, - struct dpp_bootstrap_info *own_bi, - unsigned int freq, const u8 *hdr, const u8 *attr_start, - size_t attr_len) -{ - EVP_PKEY *pi = NULL; - EVP_PKEY_CTX *ctx = NULL; - size_t secret_len; - const u8 *addr[2]; - size_t len[2]; - u8 *unwrapped = NULL; - size_t unwrapped_len = 0; - const u8 *wrapped_data, *i_proto, *i_nonce, *i_capab, *i_bootstrap, - *channel; - u16 wrapped_data_len, i_proto_len, i_nonce_len, i_capab_len, - i_bootstrap_len, channel_len; - struct dpp_authentication *auth = NULL; -#ifdef CONFIG_DPP2 - const u8 *version; - u16 version_len; -#endif /* CONFIG_DPP2 */ - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_AUTH_REQ) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at Authentication Request"); - return NULL; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, - &wrapped_data_len); - if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Missing or invalid required Wrapped Data attribute"); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data", - wrapped_data, wrapped_data_len); - attr_len = wrapped_data - 4 - attr_start; - - auth = dpp_alloc_auth(msg_ctx); - if (!auth) - goto fail; - auth->peer_bi = peer_bi; - auth->own_bi = own_bi; - auth->curve = own_bi->curve; - auth->curr_freq = freq; - - auth->peer_version = 1; /* default to the first version */ -#ifdef CONFIG_DPP2 - version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, - &version_len); - if (version) { - if (version_len < 1 || version[0] == 0) { - dpp_auth_fail(auth, - "Invalid Protocol Version attribute"); - goto fail; - } - auth->peer_version = version[0]; - wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", - auth->peer_version); - } -#endif /* CONFIG_DPP2 */ - - channel = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CHANNEL, - &channel_len); - if (channel) { - int neg_freq; - - if (channel_len < 2) { - dpp_auth_fail(auth, "Too short Channel attribute"); - goto fail; - } - - neg_freq = ieee80211_chan_to_freq(NULL, channel[0], channel[1]); - wpa_printf(MSG_DEBUG, - "DPP: Initiator requested different channel for negotiation: op_class=%u channel=%u --> freq=%d", - channel[0], channel[1], neg_freq); - if (neg_freq < 0) { - dpp_auth_fail(auth, - "Unsupported Channel attribute value"); - goto fail; - } - - if (auth->curr_freq != (unsigned int) neg_freq) { - wpa_printf(MSG_DEBUG, - "DPP: Changing negotiation channel from %u MHz to %u MHz", - freq, neg_freq); - auth->curr_freq = neg_freq; - } - } - - i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY, - &i_proto_len); - if (!i_proto) { - dpp_auth_fail(auth, - "Missing required Initiator Protocol Key attribute"); - goto fail; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key", - i_proto, i_proto_len); - - /* M = bR * PI */ - pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len); - if (!pi) { - dpp_auth_fail(auth, "Invalid Initiator Protocol Key"); - goto fail; - } - dpp_debug_print_key("Peer (Initiator) Protocol Key", pi); - - if (dpp_ecdh(own_bi->pubkey, pi, auth->Mx, &secret_len) < 0) - goto fail; - auth->secret_len = secret_len; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)", - auth->Mx, auth->secret_len); - auth->Mx_len = auth->secret_len; - - if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1, - auth->curve->hash_len) < 0) - goto fail; - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - addr[1] = attr_start; - len[1] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) - goto fail; - if (aes_siv_decrypt(auth->k1, auth->curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_auth_fail(auth, "AES-SIV decryption failed"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); - goto fail; - } - - i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, - &i_nonce_len); - if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { - dpp_auth_fail(auth, "Missing or invalid I-nonce"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); - os_memcpy(auth->i_nonce, i_nonce, i_nonce_len); - - i_capab = dpp_get_attr(unwrapped, unwrapped_len, - DPP_ATTR_I_CAPABILITIES, - &i_capab_len); - if (!i_capab || i_capab_len < 1) { - dpp_auth_fail(auth, "Missing or invalid I-capabilities"); - goto fail; - } - auth->i_capab = i_capab[0]; - wpa_printf(MSG_DEBUG, "DPP: I-capabilities: 0x%02x", auth->i_capab); - - bin_clear_free(unwrapped, unwrapped_len); - unwrapped = NULL; - - switch (auth->i_capab & DPP_CAPAB_ROLE_MASK) { - case DPP_CAPAB_ENROLLEE: - if (!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)) { - wpa_printf(MSG_DEBUG, - "DPP: Local policy does not allow Configurator role"); - goto not_compatible; - } - wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator"); - auth->configurator = 1; - break; - case DPP_CAPAB_CONFIGURATOR: - if (!(dpp_allowed_roles & DPP_CAPAB_ENROLLEE)) { - wpa_printf(MSG_DEBUG, - "DPP: Local policy does not allow Enrollee role"); - goto not_compatible; - } - wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee"); - auth->configurator = 0; - break; - case DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE: - if (dpp_allowed_roles & DPP_CAPAB_ENROLLEE) { - wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee"); - auth->configurator = 0; - } else if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) { - wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator"); - auth->configurator = 1; - } else { - wpa_printf(MSG_DEBUG, - "DPP: Local policy does not allow Configurator/Enrollee role"); - goto not_compatible; - } - break; - default: - wpa_printf(MSG_DEBUG, "DPP: Unexpected role in I-capabilities"); - wpa_msg(auth->msg_ctx, MSG_INFO, - DPP_EVENT_FAIL "Invalid role in I-capabilities 0x%02x", - auth->i_capab & DPP_CAPAB_ROLE_MASK); - goto fail; - } - - auth->peer_protocol_key = pi; - pi = NULL; - if (qr_mutual && !peer_bi && own_bi->type == DPP_BOOTSTRAP_QR_CODE) { - char hex[SHA256_MAC_LEN * 2 + 1]; - - wpa_printf(MSG_DEBUG, - "DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time"); - if (dpp_auth_build_resp_status(auth, - DPP_STATUS_RESPONSE_PENDING) < 0) - goto fail; - i_bootstrap = dpp_get_attr(attr_start, attr_len, - DPP_ATTR_I_BOOTSTRAP_KEY_HASH, - &i_bootstrap_len); - if (i_bootstrap && i_bootstrap_len == SHA256_MAC_LEN) { - auth->response_pending = 1; - os_memcpy(auth->waiting_pubkey_hash, - i_bootstrap, i_bootstrap_len); - wpa_snprintf_hex(hex, sizeof(hex), i_bootstrap, - i_bootstrap_len); - } else { - hex[0] = '\0'; - } - - wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_SCAN_PEER_QR_CODE - "%s", hex); - return auth; - } - if (dpp_auth_build_resp_ok(auth) < 0) - goto fail; - - return auth; - -not_compatible: - wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE - "i-capab=0x%02x", auth->i_capab); - if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) - auth->configurator = 1; - else - auth->configurator = 0; - auth->peer_protocol_key = pi; - pi = NULL; - if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0) - goto fail; - - auth->remove_on_tx_status = 1; - return auth; -fail: - bin_clear_free(unwrapped, unwrapped_len); - EVP_PKEY_free(pi); - EVP_PKEY_CTX_free(ctx); - dpp_auth_deinit(auth); - return NULL; -} - - -int dpp_notify_new_qr_code(struct dpp_authentication *auth, - struct dpp_bootstrap_info *peer_bi) -{ - if (!auth || !auth->response_pending || - os_memcmp(auth->waiting_pubkey_hash, peer_bi->pubkey_hash, - SHA256_MAC_LEN) != 0) - return 0; - - wpa_printf(MSG_DEBUG, - "DPP: New scanned QR Code has matching public key that was needed to continue DPP Authentication exchange with " - MACSTR, MAC2STR(auth->peer_mac_addr)); - auth->peer_bi = peer_bi; - - if (dpp_auth_build_resp_ok(auth) < 0) - return -1; - - return 1; -} - - -static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth, - enum dpp_status_error status) -{ - struct wpabuf *msg; - u8 i_auth[4 + DPP_MAX_HASH_LEN]; - size_t i_auth_len; - u8 r_nonce[4 + DPP_MAX_NONCE_LEN]; - size_t r_nonce_len; - const u8 *addr[2]; - size_t len[2], attr_len; - u8 *wrapped_i_auth; - u8 *wrapped_r_nonce; - u8 *attr_start, *attr_end; - const u8 *r_pubkey_hash, *i_pubkey_hash; -#ifdef CONFIG_TESTING_OPTIONS - u8 test_hash[SHA256_MAC_LEN]; -#endif /* CONFIG_TESTING_OPTIONS */ - - wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation"); - - i_auth_len = 4 + auth->curve->hash_len; - r_nonce_len = 4 + auth->curve->nonce_len; - /* Build DPP Authentication Confirmation frame attributes */ - attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + - 4 + i_auth_len + r_nonce_len + AES_BLOCK_SIZE; -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) - attr_len += 5; -#endif /* CONFIG_TESTING_OPTIONS */ - msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, attr_len); - if (!msg) - goto fail; - - attr_start = wpabuf_put(msg, 0); - - r_pubkey_hash = auth->peer_bi->pubkey_hash; - if (auth->own_bi) - i_pubkey_hash = auth->own_bi->pubkey_hash; - else - i_pubkey_hash = NULL; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_STATUS_AUTH_CONF) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); - goto skip_status; - } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_CONF) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); - status = 254; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* DPP Status */ - dpp_build_attr_status(msg, status); - -#ifdef CONFIG_TESTING_OPTIONS -skip_status: - if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); - r_pubkey_hash = NULL; - } else if (dpp_test == - DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid R-Bootstrap Key Hash"); - os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - r_pubkey_hash = test_hash; - } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); - i_pubkey_hash = NULL; - } else if (dpp_test == - DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) { - wpa_printf(MSG_INFO, - "DPP: TESTING - invalid I-Bootstrap Key Hash"); - if (i_pubkey_hash) - os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); - else - os_memset(test_hash, 0, SHA256_MAC_LEN); - test_hash[SHA256_MAC_LEN - 1] ^= 0x01; - i_pubkey_hash = test_hash; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* Responder Bootstrapping Key Hash */ - dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); - - /* Initiator Bootstrapping Key Hash (mutual authentication) */ - dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF) - goto skip_wrapped_data; - if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF) - i_auth_len = 0; -#endif /* CONFIG_TESTING_OPTIONS */ - - attr_end = wpabuf_put(msg, 0); - - /* OUI, OUI type, Crypto Suite, DPP frame type */ - addr[0] = wpabuf_head_u8(msg) + 2; - len[0] = 3 + 1 + 1 + 1; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - - /* Attributes before Wrapped Data */ - addr[1] = attr_start; - len[1] = attr_end - attr_start; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - if (status == DPP_STATUS_OK) { - /* I-auth wrapped with ke */ - wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); - wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE); - wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF) - goto skip_i_auth; -#endif /* CONFIG_TESTING_OPTIONS */ - - /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] - * 1) */ - WPA_PUT_LE16(i_auth, DPP_ATTR_I_AUTH_TAG); - WPA_PUT_LE16(&i_auth[2], auth->curve->hash_len); - if (dpp_gen_i_auth(auth, i_auth + 4) < 0) - goto fail; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF) { - wpa_printf(MSG_INFO, "DPP: TESTING - I-auth mismatch"); - i_auth[4 + auth->curve->hash_len / 2] ^= 0x01; - } -skip_i_auth: -#endif /* CONFIG_TESTING_OPTIONS */ - if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, - i_auth, i_auth_len, - 2, addr, len, wrapped_i_auth) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke", - wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE); - } else { - /* R-nonce wrapped with k2 */ - wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); - wpabuf_put_le16(msg, r_nonce_len + AES_BLOCK_SIZE); - wrapped_r_nonce = wpabuf_put(msg, r_nonce_len + AES_BLOCK_SIZE); - - WPA_PUT_LE16(r_nonce, DPP_ATTR_R_NONCE); - WPA_PUT_LE16(&r_nonce[2], auth->curve->nonce_len); - os_memcpy(r_nonce + 4, auth->r_nonce, auth->curve->nonce_len); - - if (aes_siv_encrypt(auth->k2, auth->curve->hash_len, - r_nonce, r_nonce_len, - 2, addr, len, wrapped_r_nonce) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: {R-nonce}k2", - wrapped_r_nonce, r_nonce_len + AES_BLOCK_SIZE); - } - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) { - wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); - dpp_build_attr_status(msg, DPP_STATUS_OK); - } -skip_wrapped_data: -#endif /* CONFIG_TESTING_OPTIONS */ - - wpa_hexdump_buf(MSG_DEBUG, - "DPP: Authentication Confirmation frame attributes", - msg); - if (status == DPP_STATUS_OK) - dpp_auth_success(auth); - - return msg; - -fail: - wpabuf_free(msg); - return NULL; -} - - -static void -dpp_auth_resp_rx_status(struct dpp_authentication *auth, const u8 *hdr, - const u8 *attr_start, size_t attr_len, - const u8 *wrapped_data, u16 wrapped_data_len, - enum dpp_status_error status) -{ - const u8 *addr[2]; - size_t len[2]; - u8 *unwrapped = NULL; - size_t unwrapped_len = 0; - const u8 *i_nonce, *r_capab; - u16 i_nonce_len, r_capab_len; - - if (status == DPP_STATUS_NOT_COMPATIBLE) { - wpa_printf(MSG_DEBUG, - "DPP: Responder reported incompatible roles"); - } else if (status == DPP_STATUS_RESPONSE_PENDING) { - wpa_printf(MSG_DEBUG, - "DPP: Responder reported more time needed"); - } else { - wpa_printf(MSG_DEBUG, - "DPP: Responder reported failure (status %d)", - status); - dpp_auth_fail(auth, "Responder reported failure"); - return; - } - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - addr[1] = attr_start; - len[1] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) - goto fail; - if (aes_siv_decrypt(auth->k1, auth->curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_auth_fail(auth, "AES-SIV decryption failed"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); - goto fail; - } - - i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, - &i_nonce_len); - if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { - dpp_auth_fail(auth, "Missing or invalid I-nonce"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); - if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) { - dpp_auth_fail(auth, "I-nonce mismatch"); - goto fail; - } - - r_capab = dpp_get_attr(unwrapped, unwrapped_len, - DPP_ATTR_R_CAPABILITIES, - &r_capab_len); - if (!r_capab || r_capab_len < 1) { - dpp_auth_fail(auth, "Missing or invalid R-capabilities"); - goto fail; - } - auth->r_capab = r_capab[0]; - wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab); - if (status == DPP_STATUS_NOT_COMPATIBLE) { - wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE - "r-capab=0x%02x", auth->r_capab); - } else if (status == DPP_STATUS_RESPONSE_PENDING) { - u8 role = auth->r_capab & DPP_CAPAB_ROLE_MASK; - - if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) || - (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) { - wpa_msg(auth->msg_ctx, MSG_INFO, - DPP_EVENT_FAIL "Unexpected role in R-capabilities 0x%02x", - role); - } else { - wpa_printf(MSG_DEBUG, - "DPP: Continue waiting for full DPP Authentication Response"); - wpa_msg(auth->msg_ctx, MSG_INFO, - DPP_EVENT_RESPONSE_PENDING "%s", - auth->tmp_own_bi ? auth->tmp_own_bi->uri : ""); - } - } -fail: - bin_clear_free(unwrapped, unwrapped_len); -} - - -struct wpabuf * -dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, - const u8 *attr_start, size_t attr_len) -{ - EVP_PKEY *pr; - size_t secret_len; - const u8 *addr[2]; - size_t len[2]; - u8 *unwrapped = NULL, *unwrapped2 = NULL; - size_t unwrapped_len = 0, unwrapped2_len = 0; - const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto, - *r_nonce, *i_nonce, *r_capab, *wrapped2, *r_auth; - u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len, - r_proto_len, r_nonce_len, i_nonce_len, r_capab_len, - wrapped2_len, r_auth_len; - u8 r_auth2[DPP_MAX_HASH_LEN]; - u8 role; -#ifdef CONFIG_DPP2 - const u8 *version; - u16 version_len; -#endif /* CONFIG_DPP2 */ - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_AUTH_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at Authentication Response"); - return NULL; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (!auth->initiator || !auth->peer_bi) { - dpp_auth_fail(auth, "Unexpected Authentication Response"); - return NULL; - } - - auth->waiting_auth_resp = 0; - - wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, - &wrapped_data_len); - if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { - dpp_auth_fail(auth, - "Missing or invalid required Wrapped Data attribute"); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data", - wrapped_data, wrapped_data_len); - - attr_len = wrapped_data - 4 - attr_start; - - r_bootstrap = dpp_get_attr(attr_start, attr_len, - DPP_ATTR_R_BOOTSTRAP_KEY_HASH, - &r_bootstrap_len); - if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { - dpp_auth_fail(auth, - "Missing or invalid required Responder Bootstrapping Key Hash attribute"); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash", - r_bootstrap, r_bootstrap_len); - if (os_memcmp(r_bootstrap, auth->peer_bi->pubkey_hash, - SHA256_MAC_LEN) != 0) { - dpp_auth_fail(auth, - "Unexpected Responder Bootstrapping Key Hash value"); - wpa_hexdump(MSG_DEBUG, - "DPP: Expected Responder Bootstrapping Key Hash", - auth->peer_bi->pubkey_hash, SHA256_MAC_LEN); - return NULL; - } - - i_bootstrap = dpp_get_attr(attr_start, attr_len, - DPP_ATTR_I_BOOTSTRAP_KEY_HASH, - &i_bootstrap_len); - if (i_bootstrap) { - if (i_bootstrap_len != SHA256_MAC_LEN) { - dpp_auth_fail(auth, - "Invalid Initiator Bootstrapping Key Hash attribute"); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, - "DPP: Initiator Bootstrapping Key Hash", - i_bootstrap, i_bootstrap_len); - if (!auth->own_bi || - os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash, - SHA256_MAC_LEN) != 0) { - dpp_auth_fail(auth, - "Initiator Bootstrapping Key Hash attribute did not match"); - return NULL; - } - } else if (auth->own_bi && auth->own_bi->type == DPP_BOOTSTRAP_PKEX) { - /* PKEX bootstrapping mandates use of mutual authentication */ - dpp_auth_fail(auth, - "Missing Initiator Bootstrapping Key Hash attribute"); - return NULL; - } - - auth->peer_version = 1; /* default to the first version */ -#ifdef CONFIG_DPP2 - version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, - &version_len); - if (version) { - if (version_len < 1 || version[0] == 0) { - dpp_auth_fail(auth, - "Invalid Protocol Version attribute"); - return NULL; - } - auth->peer_version = version[0]; - wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", - auth->peer_version); - } -#endif /* CONFIG_DPP2 */ - - status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, - &status_len); - if (!status || status_len < 1) { - dpp_auth_fail(auth, - "Missing or invalid required DPP Status attribute"); - return NULL; - } - wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); - auth->auth_resp_status = status[0]; - if (status[0] != DPP_STATUS_OK) { - dpp_auth_resp_rx_status(auth, hdr, attr_start, - attr_len, wrapped_data, - wrapped_data_len, status[0]); - return NULL; - } - - if (!i_bootstrap && auth->own_bi) { - wpa_printf(MSG_DEBUG, - "DPP: Responder decided not to use mutual authentication"); - auth->own_bi = NULL; - } - - wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_DIRECTION "mutual=%d", - auth->own_bi != NULL); - - r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY, - &r_proto_len); - if (!r_proto) { - dpp_auth_fail(auth, - "Missing required Responder Protocol Key attribute"); - return NULL; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key", - r_proto, r_proto_len); - - /* N = pI * PR */ - pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len); - if (!pr) { - dpp_auth_fail(auth, "Invalid Responder Protocol Key"); - return NULL; - } - dpp_debug_print_key("Peer (Responder) Protocol Key", pr); - - if (dpp_ecdh(auth->own_protocol_key, pr, auth->Nx, &secret_len) < 0) { - dpp_auth_fail(auth, "Failed to derive ECDH shared secret"); - goto fail; - } - EVP_PKEY_free(auth->peer_protocol_key); - auth->peer_protocol_key = pr; - pr = NULL; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)", - auth->Nx, auth->secret_len); - auth->Nx_len = auth->secret_len; - - if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2, - auth->curve->hash_len) < 0) - goto fail; - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - addr[1] = attr_start; - len[1] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) - goto fail; - if (aes_siv_decrypt(auth->k2, auth->curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_auth_fail(auth, "AES-SIV decryption failed"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); - goto fail; - } - - r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, - &r_nonce_len); - if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { - dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len); - os_memcpy(auth->r_nonce, r_nonce, r_nonce_len); - - i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, - &i_nonce_len); - if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { - dpp_auth_fail(auth, "Missing or invalid I-nonce"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); - if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) { - dpp_auth_fail(auth, "I-nonce mismatch"); - goto fail; - } - - if (auth->own_bi) { - /* Mutual authentication */ - if (dpp_auth_derive_l_initiator(auth) < 0) - goto fail; - } - - r_capab = dpp_get_attr(unwrapped, unwrapped_len, - DPP_ATTR_R_CAPABILITIES, - &r_capab_len); - if (!r_capab || r_capab_len < 1) { - dpp_auth_fail(auth, "Missing or invalid R-capabilities"); - goto fail; - } - auth->r_capab = r_capab[0]; - wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab); - role = auth->r_capab & DPP_CAPAB_ROLE_MASK; - if ((auth->allowed_roles == - (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) && - (role == DPP_CAPAB_CONFIGURATOR || role == DPP_CAPAB_ENROLLEE)) { - /* Peer selected its role, so move from "either role" to the - * role that is compatible with peer's selection. */ - auth->configurator = role == DPP_CAPAB_ENROLLEE; - wpa_printf(MSG_DEBUG, "DPP: Acting as %s", - auth->configurator ? "Configurator" : "Enrollee"); - } else if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) || - (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) { - wpa_printf(MSG_DEBUG, "DPP: Incompatible role selection"); - wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Unexpected role in R-capabilities 0x%02x", - role); - if (role != DPP_CAPAB_ENROLLEE && - role != DPP_CAPAB_CONFIGURATOR) - goto fail; - bin_clear_free(unwrapped, unwrapped_len); - auth->remove_on_tx_status = 1; - return dpp_auth_build_conf(auth, DPP_STATUS_NOT_COMPATIBLE); - } - - wrapped2 = dpp_get_attr(unwrapped, unwrapped_len, - DPP_ATTR_WRAPPED_DATA, &wrapped2_len); - if (!wrapped2 || wrapped2_len < AES_BLOCK_SIZE) { - dpp_auth_fail(auth, - "Missing or invalid Secondary Wrapped Data"); - goto fail; - } - - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped2, wrapped2_len); - - if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0) - goto fail; - - unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE; - unwrapped2 = os_malloc(unwrapped2_len); - if (!unwrapped2) - goto fail; - if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, - wrapped2, wrapped2_len, - 0, NULL, NULL, unwrapped2) < 0) { - dpp_auth_fail(auth, "AES-SIV decryption failed"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped2, unwrapped2_len); - - if (dpp_check_attrs(unwrapped2, unwrapped2_len) < 0) { - dpp_auth_fail(auth, - "Invalid attribute in secondary unwrapped data"); - goto fail; - } - - r_auth = dpp_get_attr(unwrapped2, unwrapped2_len, DPP_ATTR_R_AUTH_TAG, - &r_auth_len); - if (!r_auth || r_auth_len != auth->curve->hash_len) { - dpp_auth_fail(auth, - "Missing or invalid Responder Authenticating Tag"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag", - r_auth, r_auth_len); - /* R-auth' = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ - if (dpp_gen_r_auth(auth, r_auth2) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: Calculated Responder Authenticating Tag", - r_auth2, r_auth_len); - if (os_memcmp(r_auth, r_auth2, r_auth_len) != 0) { - dpp_auth_fail(auth, "Mismatching Responder Authenticating Tag"); - bin_clear_free(unwrapped, unwrapped_len); - bin_clear_free(unwrapped2, unwrapped2_len); - auth->remove_on_tx_status = 1; - return dpp_auth_build_conf(auth, DPP_STATUS_AUTH_FAILURE); - } - - bin_clear_free(unwrapped, unwrapped_len); - bin_clear_free(unwrapped2, unwrapped2_len); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF) { - wpa_printf(MSG_INFO, - "DPP: TESTING - Authentication Response in place of Confirm"); - if (dpp_auth_build_resp_ok(auth) < 0) - return NULL; - return wpabuf_dup(auth->resp_msg); - } -#endif /* CONFIG_TESTING_OPTIONS */ - - return dpp_auth_build_conf(auth, DPP_STATUS_OK); - -fail: - bin_clear_free(unwrapped, unwrapped_len); - bin_clear_free(unwrapped2, unwrapped2_len); - EVP_PKEY_free(pr); - return NULL; -} - - -static int dpp_auth_conf_rx_failure(struct dpp_authentication *auth, - const u8 *hdr, - const u8 *attr_start, size_t attr_len, - const u8 *wrapped_data, - u16 wrapped_data_len, - enum dpp_status_error status) -{ - const u8 *addr[2]; - size_t len[2]; - u8 *unwrapped = NULL; - size_t unwrapped_len = 0; - const u8 *r_nonce; - u16 r_nonce_len; - - /* Authentication Confirm failure cases are expected to include - * {R-nonce}k2 in the Wrapped Data attribute. */ - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - addr[1] = attr_start; - len[1] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) { - dpp_auth_fail(auth, "Authentication failed"); - goto fail; - } - if (aes_siv_decrypt(auth->k2, auth->curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_auth_fail(auth, "AES-SIV decryption failed"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); - goto fail; - } - - r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, - &r_nonce_len); - if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { - dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce"); - goto fail; - } - if (os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) { - wpa_hexdump(MSG_DEBUG, "DPP: Received R-nonce", - r_nonce, r_nonce_len); - wpa_hexdump(MSG_DEBUG, "DPP: Expected R-nonce", - auth->r_nonce, r_nonce_len); - dpp_auth_fail(auth, "R-nonce mismatch"); - goto fail; - } - - if (status == DPP_STATUS_NOT_COMPATIBLE) - dpp_auth_fail(auth, "Peer reported incompatible R-capab role"); - else if (status == DPP_STATUS_AUTH_FAILURE) - dpp_auth_fail(auth, "Peer reported authentication failure)"); - -fail: - bin_clear_free(unwrapped, unwrapped_len); - return -1; -} - - -int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, - const u8 *attr_start, size_t attr_len) -{ - const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth; - u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len, - i_auth_len; - const u8 *addr[2]; - size_t len[2]; - u8 *unwrapped = NULL; - size_t unwrapped_len = 0; - u8 i_auth2[DPP_MAX_HASH_LEN]; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at Authentication Confirm"); - return -1; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (auth->initiator || !auth->own_bi || !auth->waiting_auth_conf) { - wpa_printf(MSG_DEBUG, - "DPP: initiator=%d own_bi=%d waiting_auth_conf=%d", - auth->initiator, !!auth->own_bi, - auth->waiting_auth_conf); - dpp_auth_fail(auth, "Unexpected Authentication Confirm"); - return -1; - } - - auth->waiting_auth_conf = 0; - - wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, - &wrapped_data_len); - if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { - dpp_auth_fail(auth, - "Missing or invalid required Wrapped Data attribute"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data", - wrapped_data, wrapped_data_len); - - attr_len = wrapped_data - 4 - attr_start; - - r_bootstrap = dpp_get_attr(attr_start, attr_len, - DPP_ATTR_R_BOOTSTRAP_KEY_HASH, - &r_bootstrap_len); - if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { - dpp_auth_fail(auth, - "Missing or invalid required Responder Bootstrapping Key Hash attribute"); - return -1; - } - wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash", - r_bootstrap, r_bootstrap_len); - if (os_memcmp(r_bootstrap, auth->own_bi->pubkey_hash, - SHA256_MAC_LEN) != 0) { - wpa_hexdump(MSG_DEBUG, - "DPP: Expected Responder Bootstrapping Key Hash", - auth->peer_bi->pubkey_hash, SHA256_MAC_LEN); - dpp_auth_fail(auth, - "Responder Bootstrapping Key Hash mismatch"); - return -1; - } - - i_bootstrap = dpp_get_attr(attr_start, attr_len, - DPP_ATTR_I_BOOTSTRAP_KEY_HASH, - &i_bootstrap_len); - if (i_bootstrap) { - if (i_bootstrap_len != SHA256_MAC_LEN) { - dpp_auth_fail(auth, - "Invalid Initiator Bootstrapping Key Hash attribute"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, - "DPP: Initiator Bootstrapping Key Hash", - i_bootstrap, i_bootstrap_len); - if (!auth->peer_bi || - os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash, - SHA256_MAC_LEN) != 0) { - dpp_auth_fail(auth, - "Initiator Bootstrapping Key Hash mismatch"); - return -1; - } - } else if (auth->peer_bi) { - /* Mutual authentication and peer did not include its - * Bootstrapping Key Hash attribute. */ - dpp_auth_fail(auth, - "Missing Initiator Bootstrapping Key Hash attribute"); - return -1; - } - - status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, - &status_len); - if (!status || status_len < 1) { - dpp_auth_fail(auth, - "Missing or invalid required DPP Status attribute"); - return -1; - } - wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); - if (status[0] == DPP_STATUS_NOT_COMPATIBLE || - status[0] == DPP_STATUS_AUTH_FAILURE) - return dpp_auth_conf_rx_failure(auth, hdr, attr_start, - attr_len, wrapped_data, - wrapped_data_len, status[0]); - - if (status[0] != DPP_STATUS_OK) { - dpp_auth_fail(auth, "Authentication failed"); - return -1; - } - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - addr[1] = attr_start; - len[1] = attr_len; - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) - return -1; - if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_auth_fail(auth, "AES-SIV decryption failed"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); - goto fail; - } - - i_auth = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG, - &i_auth_len); - if (!i_auth || i_auth_len != auth->curve->hash_len) { - dpp_auth_fail(auth, - "Missing or invalid Initiator Authenticating Tag"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag", - i_auth, i_auth_len); - /* I-auth' = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ - if (dpp_gen_i_auth(auth, i_auth2) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: Calculated Initiator Authenticating Tag", - i_auth2, i_auth_len); - if (os_memcmp(i_auth, i_auth2, i_auth_len) != 0) { - dpp_auth_fail(auth, "Mismatching Initiator Authenticating Tag"); - goto fail; - } - - bin_clear_free(unwrapped, unwrapped_len); - dpp_auth_success(auth); - return 0; -fail: - bin_clear_free(unwrapped, unwrapped_len); - return -1; -} - - static int bin_str_eq(const char *val, size_t len, const char *cmp) { return os_strlen(cmp) == len && os_memcmp(val, cmp, len) == 0; @@ -4426,6 +935,8 @@ struct dpp_configuration * dpp_configuration_alloc(const char *type) conf->akm = DPP_AKM_PSK_SAE_DPP; else if (bin_str_eq(type, len, "dpp")) conf->akm = DPP_AKM_DPP; + else if (bin_str_eq(type, len, "dot1x")) + conf->akm = DPP_AKM_DOT1X; else goto fail; @@ -4488,6 +999,7 @@ void dpp_configuration_free(struct dpp_configuration *conf) return; str_clear_free(conf->passphrase); os_free(conf->group_id); + os_free(conf->csrattrs); bin_clear_free(conf, sizeof(*conf)); } @@ -4498,6 +1010,7 @@ static int dpp_configuration_parse_helper(struct dpp_authentication *auth, const char *pos, *end; struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL; struct dpp_configuration *conf = NULL; + size_t len; pos = os_strstr(cmd, " conf=sta-"); if (pos) { @@ -4602,6 +1115,17 @@ static int dpp_configuration_parse_helper(struct dpp_authentication *auth, conf->netaccesskey_expiry = val; } + pos = os_strstr(cmd, " csrattrs="); + if (pos) { + pos += 10; + end = os_strchr(pos, ' '); + len = end ? (size_t) (end - pos) : os_strlen(pos); + conf->csrattrs = os_zalloc(len + 1); + if (!conf->csrattrs) + goto fail; + os_memcpy(conf->csrattrs, pos, len); + } + if (!dpp_configuration_valid(conf)) goto fail; @@ -4675,16 +1199,16 @@ dpp_configurator_get_id(struct dpp_global *dpp, unsigned int id) } -int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx, - struct dpp_authentication *auth, - const char *cmd) +int dpp_set_configurator(struct dpp_authentication *auth, const char *cmd) { const char *pos; char *tmp = NULL; int ret = -1; - if (!cmd) + if (!cmd || auth->configurator_set) return 0; + auth->configurator_set = 1; + if (cmd[0] != ' ') { size_t len; @@ -4700,9 +1224,9 @@ int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx, wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd); pos = os_strstr(cmd, " configurator="); - if (pos) { + if (!auth->conf && pos) { pos += 14; - auth->conf = dpp_configurator_get_id(dpp, atoi(pos)); + auth->conf = dpp_configurator_get_id(auth->global, atoi(pos)); if (!auth->conf) { wpa_printf(MSG_INFO, "DPP: Could not find the specified configurator"); @@ -4723,7 +1247,7 @@ int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx, } if (dpp_configuration_parse(auth, cmd) < 0) { - wpa_msg(msg_ctx, MSG_INFO, + wpa_msg(auth->msg_ctx, MSG_INFO, "DPP: Failed to set configurator parameters"); goto fail; } @@ -4734,20 +1258,6 @@ fail: } -static void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key) -{ - while (key) { - struct dpp_asymmetric_key *next = key->next; - - EVP_PKEY_free(key->csign); - str_clear_free(key->config_template); - str_clear_free(key->connector_template); - os_free(key); - key = next; - } -} - - void dpp_auth_deinit(struct dpp_authentication *auth) { unsigned int i; @@ -4760,18 +1270,39 @@ void dpp_auth_deinit(struct dpp_authentication *auth) dpp_configuration_free(auth->conf2_sta); EVP_PKEY_free(auth->own_protocol_key); EVP_PKEY_free(auth->peer_protocol_key); + EVP_PKEY_free(auth->reconfig_old_protocol_key); wpabuf_free(auth->req_msg); wpabuf_free(auth->resp_msg); wpabuf_free(auth->conf_req); + wpabuf_free(auth->reconfig_req_msg); + wpabuf_free(auth->reconfig_resp_msg); for (i = 0; i < auth->num_conf_obj; i++) { struct dpp_config_obj *conf = &auth->conf_obj[i]; os_free(conf->connector); wpabuf_free(conf->c_sign_key); + wpabuf_free(conf->certbag); + wpabuf_free(conf->certs); + wpabuf_free(conf->cacert); + os_free(conf->server_name); + wpabuf_free(conf->pp_key); } +#ifdef CONFIG_DPP2 dpp_free_asymmetric_key(auth->conf_key_pkg); + os_free(auth->csrattrs); + wpabuf_free(auth->csr); + wpabuf_free(auth->priv_key); + wpabuf_free(auth->cacert); + wpabuf_free(auth->certbag); + os_free(auth->trusted_eap_server_name); + wpabuf_free(auth->conf_resp_tcp); +#endif /* CONFIG_DPP2 */ wpabuf_free(auth->net_access_key); dpp_bootstrap_info_free(auth->tmp_own_bi); + if (auth->tmp_peer_bi) { + dl_list_del(&auth->tmp_peer_bi->list); + dpp_bootstrap_info_free(auth->tmp_peer_bi); + } #ifdef CONFIG_TESTING_OPTIONS os_free(auth->config_obj_override); os_free(auth->discovery_override); @@ -4829,8 +1360,8 @@ dpp_build_conf_start(struct dpp_authentication *auth, } -static int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key, - const char *kid, const struct dpp_curve_params *curve) +int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key, + const char *kid, const struct dpp_curve_params *curve) { struct wpabuf *pub; const u8 *pos; @@ -4901,20 +1432,10 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth, struct dpp_configuration *conf) { struct wpabuf *buf = NULL; - char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL; + char *signed_conn = NULL; size_t tailroom; const struct dpp_curve_params *curve; - struct wpabuf *jws_prot_hdr; - size_t signed1_len, signed2_len, signed3_len; struct wpabuf *dppcon = NULL; - unsigned char *signature = NULL; - const unsigned char *p; - size_t signature_len; - EVP_MD_CTX *md_ctx = NULL; - ECDSA_SIG *sig = NULL; - char *dot = "."; - const EVP_MD *sign_md; - const BIGNUM *r, *s; size_t extra_len = 1000; int incl_legacy; enum dpp_akm akm; @@ -4926,16 +1447,6 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth, goto fail; } curve = auth->conf->curve; - if (curve->hash_len == SHA256_MAC_LEN) { - sign_md = EVP_sha256(); - } else if (curve->hash_len == SHA384_MAC_LEN) { - sign_md = EVP_sha384(); - } else if (curve->hash_len == SHA512_MAC_LEN) { - sign_md = EVP_sha512(); - } else { - wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); - goto fail; - } akm = conf->akm; if (dpp_akm_ver2(akm) && auth->peer_version < 2) { @@ -4983,7 +1494,8 @@ dpp_build_conf_obj_dpp(struct dpp_authentication *auth, #ifdef CONFIG_TESTING_OPTIONS skip_groups: #endif /* CONFIG_TESTING_OPTIONS */ - if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL, + if (!auth->peer_protocol_key || + dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL, auth->curve) < 0) { wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK"); goto fail; @@ -5008,81 +1520,25 @@ skip_groups: wpa_printf(MSG_DEBUG, "DPP: dppCon: %s", (const char *) wpabuf_head(dppcon)); - jws_prot_hdr = wpabuf_alloc(100); - if (!jws_prot_hdr) - goto fail; - json_start_object(jws_prot_hdr, NULL); - json_add_string(jws_prot_hdr, "typ", "dppCon"); - json_value_sep(jws_prot_hdr); - json_add_string(jws_prot_hdr, "kid", auth->conf->kid); - json_value_sep(jws_prot_hdr); - json_add_string(jws_prot_hdr, "alg", curve->jws_alg); - json_end_object(jws_prot_hdr); - signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr), - wpabuf_len(jws_prot_hdr), - &signed1_len); - wpabuf_free(jws_prot_hdr); - signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon), - &signed2_len); - if (!signed1 || !signed2) - goto fail; - - md_ctx = EVP_MD_CTX_create(); - if (!md_ctx) - goto fail; - - ERR_clear_error(); - if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL, - auth->conf->csign) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 || - EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 || - EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - signature = os_malloc(signature_len); - if (!signature) - goto fail; - if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)", - signature, signature_len); - /* Convert to raw coordinates r,s */ - p = signature; - sig = d2i_ECDSA_SIG(NULL, &p, signature_len); - if (!sig) - goto fail; - ECDSA_SIG_get0(sig, &r, &s); - if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 || - dpp_bn2bin_pad(s, signature + curve->prime_len, - curve->prime_len) < 0) - goto fail; - signature_len = 2 * curve->prime_len; - wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)", - signature, signature_len); - signed3 = base64_url_encode(signature, signature_len, &signed3_len); - if (!signed3) + signed_conn = dpp_sign_connector(auth->conf, dppcon); + if (!signed_conn) goto fail; incl_legacy = dpp_akm_psk(akm) || dpp_akm_sae(akm); tailroom = 1000; tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid); - tailroom += signed1_len + signed2_len + signed3_len; + tailroom += os_strlen(signed_conn); if (incl_legacy) tailroom += 1000; + if (akm == DPP_AKM_DOT1X) { + if (auth->certbag) + tailroom += 2 * wpabuf_len(auth->certbag); + if (auth->cacert) + tailroom += 2 * wpabuf_len(auth->cacert); + if (auth->trusted_eap_server_name) + tailroom += os_strlen(auth->trusted_eap_server_name); + tailroom += 1000; + } buf = dpp_build_conf_start(auth, conf, tailroom); if (!buf) goto fail; @@ -5098,12 +1554,32 @@ skip_groups: dpp_build_legacy_cred_params(buf, conf); json_value_sep(buf); } + if (akm == DPP_AKM_DOT1X) { + json_start_object(buf, "entCreds"); + if (!auth->certbag) + goto fail; + json_add_base64(buf, "certBag", wpabuf_head(auth->certbag), + wpabuf_len(auth->certbag)); + if (auth->cacert) { + json_value_sep(buf); + json_add_base64(buf, "caCert", + wpabuf_head(auth->cacert), + wpabuf_len(auth->cacert)); + } + if (auth->trusted_eap_server_name) { + json_value_sep(buf); + json_add_string(buf, "trustedEapServerName", + auth->trusted_eap_server_name); + } + json_value_sep(buf); + json_start_array(buf, "eapMethods"); + wpabuf_printf(buf, "%d", EAP_TYPE_TLS); + json_end_array(buf); + json_end_object(buf); + json_value_sep(buf); + } wpabuf_put_str(buf, "\"signedConnector\":\""); - wpabuf_put_str(buf, signed1); - wpabuf_put_u8(buf, '.'); - wpabuf_put_str(buf, signed2); - wpabuf_put_u8(buf, '.'); - wpabuf_put_str(buf, signed3); + wpabuf_put_str(buf, signed_conn); wpabuf_put_str(buf, "\""); json_value_sep(buf); if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid, @@ -5111,6 +1587,16 @@ skip_groups: wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK"); goto fail; } +#ifdef CONFIG_DPP2 + if (auth->peer_version >= 2 && auth->conf->pp_key) { + json_value_sep(buf); + if (dpp_build_jwk(buf, "ppKey", auth->conf->pp_key, NULL, + curve) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to build ppKey JWK"); + goto fail; + } + } +#endif /* CONFIG_DPP2 */ json_end_object(buf); json_end_object(buf); @@ -5119,12 +1605,7 @@ skip_groups: wpabuf_head(buf), wpabuf_len(buf)); out: - EVP_MD_CTX_destroy(md_ctx); - ECDSA_SIG_free(sig); - os_free(signed1); - os_free(signed2); - os_free(signed3); - os_free(signature); + os_free(signed_conn); wpabuf_free(dppcon); return buf; fail: @@ -5166,7 +1647,7 @@ dpp_build_conf_obj_legacy(struct dpp_authentication *auth, static struct wpabuf * dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole, - int idx) + int idx, bool cert_req) { struct dpp_configuration *conf = NULL; @@ -5199,498 +1680,28 @@ dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole, return NULL; } - if (dpp_akm_dpp(conf->akm)) + if (conf->akm == DPP_AKM_DOT1X) { + if (!auth->conf) { + wpa_printf(MSG_DEBUG, + "DPP: No Configurator data available"); + return NULL; + } + if (!cert_req && !auth->certbag) { + wpa_printf(MSG_DEBUG, + "DPP: No certificate data available for dot1x configuration"); + return NULL; + } + return dpp_build_conf_obj_dpp(auth, conf); + } + if (dpp_akm_dpp(conf->akm) || (auth->peer_version >= 2 && auth->conf)) return dpp_build_conf_obj_dpp(auth, conf); return dpp_build_conf_obj_legacy(auth, conf); } -#ifdef CONFIG_DPP2 - -static struct wpabuf * dpp_build_conf_params(void) -{ - struct wpabuf *buf; - size_t len; - /* TODO: proper template values */ - const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}"; - const char *connector_template = NULL; - - len = 100 + os_strlen(conf_template); - if (connector_template) - len += os_strlen(connector_template); - buf = wpabuf_alloc(len); - if (!buf) - return NULL; - - /* - * DPPConfigurationParameters ::= SEQUENCE { - * configurationTemplate UTF8String, - * connectorTemplate UTF8String OPTIONAL} - */ - - asn1_put_utf8string(buf, conf_template); - if (connector_template) - asn1_put_utf8string(buf, conf_template); - return asn1_encaps(buf, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); -} - - -static struct wpabuf * dpp_build_attribute(void) -{ - struct wpabuf *conf_params, *attr; - - /* - * aa-DPPConfigurationParameters ATTRIBUTE ::= - * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams } - * - * Attribute ::= SEQUENCE { - * type OBJECT IDENTIFIER, - * values SET SIZE(1..MAX) OF Type - */ - conf_params = dpp_build_conf_params(); - conf_params = asn1_encaps(conf_params, ASN1_CLASS_UNIVERSAL, - ASN1_TAG_SET); - if (!conf_params) - return NULL; - - attr = wpabuf_alloc(100 + wpabuf_len(conf_params)); - if (!attr) { - wpabuf_clear_free(conf_params); - return NULL; - } - - asn1_put_oid(attr, &asn1_dpp_config_params_oid); - wpabuf_put_buf(attr, conf_params); - wpabuf_clear_free(conf_params); - - return asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); -} - - -static struct wpabuf * dpp_build_key_alg(const struct dpp_curve_params *curve) -{ - const struct asn1_oid *oid; - struct wpabuf *params, *res; - - switch (curve->ike_group) { - case 19: - oid = &asn1_prime256v1_oid; - break; - case 20: - oid = &asn1_secp384r1_oid; - break; - case 21: - oid = &asn1_secp521r1_oid; - break; - case 28: - oid = &asn1_brainpoolP256r1_oid; - break; - case 29: - oid = &asn1_brainpoolP384r1_oid; - break; - case 30: - oid = &asn1_brainpoolP512r1_oid; - break; - default: - return NULL; - } - - params = wpabuf_alloc(20); - if (!params) - return NULL; - asn1_put_oid(params, oid); /* namedCurve */ - - res = asn1_build_alg_id(&asn1_ec_public_key_oid, params); - wpabuf_free(params); - return res; -} - - -static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth) -{ - struct wpabuf *key = NULL, *attr, *alg, *priv_key = NULL; - EC_KEY *eckey; - unsigned char *der = NULL; - int der_len; - - eckey = EVP_PKEY_get0_EC_KEY(auth->conf->csign); - if (!eckey) - return NULL; - - EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); - der_len = i2d_ECPrivateKey(eckey, &der); - if (der_len > 0) - priv_key = wpabuf_alloc_copy(der, der_len); - OPENSSL_free(der); - - alg = dpp_build_key_alg(auth->conf->curve); - - /* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */ - attr = dpp_build_attribute(); - attr = asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SET); - if (!priv_key || !attr || !alg) - goto fail; - - /* - * OneAsymmetricKey ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] Attributes OPTIONAL, - * ..., - * [[2: publicKey [1] BIT STRING OPTIONAL ]], - * ... - * } - */ - - key = wpabuf_alloc(100 + wpabuf_len(alg) + wpabuf_len(priv_key) + - wpabuf_len(attr)); - if (!key) - goto fail; - - asn1_put_integer(key, 1); /* version = v2(1) */ - - /* PrivateKeyAlgorithmIdentifier */ - wpabuf_put_buf(key, alg); - - /* PrivateKey ::= OCTET STRING */ - asn1_put_octet_string(key, priv_key); - - /* [0] Attributes OPTIONAL */ - asn1_put_hdr(key, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0, wpabuf_len(attr)); - wpabuf_put_buf(key, attr); - -fail: - wpabuf_clear_free(attr); - wpabuf_clear_free(priv_key); - wpabuf_free(alg); - - /* - * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage - * - * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey - * - * OneAsymmetricKey ::= SEQUENCE - */ - return asn1_encaps(asn1_encaps(key, - ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE), - ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); - return key; -} - - -static struct wpabuf * dpp_build_pbkdf2_alg_id(const struct wpabuf *salt, - size_t hash_len) -{ - struct wpabuf *params = NULL, *buf = NULL, *prf = NULL; - const struct asn1_oid *oid; - - /* - * PBKDF2-params ::= SEQUENCE { - * salt CHOICE { - * specified OCTET STRING, - * otherSource AlgorithmIdentifier} - * iterationCount INTEGER (1..MAX), - * keyLength INTEGER (1..MAX), - * prf AlgorithmIdentifier} - * - * salt is an 64 octet value, iterationCount is 1000, keyLength is based - * on Configurator signing key length, prf is - * id-hmacWithSHA{256,384,512} based on Configurator signing key. - */ - - if (hash_len == 32) - oid = &asn1_pbkdf2_hmac_sha256_oid; - else if (hash_len == 48) - oid = &asn1_pbkdf2_hmac_sha384_oid; - else if (hash_len == 64) - oid = &asn1_pbkdf2_hmac_sha512_oid; - else - goto fail; - prf = asn1_build_alg_id(oid, NULL); - if (!prf) - goto fail; - params = wpabuf_alloc(100 + wpabuf_len(salt) + wpabuf_len(prf)); - if (!params) - goto fail; - asn1_put_octet_string(params, salt); /* salt.specified */ - asn1_put_integer(params, 1000); /* iterationCount */ - asn1_put_integer(params, hash_len); /* keyLength */ - wpabuf_put_buf(params, prf); - params = asn1_encaps(params, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); - if (!params) - goto fail; - buf = asn1_build_alg_id(&asn1_pbkdf2_oid, params); -fail: - wpabuf_free(params); - wpabuf_free(prf); - return buf; -} - - -static struct wpabuf * -dpp_build_pw_recipient_info(struct dpp_authentication *auth, size_t hash_len, - const struct wpabuf *cont_enc_key) -{ - struct wpabuf *pwri = NULL, *enc_key = NULL, *key_der_alg = NULL, - *key_enc_alg = NULL, *salt; - u8 kek[DPP_MAX_HASH_LEN]; - const u8 *key; - size_t key_len; - - salt = wpabuf_alloc(64); - if (!salt || os_get_random(wpabuf_put(salt, 64), 64) < 0) - goto fail; - wpa_hexdump_buf(MSG_DEBUG, "DPP: PBKDF2 salt", salt); - - /* TODO: For initial testing, use ke as the key. Replace this with a - * new key once that has been defined. */ - key = auth->ke; - key_len = auth->curve->hash_len; - wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len); - - if (dpp_pbkdf2(hash_len, key, key_len, wpabuf_head(salt), 64, 1000, - kek, hash_len)) { - wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed"); - goto fail; - } - wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2", - kek, hash_len); - - enc_key = wpabuf_alloc(hash_len + AES_BLOCK_SIZE); - if (!enc_key || - aes_siv_encrypt(kek, hash_len, wpabuf_head(cont_enc_key), - wpabuf_len(cont_enc_key), 0, NULL, NULL, - wpabuf_put(enc_key, hash_len + AES_BLOCK_SIZE)) < 0) - goto fail; - wpa_hexdump_buf(MSG_DEBUG, "DPP: encryptedKey", enc_key); - - /* - * PasswordRecipientInfo ::= SEQUENCE { - * version CMSVersion, - * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL, - * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, - * encryptedKey EncryptedKey} - * - * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the - * parameters contains PBKDF2-params SEQUENCE. - */ - - key_der_alg = dpp_build_pbkdf2_alg_id(salt, hash_len); - key_enc_alg = asn1_build_alg_id(&asn1_aes_siv_cmac_aead_256_oid, NULL); - if (!key_der_alg || !key_enc_alg) - goto fail; - pwri = wpabuf_alloc(100 + wpabuf_len(key_der_alg) + - wpabuf_len(key_enc_alg) + wpabuf_len(enc_key)); - if (!pwri) - goto fail; - - /* version = 0 */ - asn1_put_integer(pwri, 0); - - /* [0] KeyDerivationAlgorithmIdentifier */ - asn1_put_hdr(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0, - wpabuf_len(key_der_alg)); - wpabuf_put_buf(pwri, key_der_alg); - - /* KeyEncryptionAlgorithmIdentifier */ - wpabuf_put_buf(pwri, key_enc_alg); - - /* EncryptedKey ::= OCTET STRING */ - asn1_put_octet_string(pwri, enc_key); - -fail: - wpabuf_clear_free(key_der_alg); - wpabuf_free(key_enc_alg); - wpabuf_free(enc_key); - wpabuf_free(salt); - forced_memzero(kek, sizeof(kek)); - return asn1_encaps(pwri, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); -} - - -static struct wpabuf * -dpp_build_recipient_info(struct dpp_authentication *auth, size_t hash_len, - const struct wpabuf *cont_enc_key) -{ - struct wpabuf *pwri; - - /* - * RecipientInfo ::= CHOICE { - * ktri KeyTransRecipientInfo, - * kari [1] KeyAgreeRecipientInfo, - * kekri [2] KEKRecipientInfo, - * pwri [3] PasswordRecipientInfo, - * ori [4] OtherRecipientInfo} - * - * Shall always use the pwri CHOICE. - */ - - pwri = dpp_build_pw_recipient_info(auth, hash_len, cont_enc_key); - return asn1_encaps(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 3); -} - - -static struct wpabuf * -dpp_build_enc_cont_info(struct dpp_authentication *auth, size_t hash_len, - const struct wpabuf *cont_enc_key) -{ - struct wpabuf *key_pkg, *enc_cont_info = NULL, *enc_cont = NULL, - *enc_alg; - const struct asn1_oid *oid; - size_t enc_cont_len; - - /* - * EncryptedContentInfo ::= SEQUENCE { - * contentType ContentType, - * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, - * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL} - */ - - if (hash_len == 32) - oid = &asn1_aes_siv_cmac_aead_256_oid; - else if (hash_len == 48) - oid = &asn1_aes_siv_cmac_aead_384_oid; - else if (hash_len == 64) - oid = &asn1_aes_siv_cmac_aead_512_oid; - else - return NULL; - - key_pkg = dpp_build_key_pkg(auth); - enc_alg = asn1_build_alg_id(oid, NULL); - if (!key_pkg || !enc_alg) - goto fail; - - wpa_hexdump_buf_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage", - key_pkg); - - enc_cont_len = wpabuf_len(key_pkg) + AES_BLOCK_SIZE; - enc_cont = wpabuf_alloc(enc_cont_len); - if (!enc_cont || - aes_siv_encrypt(wpabuf_head(cont_enc_key), wpabuf_len(cont_enc_key), - wpabuf_head(key_pkg), wpabuf_len(key_pkg), - 0, NULL, NULL, - wpabuf_put(enc_cont, enc_cont_len)) < 0) - goto fail; - - enc_cont_info = wpabuf_alloc(100 + wpabuf_len(enc_alg) + - wpabuf_len(enc_cont)); - if (!enc_cont_info) - goto fail; - - /* ContentType ::= OBJECT IDENTIFIER */ - asn1_put_oid(enc_cont_info, &asn1_dpp_asymmetric_key_package_oid); - - /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */ - wpabuf_put_buf(enc_cont_info, enc_alg); - - /* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL - * EncryptedContent ::= OCTET STRING */ - asn1_put_hdr(enc_cont_info, ASN1_CLASS_CONTEXT_SPECIFIC, 0, 0, - wpabuf_len(enc_cont)); - wpabuf_put_buf(enc_cont_info, enc_cont); - -fail: - wpabuf_clear_free(key_pkg); - wpabuf_free(enc_cont); - wpabuf_free(enc_alg); - return enc_cont_info; -} - - -static struct wpabuf * dpp_gen_random(size_t len) -{ - struct wpabuf *key; - - key = wpabuf_alloc(len); - if (!key || os_get_random(wpabuf_put(key, len), len) < 0) { - wpabuf_free(key); - key = NULL; - } - wpa_hexdump_buf_key(MSG_DEBUG, "DPP: content-encryption key", key); - return key; -} - - -static struct wpabuf * dpp_build_enveloped_data(struct dpp_authentication *auth) -{ - struct wpabuf *env = NULL; - struct wpabuf *recipient_info = NULL, *enc_cont_info = NULL; - struct wpabuf *cont_enc_key = NULL; - size_t hash_len; - - if (!auth->conf) { - wpa_printf(MSG_DEBUG, - "DPP: No Configurator instance selected for the session - cannot build DPPEnvelopedData"); - return NULL; - } - - if (!auth->provision_configurator) { - wpa_printf(MSG_DEBUG, - "DPP: Configurator provisioning not allowed"); - return NULL; - } - - wpa_printf(MSG_DEBUG, "DPP: Building DPPEnvelopedData"); - - hash_len = auth->conf->curve->hash_len; - cont_enc_key = dpp_gen_random(hash_len); - if (!cont_enc_key) - goto fail; - recipient_info = dpp_build_recipient_info(auth, hash_len, cont_enc_key); - enc_cont_info = dpp_build_enc_cont_info(auth, hash_len, cont_enc_key); - if (!recipient_info || !enc_cont_info) - goto fail; - - env = wpabuf_alloc(wpabuf_len(recipient_info) + - wpabuf_len(enc_cont_info) + - 100); - if (!env) - goto fail; - - /* - * DPPEnvelopedData ::= EnvelopedData - * - * EnvelopedData ::= SEQUENCE { - * version CMSVersion, - * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, - * recipientInfos RecipientInfos, - * encryptedContentInfo EncryptedContentInfo, - * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL} - * - * For DPP, version is 3, both originatorInfo and - * unprotectedAttrs are omitted, and recipientInfos contains a single - * RecipientInfo. - */ - - /* EnvelopedData.version = 3 */ - asn1_put_integer(env, 3); - - /* RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo */ - asn1_put_set(env, recipient_info); - - /* EncryptedContentInfo ::= SEQUENCE */ - asn1_put_sequence(env, enc_cont_info); - - env = asn1_encaps(env, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); - wpa_hexdump_buf(MSG_MSGDUMP, "DPP: DPPEnvelopedData", env); -out: - wpabuf_clear_free(cont_enc_key); - wpabuf_clear_free(recipient_info); - wpabuf_free(enc_cont_info); - return env; -fail: - wpabuf_free(env); - env = NULL; - goto out; -} - -#endif /* CONFIG_DPP2 */ - - -static struct wpabuf * +struct wpabuf * dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, - u16 e_nonce_len, enum dpp_netrole netrole) + u16 e_nonce_len, enum dpp_netrole netrole, bool cert_req) { struct wpabuf *conf = NULL, *conf2 = NULL, *env_data = NULL; size_t clear_len, attr_len; @@ -5700,21 +1711,33 @@ dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, size_t len[1]; enum dpp_status_error status; + if (auth->force_conf_resp_status != DPP_STATUS_OK) { + status = auth->force_conf_resp_status; + goto forced_status; + } + if (netrole == DPP_NETROLE_CONFIGURATOR) { #ifdef CONFIG_DPP2 env_data = dpp_build_enveloped_data(auth); #endif /* CONFIG_DPP2 */ } else { - conf = dpp_build_conf_obj(auth, netrole, 0); + conf = dpp_build_conf_obj(auth, netrole, 0, cert_req); if (conf) { wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON", wpabuf_head(conf), wpabuf_len(conf)); - conf2 = dpp_build_conf_obj(auth, netrole, 1); + conf2 = dpp_build_conf_obj(auth, netrole, 1, cert_req); } } - status = (conf || env_data) ? DPP_STATUS_OK : - DPP_STATUS_CONFIGURE_FAILURE; + + if (conf || env_data) + status = DPP_STATUS_OK; + else if (!cert_req && netrole == DPP_NETROLE_STA && auth->conf_sta && + auth->conf_sta->akm == DPP_AKM_DOT1X && !auth->waiting_csr) + status = DPP_STATUS_CSR_NEEDED; + else + status = DPP_STATUS_CONFIGURE_FAILURE; +forced_status: auth->conf_resp_status = status; /* { E-nonce, configurationObject[, sendConnStatus]}ke */ @@ -5728,6 +1751,9 @@ dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, if (auth->peer_version >= 2 && auth->send_conn_status && netrole == DPP_NETROLE_STA) clear_len += 4; + if (status == DPP_STATUS_CSR_NEEDED && auth->conf_sta && + auth->conf_sta->csrattrs) + clear_len += 4 + os_strlen(auth->conf_sta->csrattrs); clear = wpabuf_alloc(clear_len); attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE; #ifdef CONFIG_TESTING_OPTIONS @@ -5790,12 +1816,21 @@ skip_e_nonce: } if (auth->peer_version >= 2 && auth->send_conn_status && - netrole == DPP_NETROLE_STA) { + netrole == DPP_NETROLE_STA && status == DPP_STATUS_OK) { wpa_printf(MSG_DEBUG, "DPP: sendConnStatus"); wpabuf_put_le16(clear, DPP_ATTR_SEND_CONN_STATUS); wpabuf_put_le16(clear, 0); } + if (status == DPP_STATUS_CSR_NEEDED && auth->conf_sta && + auth->conf_sta->csrattrs) { + auth->waiting_csr = true; + wpa_printf(MSG_DEBUG, "DPP: CSR Attributes Request"); + wpabuf_put_le16(clear, DPP_ATTR_CSR_ATTR_REQ); + wpabuf_put_le16(clear, os_strlen(auth->conf_sta->csrattrs)); + wpabuf_put_str(clear, auth->conf_sta->csrattrs); + } + #ifdef CONFIG_TESTING_OPTIONS skip_config_obj: if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) { @@ -5866,6 +1901,7 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, struct wpabuf *resp = NULL; struct json_token *root = NULL, *token; enum dpp_netrole netrole; + struct wpabuf *cert_req = NULL; #ifdef CONFIG_TESTING_OPTIONS if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) { @@ -5974,116 +2010,109 @@ dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, dpp_auth_fail(auth, "Unsupported netRole"); goto fail; } + auth->e_netrole = netrole; token = json_get_member(root, "mudurl"); - if (token && token->type == JSON_STRING) + if (token && token->type == JSON_STRING) { wpa_printf(MSG_DEBUG, "DPP: mudurl = '%s'", token->string); + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_MUD_URL "%s", + token->string); + } token = json_get_member(root, "bandSupport"); if (token && token->type == JSON_ARRAY) { + int *opclass = NULL; + char txt[200], *pos, *end; + int i, res; + wpa_printf(MSG_DEBUG, "DPP: bandSupport"); token = token->child; while (token) { - if (token->type != JSON_NUMBER) + if (token->type != JSON_NUMBER) { wpa_printf(MSG_DEBUG, "DPP: Invalid bandSupport array member type"); - else + } else { wpa_printf(MSG_DEBUG, "DPP: Supported global operating class: %d", token->number); + int_array_add_unique(&opclass, token->number); + } token = token->sibling; } + + txt[0] = '\0'; + pos = txt; + end = txt + sizeof(txt); + for (i = 0; opclass && opclass[i]; i++) { + res = os_snprintf(pos, end - pos, "%s%d", + pos == txt ? "" : ",", opclass[i]); + if (os_snprintf_error(end - pos, res)) { + *pos = '\0'; + break; + } + pos += res; + } + os_free(opclass); + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_BAND_SUPPORT "%s", + txt); } - resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole); +#ifdef CONFIG_DPP2 + cert_req = json_get_member_base64(root, "pkcs10"); + if (cert_req) { + char *txt; + int id; + + wpa_hexdump_buf(MSG_DEBUG, "DPP: CertificateRequest", cert_req); + if (dpp_validate_csr(auth, cert_req) < 0) { + wpa_printf(MSG_DEBUG, "DPP: CSR is not valid"); + auth->force_conf_resp_status = DPP_STATUS_CSR_BAD; + goto cont; + } + + if (auth->peer_bi) { + id = auth->peer_bi->id; + } else if (auth->tmp_peer_bi) { + id = auth->tmp_peer_bi->id; + } else { + struct dpp_bootstrap_info *bi; + + bi = os_zalloc(sizeof(*bi)); + if (!bi) + goto fail; + bi->id = dpp_next_id(auth->global); + dl_list_add(&auth->global->bootstrap, &bi->list); + auth->tmp_peer_bi = bi; + id = bi->id; + } + + wpa_printf(MSG_DEBUG, "DPP: CSR is valid - forward to CA/RA"); + txt = base64_encode_no_lf(wpabuf_head(cert_req), + wpabuf_len(cert_req), NULL); + if (!txt) + goto fail; + + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_CSR "peer=%d csr=%s", + id, txt); + os_free(txt); + auth->waiting_csr = false; + auth->waiting_cert = true; + goto fail; + } +cont: +#endif /* CONFIG_DPP2 */ + + resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, netrole, + cert_req); fail: + wpabuf_free(cert_req); json_free(root); os_free(unwrapped); return resp; } -static struct wpabuf * -dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, - const u8 *prot_hdr, u16 prot_hdr_len, - const EVP_MD **ret_md) -{ - struct json_token *root, *token; - struct wpabuf *kid = NULL; - - root = json_parse((const char *) prot_hdr, prot_hdr_len); - if (!root) { - wpa_printf(MSG_DEBUG, - "DPP: JSON parsing failed for JWS Protected Header"); - goto fail; - } - - if (root->type != JSON_OBJECT) { - wpa_printf(MSG_DEBUG, - "DPP: JWS Protected Header root is not an object"); - goto fail; - } - - token = json_get_member(root, "typ"); - if (!token || token->type != JSON_STRING) { - wpa_printf(MSG_DEBUG, "DPP: No typ string value found"); - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s", - token->string); - if (os_strcmp(token->string, "dppCon") != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Unsupported JWS Protected Header typ=%s", - token->string); - goto fail; - } - - token = json_get_member(root, "alg"); - if (!token || token->type != JSON_STRING) { - wpa_printf(MSG_DEBUG, "DPP: No alg string value found"); - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s", - token->string); - if (os_strcmp(token->string, curve->jws_alg) != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)", - token->string, curve->jws_alg); - goto fail; - } - if (os_strcmp(token->string, "ES256") == 0 || - os_strcmp(token->string, "BS256") == 0) - *ret_md = EVP_sha256(); - else if (os_strcmp(token->string, "ES384") == 0 || - os_strcmp(token->string, "BS384") == 0) - *ret_md = EVP_sha384(); - else if (os_strcmp(token->string, "ES512") == 0 || - os_strcmp(token->string, "BS512") == 0) - *ret_md = EVP_sha512(); - else - *ret_md = NULL; - if (!*ret_md) { - wpa_printf(MSG_DEBUG, - "DPP: Unsupported JWS Protected Header alg=%s", - token->string); - goto fail; - } - - kid = json_get_member_base64url(root, "kid"); - if (!kid) { - wpa_printf(MSG_DEBUG, "DPP: No kid string value found"); - goto fail; - } - wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)", - kid); - -fail: - json_free(root); - return kid; -} - - static int dpp_parse_cred_legacy(struct dpp_config_obj *conf, struct json_token *cred) { @@ -6131,8 +2160,8 @@ static int dpp_parse_cred_legacy(struct dpp_config_obj *conf, } -static EVP_PKEY * dpp_parse_jwk(struct json_token *jwk, - const struct dpp_curve_params **key_curve) +EVP_PKEY * dpp_parse_jwk(struct json_token *jwk, + const struct dpp_curve_params **key_curve) { struct json_token *token; const struct dpp_curve_params *curve; @@ -6386,38 +2415,6 @@ fail: } -static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash) -{ - struct wpabuf *uncomp; - int res; - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[1]; - size_t len[1]; - - if (wpabuf_len(r_hash) != SHA256_MAC_LEN) - return -1; - uncomp = dpp_get_pubkey_point(pub, 1); - if (!uncomp) - return -1; - addr[0] = wpabuf_head(uncomp); - len[0] = wpabuf_len(uncomp); - wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key", - addr[0], len[0]); - res = sha256_vector(1, addr, len, hash); - wpabuf_free(uncomp); - if (res < 0) - return -1; - if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Received hash value does not match calculated public key hash value"); - wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash", - hash, SHA256_MAC_LEN); - return -1; - } - return 0; -} - - static void dpp_copy_csign(struct dpp_config_obj *conf, EVP_PKEY *csign) { unsigned char *der = NULL; @@ -6432,14 +2429,35 @@ static void dpp_copy_csign(struct dpp_config_obj *conf, EVP_PKEY *csign) } +static void dpp_copy_ppkey(struct dpp_config_obj *conf, EVP_PKEY *ppkey) +{ + unsigned char *der = NULL; + int der_len; + + der_len = i2d_PUBKEY(ppkey, &der); + if (der_len <= 0) + return; + wpabuf_free(conf->pp_key); + conf->pp_key = wpabuf_alloc_copy(der, der_len); + OPENSSL_free(der); +} + + static void dpp_copy_netaccesskey(struct dpp_authentication *auth, struct dpp_config_obj *conf) { unsigned char *der = NULL; int der_len; EC_KEY *eckey; + EVP_PKEY *own_key; - eckey = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key); + own_key = auth->own_protocol_key; +#ifdef CONFIG_DPP2 + if (auth->reconfig_connector_key == DPP_CONFIG_REUSEKEY && + auth->reconfig_old_protocol_key) + own_key = auth->reconfig_old_protocol_key; +#endif /* CONFIG_DPP2 */ + eckey = EVP_PKEY_get1_EC_KEY(own_key); if (!eckey) return; @@ -6455,183 +2473,15 @@ static void dpp_copy_netaccesskey(struct dpp_authentication *auth, } -struct dpp_signed_connector_info { - unsigned char *payload; - size_t payload_len; -}; - -static enum dpp_status_error -dpp_process_signed_connector(struct dpp_signed_connector_info *info, - EVP_PKEY *csign_pub, const char *connector) -{ - enum dpp_status_error ret = 255; - const char *pos, *end, *signed_start, *signed_end; - struct wpabuf *kid = NULL; - unsigned char *prot_hdr = NULL, *signature = NULL; - size_t prot_hdr_len = 0, signature_len = 0; - const EVP_MD *sign_md = NULL; - unsigned char *der = NULL; - int der_len; - int res; - EVP_MD_CTX *md_ctx = NULL; - ECDSA_SIG *sig = NULL; - BIGNUM *r = NULL, *s = NULL; - const struct dpp_curve_params *curve; - EC_KEY *eckey; - const EC_GROUP *group; - int nid; - - eckey = EVP_PKEY_get1_EC_KEY(csign_pub); - if (!eckey) - goto fail; - group = EC_KEY_get0_group(eckey); - if (!group) - goto fail; - nid = EC_GROUP_get_curve_name(group); - curve = dpp_get_curve_nid(nid); - if (!curve) - goto fail; - wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv); - os_memset(info, 0, sizeof(*info)); - - signed_start = pos = connector; - end = os_strchr(pos, '.'); - if (!end) { - wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len); - if (!prot_hdr) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode signedConnector JWS Protected Header"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - wpa_hexdump_ascii(MSG_DEBUG, - "DPP: signedConnector - JWS Protected Header", - prot_hdr, prot_hdr_len); - kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md); - if (!kid) { - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - if (wpabuf_len(kid) != SHA256_MAC_LEN) { - wpa_printf(MSG_DEBUG, - "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)", - (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - - pos = end + 1; - end = os_strchr(pos, '.'); - if (!end) { - wpa_printf(MSG_DEBUG, - "DPP: Missing dot(2) in signedConnector"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - signed_end = end - 1; - info->payload = base64_url_decode(pos, end - pos, &info->payload_len); - if (!info->payload) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode signedConnector JWS Payload"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - wpa_hexdump_ascii(MSG_DEBUG, - "DPP: signedConnector - JWS Payload", - info->payload, info->payload_len); - pos = end + 1; - signature = base64_url_decode(pos, os_strlen(pos), &signature_len); - if (!signature) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode signedConnector signature"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature", - signature, signature_len); - - if (dpp_check_pubkey_match(csign_pub, kid) < 0) { - ret = DPP_STATUS_NO_MATCH; - goto fail; - } - - if (signature_len & 0x01) { - wpa_printf(MSG_DEBUG, - "DPP: Unexpected signedConnector signature length (%d)", - (int) signature_len); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - - /* JWS Signature encodes the signature (r,s) as two octet strings. Need - * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */ - r = BN_bin2bn(signature, signature_len / 2, NULL); - s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL); - sig = ECDSA_SIG_new(); - if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1) - goto fail; - r = NULL; - s = NULL; - - der_len = i2d_ECDSA_SIG(sig, &der); - if (der_len <= 0) { - wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len); - md_ctx = EVP_MD_CTX_create(); - if (!md_ctx) - goto fail; - - ERR_clear_error(); - if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, csign_pub) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - if (EVP_DigestVerifyUpdate(md_ctx, signed_start, - signed_end - signed_start + 1) != 1) { - wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - res = EVP_DigestVerifyFinal(md_ctx, der, der_len); - if (res != 1) { - wpa_printf(MSG_DEBUG, - "DPP: EVP_DigestVerifyFinal failed (res=%d): %s", - res, ERR_error_string(ERR_get_error(), NULL)); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - - ret = DPP_STATUS_OK; -fail: - EC_KEY_free(eckey); - EVP_MD_CTX_destroy(md_ctx); - os_free(prot_hdr); - wpabuf_free(kid); - os_free(signature); - ECDSA_SIG_free(sig); - BN_free(r); - BN_free(s); - OPENSSL_free(der); - return ret; -} - - static int dpp_parse_cred_dpp(struct dpp_authentication *auth, struct dpp_config_obj *conf, struct json_token *cred) { struct dpp_signed_connector_info info; - struct json_token *token, *csign; + struct json_token *token, *csign, *ppkey; int ret = -1; - EVP_PKEY *csign_pub = NULL; - const struct dpp_curve_params *key_curve = NULL; + EVP_PKEY *csign_pub = NULL, *pp_pub = NULL; + const struct dpp_curve_params *key_curve = NULL, *pp_curve = NULL; const char *signed_connector; os_memset(&info, 0, sizeof(info)); @@ -6658,6 +2508,21 @@ static int dpp_parse_cred_dpp(struct dpp_authentication *auth, } dpp_debug_print_key("DPP: Received C-sign-key", csign_pub); + ppkey = json_get_member(cred, "ppKey"); + if (ppkey && ppkey->type == JSON_OBJECT) { + pp_pub = dpp_parse_jwk(ppkey, &pp_curve); + if (!pp_pub) { + wpa_printf(MSG_DEBUG, "DPP: Failed to parse ppKey JWK"); + goto fail; + } + dpp_debug_print_key("DPP: Received ppKey", pp_pub); + if (key_curve != pp_curve) { + wpa_printf(MSG_DEBUG, + "DPP: C-sign-key and ppKey do not use the same curve"); + goto fail; + } + } + token = json_get_member(cred, "signedConnector"); if (!token || token->type != JSON_STRING) { wpa_printf(MSG_DEBUG, "DPP: No signedConnector string found"); @@ -6688,16 +2553,72 @@ static int dpp_parse_cred_dpp(struct dpp_authentication *auth, conf->connector = os_strdup(signed_connector); dpp_copy_csign(conf, csign_pub); - dpp_copy_netaccesskey(auth, conf); + if (pp_pub) + dpp_copy_ppkey(conf, pp_pub); + if (dpp_akm_dpp(conf->akm) || auth->peer_version >= 2) + dpp_copy_netaccesskey(auth, conf); ret = 0; fail: EVP_PKEY_free(csign_pub); + EVP_PKEY_free(pp_pub); os_free(info.payload); return ret; } +#ifdef CONFIG_DPP2 +static int dpp_parse_cred_dot1x(struct dpp_authentication *auth, + struct dpp_config_obj *conf, + struct json_token *cred) +{ + struct json_token *ent, *name; + + ent = json_get_member(cred, "entCreds"); + if (!ent || ent->type != JSON_OBJECT) { + dpp_auth_fail(auth, "No entCreds in JSON"); + return -1; + } + + conf->certbag = json_get_member_base64(ent, "certBag"); + if (!conf->certbag) { + dpp_auth_fail(auth, "No certBag in JSON"); + return -1; + } + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received certBag", conf->certbag); + conf->certs = dpp_pkcs7_certs(conf->certbag); + if (!conf->certs) { + dpp_auth_fail(auth, "No certificates in certBag"); + return -1; + } + + conf->cacert = json_get_member_base64(ent, "caCert"); + if (conf->cacert) + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Received caCert", + conf->cacert); + + name = json_get_member(ent, "trustedEapServerName"); + if (name && + (name->type != JSON_STRING || + has_ctrl_char((const u8 *) name->string, + os_strlen(name->string)))) { + dpp_auth_fail(auth, + "Invalid trustedEapServerName type in JSON"); + return -1; + } + if (name && name->string) { + wpa_printf(MSG_DEBUG, "DPP: Received trustedEapServerName: %s", + name->string); + conf->server_name = os_strdup(name->string); + if (!conf->server_name) + return -1; + } + + return 0; +} +#endif /* CONFIG_DPP2 */ + + const char * dpp_akm_str(enum dpp_akm akm) { switch (akm) { @@ -6713,6 +2634,8 @@ const char * dpp_akm_str(enum dpp_akm akm) return "dpp+sae"; case DPP_AKM_PSK_SAE_DPP: return "dpp+psk+sae"; + case DPP_AKM_DOT1X: + return "dot1x"; default: return "??"; } @@ -6734,6 +2657,8 @@ const char * dpp_akm_selector_str(enum dpp_akm akm) return "506F9A02+000FAC08"; case DPP_AKM_PSK_SAE_DPP: return "506F9A02+000FAC08+000FAC02+000FAC06"; + case DPP_AKM_DOT1X: + return "000FAC01+000FAC05"; default: return "??"; } @@ -6743,7 +2668,7 @@ const char * dpp_akm_selector_str(enum dpp_akm akm) static enum dpp_akm dpp_akm_from_str(const char *akm) { const char *pos; - int dpp = 0, psk = 0, sae = 0; + int dpp = 0, psk = 0, sae = 0, dot1x = 0; if (os_strcmp(akm, "psk") == 0) return DPP_AKM_PSK; @@ -6757,6 +2682,8 @@ static enum dpp_akm dpp_akm_from_str(const char *akm) return DPP_AKM_SAE_DPP; if (os_strcmp(akm, "dpp+psk+sae") == 0) return DPP_AKM_PSK_SAE_DPP; + if (os_strcmp(akm, "dot1x") == 0) + return DPP_AKM_DOT1X; pos = akm; while (*pos) { @@ -6770,6 +2697,10 @@ static enum dpp_akm dpp_akm_from_str(const char *akm) psk = 1; else if (os_strncasecmp(pos, "000FAC08", 8) == 0) sae = 1; + else if (os_strncasecmp(pos, "000FAC01", 8) == 0) + dot1x = 1; + else if (os_strncasecmp(pos, "000FAC05", 8) == 0) + dot1x = 1; pos += 8; if (*pos != '+') break; @@ -6788,6 +2719,8 @@ static enum dpp_akm dpp_akm_from_str(const char *akm) return DPP_AKM_SAE; if (psk) return DPP_AKM_PSK; + if (dot1x) + return DPP_AKM_DOT1X; return DPP_AKM_UNKNOWN; } @@ -6800,6 +2733,7 @@ static int dpp_parse_conf_obj(struct dpp_authentication *auth, struct json_token *root, *token, *discovery, *cred; struct dpp_config_obj *conf; struct wpabuf *ssid64 = NULL; + int legacy; root = json_parse((const char *) conf_obj, conf_obj_len); if (!root) @@ -6887,12 +2821,29 @@ static int dpp_parse_conf_obj(struct dpp_authentication *auth, } conf->akm = dpp_akm_from_str(token->string); - if (dpp_akm_legacy(conf->akm)) { + legacy = dpp_akm_legacy(conf->akm); + if (legacy && auth->peer_version >= 2) { + struct json_token *csign, *s_conn; + + csign = json_get_member(cred, "csign"); + s_conn = json_get_member(cred, "signedConnector"); + if (csign && csign->type == JSON_OBJECT && + s_conn && s_conn->type == JSON_STRING) + legacy = 0; + } + if (legacy) { if (dpp_parse_cred_legacy(conf, cred) < 0) goto fail; - } else if (dpp_akm_dpp(conf->akm)) { + } else if (dpp_akm_dpp(conf->akm) || + (auth->peer_version >= 2 && dpp_akm_legacy(conf->akm))) { if (dpp_parse_cred_dpp(auth, conf, cred) < 0) goto fail; +#ifdef CONFIG_DPP2 + } else if (conf->akm == DPP_AKM_DOT1X) { + if (dpp_parse_cred_dot1x(auth, conf, cred) < 0 || + dpp_parse_cred_dpp(auth, conf, cred) < 0) + goto fail; +#endif /* CONFIG_DPP2 */ } else { wpa_printf(MSG_DEBUG, "DPP: Unsupported akm: %s", token->string); @@ -6910,705 +2861,16 @@ fail: #ifdef CONFIG_DPP2 - -struct dpp_enveloped_data { - const u8 *enc_cont; - size_t enc_cont_len; - const u8 *enc_key; - size_t enc_key_len; - const u8 *salt; - size_t pbkdf2_key_len; - size_t prf_hash_len; -}; - - -static int dpp_parse_recipient_infos(const u8 *pos, size_t len, - struct dpp_enveloped_data *data) +static u8 * dpp_get_csr_attrs(const u8 *attrs, size_t attrs_len, size_t *len) { - struct asn1_hdr hdr; - const u8 *end = pos + len; - const u8 *next, *e_end; - struct asn1_oid oid; - int val; - const u8 *params; - size_t params_len; + const u8 *b64; + u16 b64_len; - wpa_hexdump(MSG_MSGDUMP, "DPP: RecipientInfos", pos, len); - - /* - * RecipientInfo ::= CHOICE { - * ktri KeyTransRecipientInfo, - * kari [1] KeyAgreeRecipientInfo, - * kekri [2] KEKRecipientInfo, - * pwri [3] PasswordRecipientInfo, - * ori [4] OtherRecipientInfo} - * - * Shall always use the pwri CHOICE. - */ - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 3) { - wpa_printf(MSG_DEBUG, - "DPP: Expected CHOICE [3] (pwri) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: PasswordRecipientInfo", - hdr.payload, hdr.length); - pos = hdr.payload; - end = pos + hdr.length; - - /* - * PasswordRecipientInfo ::= SEQUENCE { - * version CMSVersion, - * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL, - * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, - * encryptedKey EncryptedKey} - * - * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the - * parameters contains PBKDF2-params SEQUENCE. - */ - - if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0) - return -1; - pos = hdr.payload; - - if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) - return -1; - if (val != 0) { - wpa_printf(MSG_DEBUG, "DPP: pwri.version != 0"); - return -1; - } - - wpa_hexdump(MSG_MSGDUMP, "DPP: Remaining PasswordRecipientInfo after version", - pos, end - pos); - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Expected keyDerivationAlgorithm [0] - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - pos = hdr.payload; - e_end = pos + hdr.length; - - /* KeyDerivationAlgorithmIdentifier ::= AlgorithmIdentifier */ - if (asn1_get_alg_id(pos, e_end - pos, &oid, ¶ms, ¶ms_len, - &next) < 0) - return -1; - if (!asn1_oid_equal(&oid, &asn1_pbkdf2_oid)) { - char buf[80]; - - asn1_oid_to_str(&oid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, - "DPP: Unexpected KeyDerivationAlgorithmIdentifier %s", - buf); - return -1; - } - - /* - * PBKDF2-params ::= SEQUENCE { - * salt CHOICE { - * specified OCTET STRING, - * otherSource AlgorithmIdentifier} - * iterationCount INTEGER (1..MAX), - * keyLength INTEGER (1..MAX), - * prf AlgorithmIdentifier} - * - * salt is an 64 octet value, iterationCount is 1000, keyLength is based - * on Configurator signing key length, prf is - * id-hmacWithSHA{256,384,512} based on Configurator signing key. - */ - if (!params || - asn1_get_sequence(params, params_len, &hdr, &e_end) < 0) - return -1; - pos = hdr.payload; - - if (asn1_get_next(pos, e_end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, - "DPP: Expected OCTETSTRING (salt.specified) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: salt.specified", - hdr.payload, hdr.length); - if (hdr.length != 64) { - wpa_printf(MSG_DEBUG, "DPP: Unexpected salt length %u", - hdr.length); - return -1; - } - data->salt = hdr.payload; - pos = hdr.payload + hdr.length; - - if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0) - return -1; - if (val != 1000) { - wpa_printf(MSG_DEBUG, "DPP: Unexpected iterationCount %d", val); - return -1; - } - - if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0) - return -1; - if (val != 32 && val != 48 && val != 64) { - wpa_printf(MSG_DEBUG, "DPP: Unexpected keyLength %d", val); - return -1; - } - data->pbkdf2_key_len = val; - - if (asn1_get_sequence(pos, e_end - pos, &hdr, NULL) < 0 || - asn1_get_oid(hdr.payload, hdr.length, &oid, &pos) < 0) { - wpa_printf(MSG_DEBUG, "DPP: Could not parse prf"); - return -1; - } - if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha256_oid)) { - data->prf_hash_len = 32; - } else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha384_oid)) { - data->prf_hash_len = 48; - } else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha512_oid)) { - data->prf_hash_len = 64; - } else { - char buf[80]; - - asn1_oid_to_str(&oid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, "DPP: Unexpected PBKDF2-params.prf %s", - buf); - return -1; - } - - pos = next; - - /* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier - * - * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier - * - * id-alg-AES-SIV-CMAC-aed-256, id-alg-AES-SIV-CMAC-aed-384, or - * id-alg-AES-SIV-CMAC-aed-512. */ - if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0) - return -1; - if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) && - !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) && - !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) { - char buf[80]; - - asn1_oid_to_str(&oid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, - "DPP: Unexpected KeyEncryptionAlgorithmIdentifier %s", - buf); - return -1; - } - - /* - * encryptedKey EncryptedKey - * - * EncryptedKey ::= OCTET STRING - */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, - "DPP: Expected OCTETSTRING (pwri.encryptedKey) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: pwri.encryptedKey", - hdr.payload, hdr.length); - data->enc_key = hdr.payload; - data->enc_key_len = hdr.length; - - return 0; -} - - -static int dpp_parse_encrypted_content_info(const u8 *pos, const u8 *end, - struct dpp_enveloped_data *data) -{ - struct asn1_hdr hdr; - struct asn1_oid oid; - - /* - * EncryptedContentInfo ::= SEQUENCE { - * contentType ContentType, - * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, - * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL} - */ - if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) - return -1; - wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContentInfo", - hdr.payload, hdr.length); - if (pos < end) { - wpa_hexdump(MSG_DEBUG, - "DPP: Unexpected extra data after EncryptedContentInfo", - pos, end - pos); - return -1; - } - - end = pos; - pos = hdr.payload; - - /* ContentType ::= OBJECT IDENTIFIER */ - if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { - wpa_printf(MSG_DEBUG, "DPP: Could not parse ContentType"); - return -1; - } - if (!asn1_oid_equal(&oid, &asn1_dpp_asymmetric_key_package_oid)) { - char buf[80]; - - asn1_oid_to_str(&oid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, "DPP: Unexpected ContentType %s", buf); - return -1; - } - - /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */ - if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0) - return -1; - if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) && - !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) && - !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) { - char buf[80]; - - asn1_oid_to_str(&oid, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, - "DPP: Unexpected ContentEncryptionAlgorithmIdentifier %s", - buf); - return -1; - } - /* ignore optional parameters */ - - /* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL - * EncryptedContent ::= OCTET STRING */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Expected [0] IMPLICIT (EncryptedContent) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContent", - hdr.payload, hdr.length); - data->enc_cont = hdr.payload; - data->enc_cont_len = hdr.length; - return 0; -} - - -static int dpp_parse_enveloped_data(const u8 *env_data, size_t env_data_len, - struct dpp_enveloped_data *data) -{ - struct asn1_hdr hdr; - const u8 *pos, *end; - int val; - - os_memset(data, 0, sizeof(*data)); - - /* - * DPPEnvelopedData ::= EnvelopedData - * - * EnvelopedData ::= SEQUENCE { - * version CMSVersion, - * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, - * recipientInfos RecipientInfos, - * encryptedContentInfo EncryptedContentInfo, - * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL} - * - * CMSVersion ::= INTEGER - * - * RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo - * - * For DPP, version is 3, both originatorInfo and - * unprotectedAttrs are omitted, and recipientInfos contains a single - * RecipientInfo. - */ - if (asn1_get_sequence(env_data, env_data_len, &hdr, &end) < 0) - return -1; - pos = hdr.payload; - if (end < env_data + env_data_len) { - wpa_hexdump(MSG_DEBUG, - "DPP: Unexpected extra data after DPPEnvelopedData", - end, env_data + env_data_len - end); - return -1; - } - - if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) - return -1; - if (val != 3) { - wpa_printf(MSG_DEBUG, "DPP: EnvelopedData.version != 3"); - return -1; - } - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { - wpa_printf(MSG_DEBUG, - "DPP: Expected SET (RecipientInfos) - found class %d tag 0x%x", - hdr.class, hdr.tag); - return -1; - } - - if (dpp_parse_recipient_infos(hdr.payload, hdr.length, data) < 0) - return -1; - return dpp_parse_encrypted_content_info(hdr.payload + hdr.length, end, - data); -} - - -static struct dpp_asymmetric_key * -dpp_parse_one_asymmetric_key(const u8 *buf, size_t len) -{ - struct asn1_hdr hdr; - const u8 *pos = buf, *end = buf + len, *next; - int val; - const u8 *params; - size_t params_len; - struct asn1_oid oid; - char txt[80]; - struct dpp_asymmetric_key *key; - EC_KEY *eckey; - - wpa_hexdump_key(MSG_MSGDUMP, "DPP: OneAsymmetricKey", buf, len); - - key = os_zalloc(sizeof(*key)); - if (!key) + b64 = dpp_get_attr(attrs, attrs_len, DPP_ATTR_CSR_ATTR_REQ, &b64_len); + if (!b64) return NULL; - - /* - * OneAsymmetricKey ::= SEQUENCE { - * version Version, - * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, - * privateKey PrivateKey, - * attributes [0] Attributes OPTIONAL, - * ..., - * [[2: publicKey [1] BIT STRING OPTIONAL ]], - * ... - * } - */ - if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0) - goto fail; - pos = hdr.payload; - - /* Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2) */ - if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) - goto fail; - if (val != 1) { - wpa_printf(MSG_DEBUG, - "DPP: Unsupported DPPAsymmetricKeyPackage version %d", - val); - goto fail; - } - - /* PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier */ - if (asn1_get_alg_id(pos, end - pos, &oid, ¶ms, ¶ms_len, - &pos) < 0) - goto fail; - if (!asn1_oid_equal(&oid, &asn1_ec_public_key_oid)) { - asn1_oid_to_str(&oid, txt, sizeof(txt)); - wpa_printf(MSG_DEBUG, - "DPP: Unsupported PrivateKeyAlgorithmIdentifier %s", - txt); - goto fail; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: PrivateKeyAlgorithmIdentifier params", - params, params_len); - /* - * ECParameters ::= CHOICE { - * namedCurve OBJECT IDENTIFIER - * -- implicitCurve NULL - * -- specifiedCurve SpecifiedECDomain} - */ - if (!params || asn1_get_oid(params, params_len, &oid, &next) < 0) { - wpa_printf(MSG_DEBUG, - "DPP: Could not parse ECParameters.namedCurve"); - goto fail; - } - asn1_oid_to_str(&oid, txt, sizeof(txt)); - wpa_printf(MSG_MSGDUMP, "DPP: namedCurve %s", txt); - /* Assume the curve is identified within ECPrivateKey, so that this - * separate indication is not really needed. */ - - /* - * PrivateKey ::= OCTET STRING - * (Contains DER encoding of ECPrivateKey) - */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_OCTETSTRING) { - wpa_printf(MSG_DEBUG, - "DPP: Expected OCTETSTRING (PrivateKey) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto fail; - } - wpa_hexdump_key(MSG_MSGDUMP, "DPP: PrivateKey", - hdr.payload, hdr.length); - pos = hdr.payload + hdr.length; - eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length); - if (!eckey) { - wpa_printf(MSG_INFO, - "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - key->csign = EVP_PKEY_new(); - if (!key->csign || EVP_PKEY_assign_EC_KEY(key->csign, eckey) != 1) { - EC_KEY_free(eckey); - goto fail; - } - if (wpa_debug_show_keys) - dpp_debug_print_key("DPP: Received c-sign-key", key->csign); - - /* - * Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } - * - * Exactly one instance of type Attribute in OneAsymmetricKey. - */ - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Expected [0] Attributes - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto fail; - } - wpa_hexdump_key(MSG_MSGDUMP, "DPP: Attributes", - hdr.payload, hdr.length); - if (hdr.payload + hdr.length < end) { - wpa_hexdump_key(MSG_MSGDUMP, - "DPP: Ignore additional data at the end of OneAsymmetricKey", - hdr.payload + hdr.length, - end - (hdr.payload + hdr.length)); - } - pos = hdr.payload; - end = hdr.payload + hdr.length; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { - wpa_printf(MSG_DEBUG, - "DPP: Expected SET (Attributes) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto fail; - } - if (hdr.payload + hdr.length < end) { - wpa_hexdump_key(MSG_MSGDUMP, - "DPP: Ignore additional data at the end of OneAsymmetricKey (after SET)", - hdr.payload + hdr.length, - end - (hdr.payload + hdr.length)); - } - pos = hdr.payload; - end = hdr.payload + hdr.length; - - /* - * OneAsymmetricKeyAttributes ATTRIBUTE ::= { - * aa-DPPConfigurationParameters, - * ... -- For local profiles - * } - * - * aa-DPPConfigurationParameters ATTRIBUTE ::= - * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams } - * - * Attribute ::= SEQUENCE { - * type OBJECT IDENTIFIER, - * values SET SIZE(1..MAX) OF Type - * - * Exactly one instance of ATTRIBUTE in attrValues. - */ - if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) - goto fail; - if (pos < end) { - wpa_hexdump_key(MSG_MSGDUMP, - "DPP: Ignore additional data at the end of ATTRIBUTE", - pos, end - pos); - } - end = pos; - pos = hdr.payload; - - if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) - goto fail; - if (!asn1_oid_equal(&oid, &asn1_dpp_config_params_oid)) { - asn1_oid_to_str(&oid, txt, sizeof(txt)); - wpa_printf(MSG_DEBUG, - "DPP: Unexpected Attribute identifier %s", txt); - goto fail; - } - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { - wpa_printf(MSG_DEBUG, - "DPP: Expected SET (Attribute) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto fail; - } - pos = hdr.payload; - end = hdr.payload + hdr.length; - - /* - * DPPConfigurationParameters ::= SEQUENCE { - * configurationTemplate UTF8String, - * connectorTemplate UTF8String OPTIONAL} - */ - - wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPConfigurationParameters", - pos, end - pos); - if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) - goto fail; - if (pos < end) { - wpa_hexdump_key(MSG_MSGDUMP, - "DPP: Ignore additional data after DPPConfigurationParameters", - pos, end - pos); - } - end = pos; - pos = hdr.payload; - - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_UTF8STRING) { - wpa_printf(MSG_DEBUG, - "DPP: Expected UTF8STRING (configurationTemplate) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto fail; - } - wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: configurationTemplate", - hdr.payload, hdr.length); - key->config_template = os_zalloc(hdr.length + 1); - if (!key->config_template) - goto fail; - os_memcpy(key->config_template, hdr.payload, hdr.length); - - pos = hdr.payload + hdr.length; - - if (pos < end) { - if (asn1_get_next(pos, end - pos, &hdr) < 0 || - hdr.class != ASN1_CLASS_UNIVERSAL || - hdr.tag != ASN1_TAG_UTF8STRING) { - wpa_printf(MSG_DEBUG, - "DPP: Expected UTF8STRING (connectorTemplate) - found class %d tag 0x%x", - hdr.class, hdr.tag); - goto fail; - } - wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: connectorTemplate", - hdr.payload, hdr.length); - key->connector_template = os_zalloc(hdr.length + 1); - if (!key->connector_template) - goto fail; - os_memcpy(key->connector_template, hdr.payload, hdr.length); - } - - return key; -fail: - wpa_printf(MSG_DEBUG, "DPP: Failed to parse OneAsymmetricKey"); - dpp_free_asymmetric_key(key); - return NULL; + return base64_decode((const char *) b64, b64_len, len); } - - -static struct dpp_asymmetric_key * -dpp_parse_dpp_asymmetric_key_package(const u8 *key_pkg, size_t key_pkg_len) -{ - struct asn1_hdr hdr; - const u8 *pos = key_pkg, *end = key_pkg + key_pkg_len; - struct dpp_asymmetric_key *first = NULL, *last = NULL, *key; - - wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage", - key_pkg, key_pkg_len); - - /* - * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage - * - * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey - */ - while (pos < end) { - if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0 || - !(key = dpp_parse_one_asymmetric_key(hdr.payload, - hdr.length))) { - dpp_free_asymmetric_key(first); - return NULL; - } - if (!last) { - first = last = key; - } else { - last->next = key; - last = key; - } - } - - return first; -} - - -static int dpp_conf_resp_env_data(struct dpp_authentication *auth, - const u8 *env_data, size_t env_data_len) -{ - const u8 *key; - size_t key_len; - u8 kek[DPP_MAX_HASH_LEN]; - u8 cont_encr_key[DPP_MAX_HASH_LEN]; - size_t cont_encr_key_len; - int res; - u8 *key_pkg; - size_t key_pkg_len; - struct dpp_enveloped_data data; - struct dpp_asymmetric_key *keys; - - wpa_hexdump(MSG_DEBUG, "DPP: DPPEnvelopedData", env_data, env_data_len); - - if (dpp_parse_enveloped_data(env_data, env_data_len, &data) < 0) - return -1; - - /* TODO: For initial testing, use ke as the key. Replace this with a - * new key once that has been defined. */ - key = auth->ke; - key_len = auth->curve->hash_len; - wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len); - - if (dpp_pbkdf2(data.prf_hash_len, key, key_len, data.salt, 64, 1000, - kek, data.pbkdf2_key_len)) { - wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed"); - return -1; - } - wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2", - kek, data.pbkdf2_key_len); - - if (data.enc_key_len < AES_BLOCK_SIZE || - data.enc_key_len > sizeof(cont_encr_key) + AES_BLOCK_SIZE) { - wpa_printf(MSG_DEBUG, "DPP: Invalid encryptedKey length"); - return -1; - } - res = aes_siv_decrypt(kek, data.pbkdf2_key_len, - data.enc_key, data.enc_key_len, - 0, NULL, NULL, cont_encr_key); - forced_memzero(kek, data.pbkdf2_key_len); - if (res < 0) { - wpa_printf(MSG_DEBUG, - "DPP: AES-SIV decryption of encryptedKey failed"); - return -1; - } - cont_encr_key_len = data.enc_key_len - AES_BLOCK_SIZE; - wpa_hexdump_key(MSG_DEBUG, "DPP: content-encryption key", - cont_encr_key, cont_encr_key_len); - - if (data.enc_cont_len < AES_BLOCK_SIZE) - return -1; - key_pkg_len = data.enc_cont_len - AES_BLOCK_SIZE; - key_pkg = os_malloc(key_pkg_len); - if (!key_pkg) - return -1; - res = aes_siv_decrypt(cont_encr_key, cont_encr_key_len, - data.enc_cont, data.enc_cont_len, - 0, NULL, NULL, key_pkg); - forced_memzero(cont_encr_key, cont_encr_key_len); - if (res < 0) { - bin_clear_free(key_pkg, key_pkg_len); - wpa_printf(MSG_DEBUG, - "DPP: AES-SIV decryption of encryptedContent failed"); - return -1; - } - - keys = dpp_parse_dpp_asymmetric_key_package(key_pkg, key_pkg_len); - bin_clear_free(key_pkg, key_pkg_len); - dpp_free_asymmetric_key(auth->conf_key_pkg); - auth->conf_key_pkg = keys; - - return keys != NULL;; -} - #endif /* CONFIG_DPP2 */ @@ -7689,6 +2951,28 @@ int dpp_conf_resp_rx(struct dpp_authentication *auth, } auth->conf_resp_status = status[0]; wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); +#ifdef CONFIG_DPP2 + if (status[0] == DPP_STATUS_CSR_NEEDED) { + u8 *csrattrs; + size_t csrattrs_len; + + wpa_printf(MSG_DEBUG, "DPP: Configurator requested CSR"); + + csrattrs = dpp_get_csr_attrs(unwrapped, unwrapped_len, + &csrattrs_len); + if (!csrattrs) { + dpp_auth_fail(auth, + "Missing or invalid CSR Attributes Request attribute"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: CsrAttrs", csrattrs, csrattrs_len); + os_free(auth->csrattrs); + auth->csrattrs = csrattrs; + auth->csrattrs_len = csrattrs_len; + ret = -2; + goto fail; + } +#endif /* CONFIG_DPP2 */ if (status[0] != DPP_STATUS_OK) { dpp_auth_fail(auth, "Configurator rejected configuration"); goto fail; @@ -8007,6 +3291,36 @@ fail: } +struct wpabuf * dpp_build_conn_status(enum dpp_status_error result, + const u8 *ssid, size_t ssid_len, + const char *channel_list) +{ + struct wpabuf *json; + + json = wpabuf_alloc(1000); + if (!json) + return NULL; + json_start_object(json, NULL); + json_add_int(json, "result", result); + if (ssid) { + json_value_sep(json); + if (json_add_base64url(json, "ssid64", ssid, ssid_len) < 0) { + wpabuf_free(json); + return NULL; + } + } + if (channel_list) { + json_value_sep(json); + json_add_string(json, "channelList", channel_list); + } + json_end_object(json); + wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON", + wpabuf_head(json), wpabuf_len(json)); + + return json; +} + + struct wpabuf * dpp_build_conn_status_result(struct dpp_authentication *auth, enum dpp_status_error result, const u8 *ssid, size_t ssid_len, @@ -8018,23 +3332,9 @@ struct wpabuf * dpp_build_conn_status_result(struct dpp_authentication *auth, size_t len[2]; u8 *wrapped; - json = wpabuf_alloc(1000); + json = dpp_build_conn_status(result, ssid, ssid_len, channel_list); if (!json) return NULL; - json_start_object(json, NULL); - json_add_int(json, "result", result); - if (ssid) { - json_value_sep(json); - if (json_add_base64url(json, "ssid64", ssid, ssid_len) < 0) - goto fail; - } - if (channel_list) { - json_value_sep(json); - json_add_string(json, "channelList", channel_list); - } - json_end_object(json); - wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus JSON", - wpabuf_head(json), wpabuf_len(json)); nonce_len = auth->curve->nonce_len; clear_len = 5 + 4 + nonce_len + 4 + wpabuf_len(json); @@ -8096,6 +3396,9 @@ void dpp_configurator_free(struct dpp_configurator *conf) return; EVP_PKEY_free(conf->csign); os_free(conf->kid); + os_free(conf->connector); + EVP_PKEY_free(conf->connector_key); + EVP_PKEY_free(conf->pp_key); os_free(conf); } @@ -8127,7 +3430,6 @@ int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf, static int dpp_configurator_gen_kid(struct dpp_configurator *conf) { struct wpabuf *csign_pub = NULL; - u8 kid_hash[SHA256_MAC_LEN]; const u8 *addr[1]; size_t len[1]; int res; @@ -8141,7 +3443,7 @@ static int dpp_configurator_gen_kid(struct dpp_configurator *conf) /* kid = SHA256(ANSI X9.63 uncompressed C-sign-key) */ addr[0] = wpabuf_head(csign_pub); len[0] = wpabuf_len(csign_pub); - res = sha256_vector(1, addr, len, kid_hash); + res = sha256_vector(1, addr, len, conf->kid_hash); wpabuf_free(csign_pub); if (res < 0) { wpa_printf(MSG_DEBUG, @@ -8149,14 +3451,15 @@ static int dpp_configurator_gen_kid(struct dpp_configurator *conf) return -1; } - conf->kid = base64_url_encode(kid_hash, sizeof(kid_hash), NULL); + conf->kid = base64_url_encode(conf->kid_hash, sizeof(conf->kid_hash), + NULL); return conf->kid ? 0 : -1; } -struct dpp_configurator * +static struct dpp_configurator * dpp_keygen_configurator(const char *curve, const u8 *privkey, - size_t privkey_len) + size_t privkey_len, const u8 *pp_key, size_t pp_key_len) { struct dpp_configurator *conf; @@ -8164,23 +3467,24 @@ dpp_keygen_configurator(const char *curve, const u8 *privkey, if (!conf) return NULL; - if (!curve) { - conf->curve = &dpp_curves[0]; - } else { - conf->curve = dpp_get_curve_name(curve); - if (!conf->curve) { - wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", - curve); - os_free(conf); - return NULL; - } + conf->curve = dpp_get_curve_name(curve); + if (!conf->curve) { + wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve); + os_free(conf); + return NULL; } + if (privkey) conf->csign = dpp_set_keypair(&conf->curve, privkey, privkey_len); else conf->csign = dpp_gen_keypair(conf->curve); - if (!conf->csign) + if (pp_key) + conf->pp_key = dpp_set_keypair(&conf->curve, pp_key, + pp_key_len); + else + conf->pp_key = dpp_gen_keypair(conf->curve); + if (!conf->csign || !conf->pp_key) goto fail; conf->own = 1; @@ -8204,16 +3508,12 @@ int dpp_configurator_own_config(struct dpp_authentication *auth, return -1; } - if (!curve) { - auth->curve = &dpp_curves[0]; - } else { - auth->curve = dpp_get_curve_name(curve); - if (!auth->curve) { - wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", - curve); - return -1; - } + auth->curve = dpp_get_curve_name(curve); + if (!auth->curve) { + wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve); + return -1; } + wpa_printf(MSG_DEBUG, "DPP: Building own configuration/connector with curve %s", auth->curve->name); @@ -8225,7 +3525,7 @@ int dpp_configurator_own_config(struct dpp_authentication *auth, auth->peer_protocol_key = auth->own_protocol_key; dpp_copy_csign(&auth->conf_obj[0], auth->conf->csign); - conf_obj = dpp_build_conf_obj(auth, ap, 0); + conf_obj = dpp_build_conf_obj(auth, ap, 0, NULL); if (!conf_obj) { wpabuf_free(auth->conf_obj[0].c_sign_key); auth->conf_obj[0].c_sign_key = NULL; @@ -8249,7 +3549,8 @@ static int dpp_compatible_netrole(const char *role1, const char *role2) static int dpp_connector_compatible_group(struct json_token *root, const char *group_id, - const char *net_role) + const char *net_role, + bool reconfig) { struct json_token *groups, *token; @@ -8273,7 +3574,9 @@ static int dpp_connector_compatible_group(struct json_token *root, os_strcmp(id->string, group_id) != 0) continue; - if (dpp_compatible_netrole(role->string, net_role)) + if (reconfig && os_strcmp(net_role, "configurator") == 0) + return 1; + if (!reconfig && dpp_compatible_netrole(role->string, net_role)) return 1; } @@ -8281,8 +3584,8 @@ static int dpp_connector_compatible_group(struct json_token *root, } -static int dpp_connector_match_groups(struct json_token *own_root, - struct json_token *peer_root) +int dpp_connector_match_groups(struct json_token *own_root, + struct json_token *peer_root, bool reconfig) { struct json_token *groups, *token; @@ -8312,7 +3615,7 @@ static int dpp_connector_match_groups(struct json_token *own_root, "DPP: peer connector group: groupId='%s' netRole='%s'", id->string, role->string); if (dpp_connector_compatible_group(own_root, id->string, - role->string)) { + role->string, reconfig)) { wpa_printf(MSG_DEBUG, "DPP: Compatible group/netRole in own connector"); return 1; @@ -8323,71 +3626,37 @@ static int dpp_connector_match_groups(struct json_token *own_root, } -static int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, - unsigned int hash_len) +struct json_token * dpp_parse_own_connector(const char *own_connector) { - u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; - const char *info = "DPP PMK"; - int res; + unsigned char *own_conn; + size_t own_conn_len; + const char *pos, *end; + struct json_token *own_root; - /* PMK = HKDF(<>, "DPP PMK", N.x) */ - - /* HKDF-Extract(<>, N.x) */ - os_memset(salt, 0, hash_len); - if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", - prk, hash_len); - - /* HKDF-Expand(PRK, info, L) */ - res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len); - os_memset(prk, 0, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)", - pmk, hash_len); - return 0; -} - - -static int dpp_derive_pmkid(const struct dpp_curve_params *curve, - EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid) -{ - struct wpabuf *nkx, *pkx; - int ret = -1, res; - const u8 *addr[2]; - size_t len[2]; - u8 hash[SHA256_MAC_LEN]; - - /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */ - nkx = dpp_get_pubkey_point(own_key, 0); - pkx = dpp_get_pubkey_point(peer_key, 0); - if (!nkx || !pkx) - goto fail; - addr[0] = wpabuf_head(nkx); - len[0] = wpabuf_len(nkx) / 2; - addr[1] = wpabuf_head(pkx); - len[1] = wpabuf_len(pkx) / 2; - if (len[0] != len[1]) - goto fail; - if (os_memcmp(addr[0], addr[1], len[0]) > 0) { - addr[0] = wpabuf_head(pkx); - addr[1] = wpabuf_head(nkx); + pos = os_strchr(own_connector, '.'); + if (!pos) { + wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)"); + return NULL; } - wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]); - res = sha256_vector(2, addr, len, hash); - if (res < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN); - os_memcpy(pmkid, hash, PMKID_LEN); - wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN); - ret = 0; -fail: - wpabuf_free(nkx); - wpabuf_free(pkx); - return ret; + pos++; + end = os_strchr(pos, '.'); + if (!end) { + wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)"); + return NULL; + } + own_conn = base64_url_decode(pos, end - pos, &own_conn_len); + if (!own_conn) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to base64url decode own signedConnector JWS Payload"); + return NULL; + } + + own_root = json_parse((const char *) own_conn, own_conn_len); + os_free(own_conn); + if (!own_root) + wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector"); + + return own_root; } @@ -8405,12 +3674,6 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, struct wpabuf *own_key_pub = NULL; const struct dpp_curve_params *curve, *own_curve; struct dpp_signed_connector_info info; - const unsigned char *p; - EVP_PKEY *csign = NULL; - char *signed_connector = NULL; - const char *pos, *end; - unsigned char *own_conn = NULL; - size_t own_conn_len; size_t Nx_len; u8 Nx[DPP_MAX_SHARED_SECRET_LEN]; @@ -8419,14 +3682,6 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, if (expiry) *expiry = 0; - p = csign_key; - csign = d2i_PUBKEY(NULL, &p, csign_key_len); - if (!csign) { - wpa_printf(MSG_ERROR, - "DPP: Failed to parse local C-sign-key information"); - goto fail; - } - own_key = dpp_set_keypair(&own_curve, net_access_key, net_access_key_len); if (!own_key) { @@ -8434,39 +3689,12 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, goto fail; } - pos = os_strchr(own_connector, '.'); - if (!pos) { - wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)"); + own_root = dpp_parse_own_connector(own_connector); + if (!own_root) goto fail; - } - pos++; - end = os_strchr(pos, '.'); - if (!end) { - wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)"); - goto fail; - } - own_conn = base64_url_decode(pos, end - pos, &own_conn_len); - if (!own_conn) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode own signedConnector JWS Payload"); - goto fail; - } - own_root = json_parse((const char *) own_conn, own_conn_len); - if (!own_root) { - wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector"); - goto fail; - } - - wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector", - peer_connector, peer_connector_len); - signed_connector = os_malloc(peer_connector_len + 1); - if (!signed_connector) - goto fail; - os_memcpy(signed_connector, peer_connector, peer_connector_len); - signed_connector[peer_connector_len] = '\0'; - - res = dpp_process_signed_connector(&info, csign, signed_connector); + res = dpp_check_signed_connector(&info, csign_key, csign_key_len, + peer_connector, peer_connector_len); if (res != DPP_STATUS_OK) { ret = res; goto fail; @@ -8479,7 +3707,7 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, goto fail; } - if (!dpp_connector_match_groups(own_root, root)) { + if (!dpp_connector_match_groups(own_root, root, false)) { wpa_printf(MSG_DEBUG, "DPP: Peer connector does not include compatible group netrole with own connector"); ret = DPP_STATUS_NO_MATCH; @@ -8547,1751 +3775,17 @@ fail: if (ret != DPP_STATUS_OK) os_memset(intro, 0, sizeof(*intro)); os_memset(Nx, 0, sizeof(Nx)); - os_free(own_conn); - os_free(signed_connector); os_free(info.payload); EVP_PKEY_free(own_key); wpabuf_free(own_key_pub); EVP_PKEY_free(peer_key); - EVP_PKEY_free(csign); json_free(root); json_free(own_root); return ret; } -static EVP_PKEY * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, - int init) -{ - EC_GROUP *group; - size_t len = curve->prime_len; - const u8 *x, *y; - EVP_PKEY *res; - - switch (curve->ike_group) { - case 19: - x = init ? pkex_init_x_p256 : pkex_resp_x_p256; - y = init ? pkex_init_y_p256 : pkex_resp_y_p256; - break; - case 20: - x = init ? pkex_init_x_p384 : pkex_resp_x_p384; - y = init ? pkex_init_y_p384 : pkex_resp_y_p384; - break; - case 21: - x = init ? pkex_init_x_p521 : pkex_resp_x_p521; - y = init ? pkex_init_y_p521 : pkex_resp_y_p521; - break; - case 28: - x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1; - y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1; - break; - case 29: - x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1; - y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1; - break; - case 30: - x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1; - y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1; - break; - default: - return NULL; - } - - group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); - if (!group) - return NULL; - res = dpp_set_pubkey_point_group(group, x, y, len); - EC_GROUP_free(group); - return res; -} - - -static EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, - const u8 *mac_init, const char *code, - const char *identifier, BN_CTX *bnctx, - EC_GROUP **ret_group) -{ - u8 hash[DPP_MAX_HASH_LEN]; - const u8 *addr[3]; - size_t len[3]; - unsigned int num_elem = 0; - EC_POINT *Qi = NULL; - EVP_PKEY *Pi = NULL; - EC_KEY *Pi_ec = NULL; - const EC_POINT *Pi_point; - BIGNUM *hash_bn = NULL; - const EC_GROUP *group = NULL; - EC_GROUP *group2 = NULL; - - /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ - - wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init)); - addr[num_elem] = mac_init; - len[num_elem] = ETH_ALEN; - num_elem++; - if (identifier) { - wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", - identifier); - addr[num_elem] = (const u8 *) identifier; - len[num_elem] = os_strlen(identifier); - num_elem++; - } - wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); - addr[num_elem] = (const u8 *) code; - len[num_elem] = os_strlen(code); - num_elem++; - if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) - goto fail; - wpa_hexdump_key(MSG_DEBUG, - "DPP: H(MAC-Initiator | [identifier |] code)", - hash, curve->hash_len); - Pi = dpp_pkex_get_role_elem(curve, 1); - if (!Pi) - goto fail; - dpp_debug_print_key("DPP: Pi", Pi); - Pi_ec = EVP_PKEY_get1_EC_KEY(Pi); - if (!Pi_ec) - goto fail; - Pi_point = EC_KEY_get0_public_key(Pi_ec); - - group = EC_KEY_get0_group(Pi_ec); - if (!group) - goto fail; - group2 = EC_GROUP_dup(group); - if (!group2) - goto fail; - Qi = EC_POINT_new(group2); - if (!Qi) { - EC_GROUP_free(group2); - goto fail; - } - hash_bn = BN_bin2bn(hash, curve->hash_len, NULL); - if (!hash_bn || - EC_POINT_mul(group2, Qi, NULL, Pi_point, hash_bn, bnctx) != 1) - goto fail; - if (EC_POINT_is_at_infinity(group, Qi)) { - wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity"); - goto fail; - } - dpp_debug_print_point("DPP: Qi", group, Qi); -out: - EC_KEY_free(Pi_ec); - EVP_PKEY_free(Pi); - BN_clear_free(hash_bn); - if (ret_group && Qi) - *ret_group = group2; - else - EC_GROUP_free(group2); - return Qi; -fail: - EC_POINT_free(Qi); - Qi = NULL; - goto out; -} - - -static EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, - const u8 *mac_resp, const char *code, - const char *identifier, BN_CTX *bnctx, - EC_GROUP **ret_group) -{ - u8 hash[DPP_MAX_HASH_LEN]; - const u8 *addr[3]; - size_t len[3]; - unsigned int num_elem = 0; - EC_POINT *Qr = NULL; - EVP_PKEY *Pr = NULL; - EC_KEY *Pr_ec = NULL; - const EC_POINT *Pr_point; - BIGNUM *hash_bn = NULL; - const EC_GROUP *group = NULL; - EC_GROUP *group2 = NULL; - - /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */ - - wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp)); - addr[num_elem] = mac_resp; - len[num_elem] = ETH_ALEN; - num_elem++; - if (identifier) { - wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", - identifier); - addr[num_elem] = (const u8 *) identifier; - len[num_elem] = os_strlen(identifier); - num_elem++; - } - wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); - addr[num_elem] = (const u8 *) code; - len[num_elem] = os_strlen(code); - num_elem++; - if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) - goto fail; - wpa_hexdump_key(MSG_DEBUG, - "DPP: H(MAC-Responder | [identifier |] code)", - hash, curve->hash_len); - Pr = dpp_pkex_get_role_elem(curve, 0); - if (!Pr) - goto fail; - dpp_debug_print_key("DPP: Pr", Pr); - Pr_ec = EVP_PKEY_get1_EC_KEY(Pr); - if (!Pr_ec) - goto fail; - Pr_point = EC_KEY_get0_public_key(Pr_ec); - - group = EC_KEY_get0_group(Pr_ec); - if (!group) - goto fail; - group2 = EC_GROUP_dup(group); - if (!group2) - goto fail; - Qr = EC_POINT_new(group2); - if (!Qr) { - EC_GROUP_free(group2); - goto fail; - } - hash_bn = BN_bin2bn(hash, curve->hash_len, NULL); - if (!hash_bn || - EC_POINT_mul(group2, Qr, NULL, Pr_point, hash_bn, bnctx) != 1) - goto fail; - if (EC_POINT_is_at_infinity(group, Qr)) { - wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity"); - goto fail; - } - dpp_debug_print_point("DPP: Qr", group, Qr); -out: - EC_KEY_free(Pr_ec); - EVP_PKEY_free(Pr); - BN_clear_free(hash_bn); - if (ret_group && Qr) - *ret_group = group2; - else - EC_GROUP_free(group2); - return Qr; -fail: - EC_POINT_free(Qr); - Qr = NULL; - goto out; -} - - -#ifdef CONFIG_TESTING_OPTIONS -static int dpp_test_gen_invalid_key(struct wpabuf *msg, - const struct dpp_curve_params *curve) -{ - BN_CTX *ctx; - BIGNUM *x, *y; - int ret = -1; - EC_GROUP *group; - EC_POINT *point; - - group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); - if (!group) - return -1; - - ctx = BN_CTX_new(); - point = EC_POINT_new(group); - x = BN_new(); - y = BN_new(); - if (!ctx || !point || !x || !y) - goto fail; - - if (BN_rand(x, curve->prime_len * 8, 0, 0) != 1) - goto fail; - - /* Generate a random y coordinate that results in a point that is not - * on the curve. */ - for (;;) { - if (BN_rand(y, curve->prime_len * 8, 0, 0) != 1) - goto fail; - - if (EC_POINT_set_affine_coordinates_GFp(group, point, x, y, - ctx) != 1) { -#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL) - /* Unlike older OpenSSL versions, OpenSSL 1.1.1 and BoringSSL - * return an error from EC_POINT_set_affine_coordinates_GFp() - * when the point is not on the curve. */ - break; -#else /* >=1.1.0 or OPENSSL_IS_BORINGSSL */ - goto fail; -#endif /* >= 1.1.0 or OPENSSL_IS_BORINGSSL */ - } - - if (!EC_POINT_is_on_curve(group, point, ctx)) - break; - } - - if (dpp_bn2bin_pad(x, wpabuf_put(msg, curve->prime_len), - curve->prime_len) < 0 || - dpp_bn2bin_pad(y, wpabuf_put(msg, curve->prime_len), - curve->prime_len) < 0) - goto fail; - - ret = 0; -fail: - if (ret < 0) - wpa_printf(MSG_INFO, "DPP: Failed to generate invalid key"); - BN_free(x); - BN_free(y); - EC_POINT_free(point); - BN_CTX_free(ctx); - EC_GROUP_free(group); - - return ret; -} -#endif /* CONFIG_TESTING_OPTIONS */ - - -static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex) -{ - EC_KEY *X_ec = NULL; - const EC_POINT *X_point; - BN_CTX *bnctx = NULL; - EC_GROUP *group = NULL; - EC_POINT *Qi = NULL, *M = NULL; - struct wpabuf *M_buf = NULL; - BIGNUM *Mx = NULL, *My = NULL; - struct wpabuf *msg = NULL; - size_t attr_len; - const struct dpp_curve_params *curve = pkex->own_bi->curve; - - wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request"); - - /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ - bnctx = BN_CTX_new(); - if (!bnctx) - goto fail; - Qi = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code, - pkex->identifier, bnctx, &group); - if (!Qi) - goto fail; - - /* Generate a random ephemeral keypair x/X */ -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_pkex_ephemeral_key_override_len) { - const struct dpp_curve_params *tmp_curve; - - wpa_printf(MSG_INFO, - "DPP: TESTING - override ephemeral key x/X"); - pkex->x = dpp_set_keypair(&tmp_curve, - dpp_pkex_ephemeral_key_override, - dpp_pkex_ephemeral_key_override_len); - } else { - pkex->x = dpp_gen_keypair(curve); - } -#else /* CONFIG_TESTING_OPTIONS */ - pkex->x = dpp_gen_keypair(curve); -#endif /* CONFIG_TESTING_OPTIONS */ - if (!pkex->x) - goto fail; - - /* M = X + Qi */ - X_ec = EVP_PKEY_get1_EC_KEY(pkex->x); - if (!X_ec) - goto fail; - X_point = EC_KEY_get0_public_key(X_ec); - if (!X_point) - goto fail; - dpp_debug_print_point("DPP: X", group, X_point); - M = EC_POINT_new(group); - Mx = BN_new(); - My = BN_new(); - if (!M || !Mx || !My || - EC_POINT_add(group, M, X_point, Qi, bnctx) != 1 || - EC_POINT_get_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1) - goto fail; - dpp_debug_print_point("DPP: M", group, M); - - /* Initiator -> Responder: group, [identifier,] M */ - attr_len = 4 + 2; - if (pkex->identifier) - attr_len += 4 + os_strlen(pkex->identifier); - attr_len += 4 + 2 * curve->prime_len; - msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_REQ, attr_len); - if (!msg) - goto fail; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Finite Cyclic Group"); - goto skip_finite_cyclic_group; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* Finite Cyclic Group attribute */ - wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP); - wpabuf_put_le16(msg, 2); - wpabuf_put_le16(msg, curve->ike_group); - -#ifdef CONFIG_TESTING_OPTIONS -skip_finite_cyclic_group: -#endif /* CONFIG_TESTING_OPTIONS */ - - /* Code Identifier attribute */ - if (pkex->identifier) { - wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER); - wpabuf_put_le16(msg, os_strlen(pkex->identifier)); - wpabuf_put_str(msg, pkex->identifier); - } - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key"); - goto out; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* M in Encrypted Key attribute */ - wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY); - wpabuf_put_le16(msg, 2 * curve->prime_len); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key"); - if (dpp_test_gen_invalid_key(msg, curve) < 0) - goto fail; - goto out; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (dpp_bn2bin_pad(Mx, wpabuf_put(msg, curve->prime_len), - curve->prime_len) < 0 || - dpp_bn2bin_pad(Mx, pkex->Mx, curve->prime_len) < 0 || - dpp_bn2bin_pad(My, wpabuf_put(msg, curve->prime_len), - curve->prime_len) < 0) - goto fail; - -out: - wpabuf_free(M_buf); - EC_KEY_free(X_ec); - EC_POINT_free(M); - EC_POINT_free(Qi); - BN_clear_free(Mx); - BN_clear_free(My); - BN_CTX_free(bnctx); - EC_GROUP_free(group); - return msg; -fail: - wpa_printf(MSG_INFO, "DPP: Failed to build PKEX Exchange Request"); - wpabuf_free(msg); - msg = NULL; - goto out; -} - - -static void dpp_pkex_fail(struct dpp_pkex *pkex, const char *txt) -{ - wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt); -} - - -struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi, - const u8 *own_mac, - const char *identifier, - const char *code) -{ - struct dpp_pkex *pkex; - -#ifdef CONFIG_TESTING_OPTIONS - if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) { - wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR, - MAC2STR(dpp_pkex_own_mac_override)); - own_mac = dpp_pkex_own_mac_override; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - pkex = os_zalloc(sizeof(*pkex)); - if (!pkex) - return NULL; - pkex->msg_ctx = msg_ctx; - pkex->initiator = 1; - pkex->own_bi = bi; - os_memcpy(pkex->own_mac, own_mac, ETH_ALEN); - if (identifier) { - pkex->identifier = os_strdup(identifier); - if (!pkex->identifier) - goto fail; - } - pkex->code = os_strdup(code); - if (!pkex->code) - goto fail; - pkex->exchange_req = dpp_pkex_build_exchange_req(pkex); - if (!pkex->exchange_req) - goto fail; - return pkex; -fail: - dpp_pkex_free(pkex); - return NULL; -} - - -static struct wpabuf * -dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex, - enum dpp_status_error status, - const BIGNUM *Nx, const BIGNUM *Ny) -{ - struct wpabuf *msg = NULL; - size_t attr_len; - const struct dpp_curve_params *curve = pkex->own_bi->curve; - - /* Initiator -> Responder: DPP Status, [identifier,] N */ - attr_len = 4 + 1; - if (pkex->identifier) - attr_len += 4 + os_strlen(pkex->identifier); - attr_len += 4 + 2 * curve->prime_len; - msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_RESP, attr_len); - if (!msg) - goto fail; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_STATUS_PKEX_EXCHANGE_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); - goto skip_status; - } - - if (dpp_test == DPP_TEST_INVALID_STATUS_PKEX_EXCHANGE_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); - status = 255; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* DPP Status */ - dpp_build_attr_status(msg, status); - -#ifdef CONFIG_TESTING_OPTIONS -skip_status: -#endif /* CONFIG_TESTING_OPTIONS */ - - /* Code Identifier attribute */ - if (pkex->identifier) { - wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER); - wpabuf_put_le16(msg, os_strlen(pkex->identifier)); - wpabuf_put_str(msg, pkex->identifier); - } - - if (status != DPP_STATUS_OK) - goto skip_encrypted_key; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key"); - goto skip_encrypted_key; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* N in Encrypted Key attribute */ - wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY); - wpabuf_put_le16(msg, 2 * curve->prime_len); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key"); - if (dpp_test_gen_invalid_key(msg, curve) < 0) - goto fail; - goto skip_encrypted_key; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (dpp_bn2bin_pad(Nx, wpabuf_put(msg, curve->prime_len), - curve->prime_len) < 0 || - dpp_bn2bin_pad(Nx, pkex->Nx, curve->prime_len) < 0 || - dpp_bn2bin_pad(Ny, wpabuf_put(msg, curve->prime_len), - curve->prime_len) < 0) - goto fail; - -skip_encrypted_key: - if (status == DPP_STATUS_BAD_GROUP) { - /* Finite Cyclic Group attribute */ - wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP); - wpabuf_put_le16(msg, 2); - wpabuf_put_le16(msg, curve->ike_group); - } - - return msg; -fail: - wpabuf_free(msg); - return NULL; -} - - -static int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp, - const u8 *Mx, size_t Mx_len, - const u8 *Nx, size_t Nx_len, - const char *code, - const u8 *Kx, size_t Kx_len, - u8 *z, unsigned int hash_len) -{ - u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; - int res; - u8 *info, *pos; - size_t info_len; - - /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) - */ - - /* HKDF-Extract(<>, IKM=K.x) */ - os_memset(salt, 0, hash_len); - if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", - prk, hash_len); - info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code); - info = os_malloc(info_len); - if (!info) - return -1; - pos = info; - os_memcpy(pos, mac_init, ETH_ALEN); - pos += ETH_ALEN; - os_memcpy(pos, mac_resp, ETH_ALEN); - pos += ETH_ALEN; - os_memcpy(pos, Mx, Mx_len); - pos += Mx_len; - os_memcpy(pos, Nx, Nx_len); - pos += Nx_len; - os_memcpy(pos, code, os_strlen(code)); - - /* HKDF-Expand(PRK, info, L) */ - if (hash_len == 32) - res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len, - z, hash_len); - else if (hash_len == 48) - res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len, - z, hash_len); - else if (hash_len == 64) - res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len, - z, hash_len); - else - res = -1; - os_free(info); - os_memset(prk, 0, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)", - z, hash_len); - return 0; -} - - -static int dpp_pkex_identifier_match(const u8 *attr_id, u16 attr_id_len, - const char *identifier) -{ - if (!attr_id && identifier) { - wpa_printf(MSG_DEBUG, - "DPP: No PKEX code identifier received, but expected one"); - return 0; - } - - if (attr_id && !identifier) { - wpa_printf(MSG_DEBUG, - "DPP: PKEX code identifier received, but not expecting one"); - return 0; - } - - if (attr_id && identifier && - (os_strlen(identifier) != attr_id_len || - os_memcmp(identifier, attr_id, attr_id_len) != 0)) { - wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch"); - return 0; - } - - return 1; -} - - -struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx, - struct dpp_bootstrap_info *bi, - const u8 *own_mac, - const u8 *peer_mac, - const char *identifier, - const char *code, - const u8 *buf, size_t len) -{ - const u8 *attr_group, *attr_id, *attr_key; - u16 attr_group_len, attr_id_len, attr_key_len; - const struct dpp_curve_params *curve = bi->curve; - u16 ike_group; - struct dpp_pkex *pkex = NULL; - EC_POINT *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL, *N = NULL; - BN_CTX *bnctx = NULL; - EC_GROUP *group = NULL; - BIGNUM *Mx = NULL, *My = NULL; - EC_KEY *Y_ec = NULL, *X_ec = NULL;; - const EC_POINT *Y_point; - BIGNUM *Nx = NULL, *Ny = NULL; - u8 Kx[DPP_MAX_SHARED_SECRET_LEN]; - size_t Kx_len; - int res; - - if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) { - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "PKEX counter t limit reached - ignore message"); - return NULL; - } - -#ifdef CONFIG_TESTING_OPTIONS - if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) { - wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR, - MAC2STR(dpp_pkex_peer_mac_override)); - peer_mac = dpp_pkex_peer_mac_override; - } - if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) { - wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR, - MAC2STR(dpp_pkex_own_mac_override)); - own_mac = dpp_pkex_own_mac_override; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - attr_id_len = 0; - attr_id = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER, - &attr_id_len); - if (!dpp_pkex_identifier_match(attr_id, attr_id_len, identifier)) - return NULL; - - attr_group = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, - &attr_group_len); - if (!attr_group || attr_group_len != 2) { - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Missing or invalid Finite Cyclic Group attribute"); - return NULL; - } - ike_group = WPA_GET_LE16(attr_group); - if (ike_group != curve->ike_group) { - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Mismatching PKEX curve: peer=%u own=%u", - ike_group, curve->ike_group); - pkex = os_zalloc(sizeof(*pkex)); - if (!pkex) - goto fail; - pkex->own_bi = bi; - pkex->failed = 1; - pkex->exchange_resp = dpp_pkex_build_exchange_resp( - pkex, DPP_STATUS_BAD_GROUP, NULL, NULL); - if (!pkex->exchange_resp) - goto fail; - return pkex; - } - - /* M in Encrypted Key attribute */ - attr_key = dpp_get_attr(buf, len, DPP_ATTR_ENCRYPTED_KEY, - &attr_key_len); - if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2 || - attr_key_len / 2 > DPP_MAX_SHARED_SECRET_LEN) { - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Missing Encrypted Key attribute"); - return NULL; - } - - /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ - bnctx = BN_CTX_new(); - if (!bnctx) - goto fail; - Qi = dpp_pkex_derive_Qi(curve, peer_mac, code, identifier, bnctx, - &group); - if (!Qi) - goto fail; - - /* X' = M - Qi */ - X = EC_POINT_new(group); - M = EC_POINT_new(group); - Mx = BN_bin2bn(attr_key, attr_key_len / 2, NULL); - My = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL); - if (!X || !M || !Mx || !My || - EC_POINT_set_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1 || - EC_POINT_is_at_infinity(group, M) || - !EC_POINT_is_on_curve(group, M, bnctx) || - EC_POINT_invert(group, Qi, bnctx) != 1 || - EC_POINT_add(group, X, M, Qi, bnctx) != 1 || - EC_POINT_is_at_infinity(group, X) || - !EC_POINT_is_on_curve(group, X, bnctx)) { - wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Invalid Encrypted Key value"); - bi->pkex_t++; - goto fail; - } - dpp_debug_print_point("DPP: M", group, M); - dpp_debug_print_point("DPP: X'", group, X); - - pkex = os_zalloc(sizeof(*pkex)); - if (!pkex) - goto fail; - pkex->t = bi->pkex_t; - pkex->msg_ctx = msg_ctx; - pkex->own_bi = bi; - os_memcpy(pkex->own_mac, own_mac, ETH_ALEN); - os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); - if (identifier) { - pkex->identifier = os_strdup(identifier); - if (!pkex->identifier) - goto fail; - } - pkex->code = os_strdup(code); - if (!pkex->code) - goto fail; - - os_memcpy(pkex->Mx, attr_key, attr_key_len / 2); - - X_ec = EC_KEY_new(); - if (!X_ec || - EC_KEY_set_group(X_ec, group) != 1 || - EC_KEY_set_public_key(X_ec, X) != 1) - goto fail; - pkex->x = EVP_PKEY_new(); - if (!pkex->x || - EVP_PKEY_set1_EC_KEY(pkex->x, X_ec) != 1) - goto fail; - - /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */ - Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, bnctx, NULL); - if (!Qr) - goto fail; - - /* Generate a random ephemeral keypair y/Y */ -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_pkex_ephemeral_key_override_len) { - const struct dpp_curve_params *tmp_curve; - - wpa_printf(MSG_INFO, - "DPP: TESTING - override ephemeral key y/Y"); - pkex->y = dpp_set_keypair(&tmp_curve, - dpp_pkex_ephemeral_key_override, - dpp_pkex_ephemeral_key_override_len); - } else { - pkex->y = dpp_gen_keypair(curve); - } -#else /* CONFIG_TESTING_OPTIONS */ - pkex->y = dpp_gen_keypair(curve); -#endif /* CONFIG_TESTING_OPTIONS */ - if (!pkex->y) - goto fail; - - /* N = Y + Qr */ - Y_ec = EVP_PKEY_get1_EC_KEY(pkex->y); - if (!Y_ec) - goto fail; - Y_point = EC_KEY_get0_public_key(Y_ec); - if (!Y_point) - goto fail; - dpp_debug_print_point("DPP: Y", group, Y_point); - N = EC_POINT_new(group); - Nx = BN_new(); - Ny = BN_new(); - if (!N || !Nx || !Ny || - EC_POINT_add(group, N, Y_point, Qr, bnctx) != 1 || - EC_POINT_get_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1) - goto fail; - dpp_debug_print_point("DPP: N", group, N); - - pkex->exchange_resp = dpp_pkex_build_exchange_resp(pkex, DPP_STATUS_OK, - Nx, Ny); - if (!pkex->exchange_resp) - goto fail; - - /* K = y * X' */ - if (dpp_ecdh(pkex->y, pkex->x, Kx, &Kx_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)", - Kx, Kx_len); - - /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) - */ - res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac, - pkex->Mx, curve->prime_len, - pkex->Nx, curve->prime_len, pkex->code, - Kx, Kx_len, pkex->z, curve->hash_len); - os_memset(Kx, 0, Kx_len); - if (res < 0) - goto fail; - - pkex->exchange_done = 1; - -out: - BN_CTX_free(bnctx); - EC_POINT_free(Qi); - EC_POINT_free(Qr); - BN_free(Mx); - BN_free(My); - BN_free(Nx); - BN_free(Ny); - EC_POINT_free(M); - EC_POINT_free(N); - EC_POINT_free(X); - EC_KEY_free(X_ec); - EC_KEY_free(Y_ec); - EC_GROUP_free(group); - return pkex; -fail: - wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing failed"); - dpp_pkex_free(pkex); - pkex = NULL; - goto out; -} - - -static struct wpabuf * -dpp_pkex_build_commit_reveal_req(struct dpp_pkex *pkex, - const struct wpabuf *A_pub, const u8 *u) -{ - const struct dpp_curve_params *curve = pkex->own_bi->curve; - struct wpabuf *msg = NULL; - size_t clear_len, attr_len; - struct wpabuf *clear = NULL; - u8 *wrapped; - u8 octet; - const u8 *addr[2]; - size_t len[2]; - - /* {A, u, [bootstrapping info]}z */ - clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len; - clear = wpabuf_alloc(clear_len); - attr_len = 4 + clear_len + AES_BLOCK_SIZE; -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) - attr_len += 5; -#endif /* CONFIG_TESTING_OPTIONS */ - msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_REQ, attr_len); - if (!clear || !msg) - goto fail; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key"); - goto skip_bootstrap_key; - } - if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key"); - wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); - wpabuf_put_le16(clear, 2 * curve->prime_len); - if (dpp_test_gen_invalid_key(clear, curve) < 0) - goto fail; - goto skip_bootstrap_key; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* A in Bootstrap Key attribute */ - wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); - wpabuf_put_le16(clear, wpabuf_len(A_pub)); - wpabuf_put_buf(clear, A_pub); - -#ifdef CONFIG_TESTING_OPTIONS -skip_bootstrap_key: - if (dpp_test == DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no I-Auth tag"); - goto skip_i_auth_tag; - } - if (dpp_test == DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - I-Auth tag mismatch"); - wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG); - wpabuf_put_le16(clear, curve->hash_len); - wpabuf_put_data(clear, u, curve->hash_len - 1); - wpabuf_put_u8(clear, u[curve->hash_len - 1] ^ 0x01); - goto skip_i_auth_tag; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* u in I-Auth tag attribute */ - wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG); - wpabuf_put_le16(clear, curve->hash_len); - wpabuf_put_data(clear, u, curve->hash_len); - -#ifdef CONFIG_TESTING_OPTIONS -skip_i_auth_tag: - if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); - goto skip_wrapped_data; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - addr[0] = wpabuf_head_u8(msg) + 2; - len[0] = DPP_HDR_LEN; - octet = 0; - addr[1] = &octet; - len[1] = sizeof(octet); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); - wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); - wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); - - wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); - if (aes_siv_encrypt(pkex->z, curve->hash_len, - wpabuf_head(clear), wpabuf_len(clear), - 2, addr, len, wrapped) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); - dpp_build_attr_status(msg, DPP_STATUS_OK); - } -skip_wrapped_data: -#endif /* CONFIG_TESTING_OPTIONS */ - -out: - wpabuf_free(clear); - return msg; - -fail: - wpabuf_free(msg); - msg = NULL; - goto out; -} - - -struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex, - const u8 *peer_mac, - const u8 *buf, size_t buflen) -{ - const u8 *attr_status, *attr_id, *attr_key, *attr_group; - u16 attr_status_len, attr_id_len, attr_key_len, attr_group_len; - EC_GROUP *group = NULL; - BN_CTX *bnctx = NULL; - struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL; - const struct dpp_curve_params *curve = pkex->own_bi->curve; - EC_POINT *Qr = NULL, *Y = NULL, *N = NULL; - BIGNUM *Nx = NULL, *Ny = NULL; - EC_KEY *Y_ec = NULL; - size_t Jx_len, Kx_len; - u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN]; - const u8 *addr[4]; - size_t len[4]; - u8 u[DPP_MAX_HASH_LEN]; - int res; - - if (pkex->failed || pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator) - return NULL; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at PKEX Exchange Response"); - pkex->failed = 1; - return NULL; - } - - if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) { - wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR, - MAC2STR(dpp_pkex_peer_mac_override)); - peer_mac = dpp_pkex_peer_mac_override; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); - - attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS, - &attr_status_len); - if (!attr_status || attr_status_len != 1) { - dpp_pkex_fail(pkex, "No DPP Status attribute"); - return NULL; - } - wpa_printf(MSG_DEBUG, "DPP: Status %u", attr_status[0]); - - if (attr_status[0] == DPP_STATUS_BAD_GROUP) { - attr_group = dpp_get_attr(buf, buflen, - DPP_ATTR_FINITE_CYCLIC_GROUP, - &attr_group_len); - if (attr_group && attr_group_len == 2) { - wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL - "Peer indicated mismatching PKEX group - proposed %u", - WPA_GET_LE16(attr_group)); - return NULL; - } - } - - if (attr_status[0] != DPP_STATUS_OK) { - dpp_pkex_fail(pkex, "PKEX failed (peer indicated failure)"); - return NULL; - } - - attr_id_len = 0; - attr_id = dpp_get_attr(buf, buflen, DPP_ATTR_CODE_IDENTIFIER, - &attr_id_len); - if (!dpp_pkex_identifier_match(attr_id, attr_id_len, - pkex->identifier)) { - dpp_pkex_fail(pkex, "PKEX code identifier mismatch"); - return NULL; - } - - /* N in Encrypted Key attribute */ - attr_key = dpp_get_attr(buf, buflen, DPP_ATTR_ENCRYPTED_KEY, - &attr_key_len); - if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2) { - dpp_pkex_fail(pkex, "Missing Encrypted Key attribute"); - return NULL; - } - - /* Qr = H(MAC-Responder | [identifier |] code) * Pr */ - bnctx = BN_CTX_new(); - if (!bnctx) - goto fail; - Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code, - pkex->identifier, bnctx, &group); - if (!Qr) - goto fail; - - /* Y' = N - Qr */ - Y = EC_POINT_new(group); - N = EC_POINT_new(group); - Nx = BN_bin2bn(attr_key, attr_key_len / 2, NULL); - Ny = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL); - if (!Y || !N || !Nx || !Ny || - EC_POINT_set_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1 || - EC_POINT_is_at_infinity(group, N) || - !EC_POINT_is_on_curve(group, N, bnctx) || - EC_POINT_invert(group, Qr, bnctx) != 1 || - EC_POINT_add(group, Y, N, Qr, bnctx) != 1 || - EC_POINT_is_at_infinity(group, Y) || - !EC_POINT_is_on_curve(group, Y, bnctx)) { - dpp_pkex_fail(pkex, "Invalid Encrypted Key value"); - pkex->t++; - goto fail; - } - dpp_debug_print_point("DPP: N", group, N); - dpp_debug_print_point("DPP: Y'", group, Y); - - pkex->exchange_done = 1; - - /* ECDH: J = a * Y’ */ - Y_ec = EC_KEY_new(); - if (!Y_ec || - EC_KEY_set_group(Y_ec, group) != 1 || - EC_KEY_set_public_key(Y_ec, Y) != 1) - goto fail; - pkex->y = EVP_PKEY_new(); - if (!pkex->y || - EVP_PKEY_set1_EC_KEY(pkex->y, Y_ec) != 1) - goto fail; - if (dpp_ecdh(pkex->own_bi->pubkey, pkex->y, Jx, &Jx_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)", - Jx, Jx_len); - - /* u = HMAC(J.x, MAC-Initiator | A.x | Y’.x | X.x ) */ - A_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0); - Y_pub = dpp_get_pubkey_point(pkex->y, 0); - X_pub = dpp_get_pubkey_point(pkex->x, 0); - if (!A_pub || !Y_pub || !X_pub) - goto fail; - addr[0] = pkex->own_mac; - len[0] = ETH_ALEN; - addr[1] = wpabuf_head(A_pub); - len[1] = wpabuf_len(A_pub) / 2; - addr[2] = wpabuf_head(Y_pub); - len[2] = wpabuf_len(Y_pub) / 2; - addr[3] = wpabuf_head(X_pub); - len[3] = wpabuf_len(X_pub) / 2; - if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len); - - /* K = x * Y’ */ - if (dpp_ecdh(pkex->x, pkex->y, Kx, &Kx_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)", - Kx, Kx_len); - - /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) - */ - res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac, - pkex->Mx, curve->prime_len, - attr_key /* N.x */, attr_key_len / 2, - pkex->code, Kx, Kx_len, - pkex->z, curve->hash_len); - os_memset(Kx, 0, Kx_len); - if (res < 0) - goto fail; - - msg = dpp_pkex_build_commit_reveal_req(pkex, A_pub, u); - if (!msg) - goto fail; - -out: - wpabuf_free(A_pub); - wpabuf_free(X_pub); - wpabuf_free(Y_pub); - EC_POINT_free(Qr); - EC_POINT_free(Y); - EC_POINT_free(N); - BN_free(Nx); - BN_free(Ny); - EC_KEY_free(Y_ec); - BN_CTX_free(bnctx); - EC_GROUP_free(group); - return msg; -fail: - wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing failed"); - goto out; -} - - -static struct wpabuf * -dpp_pkex_build_commit_reveal_resp(struct dpp_pkex *pkex, - const struct wpabuf *B_pub, const u8 *v) -{ - const struct dpp_curve_params *curve = pkex->own_bi->curve; - struct wpabuf *msg = NULL; - const u8 *addr[2]; - size_t len[2]; - u8 octet; - u8 *wrapped; - struct wpabuf *clear = NULL; - size_t clear_len, attr_len; - - /* {B, v [bootstrapping info]}z */ - clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len; - clear = wpabuf_alloc(clear_len); - attr_len = 4 + clear_len + AES_BLOCK_SIZE; -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) - attr_len += 5; -#endif /* CONFIG_TESTING_OPTIONS */ - msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_RESP, attr_len); - if (!clear || !msg) - goto fail; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key"); - goto skip_bootstrap_key; - } - if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key"); - wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); - wpabuf_put_le16(clear, 2 * curve->prime_len); - if (dpp_test_gen_invalid_key(clear, curve) < 0) - goto fail; - goto skip_bootstrap_key; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* B in Bootstrap Key attribute */ - wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); - wpabuf_put_le16(clear, wpabuf_len(B_pub)); - wpabuf_put_buf(clear, B_pub); - -#ifdef CONFIG_TESTING_OPTIONS -skip_bootstrap_key: - if (dpp_test == DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth tag"); - goto skip_r_auth_tag; - } - if (dpp_test == DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - R-Auth tag mismatch"); - wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG); - wpabuf_put_le16(clear, curve->hash_len); - wpabuf_put_data(clear, v, curve->hash_len - 1); - wpabuf_put_u8(clear, v[curve->hash_len - 1] ^ 0x01); - goto skip_r_auth_tag; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - /* v in R-Auth tag attribute */ - wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG); - wpabuf_put_le16(clear, curve->hash_len); - wpabuf_put_data(clear, v, curve->hash_len); - -#ifdef CONFIG_TESTING_OPTIONS -skip_r_auth_tag: - if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); - goto skip_wrapped_data; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - addr[0] = wpabuf_head_u8(msg) + 2; - len[0] = DPP_HDR_LEN; - octet = 1; - addr[1] = &octet; - len[1] = sizeof(octet); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); - wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); - wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); - - wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); - if (aes_siv_encrypt(pkex->z, curve->hash_len, - wpabuf_head(clear), wpabuf_len(clear), - 2, addr, len, wrapped) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); - dpp_build_attr_status(msg, DPP_STATUS_OK); - } -skip_wrapped_data: -#endif /* CONFIG_TESTING_OPTIONS */ - -out: - wpabuf_free(clear); - return msg; - -fail: - wpabuf_free(msg); - msg = NULL; - goto out; -} - - -struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex, - const u8 *hdr, - const u8 *buf, size_t buflen) -{ - const struct dpp_curve_params *curve = pkex->own_bi->curve; - size_t Jx_len, Lx_len; - u8 Jx[DPP_MAX_SHARED_SECRET_LEN]; - u8 Lx[DPP_MAX_SHARED_SECRET_LEN]; - const u8 *wrapped_data, *b_key, *peer_u; - u16 wrapped_data_len, b_key_len, peer_u_len = 0; - const u8 *addr[4]; - size_t len[4]; - u8 octet; - u8 *unwrapped = NULL; - size_t unwrapped_len = 0; - struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL; - struct wpabuf *B_pub = NULL; - u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN]; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_REQ) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at PKEX CR Request"); - pkex->failed = 1; - return NULL; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (!pkex->exchange_done || pkex->failed || - pkex->t >= PKEX_COUNTER_T_LIMIT || pkex->initiator) - goto fail; - - wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA, - &wrapped_data_len); - if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { - dpp_pkex_fail(pkex, - "Missing or invalid required Wrapped Data attribute"); - goto fail; - } - - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) - goto fail; - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - octet = 0; - addr[1] = &octet; - len[1] = sizeof(octet); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - if (aes_siv_decrypt(pkex->z, curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_pkex_fail(pkex, - "AES-SIV decryption failed - possible PKEX code mismatch"); - pkex->failed = 1; - pkex->t++; - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data"); - goto fail; - } - - b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY, - &b_key_len); - if (!b_key || b_key_len != 2 * curve->prime_len) { - dpp_pkex_fail(pkex, "No valid peer bootstrapping key found"); - goto fail; - } - pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key, - b_key_len); - if (!pkex->peer_bootstrap_key) { - dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid"); - goto fail; - } - dpp_debug_print_key("DPP: Peer bootstrap public key", - pkex->peer_bootstrap_key); - - /* ECDH: J' = y * A' */ - if (dpp_ecdh(pkex->y, pkex->peer_bootstrap_key, Jx, &Jx_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)", - Jx, Jx_len); - - /* u' = HMAC(J'.x, MAC-Initiator | A'.x | Y.x | X'.x) */ - A_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0); - Y_pub = dpp_get_pubkey_point(pkex->y, 0); - X_pub = dpp_get_pubkey_point(pkex->x, 0); - if (!A_pub || !Y_pub || !X_pub) - goto fail; - addr[0] = pkex->peer_mac; - len[0] = ETH_ALEN; - addr[1] = wpabuf_head(A_pub); - len[1] = wpabuf_len(A_pub) / 2; - addr[2] = wpabuf_head(Y_pub); - len[2] = wpabuf_len(Y_pub) / 2; - addr[3] = wpabuf_head(X_pub); - len[3] = wpabuf_len(X_pub) / 2; - if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0) - goto fail; - - peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG, - &peer_u_len); - if (!peer_u || peer_u_len != curve->hash_len || - os_memcmp(peer_u, u, curve->hash_len) != 0) { - dpp_pkex_fail(pkex, "No valid u (I-Auth tag) found"); - wpa_hexdump(MSG_DEBUG, "DPP: Calculated u'", - u, curve->hash_len); - wpa_hexdump(MSG_DEBUG, "DPP: Received u", peer_u, peer_u_len); - pkex->t++; - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: Valid u (I-Auth tag) received"); - - /* ECDH: L = b * X' */ - if (dpp_ecdh(pkex->own_bi->pubkey, pkex->x, Lx, &Lx_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)", - Lx, Lx_len); - - /* v = HMAC(L.x, MAC-Responder | B.x | X'.x | Y.x) */ - B_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0); - if (!B_pub) - goto fail; - addr[0] = pkex->own_mac; - len[0] = ETH_ALEN; - addr[1] = wpabuf_head(B_pub); - len[1] = wpabuf_len(B_pub) / 2; - addr[2] = wpabuf_head(X_pub); - len[2] = wpabuf_len(X_pub) / 2; - addr[3] = wpabuf_head(Y_pub); - len[3] = wpabuf_len(Y_pub) / 2; - if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len); - - msg = dpp_pkex_build_commit_reveal_resp(pkex, B_pub, v); - if (!msg) - goto fail; - -out: - os_free(unwrapped); - wpabuf_free(A_pub); - wpabuf_free(B_pub); - wpabuf_free(X_pub); - wpabuf_free(Y_pub); - return msg; -fail: - wpa_printf(MSG_DEBUG, - "DPP: PKEX Commit-Reveal Request processing failed"); - goto out; -} - - -int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr, - const u8 *buf, size_t buflen) -{ - const struct dpp_curve_params *curve = pkex->own_bi->curve; - const u8 *wrapped_data, *b_key, *peer_v; - u16 wrapped_data_len, b_key_len, peer_v_len = 0; - const u8 *addr[4]; - size_t len[4]; - u8 octet; - u8 *unwrapped = NULL; - size_t unwrapped_len = 0; - int ret = -1; - u8 v[DPP_MAX_HASH_LEN]; - size_t Lx_len; - u8 Lx[DPP_MAX_SHARED_SECRET_LEN]; - struct wpabuf *B_pub = NULL, *X_pub = NULL, *Y_pub = NULL; - -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_RESP) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at PKEX CR Response"); - pkex->failed = 1; - goto fail; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (!pkex->exchange_done || pkex->failed || - pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator) - goto fail; - - wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA, - &wrapped_data_len); - if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { - dpp_pkex_fail(pkex, - "Missing or invalid required Wrapped Data attribute"); - goto fail; - } - - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", - wrapped_data, wrapped_data_len); - unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; - unwrapped = os_malloc(unwrapped_len); - if (!unwrapped) - goto fail; - - addr[0] = hdr; - len[0] = DPP_HDR_LEN; - octet = 1; - addr[1] = &octet; - len[1] = sizeof(octet); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); - - if (aes_siv_decrypt(pkex->z, curve->hash_len, - wrapped_data, wrapped_data_len, - 2, addr, len, unwrapped) < 0) { - dpp_pkex_fail(pkex, - "AES-SIV decryption failed - possible PKEX code mismatch"); - pkex->t++; - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", - unwrapped, unwrapped_len); - - if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { - dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data"); - goto fail; - } - - b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY, - &b_key_len); - if (!b_key || b_key_len != 2 * curve->prime_len) { - dpp_pkex_fail(pkex, "No valid peer bootstrapping key found"); - goto fail; - } - pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key, - b_key_len); - if (!pkex->peer_bootstrap_key) { - dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid"); - goto fail; - } - dpp_debug_print_key("DPP: Peer bootstrap public key", - pkex->peer_bootstrap_key); - - /* ECDH: L' = x * B' */ - if (dpp_ecdh(pkex->x, pkex->peer_bootstrap_key, Lx, &Lx_len) < 0) - goto fail; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)", - Lx, Lx_len); - - /* v' = HMAC(L.x, MAC-Responder | B'.x | X.x | Y'.x) */ - B_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0); - X_pub = dpp_get_pubkey_point(pkex->x, 0); - Y_pub = dpp_get_pubkey_point(pkex->y, 0); - if (!B_pub || !X_pub || !Y_pub) - goto fail; - addr[0] = pkex->peer_mac; - len[0] = ETH_ALEN; - addr[1] = wpabuf_head(B_pub); - len[1] = wpabuf_len(B_pub) / 2; - addr[2] = wpabuf_head(X_pub); - len[2] = wpabuf_len(X_pub) / 2; - addr[3] = wpabuf_head(Y_pub); - len[3] = wpabuf_len(Y_pub) / 2; - if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0) - goto fail; - - peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG, - &peer_v_len); - if (!peer_v || peer_v_len != curve->hash_len || - os_memcmp(peer_v, v, curve->hash_len) != 0) { - dpp_pkex_fail(pkex, "No valid v (R-Auth tag) found"); - wpa_hexdump(MSG_DEBUG, "DPP: Calculated v'", - v, curve->hash_len); - wpa_hexdump(MSG_DEBUG, "DPP: Received v", peer_v, peer_v_len); - pkex->t++; - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: Valid v (R-Auth tag) received"); - - ret = 0; -out: - wpabuf_free(B_pub); - wpabuf_free(X_pub); - wpabuf_free(Y_pub); - os_free(unwrapped); - return ret; -fail: - goto out; -} - - -void dpp_pkex_free(struct dpp_pkex *pkex) -{ - if (!pkex) - return; - - os_free(pkex->identifier); - os_free(pkex->code); - EVP_PKEY_free(pkex->x); - EVP_PKEY_free(pkex->y); - EVP_PKEY_free(pkex->peer_bootstrap_key); - wpabuf_free(pkex->exchange_req); - wpabuf_free(pkex->exchange_resp); - os_free(pkex); -} - - -#ifdef CONFIG_TESTING_OPTIONS -char * dpp_corrupt_connector_signature(const char *connector) -{ - char *tmp, *pos, *signed3 = NULL; - unsigned char *signature = NULL; - size_t signature_len = 0, signed3_len; - - tmp = os_zalloc(os_strlen(connector) + 5); - if (!tmp) - goto fail; - os_memcpy(tmp, connector, os_strlen(connector)); - - pos = os_strchr(tmp, '.'); - if (!pos) - goto fail; - - pos = os_strchr(pos + 1, '.'); - if (!pos) - goto fail; - pos++; - - wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s", - pos); - signature = base64_url_decode(pos, os_strlen(pos), &signature_len); - if (!signature || signature_len == 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature", - signature, signature_len); - signature[signature_len - 1] ^= 0x01; - wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature", - signature, signature_len); - signed3 = base64_url_encode(signature, signature_len, &signed3_len); - if (!signed3) - goto fail; - os_memcpy(pos, signed3, signed3_len); - pos[signed3_len] = '\0'; - wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s", - pos); - -out: - os_free(signature); - os_free(signed3); - return tmp; -fail: - os_free(tmp); - tmp = NULL; - goto out; -} -#endif /* CONFIG_TESTING_OPTIONS */ - - -#ifdef CONFIG_DPP2 - -struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key, - size_t net_access_key_len) -{ - struct wpabuf *pub = NULL; - EVP_PKEY *own_key; - struct dpp_pfs *pfs; - - pfs = os_zalloc(sizeof(*pfs)); - if (!pfs) - return NULL; - - own_key = dpp_set_keypair(&pfs->curve, net_access_key, - net_access_key_len); - if (!own_key) { - wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); - goto fail; - } - EVP_PKEY_free(own_key); - - pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group); - if (!pfs->ecdh) - goto fail; - - pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0); - pub = wpabuf_zeropad(pub, pfs->curve->prime_len); - if (!pub) - goto fail; - - pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub)); - if (!pfs->ie) - goto fail; - wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION); - wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub)); - wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM); - wpabuf_put_le16(pfs->ie, pfs->curve->ike_group); - wpabuf_put_buf(pfs->ie, pub); - wpabuf_free(pub); - wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element", - pfs->ie); - - return pfs; -fail: - wpabuf_free(pub); - dpp_pfs_free(pfs); - return NULL; -} - - -int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len) -{ - if (peer_ie_len < 2) - return -1; - if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) { - wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS"); - return -1; - } - - pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2, - peer_ie_len - 2); - pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len); - if (!pfs->secret) { - wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key"); - return -1; - } - wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret); - return 0; -} - - -void dpp_pfs_free(struct dpp_pfs *pfs) -{ - if (!pfs) - return; - crypto_ecdh_deinit(pfs->ecdh); - wpabuf_free(pfs->ie); - wpabuf_clear_free(pfs->secret); - os_free(pfs); -} - -#endif /* CONFIG_DPP2 */ - - -static unsigned int dpp_next_id(struct dpp_global *dpp) +unsigned int dpp_next_id(struct dpp_global *dpp) { struct dpp_bootstrap_info *bi; unsigned int max_id = 0; @@ -10317,6 +3811,10 @@ static int dpp_bootstrap_del(struct dpp_global *dpp, unsigned int id) if (id && bi->id != id) continue; found = 1; +#ifdef CONFIG_DPP2 + if (dpp->remove_bi) + dpp->remove_bi(dpp->cb_ctx, bi); +#endif /* CONFIG_DPP2 */ dl_list_del(&bi->list); dpp_bootstrap_info_free(bi); } @@ -10458,33 +3956,6 @@ int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id) } -struct dpp_bootstrap_info * -dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer, - unsigned int freq) -{ - struct dpp_bootstrap_info *bi; - - bi = os_zalloc(sizeof(*bi)); - if (!bi) - return NULL; - bi->id = dpp_next_id(dpp); - bi->type = DPP_BOOTSTRAP_PKEX; - os_memcpy(bi->mac_addr, peer, ETH_ALEN); - bi->num_freq = 1; - bi->freq[0] = freq; - bi->curve = pkex->own_bi->curve; - bi->pubkey = pkex->peer_bootstrap_key; - pkex->peer_bootstrap_key = NULL; - if (dpp_bootstrap_key_hash(bi) < 0) { - dpp_bootstrap_info_free(bi); - return NULL; - } - dpp_pkex_free(pkex); - dl_list_add(&dpp->bootstrap, &bi->list); - return bi; -} - - const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id) { struct dpp_bootstrap_info *bi; @@ -10513,14 +3984,36 @@ int dpp_bootstrap_info(struct dpp_global *dpp, int id, "num_freq=%u\n" "use_freq=%u\n" "curve=%s\n" - "pkhash=%s\n", + "pkhash=%s\n" + "version=%d\n", dpp_bootstrap_type_txt(bi->type), MAC2STR(bi->mac_addr), bi->info ? bi->info : "", bi->num_freq, bi->num_freq == 1 ? bi->freq[0] : 0, bi->curve->name, - pkhash); + pkhash, + bi->version); +} + + +int dpp_bootstrap_set(struct dpp_global *dpp, int id, const char *params) +{ + struct dpp_bootstrap_info *bi; + + bi = dpp_bootstrap_get_id(dpp, id); + if (!bi) + return -1; + + str_clear_free(bi->configurator_params); + + if (params) { + bi->configurator_params = os_strdup(params); + return bi->configurator_params ? 0 : -1; + } + + bi->configurator_params = NULL; + return 0; } @@ -10556,10 +4049,29 @@ void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap, if (*own_bi && *peer_bi) break; } - } +#ifdef CONFIG_DPP2 +struct dpp_bootstrap_info * dpp_bootstrap_find_chirp(struct dpp_global *dpp, + const u8 *hash) +{ + struct dpp_bootstrap_info *bi; + + if (!dpp) + return NULL; + + dl_list_for_each(bi, &dpp->bootstrap, struct dpp_bootstrap_info, list) { + if (!bi->own && os_memcmp(bi->pubkey_hash_chirp, hash, + SHA256_MAC_LEN) == 0) + return bi; + } + + return NULL; +} +#endif /* CONFIG_DPP2 */ + + static int dpp_nfc_update_bi_channel(struct dpp_bootstrap_info *own_bi, struct dpp_bootstrap_info *peer_bi) { @@ -10568,11 +4080,11 @@ static int dpp_nfc_update_bi_channel(struct dpp_bootstrap_info *own_bi, u8 op_class, channel; char chan[20]; - if (peer_bi->num_freq == 0) + if (peer_bi->num_freq == 0 && !peer_bi->channels_listed) return 0; /* no channel preference/constraint */ for (i = 0; i < peer_bi->num_freq; i++) { - if (own_bi->num_freq == 0 || + if ((own_bi->num_freq == 0 && !own_bi->channels_listed) || freq_included(own_bi->freq, own_bi->num_freq, peer_bi->freq[i])) { freq = peer_bi->freq[i]; @@ -10659,14 +4171,15 @@ static unsigned int dpp_next_configurator_id(struct dpp_global *dpp) int dpp_configurator_add(struct dpp_global *dpp, const char *cmd) { char *curve = NULL; - char *key = NULL; - u8 *privkey = NULL; - size_t privkey_len = 0; + char *key = NULL, *ppkey = NULL; + u8 *privkey = NULL, *pp_key = NULL; + size_t privkey_len = 0, pp_key_len = 0; int ret = -1; struct dpp_configurator *conf = NULL; curve = get_param(cmd, " curve="); key = get_param(cmd, " key="); + ppkey = get_param(cmd, " ppkey="); if (key) { privkey_len = os_strlen(key) / 2; @@ -10676,7 +4189,16 @@ int dpp_configurator_add(struct dpp_global *dpp, const char *cmd) goto fail; } - conf = dpp_keygen_configurator(curve, privkey, privkey_len); + if (ppkey) { + pp_key_len = os_strlen(ppkey) / 2; + pp_key = os_malloc(pp_key_len); + if (!pp_key || + hexstr2bin(ppkey, pp_key, pp_key_len) < 0) + goto fail; + } + + conf = dpp_keygen_configurator(curve, privkey, privkey_len, + pp_key, pp_key_len); if (!conf) goto fail; @@ -10687,7 +4209,9 @@ int dpp_configurator_add(struct dpp_global *dpp, const char *cmd) fail: os_free(curve); str_clear_free(key); + str_clear_free(ppkey); bin_clear_free(privkey, privkey_len); + bin_clear_free(pp_key, pp_key_len); dpp_configurator_free(conf); return ret; } @@ -10751,12 +4275,12 @@ int dpp_configurator_from_backup(struct dpp_global *dpp, struct dpp_asymmetric_key *key) { struct dpp_configurator *conf; - const EC_KEY *eckey; - const EC_GROUP *group; + const EC_KEY *eckey, *eckey_pp; + const EC_GROUP *group, *group_pp; int nid; const struct dpp_curve_params *curve; - if (!key->csign) + if (!key->csign || !key->pp_key) return -1; eckey = EVP_PKEY_get0_EC_KEY(key->csign); if (!eckey) @@ -10770,6 +4294,18 @@ int dpp_configurator_from_backup(struct dpp_global *dpp, wpa_printf(MSG_INFO, "DPP: Unsupported group in c-sign-key"); return -1; } + eckey_pp = EVP_PKEY_get0_EC_KEY(key->pp_key); + if (!eckey_pp) + return -1; + group_pp = EC_KEY_get0_group(eckey_pp); + if (!group_pp) + return -1; + if (EC_GROUP_get_curve_name(group) != + EC_GROUP_get_curve_name(group_pp)) { + wpa_printf(MSG_INFO, + "DPP: Mismatch in c-sign-key and ppKey groups"); + return -1; + } conf = os_zalloc(sizeof(*conf)); if (!conf) @@ -10777,6 +4313,8 @@ int dpp_configurator_from_backup(struct dpp_global *dpp, conf->curve = curve; conf->csign = key->csign; key->csign = NULL; + conf->pp_key = key->pp_key; + key->pp_key = NULL; conf->own = 1; if (dpp_configurator_gen_kid(conf) < 0) { dpp_configurator_free(conf); @@ -10789,68 +4327,20 @@ int dpp_configurator_from_backup(struct dpp_global *dpp, } -static void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx, - void *timeout_ctx); - - -static void dpp_connection_free(struct dpp_connection *conn) +struct dpp_configurator * dpp_configurator_find_kid(struct dpp_global *dpp, + const u8 *kid) { - if (conn->sock >= 0) { - wpa_printf(MSG_DEBUG, "DPP: Close Controller socket %d", - conn->sock); - eloop_unregister_sock(conn->sock, EVENT_TYPE_READ); - eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE); - close(conn->sock); - } - eloop_cancel_timeout(dpp_controller_conn_status_result_wait_timeout, - conn, NULL); - wpabuf_free(conn->msg); - wpabuf_free(conn->msg_out); - dpp_auth_deinit(conn->auth); - os_free(conn); -} - - -static void dpp_connection_remove(struct dpp_connection *conn) -{ - dl_list_del(&conn->list); - dpp_connection_free(conn); -} - - -static void dpp_tcp_init_flush(struct dpp_global *dpp) -{ - struct dpp_connection *conn, *tmp; - - dl_list_for_each_safe(conn, tmp, &dpp->tcp_init, struct dpp_connection, - list) - dpp_connection_remove(conn); -} - - -static void dpp_relay_controller_free(struct dpp_relay_controller *ctrl) -{ - struct dpp_connection *conn, *tmp; - - dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection, - list) - dpp_connection_remove(conn); - os_free(ctrl); -} - - -static void dpp_relay_flush_controllers(struct dpp_global *dpp) -{ - struct dpp_relay_controller *ctrl, *tmp; + struct dpp_configurator *conf; if (!dpp) - return; + return NULL; - dl_list_for_each_safe(ctrl, tmp, &dpp->controllers, - struct dpp_relay_controller, list) { - dl_list_del(&ctrl->list); - dpp_relay_controller_free(ctrl); + dl_list_for_each(conf, &dpp->configurator, + struct dpp_configurator, list) { + if (os_memcmp(conf->kid_hash, kid, SHA256_MAC_LEN) == 0) + return conf; } + return NULL; } #endif /* CONFIG_DPP2 */ @@ -10863,10 +4353,9 @@ struct dpp_global * dpp_global_init(struct dpp_global_config *config) dpp = os_zalloc(sizeof(*dpp)); if (!dpp) return NULL; - dpp->msg_ctx = config->msg_ctx; #ifdef CONFIG_DPP2 dpp->cb_ctx = config->cb_ctx; - dpp->process_conf_obj = config->process_conf_obj; + dpp->remove_bi = config->remove_bi; #endif /* CONFIG_DPP2 */ dl_list_init(&dpp->bootstrap); @@ -10904,1283 +4393,33 @@ void dpp_global_deinit(struct dpp_global *dpp) #ifdef CONFIG_DPP2 -static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx); -static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx); -static void dpp_controller_auth_success(struct dpp_connection *conn, - int initiator); - - -int dpp_relay_add_controller(struct dpp_global *dpp, - struct dpp_relay_config *config) -{ - struct dpp_relay_controller *ctrl; - - if (!dpp) - return -1; - - ctrl = os_zalloc(sizeof(*ctrl)); - if (!ctrl) - return -1; - dl_list_init(&ctrl->conn); - ctrl->global = dpp; - os_memcpy(&ctrl->ipaddr, config->ipaddr, sizeof(*config->ipaddr)); - os_memcpy(ctrl->pkhash, config->pkhash, SHA256_MAC_LEN); - ctrl->cb_ctx = config->cb_ctx; - ctrl->tx = config->tx; - ctrl->gas_resp_tx = config->gas_resp_tx; - dl_list_add(&dpp->controllers, &ctrl->list); - return 0; -} - - -static struct dpp_relay_controller * -dpp_relay_controller_get(struct dpp_global *dpp, const u8 *pkhash) -{ - struct dpp_relay_controller *ctrl; - - if (!dpp) - return NULL; - - dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller, - list) { - if (os_memcmp(pkhash, ctrl->pkhash, SHA256_MAC_LEN) == 0) - return ctrl; - } - - return NULL; -} - - -static void dpp_controller_gas_done(struct dpp_connection *conn) -{ - struct dpp_authentication *auth = conn->auth; - - if (auth->peer_version >= 2 && - auth->conf_resp_status == DPP_STATUS_OK) { - wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result"); - auth->waiting_conf_result = 1; - return; - } - - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT); - dpp_connection_remove(conn); -} - - -static int dpp_tcp_send(struct dpp_connection *conn) -{ - int res; - - if (!conn->msg_out) { - eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE); - conn->write_eloop = 0; - return -1; - } - res = send(conn->sock, - wpabuf_head_u8(conn->msg_out) + conn->msg_out_pos, - wpabuf_len(conn->msg_out) - conn->msg_out_pos, 0); - if (res < 0) { - wpa_printf(MSG_DEBUG, "DPP: Failed to send buffer: %s", - strerror(errno)); - dpp_connection_remove(conn); - return -1; - } - - conn->msg_out_pos += res; - if (wpabuf_len(conn->msg_out) > conn->msg_out_pos) { - wpa_printf(MSG_DEBUG, - "DPP: %u/%u bytes of message sent to Controller", - (unsigned int) conn->msg_out_pos, - (unsigned int) wpabuf_len(conn->msg_out)); - if (!conn->write_eloop && - eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, conn, NULL) == 0) - conn->write_eloop = 1; - return 1; - } - - wpa_printf(MSG_DEBUG, "DPP: Full message sent over TCP"); - wpabuf_free(conn->msg_out); - conn->msg_out = NULL; - conn->msg_out_pos = 0; - eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE); - conn->write_eloop = 0; - if (!conn->read_eloop && - eloop_register_sock(conn->sock, EVENT_TYPE_READ, - dpp_controller_rx, conn, NULL) == 0) - conn->read_eloop = 1; - if (conn->on_tcp_tx_complete_remove) { - dpp_connection_remove(conn); - } else if (conn->ctrl && conn->on_tcp_tx_complete_gas_done && - conn->auth) { - dpp_controller_gas_done(conn); - } else if (conn->on_tcp_tx_complete_auth_ok) { - conn->on_tcp_tx_complete_auth_ok = 0; - dpp_controller_auth_success(conn, 1); - } - - return 0; -} - - -static void dpp_controller_start_gas_client(struct dpp_connection *conn) -{ - struct dpp_authentication *auth = conn->auth; - struct wpabuf *buf; - int netrole_ap = 0; /* TODO: make this configurable */ - - buf = dpp_build_conf_req_helper(auth, "Test", netrole_ap, NULL, NULL); - if (!buf) { - wpa_printf(MSG_DEBUG, - "DPP: No configuration request data available"); - return; - } - - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = wpabuf_alloc(4 + wpabuf_len(buf) - 1); - if (!conn->msg_out) { - wpabuf_free(buf); - return; - } - wpabuf_put_be32(conn->msg_out, wpabuf_len(buf) - 1); - wpabuf_put_data(conn->msg_out, wpabuf_head_u8(buf) + 1, - wpabuf_len(buf) - 1); - wpabuf_free(buf); - - if (dpp_tcp_send(conn) == 1) { - if (!conn->write_eloop) { - if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, - conn, NULL) < 0) - return; - conn->write_eloop = 1; - } - } -} - - -static void dpp_controller_auth_success(struct dpp_connection *conn, - int initiator) -{ - struct dpp_authentication *auth = conn->auth; - - if (!auth) - return; - - wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded"); - wpa_msg(conn->global->msg_ctx, MSG_INFO, - DPP_EVENT_AUTH_SUCCESS "init=%d", initiator); -#ifdef CONFIG_TESTING_OPTIONS - if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) { - wpa_printf(MSG_INFO, - "DPP: TESTING - stop at Authentication Confirm"); - if (auth->configurator) { - /* Prevent GAS response */ - auth->auth_success = 0; - } - return; - } -#endif /* CONFIG_TESTING_OPTIONS */ - - if (!auth->configurator) - dpp_controller_start_gas_client(conn); -} - - -static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx) -{ - struct dpp_connection *conn = eloop_ctx; - - wpa_printf(MSG_DEBUG, "DPP: TCP socket %d ready for TX", sock); - dpp_tcp_send(conn); -} - - -static int dpp_ipaddr_to_sockaddr(struct sockaddr *addr, socklen_t *addrlen, - const struct hostapd_ip_addr *ipaddr, - int port) -{ - struct sockaddr_in *dst; -#ifdef CONFIG_IPV6 - struct sockaddr_in6 *dst6; -#endif /* CONFIG_IPV6 */ - - switch (ipaddr->af) { - case AF_INET: - dst = (struct sockaddr_in *) addr; - os_memset(dst, 0, sizeof(*dst)); - dst->sin_family = AF_INET; - dst->sin_addr.s_addr = ipaddr->u.v4.s_addr; - dst->sin_port = htons(port); - *addrlen = sizeof(*dst); - break; -#ifdef CONFIG_IPV6 - case AF_INET6: - dst6 = (struct sockaddr_in6 *) addr; - os_memset(dst6, 0, sizeof(*dst6)); - dst6->sin6_family = AF_INET6; - os_memcpy(&dst6->sin6_addr, &ipaddr->u.v6, - sizeof(struct in6_addr)); - dst6->sin6_port = htons(port); - *addrlen = sizeof(*dst6); - break; -#endif /* CONFIG_IPV6 */ - default: - return -1; - } - - return 0; -} - - -static struct dpp_connection * -dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src, - unsigned int freq) -{ - struct dpp_connection *conn; - struct sockaddr_storage addr; - socklen_t addrlen; - char txt[100]; - - if (dl_list_len(&ctrl->conn) >= 15) { - wpa_printf(MSG_DEBUG, - "DPP: Too many ongoing Relay connections to the Controller - cannot start a new one"); - return NULL; - } - - if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &addr, &addrlen, - &ctrl->ipaddr, DPP_TCP_PORT) < 0) - return NULL; - - conn = os_zalloc(sizeof(*conn)); - if (!conn) - return NULL; - - conn->global = ctrl->global; - conn->relay = ctrl; - os_memcpy(conn->mac_addr, src, ETH_ALEN); - conn->freq = freq; - - conn->sock = socket(AF_INET, SOCK_STREAM, 0); - if (conn->sock < 0) - goto fail; - wpa_printf(MSG_DEBUG, "DPP: TCP relay socket %d connection to %s", - conn->sock, hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt))); - - if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { - wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", - strerror(errno)); - goto fail; - } - - if (connect(conn->sock, (struct sockaddr *) &addr, addrlen) < 0) { - if (errno != EINPROGRESS) { - wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s", - strerror(errno)); - goto fail; - } - - /* - * Continue connecting in the background; eloop will call us - * once the connection is ready (or failed). - */ - } - - if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, conn, NULL) < 0) - goto fail; - conn->write_eloop = 1; - - /* TODO: eloop timeout to clear a connection if it does not complete - * properly */ - - dl_list_add(&ctrl->conn, &conn->list); - return conn; -fail: - dpp_connection_free(conn); - return NULL; -} - - -static struct wpabuf * dpp_tcp_encaps(const u8 *hdr, const u8 *buf, size_t len) +struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi) { struct wpabuf *msg; - msg = wpabuf_alloc(4 + 1 + DPP_HDR_LEN + len); + wpa_printf(MSG_DEBUG, "DPP: Build Presence Announcement frame"); + + msg = dpp_alloc_msg(DPP_PA_PRESENCE_ANNOUNCEMENT, 4 + SHA256_MAC_LEN); if (!msg) return NULL; - wpabuf_put_be32(msg, 1 + DPP_HDR_LEN + len); - wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC); - wpabuf_put_data(msg, hdr, DPP_HDR_LEN); - wpabuf_put_data(msg, buf, len); - wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg); + + /* Responder Bootstrapping Key Hash */ + dpp_build_attr_r_bootstrap_key_hash(msg, bi->pubkey_hash_chirp); + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Presence Announcement frame attributes", msg); return msg; } -static int dpp_relay_tx(struct dpp_connection *conn, const u8 *hdr, - const u8 *buf, size_t len) +void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src, + unsigned int freq, const u8 *hash) { - u8 type = hdr[DPP_HDR_LEN - 1]; + char hex[SHA256_MAC_LEN * 2 + 1]; - wpa_printf(MSG_DEBUG, - "DPP: Continue already established Relay/Controller connection for this session"); - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = dpp_tcp_encaps(hdr, buf, len); - if (!conn->msg_out) { - dpp_connection_remove(conn); - return -1; - } - - /* TODO: for proto ver 1, need to do remove connection based on GAS Resp - * TX status */ - if (type == DPP_PA_CONFIGURATION_RESULT) - conn->on_tcp_tx_complete_remove = 1; - dpp_tcp_send(conn); - return 0; -} - - -int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, - const u8 *buf, size_t len, unsigned int freq, - const u8 *i_bootstrap, const u8 *r_bootstrap) -{ - struct dpp_relay_controller *ctrl; - struct dpp_connection *conn; - u8 type = hdr[DPP_HDR_LEN - 1]; - - /* Check if there is an already started session for this peer and if so, - * continue that session (send this over TCP) and return 0. - */ - if (type != DPP_PA_PEER_DISCOVERY_REQ && - type != DPP_PA_PEER_DISCOVERY_RESP) { - dl_list_for_each(ctrl, &dpp->controllers, - struct dpp_relay_controller, list) { - dl_list_for_each(conn, &ctrl->conn, - struct dpp_connection, list) { - if (os_memcmp(src, conn->mac_addr, - ETH_ALEN) == 0) - return dpp_relay_tx(conn, hdr, buf, len); - } - } - } - - if (!r_bootstrap) - return -1; - - ctrl = dpp_relay_controller_get(dpp, r_bootstrap); - if (!ctrl) - return -1; - - wpa_printf(MSG_DEBUG, - "DPP: Authentication Request for a configured Controller"); - conn = dpp_relay_new_conn(ctrl, src, freq); - if (!conn) - return -1; - - conn->msg_out = dpp_tcp_encaps(hdr, buf, len); - if (!conn->msg_out) { - dpp_connection_remove(conn); - return -1; - } - /* Message will be sent in dpp_conn_tx_ready() */ - - return 0; -} - - -int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data, - size_t data_len) -{ - struct dpp_relay_controller *ctrl; - struct dpp_connection *conn, *found = NULL; - struct wpabuf *msg; - - /* Check if there is a successfully completed authentication for this - * and if so, continue that session (send this over TCP) and return 0. - */ - dl_list_for_each(ctrl, &dpp->controllers, - struct dpp_relay_controller, list) { - if (found) - break; - dl_list_for_each(conn, &ctrl->conn, - struct dpp_connection, list) { - if (os_memcmp(src, conn->mac_addr, - ETH_ALEN) == 0) { - found = conn; - break; - } - } - } - - if (!found) - return -1; - - msg = wpabuf_alloc(4 + 1 + data_len); - if (!msg) - return -1; - wpabuf_put_be32(msg, 1 + data_len); - wpabuf_put_u8(msg, WLAN_PA_GAS_INITIAL_REQ); - wpabuf_put_data(msg, data, data_len); - wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg); - - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = msg; - dpp_tcp_send(conn); - return 0; -} - - -static void dpp_controller_free(struct dpp_controller *ctrl) -{ - struct dpp_connection *conn, *tmp; - - if (!ctrl) - return; - - dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection, - list) - dpp_connection_remove(conn); - - if (ctrl->sock >= 0) { - close(ctrl->sock); - eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ); - } - os_free(ctrl->configurator_params); - os_free(ctrl); -} - - -static int dpp_controller_rx_auth_req(struct dpp_connection *conn, - const u8 *hdr, const u8 *buf, size_t len) -{ - const u8 *r_bootstrap, *i_bootstrap; - u16 r_bootstrap_len, i_bootstrap_len; - struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL; - - if (!conn->ctrl) - return 0; - - wpa_printf(MSG_DEBUG, "DPP: Authentication Request"); - - r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, - &r_bootstrap_len); - if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { - wpa_printf(MSG_INFO, - "Missing or invalid required Responder Bootstrapping Key Hash attribute"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", - r_bootstrap, r_bootstrap_len); - - i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH, - &i_bootstrap_len); - if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) { - wpa_printf(MSG_INFO, - "Missing or invalid required Initiator Bootstrapping Key Hash attribute"); - return -1; - } - wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash", - i_bootstrap, i_bootstrap_len); - - /* Try to find own and peer bootstrapping key matches based on the - * received hash values */ - dpp_bootstrap_find_pair(conn->ctrl->global, i_bootstrap, r_bootstrap, - &own_bi, &peer_bi); - if (!own_bi) { - wpa_printf(MSG_INFO, - "No matching own bootstrapping key found - ignore message"); - return -1; - } - - if (conn->auth) { - wpa_printf(MSG_INFO, - "Already in DPP authentication exchange - ignore new one"); - return 0; - } - - conn->auth = dpp_auth_req_rx(conn->ctrl->global->msg_ctx, - conn->ctrl->allowed_roles, - conn->ctrl->qr_mutual, - peer_bi, own_bi, -1, hdr, buf, len); - if (!conn->auth) { - wpa_printf(MSG_DEBUG, "DPP: No response generated"); - return -1; - } - - if (dpp_set_configurator(conn->ctrl->global, conn->ctrl->global->msg_ctx, - conn->auth, - conn->ctrl->configurator_params) < 0) { - dpp_connection_remove(conn); - return -1; - } - - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = wpabuf_alloc(4 + wpabuf_len(conn->auth->resp_msg) - 1); - if (!conn->msg_out) - return -1; - wpabuf_put_be32(conn->msg_out, wpabuf_len(conn->auth->resp_msg) - 1); - wpabuf_put_data(conn->msg_out, wpabuf_head_u8(conn->auth->resp_msg) + 1, - wpabuf_len(conn->auth->resp_msg) - 1); - - if (dpp_tcp_send(conn) == 1) { - if (!conn->write_eloop) { - if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, - conn, NULL) < 0) - return -1; - conn->write_eloop = 1; - } - } - - return 0; -} - - -static int dpp_controller_rx_auth_resp(struct dpp_connection *conn, - const u8 *hdr, const u8 *buf, size_t len) -{ - struct dpp_authentication *auth = conn->auth; - struct wpabuf *msg; - - if (!auth) - return -1; - - wpa_printf(MSG_DEBUG, "DPP: Authentication Response"); - - msg = dpp_auth_resp_rx(auth, hdr, buf, len); - if (!msg) { - if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) { - wpa_printf(MSG_DEBUG, - "DPP: Start wait for full response"); - return -1; - } - wpa_printf(MSG_DEBUG, "DPP: No confirm generated"); - dpp_connection_remove(conn); - return -1; - } - - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = wpabuf_alloc(4 + wpabuf_len(msg) - 1); - if (!conn->msg_out) { - wpabuf_free(msg); - return -1; - } - wpabuf_put_be32(conn->msg_out, wpabuf_len(msg) - 1); - wpabuf_put_data(conn->msg_out, wpabuf_head_u8(msg) + 1, - wpabuf_len(msg) - 1); - wpabuf_free(msg); - - conn->on_tcp_tx_complete_auth_ok = 1; - if (dpp_tcp_send(conn) == 1) { - if (!conn->write_eloop) { - if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, - conn, NULL) < 0) - return -1; - conn->write_eloop = 1; - } - } - - return 0; -} - - -static int dpp_controller_rx_auth_conf(struct dpp_connection *conn, - const u8 *hdr, const u8 *buf, size_t len) -{ - struct dpp_authentication *auth = conn->auth; - - wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation"); - - if (!auth) { - wpa_printf(MSG_DEBUG, - "DPP: No DPP Authentication in progress - drop"); - return -1; - } - - if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) { - wpa_printf(MSG_DEBUG, "DPP: Authentication failed"); - return -1; - } - - dpp_controller_auth_success(conn, 0); - return 0; -} - - -static void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx, - void *timeout_ctx) -{ - struct dpp_connection *conn = eloop_ctx; - - if (!conn->auth->waiting_conf_result) - return; - - wpa_printf(MSG_DEBUG, - "DPP: Timeout while waiting for Connection Status Result"); - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONN_STATUS_RESULT "timeout"); - dpp_connection_remove(conn); -} - - -static int dpp_controller_rx_conf_result(struct dpp_connection *conn, - const u8 *hdr, const u8 *buf, - size_t len) -{ - struct dpp_authentication *auth = conn->auth; - enum dpp_status_error status; - - if (!conn->ctrl) - return 0; - - wpa_printf(MSG_DEBUG, "DPP: Configuration Result"); - - if (!auth || !auth->waiting_conf_result) { - wpa_printf(MSG_DEBUG, - "DPP: No DPP Configuration waiting for result - drop"); - return -1; - } - - status = dpp_conf_result_rx(auth, hdr, buf, len); - if (status == DPP_STATUS_OK && auth->send_conn_status) { - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONF_SENT "wait_conn_status=1"); - wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result"); - eloop_cancel_timeout( - dpp_controller_conn_status_result_wait_timeout, - conn, NULL); - eloop_register_timeout( - 16, 0, dpp_controller_conn_status_result_wait_timeout, - conn, NULL); - return 0; - } - if (status == DPP_STATUS_OK) - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONF_SENT); - else - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONF_FAILED); - return -1; /* to remove the completed connection */ -} - - -static int dpp_controller_rx_conn_status_result(struct dpp_connection *conn, - const u8 *hdr, const u8 *buf, - size_t len) -{ - struct dpp_authentication *auth = conn->auth; - enum dpp_status_error status; - u8 ssid[SSID_MAX_LEN]; - size_t ssid_len = 0; - char *channel_list = NULL; - - if (!conn->ctrl) - return 0; - - wpa_printf(MSG_DEBUG, "DPP: Connection Status Result"); - - if (!auth || !auth->waiting_conn_status_result) { - wpa_printf(MSG_DEBUG, - "DPP: No DPP Configuration waiting for connection status result - drop"); - return -1; - } - - status = dpp_conn_status_result_rx(auth, hdr, buf, len, - ssid, &ssid_len, &channel_list); - wpa_msg(conn->ctrl->global->msg_ctx, MSG_INFO, - DPP_EVENT_CONN_STATUS_RESULT - "result=%d ssid=%s channel_list=%s", - status, wpa_ssid_txt(ssid, ssid_len), - channel_list ? channel_list : "N/A"); - os_free(channel_list); - return -1; /* to remove the completed connection */ -} - - -static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg, - size_t len) -{ - const u8 *pos, *end; - u8 type; - - wpa_printf(MSG_DEBUG, "DPP: Received DPP Action frame over TCP"); - pos = msg; - end = msg + len; - - if (end - pos < DPP_HDR_LEN || - WPA_GET_BE24(pos) != OUI_WFA || - pos[3] != DPP_OUI_TYPE) { - wpa_printf(MSG_DEBUG, "DPP: Unrecognized header"); - return -1; - } - - if (pos[4] != 1) { - wpa_printf(MSG_DEBUG, "DPP: Unsupported Crypto Suite %u", - pos[4]); - return -1; - } - type = pos[5]; - wpa_printf(MSG_DEBUG, "DPP: Received message type %u", type); - pos += DPP_HDR_LEN; - - wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", - pos, end - pos); - if (dpp_check_attrs(pos, end - pos) < 0) - return -1; - - if (conn->relay) { - wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN"); - conn->relay->tx(conn->relay->cb_ctx, conn->mac_addr, - conn->freq, msg, len); - return 0; - } - - switch (type) { - case DPP_PA_AUTHENTICATION_REQ: - return dpp_controller_rx_auth_req(conn, msg, pos, end - pos); - case DPP_PA_AUTHENTICATION_RESP: - return dpp_controller_rx_auth_resp(conn, msg, pos, end - pos); - case DPP_PA_AUTHENTICATION_CONF: - return dpp_controller_rx_auth_conf(conn, msg, pos, end - pos); - case DPP_PA_CONFIGURATION_RESULT: - return dpp_controller_rx_conf_result(conn, msg, pos, end - pos); - case DPP_PA_CONNECTION_STATUS_RESULT: - return dpp_controller_rx_conn_status_result(conn, msg, pos, - end - pos); - default: - /* TODO: missing messages types */ - wpa_printf(MSG_DEBUG, - "DPP: Unsupported frame subtype %d", type); - return -1; - } -} - - -static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg, - size_t len) -{ - const u8 *pos, *end, *next; - u8 dialog_token; - const u8 *adv_proto; - u16 slen; - struct wpabuf *resp, *buf; - struct dpp_authentication *auth = conn->auth; - - if (len < 1 + 2) - return -1; - - wpa_printf(MSG_DEBUG, - "DPP: Received DPP Configuration Request over TCP"); - - if (!conn->ctrl || !auth || !auth->auth_success) { - wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); - return -1; - } - - pos = msg; - end = msg + len; - - dialog_token = *pos++; - adv_proto = pos++; - slen = *pos++; - if (*adv_proto != WLAN_EID_ADV_PROTO || - slen > end - pos || slen < 2) - return -1; - - next = pos + slen; - pos++; /* skip QueryRespLenLimit and PAME-BI */ - - if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC || - pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA || - pos[5] != DPP_OUI_TYPE || pos[6] != 0x01) - return -1; - - pos = next; - /* Query Request */ - if (end - pos < 2) - return -1; - slen = WPA_GET_LE16(pos); - pos += 2; - if (slen > end - pos) - return -1; - - resp = dpp_conf_req_rx(auth, pos, slen); - if (!resp) - return -1; - - buf = wpabuf_alloc(4 + 18 + wpabuf_len(resp)); - if (!buf) { - wpabuf_free(resp); - return -1; - } - - wpabuf_put_be32(buf, 18 + wpabuf_len(resp)); - - wpabuf_put_u8(buf, WLAN_PA_GAS_INITIAL_RESP); - wpabuf_put_u8(buf, dialog_token); - wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); - wpabuf_put_le16(buf, 0); /* GAS Comeback Delay */ - - dpp_write_adv_proto(buf); - dpp_write_gas_query(buf, resp); - wpabuf_free(resp); - - /* Send Config Response over TCP; GAS fragmentation is taken care of by - * the Relay */ - wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf); - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = buf; - conn->on_tcp_tx_complete_gas_done = 1; - dpp_tcp_send(conn); - return 0; -} - - -static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp) -{ - struct dpp_authentication *auth = conn->auth; - int res; - struct wpabuf *msg, *encaps; - enum dpp_status_error status; - - wpa_printf(MSG_DEBUG, - "DPP: Configuration Response for local stack from TCP"); - - res = dpp_conf_resp_rx(auth, resp); - wpabuf_free(resp); - if (res < 0) { - wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); - return -1; - } - - if (conn->global->process_conf_obj) - res = conn->global->process_conf_obj(conn->global->cb_ctx, - auth); - else - res = 0; - - if (auth->peer_version < 2 || auth->conf_resp_status != DPP_STATUS_OK) - return -1; - -#ifdef CONFIG_DPP2 - wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result"); - status = res < 0 ? DPP_STATUS_CONFIG_REJECTED : DPP_STATUS_OK; - msg = dpp_build_conf_result(auth, status); - if (!msg) - return -1; - - encaps = wpabuf_alloc(4 + wpabuf_len(msg) - 1); - if (!encaps) { - wpabuf_free(msg); - return -1; - } - wpabuf_put_be32(encaps, wpabuf_len(msg) - 1); - wpabuf_put_data(encaps, wpabuf_head_u8(msg) + 1, wpabuf_len(msg) - 1); - wpabuf_free(msg); - wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", encaps); - - wpabuf_free(conn->msg_out); - conn->msg_out_pos = 0; - conn->msg_out = encaps; - conn->on_tcp_tx_complete_remove = 1; - dpp_tcp_send(conn); - - /* This exchange will be terminated in the TX status handler */ - - return 0; -#else /* CONFIG_DPP2 */ - return -1; -#endif /* CONFIG_DPP2 */ -} - - -static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg, - size_t len) -{ - struct wpabuf *buf; - u8 dialog_token; - const u8 *pos, *end, *next, *adv_proto; - u16 status, slen; - - if (len < 5 + 2) - return -1; - - wpa_printf(MSG_DEBUG, - "DPP: Received DPP Configuration Response over TCP"); - - pos = msg; - end = msg + len; - - dialog_token = *pos++; - status = WPA_GET_LE16(pos); - if (status != WLAN_STATUS_SUCCESS) { - wpa_printf(MSG_DEBUG, "DPP: Unexpected Status Code %u", status); - return -1; - } - pos += 2; - pos += 2; /* ignore GAS Comeback Delay */ - - adv_proto = pos++; - slen = *pos++; - if (*adv_proto != WLAN_EID_ADV_PROTO || - slen > end - pos || slen < 2) - return -1; - - next = pos + slen; - pos++; /* skip QueryRespLenLimit and PAME-BI */ - - if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC || - pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA || - pos[5] != DPP_OUI_TYPE || pos[6] != 0x01) - return -1; - - pos = next; - /* Query Response */ - if (end - pos < 2) - return -1; - slen = WPA_GET_LE16(pos); - pos += 2; - if (slen > end - pos) - return -1; - - buf = wpabuf_alloc(slen); - if (!buf) - return -1; - wpabuf_put_data(buf, pos, slen); - - if (!conn->relay && !conn->ctrl) - return dpp_tcp_rx_gas_resp(conn, buf); - - if (!conn->relay) { - wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); - wpabuf_free(buf); - return -1; - } - wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN"); - conn->relay->gas_resp_tx(conn->relay->cb_ctx, conn->mac_addr, - dialog_token, 0, buf); - - return 0; -} - - -static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx) -{ - struct dpp_connection *conn = eloop_ctx; - int res; - const u8 *pos; - - wpa_printf(MSG_DEBUG, "DPP: TCP data available for reading (sock %d)", - sd); - - if (conn->msg_len_octets < 4) { - u32 msglen; - - res = recv(sd, &conn->msg_len[conn->msg_len_octets], - 4 - conn->msg_len_octets, 0); - if (res < 0) { - wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", - strerror(errno)); - dpp_connection_remove(conn); - return; - } - if (res == 0) { - wpa_printf(MSG_DEBUG, - "DPP: No more data available over TCP"); - dpp_connection_remove(conn); - return; - } - wpa_printf(MSG_DEBUG, - "DPP: Received %d/%d octet(s) of message length field", - res, (int) (4 - conn->msg_len_octets)); - conn->msg_len_octets += res; - - if (conn->msg_len_octets < 4) { - wpa_printf(MSG_DEBUG, - "DPP: Need %d more octets of message length field", - (int) (4 - conn->msg_len_octets)); - return; - } - - msglen = WPA_GET_BE32(conn->msg_len); - wpa_printf(MSG_DEBUG, "DPP: Message length: %u", msglen); - if (msglen > 65535) { - wpa_printf(MSG_INFO, "DPP: Unexpectedly long message"); - dpp_connection_remove(conn); - return; - } - - wpabuf_free(conn->msg); - conn->msg = wpabuf_alloc(msglen); - } - - if (!conn->msg) { - wpa_printf(MSG_DEBUG, - "DPP: No buffer available for receiving the message"); - dpp_connection_remove(conn); - return; - } - - wpa_printf(MSG_DEBUG, "DPP: Need %u more octets of message payload", - (unsigned int) wpabuf_tailroom(conn->msg)); - - res = recv(sd, wpabuf_put(conn->msg, 0), wpabuf_tailroom(conn->msg), 0); - if (res < 0) { - wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", strerror(errno)); - dpp_connection_remove(conn); - return; - } - if (res == 0) { - wpa_printf(MSG_DEBUG, "DPP: No more data available over TCP"); - dpp_connection_remove(conn); - return; - } - wpa_printf(MSG_DEBUG, "DPP: Received %d octets", res); - wpabuf_put(conn->msg, res); - - if (wpabuf_tailroom(conn->msg) > 0) { - wpa_printf(MSG_DEBUG, - "DPP: Need %u more octets of message payload", - (unsigned int) wpabuf_tailroom(conn->msg)); - return; - } - - conn->msg_len_octets = 0; - wpa_hexdump_buf(MSG_DEBUG, "DPP: Received TCP message", conn->msg); - if (wpabuf_len(conn->msg) < 1) { - dpp_connection_remove(conn); - return; - } - - pos = wpabuf_head(conn->msg); - switch (*pos) { - case WLAN_PA_VENDOR_SPECIFIC: - if (dpp_controller_rx_action(conn, pos + 1, - wpabuf_len(conn->msg) - 1) < 0) - dpp_connection_remove(conn); - break; - case WLAN_PA_GAS_INITIAL_REQ: - if (dpp_controller_rx_gas_req(conn, pos + 1, - wpabuf_len(conn->msg) - 1) < 0) - dpp_connection_remove(conn); - break; - case WLAN_PA_GAS_INITIAL_RESP: - if (dpp_rx_gas_resp(conn, pos + 1, - wpabuf_len(conn->msg) - 1) < 0) - dpp_connection_remove(conn); - break; - default: - wpa_printf(MSG_DEBUG, "DPP: Ignore unsupported message type %u", - *pos); - break; - } -} - - -static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx) -{ - struct dpp_controller *ctrl = eloop_ctx; - struct sockaddr_in addr; - socklen_t addr_len = sizeof(addr); - int fd; - struct dpp_connection *conn; - - wpa_printf(MSG_DEBUG, "DPP: New TCP connection"); - - fd = accept(ctrl->sock, (struct sockaddr *) &addr, &addr_len); - if (fd < 0) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to accept new connection: %s", - strerror(errno)); - return; - } - wpa_printf(MSG_DEBUG, "DPP: Connection from %s:%d", - inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); - - conn = os_zalloc(sizeof(*conn)); - if (!conn) - goto fail; - - conn->global = ctrl->global; - conn->ctrl = ctrl; - conn->sock = fd; - - if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { - wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", - strerror(errno)); - goto fail; - } - - if (eloop_register_sock(conn->sock, EVENT_TYPE_READ, - dpp_controller_rx, conn, NULL) < 0) - goto fail; - conn->read_eloop = 1; - - /* TODO: eloop timeout to expire connections that do not complete in - * reasonable time */ - dl_list_add(&ctrl->conn, &conn->list); - return; - -fail: - close(fd); - os_free(conn); -} - - -int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, - const struct hostapd_ip_addr *addr, int port) -{ - struct dpp_connection *conn; - struct sockaddr_storage saddr; - socklen_t addrlen; - const u8 *hdr, *pos, *end; - char txt[100]; - - wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d", - hostapd_ip_txt(addr, txt, sizeof(txt)), port); - if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen, - addr, port) < 0) { - dpp_auth_deinit(auth); - return -1; - } - - conn = os_zalloc(sizeof(*conn)); - if (!conn) { - dpp_auth_deinit(auth); - return -1; - } - - conn->global = dpp; - conn->auth = auth; - conn->sock = socket(AF_INET, SOCK_STREAM, 0); - if (conn->sock < 0) - goto fail; - - if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { - wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", - strerror(errno)); - goto fail; - } - - if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) { - if (errno != EINPROGRESS) { - wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s", - strerror(errno)); - goto fail; - } - - /* - * Continue connecting in the background; eloop will call us - * once the connection is ready (or failed). - */ - } - - if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, - dpp_conn_tx_ready, conn, NULL) < 0) - goto fail; - conn->write_eloop = 1; - - hdr = wpabuf_head(auth->req_msg); - end = hdr + wpabuf_len(auth->req_msg); - hdr += 2; /* skip Category and Actiom */ - pos = hdr + DPP_HDR_LEN; - conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos); - if (!conn->msg_out) - goto fail; - /* Message will be sent in dpp_conn_tx_ready() */ - - /* TODO: eloop timeout to clear a connection if it does not complete - * properly */ - dl_list_add(&dpp->tcp_init, &conn->list); - return 0; -fail: - dpp_connection_free(conn); - return -1; -} - - -int dpp_controller_start(struct dpp_global *dpp, - struct dpp_controller_config *config) -{ - struct dpp_controller *ctrl; - int on = 1; - struct sockaddr_in sin; - int port; - - if (!dpp || dpp->controller) - return -1; - - ctrl = os_zalloc(sizeof(*ctrl)); - if (!ctrl) - return -1; - ctrl->global = dpp; - if (config->configurator_params) - ctrl->configurator_params = - os_strdup(config->configurator_params); - dl_list_init(&ctrl->conn); - /* TODO: configure these somehow */ - ctrl->allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR; - ctrl->qr_mutual = 0; - - ctrl->sock = socket(AF_INET, SOCK_STREAM, 0); - if (ctrl->sock < 0) - goto fail; - - if (setsockopt(ctrl->sock, SOL_SOCKET, SO_REUSEADDR, - &on, sizeof(on)) < 0) { - wpa_printf(MSG_DEBUG, - "DPP: setsockopt(SO_REUSEADDR) failed: %s", - strerror(errno)); - /* try to continue anyway */ - } - - if (fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0) { - wpa_printf(MSG_INFO, "DPP: fnctl(O_NONBLOCK) failed: %s", - strerror(errno)); - goto fail; - } - - /* TODO: IPv6 */ - os_memset(&sin, 0, sizeof(sin)); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = INADDR_ANY; - port = config->tcp_port ? config->tcp_port : DPP_TCP_PORT; - sin.sin_port = htons(port); - if (bind(ctrl->sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { - wpa_printf(MSG_INFO, - "DPP: Failed to bind Controller TCP port: %s", - strerror(errno)); - goto fail; - } - if (listen(ctrl->sock, 10 /* max backlog */) < 0 || - fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0 || - eloop_register_sock(ctrl->sock, EVENT_TYPE_READ, - dpp_controller_tcp_cb, ctrl, NULL)) - goto fail; - - dpp->controller = ctrl; - wpa_printf(MSG_DEBUG, "DPP: Controller started on TCP port %d", port); - return 0; -fail: - dpp_controller_free(ctrl); - return -1; -} - - -void dpp_controller_stop(struct dpp_global *dpp) -{ - if (dpp) { - dpp_controller_free(dpp->controller); - dpp->controller = NULL; - } + wpa_snprintf_hex(hex, sizeof(hex), hash, SHA256_MAC_LEN); + wpa_msg(msg_ctx, MSG_INFO, + DPP_EVENT_CHIRP_RX "id=%d src=" MACSTR " freq=%u hash=%s", + id, MAC2STR(src), freq, hex); } #endif /* CONFIG_DPP2 */ diff --git a/src/common/dpp.h b/src/common/dpp.h index ad1bcb0fa..2fd331b1a 100644 --- a/src/common/dpp.h +++ b/src/common/dpp.h @@ -20,9 +20,22 @@ struct crypto_ecdh; struct hostapd_ip_addr; struct dpp_global; +struct json_token; +struct dpp_reconfig_id; + +#ifdef CONFIG_TESTING_OPTIONS +#define DPP_VERSION (dpp_version_override) +extern int dpp_version_override; +#else /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_DPP2 +#define DPP_VERSION 2 +#else +#define DPP_VERSION 1 +#endif +#endif /* CONFIG_TESTING_OPTIONS */ #define DPP_HDR_LEN (4 + 2) /* OUI, OUI Type, Crypto Suite, DPP frame type */ -#define DPP_TCP_PORT 7871 +#define DPP_TCP_PORT 8908 enum dpp_public_action_frame_type { DPP_PA_AUTHENTICATION_REQ = 0, @@ -36,6 +49,11 @@ enum dpp_public_action_frame_type { DPP_PA_PKEX_COMMIT_REVEAL_RESP = 10, DPP_PA_CONFIGURATION_RESULT = 11, DPP_PA_CONNECTION_STATUS_RESULT = 12, + DPP_PA_PRESENCE_ANNOUNCEMENT = 13, + DPP_PA_RECONFIG_ANNOUNCEMENT = 14, + DPP_PA_RECONFIG_AUTH_REQ = 15, + DPP_PA_RECONFIG_AUTH_RESP = 16, + DPP_PA_RECONFIG_AUTH_CONF = 17, }; enum dpp_attribute_id { @@ -67,6 +85,12 @@ enum dpp_attribute_id { DPP_ATTR_ENVELOPED_DATA = 0x101A, DPP_ATTR_SEND_CONN_STATUS = 0x101B, DPP_ATTR_CONN_STATUS = 0x101C, + DPP_ATTR_RECONFIG_FLAGS = 0x101D, + DPP_ATTR_C_SIGN_KEY_HASH = 0x101E, + DPP_ATTR_CSR_ATTR_REQ = 0x101F, + DPP_ATTR_A_NONCE = 0x1020, + DPP_ATTR_E_PRIME_ID = 0x1021, + DPP_ATTR_CONFIGURATOR_NONCE = 0x1022, }; enum dpp_status_error { @@ -81,6 +105,15 @@ enum dpp_status_error { DPP_STATUS_NO_MATCH = 8, DPP_STATUS_CONFIG_REJECTED = 9, DPP_STATUS_NO_AP = 10, + DPP_STATUS_CONFIGURE_PENDING = 11, + DPP_STATUS_CSR_NEEDED = 12, + DPP_STATUS_CSR_BAD = 13, +}; + +/* DPP Reconfig Flags object - connectorKey values */ +enum dpp_connector_key { + DPP_CONFIG_REUSEKEY = 0, + DPP_CONFIG_REPLACEKEY = 1, }; #define DPP_CAPAB_ENROLLEE BIT(0) @@ -91,6 +124,7 @@ enum dpp_status_error { #define DPP_MAX_NONCE_LEN 32 #define DPP_MAX_HASH_LEN 64 #define DPP_MAX_SHARED_SECRET_LEN 66 +#define DPP_CP_LEN 64 struct dpp_curve_params { const char *name; @@ -120,12 +154,18 @@ struct dpp_bootstrap_info { char *pk; unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ]; unsigned int num_freq; + bool channels_listed; + u8 version; int own; EVP_PKEY *pubkey; u8 pubkey_hash[SHA256_MAC_LEN]; + u8 pubkey_hash_chirp[SHA256_MAC_LEN]; const struct dpp_curve_params *curve; unsigned int pkex_t; /* number of failures before dpp_pkex * instantiation */ + int nfc_negotiated; /* whether this has been used in NFC negotiated + * connection handover */ + char *configurator_params; }; #define PKEX_COUNTER_T_LIMIT 5 @@ -162,6 +202,7 @@ enum dpp_akm { DPP_AKM_PSK_SAE, DPP_AKM_SAE_DPP, DPP_AKM_PSK_SAE_DPP, + DPP_AKM_DOT1X, }; enum dpp_netrole { @@ -187,11 +228,14 @@ struct dpp_configuration { char *passphrase; u8 psk[32]; int psk_set; + + char *csrattrs; }; struct dpp_asymmetric_key { struct dpp_asymmetric_key *next; EVP_PKEY *csign; + EVP_PKEY *pp_key; char *config_template; char *connector_template; }; @@ -199,26 +243,36 @@ struct dpp_asymmetric_key { #define DPP_MAX_CONF_OBJ 10 struct dpp_authentication { + struct dpp_global *global; void *msg_ctx; u8 peer_version; const struct dpp_curve_params *curve; struct dpp_bootstrap_info *peer_bi; struct dpp_bootstrap_info *own_bi; struct dpp_bootstrap_info *tmp_own_bi; + struct dpp_bootstrap_info *tmp_peer_bi; u8 waiting_pubkey_hash[SHA256_MAC_LEN]; int response_pending; + int reconfig; + enum dpp_connector_key reconfig_connector_key; enum dpp_status_error auth_resp_status; enum dpp_status_error conf_resp_status; + enum dpp_status_error force_conf_resp_status; u8 peer_mac_addr[ETH_ALEN]; u8 i_nonce[DPP_MAX_NONCE_LEN]; u8 r_nonce[DPP_MAX_NONCE_LEN]; u8 e_nonce[DPP_MAX_NONCE_LEN]; + u8 c_nonce[DPP_MAX_NONCE_LEN]; u8 i_capab; u8 r_capab; + enum dpp_netrole e_netrole; EVP_PKEY *own_protocol_key; EVP_PKEY *peer_protocol_key; + EVP_PKEY *reconfig_old_protocol_key; struct wpabuf *req_msg; struct wpabuf *resp_msg; + struct wpabuf *reconfig_req_msg; + struct wpabuf *reconfig_resp_msg; /* Intersection of possible frequencies for initiating DPP * Authentication exchange */ unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ]; @@ -236,6 +290,7 @@ struct dpp_authentication { u8 k1[DPP_MAX_HASH_LEN]; u8 k2[DPP_MAX_HASH_LEN]; u8 ke[DPP_MAX_HASH_LEN]; + u8 bk[DPP_MAX_HASH_LEN]; int initiator; int waiting_auth_resp; int waiting_auth_conf; @@ -248,8 +303,10 @@ struct dpp_authentication { int waiting_conf_result; int waiting_conn_status_result; int auth_success; + bool reconfig_success; struct wpabuf *conf_req; const struct wpabuf *conf_resp; /* owned by GAS server */ + struct wpabuf *conf_resp_tcp; struct dpp_configuration *conf_ap; struct dpp_configuration *conf2_ap; struct dpp_configuration *conf_sta; @@ -266,6 +323,11 @@ struct dpp_authentication { int psk_set; enum dpp_akm akm; struct wpabuf *c_sign_key; + struct wpabuf *certbag; + struct wpabuf *certs; + struct wpabuf *cacert; + char *server_name; + struct wpabuf *pp_key; } conf_obj[DPP_MAX_CONF_OBJ]; unsigned int num_conf_obj; struct dpp_asymmetric_key *conf_key_pkg; @@ -274,6 +336,18 @@ struct dpp_authentication { int send_conn_status; int conn_status_requested; int akm_use_selector; + int configurator_set; + u8 transaction_id; + u8 *csrattrs; + size_t csrattrs_len; + bool waiting_csr; + struct wpabuf *csr; + struct wpabuf *priv_key; /* DER-encoded private key used for csr */ + bool waiting_cert; + char *trusted_eap_server_name; + struct wpabuf *cacert; + struct wpabuf *certbag; + void *cert_resp_ctx; #ifdef CONFIG_TESTING_OPTIONS char *config_obj_override; char *discovery_override; @@ -287,8 +361,12 @@ struct dpp_configurator { unsigned int id; int own; EVP_PKEY *csign; + u8 kid_hash[SHA256_MAC_LEN]; char *kid; const struct dpp_curve_params *curve; + char *connector; /* own Connector for reconfiguration */ + EVP_PKEY *connector_key; + EVP_PKEY *pp_key; }; struct dpp_introduction { @@ -301,6 +379,7 @@ struct dpp_relay_config { const struct hostapd_ip_addr *ipaddr; const u8 *pkhash; + void *msg_ctx; void *cb_ctx; void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg, size_t len); @@ -311,6 +390,12 @@ struct dpp_relay_config { struct dpp_controller_config { const char *configurator_params; int tcp_port; + u8 allowed_roles; + int qr_mutual; + enum dpp_netrole netrole; + void *msg_ctx; + void *cb_ctx; + int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); }; #ifdef CONFIG_TESTING_OPTIONS @@ -422,15 +507,16 @@ extern size_t dpp_nonce_override_len; void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info); const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type); -int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi); int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi, const char *chan_list); int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac); int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info); int dpp_nfc_update_bi(struct dpp_bootstrap_info *own_bi, struct dpp_bootstrap_info *peer_bi); +struct dpp_authentication * +dpp_alloc_auth(struct dpp_global *dpp, void *msg_ctx); struct hostapd_hw_modes; -struct dpp_authentication * dpp_auth_init(void *msg_ctx, +struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx, struct dpp_bootstrap_info *peer_bi, struct dpp_bootstrap_info *own_bi, u8 dpp_allowed_roles, @@ -438,8 +524,8 @@ struct dpp_authentication * dpp_auth_init(void *msg_ctx, struct hostapd_hw_modes *own_modes, u16 num_modes); struct dpp_authentication * -dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, - struct dpp_bootstrap_info *peer_bi, +dpp_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, u8 dpp_allowed_roles, + int qr_mutual, struct dpp_bootstrap_info *peer_bi, struct dpp_bootstrap_info *own_bi, unsigned int freq, const u8 *hdr, const u8 *attr_start, size_t attr_len); @@ -464,11 +550,13 @@ int dpp_akm_dpp(enum dpp_akm akm); int dpp_akm_ver2(enum dpp_akm akm); int dpp_configuration_valid(const struct dpp_configuration *conf); void dpp_configuration_free(struct dpp_configuration *conf); -int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx, - struct dpp_authentication *auth, - const char *cmd); +int dpp_set_configurator(struct dpp_authentication *auth, const char *cmd); void dpp_auth_deinit(struct dpp_authentication *auth); struct wpabuf * +dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, + u16 e_nonce_len, enum dpp_netrole netrole, + bool cert_req); +struct wpabuf * dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, size_t attr_len); int dpp_conf_resp_rx(struct dpp_authentication *auth, @@ -498,9 +586,6 @@ const char * dpp_akm_selector_str(enum dpp_akm akm); int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf, size_t buflen); void dpp_configurator_free(struct dpp_configurator *conf); -struct dpp_configurator * -dpp_keygen_configurator(const char *curve, const u8 *privkey, - size_t privkey_len); int dpp_configurator_own_config(struct dpp_authentication *auth, const char *curve, int ap); enum dpp_status_error @@ -545,6 +630,11 @@ struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key, int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len); void dpp_pfs_free(struct dpp_pfs *pfs); +struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, + const char *name); +struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7); +int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr); + struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp, const char *uri); struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp, @@ -559,16 +649,21 @@ dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer, const char * dpp_bootstrap_get_uri(struct dpp_global *dpp, unsigned int id); int dpp_bootstrap_info(struct dpp_global *dpp, int id, char *reply, int reply_size); +int dpp_bootstrap_set(struct dpp_global *dpp, int id, const char *params); void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap, const u8 *r_bootstrap, struct dpp_bootstrap_info **own_bi, struct dpp_bootstrap_info **peer_bi); +struct dpp_bootstrap_info * dpp_bootstrap_find_chirp(struct dpp_global *dpp, + const u8 *hash); int dpp_configurator_add(struct dpp_global *dpp, const char *cmd); int dpp_configurator_remove(struct dpp_global *dpp, const char *id); int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id, char *buf, size_t buflen); int dpp_configurator_from_backup(struct dpp_global *dpp, struct dpp_asymmetric_key *key); +struct dpp_configurator * dpp_configurator_find_kid(struct dpp_global *dpp, + const u8 *kid); int dpp_relay_add_controller(struct dpp_global *dpp, struct dpp_relay_config *config); int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, @@ -579,18 +674,61 @@ int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data, int dpp_controller_start(struct dpp_global *dpp, struct dpp_controller_config *config); void dpp_controller_stop(struct dpp_global *dpp); +struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp, + unsigned int id); +void dpp_controller_new_qr_code(struct dpp_global *dpp, + struct dpp_bootstrap_info *bi); int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, - const struct hostapd_ip_addr *addr, int port); + const struct hostapd_ip_addr *addr, int port, + const char *name, enum dpp_netrole netrole, void *msg_ctx, + void *cb_ctx, + int (*process_conf_obj)(void *ctx, + struct dpp_authentication *auth)); + +struct wpabuf * dpp_build_presence_announcement(struct dpp_bootstrap_info *bi); +void dpp_notify_chirp_received(void *msg_ctx, int id, const u8 *src, + unsigned int freq, const u8 *hash); struct dpp_global_config { - void *msg_ctx; void *cb_ctx; - int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); + void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi); }; struct dpp_global * dpp_global_init(struct dpp_global_config *config); void dpp_global_clear(struct dpp_global *dpp); void dpp_global_deinit(struct dpp_global *dpp); +/* dpp_reconfig.c */ + +struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, + size_t csign_key_len, + const u8 *net_access_key, + size_t net_access_key_len, + struct dpp_reconfig_id *id); +struct dpp_authentication * +dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, + struct dpp_configurator *conf, unsigned int freq, u16 group, + const u8 *a_nonce_attr, size_t a_nonce_len, + const u8 *e_id_attr, size_t e_id_len); +struct dpp_authentication * +dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, + const char *own_connector, + const u8 *net_access_key, size_t net_access_key_len, + const u8 *csign_key, size_t csign_key_len, + unsigned int freq, const u8 *hdr, + const u8 *attr_start, size_t attr_len); +struct wpabuf * +dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len); +int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len); + +struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key, + size_t csign_key_len, + const u8 *pp_key, + size_t pp_key_len); +int dpp_update_reconfig_id(struct dpp_reconfig_id *id); +void dpp_free_reconfig_id(struct dpp_reconfig_id *id); + #endif /* CONFIG_DPP */ #endif /* DPP_H */ diff --git a/src/common/dpp_auth.c b/src/common/dpp_auth.c new file mode 100644 index 000000000..f79cfef4e --- /dev/null +++ b/src/common/dpp_auth.c @@ -0,0 +1,1976 @@ +/* + * DPP authentication exchange + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018-2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" +#include "crypto/random.h" +#include "dpp.h" +#include "dpp_i.h" + + +#ifdef CONFIG_TESTING_OPTIONS +u8 dpp_protocol_key_override[600]; +size_t dpp_protocol_key_override_len = 0; +u8 dpp_nonce_override[DPP_MAX_NONCE_LEN]; +size_t dpp_nonce_override_len = 0; +#endif /* CONFIG_TESTING_OPTIONS */ + + +static void dpp_build_attr_i_bootstrap_key_hash(struct wpabuf *msg, + const u8 *hash) +{ + if (hash) { + wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash"); + wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH); + wpabuf_put_le16(msg, SHA256_MAC_LEN); + wpabuf_put_data(msg, hash, SHA256_MAC_LEN); + } +} + + +static void dpp_auth_success(struct dpp_authentication *auth) +{ + wpa_printf(MSG_DEBUG, + "DPP: Authentication success - clear temporary keys"); + os_memset(auth->Mx, 0, sizeof(auth->Mx)); + auth->Mx_len = 0; + os_memset(auth->Nx, 0, sizeof(auth->Nx)); + auth->Nx_len = 0; + os_memset(auth->Lx, 0, sizeof(auth->Lx)); + auth->Lx_len = 0; + os_memset(auth->k1, 0, sizeof(auth->k1)); + os_memset(auth->k2, 0, sizeof(auth->k2)); + + auth->auth_success = 1; +} + + +static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth, + const struct wpabuf *pi, + size_t nonce_len, + const u8 *r_pubkey_hash, + const u8 *i_pubkey_hash, + unsigned int neg_freq) +{ + struct wpabuf *msg; + u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1]; + u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE]; + u8 *pos; + const u8 *addr[2]; + size_t len[2], siv_len, attr_len; + u8 *attr_start, *attr_end; + + /* Build DPP Authentication Request frame attributes */ + attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + (pi ? wpabuf_len(pi) : 0) + + 4 + sizeof(wrapped_data); + if (neg_freq > 0) + attr_len += 4 + 2; +#ifdef CONFIG_DPP2 + attr_len += 5; +#endif /* CONFIG_DPP2 */ +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len); + if (!msg) + return NULL; + + attr_start = wpabuf_put(msg, 0); + + /* Responder Bootstrapping Key Hash */ + dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); + + /* Initiator Bootstrapping Key Hash */ + dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); + + /* Initiator Protocol Key */ + if (pi) { + wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY); + wpabuf_put_le16(msg, wpabuf_len(pi)); + wpabuf_put_buf(msg, pi); + } + + /* Channel */ + if (neg_freq > 0) { + u8 op_class, channel; + + if (ieee80211_freq_to_channel_ext(neg_freq, 0, 0, &op_class, + &channel) == + NUM_HOSTAPD_MODES) { + wpa_printf(MSG_INFO, + "DPP: Unsupported negotiation frequency request: %d", + neg_freq); + wpabuf_free(msg); + return NULL; + } + wpabuf_put_le16(msg, DPP_ATTR_CHANNEL); + wpabuf_put_le16(msg, 2); + wpabuf_put_u8(msg, op_class); + wpabuf_put_u8(msg, channel); + } + +#ifdef CONFIG_DPP2 + /* Protocol Version */ + if (DPP_VERSION > 1) { + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + } +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); + goto skip_wrapped_data; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Wrapped data ({I-nonce, I-capabilities}k1) */ + pos = clear; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); + goto skip_i_nonce; + } + if (dpp_test == DPP_TEST_INVALID_I_NONCE_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-nonce"); + WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); + pos += 2; + WPA_PUT_LE16(pos, nonce_len - 1); + pos += 2; + os_memcpy(pos, auth->i_nonce, nonce_len - 1); + pos += nonce_len - 1; + goto skip_i_nonce; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* I-nonce */ + WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); + pos += 2; + WPA_PUT_LE16(pos, nonce_len); + pos += 2; + os_memcpy(pos, auth->i_nonce, nonce_len); + pos += nonce_len; + +#ifdef CONFIG_TESTING_OPTIONS +skip_i_nonce: + if (dpp_test == DPP_TEST_NO_I_CAPAB_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-capab"); + goto skip_i_capab; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* I-capabilities */ + WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES); + pos += 2; + WPA_PUT_LE16(pos, 1); + pos += 2; + auth->i_capab = auth->allowed_roles; + *pos++ = auth->i_capab; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_ZERO_I_CAPAB) { + wpa_printf(MSG_INFO, "DPP: TESTING - zero I-capabilities"); + pos[-1] = 0; + } +skip_i_capab: +#endif /* CONFIG_TESTING_OPTIONS */ + + attr_end = wpabuf_put(msg, 0); + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + siv_len = pos - clear; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); + if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len, + 2, addr, len, wrapped_data) < 0) { + wpabuf_free(msg); + return NULL; + } + siv_len += AES_BLOCK_SIZE; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, siv_len); + + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, siv_len); + wpabuf_put_data(msg, wrapped_data, siv_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Authentication Request frame attributes", msg); + + return msg; +} + + +static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth, + enum dpp_status_error status, + const struct wpabuf *pr, + size_t nonce_len, + const u8 *r_pubkey_hash, + const u8 *i_pubkey_hash, + const u8 *r_nonce, const u8 *i_nonce, + const u8 *wrapped_r_auth, + size_t wrapped_r_auth_len, + const u8 *siv_key) +{ + struct wpabuf *msg; +#define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \ + 4 + 4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE + u8 clear[DPP_AUTH_RESP_CLEAR_LEN]; + u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE]; + const u8 *addr[2]; + size_t len[2], siv_len, attr_len; + u8 *attr_start, *attr_end, *pos; + + auth->waiting_auth_conf = 1; + auth->auth_resp_tries = 0; + + /* Build DPP Authentication Response frame attributes */ + attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + + 4 + (pr ? wpabuf_len(pr) : 0) + 4 + sizeof(wrapped_data); +#ifdef CONFIG_DPP2 + attr_len += 5; +#endif /* CONFIG_DPP2 */ +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len); + if (!msg) + return NULL; + + attr_start = wpabuf_put(msg, 0); + + /* DPP Status */ + if (status != 255) + dpp_build_attr_status(msg, status); + + /* Responder Bootstrapping Key Hash */ + dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); + + /* Initiator Bootstrapping Key Hash (mutual authentication) */ + dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); + + /* Responder Protocol Key */ + if (pr) { + wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY); + wpabuf_put_le16(msg, wpabuf_len(pr)); + wpabuf_put_buf(msg, pr); + } + +#ifdef CONFIG_DPP2 + /* Protocol Version */ + if (auth->peer_version >= 2) { + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + } +#endif /* CONFIG_DPP2 */ + + attr_end = wpabuf_put(msg, 0); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); + goto skip_wrapped_data; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */ + pos = clear; + + if (r_nonce) { + /* R-nonce */ + WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE); + pos += 2; + WPA_PUT_LE16(pos, nonce_len); + pos += 2; + os_memcpy(pos, r_nonce, nonce_len); + pos += nonce_len; + } + + if (i_nonce) { + /* I-nonce */ + WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); + pos += 2; + WPA_PUT_LE16(pos, nonce_len); + pos += 2; + os_memcpy(pos, i_nonce, nonce_len); +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - I-nonce mismatch"); + pos[nonce_len / 2] ^= 0x01; + } +#endif /* CONFIG_TESTING_OPTIONS */ + pos += nonce_len; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_R_CAPAB_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-capab"); + goto skip_r_capab; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* R-capabilities */ + WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES); + pos += 2; + WPA_PUT_LE16(pos, 1); + pos += 2; + auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR : + DPP_CAPAB_ENROLLEE; + *pos++ = auth->r_capab; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_ZERO_R_CAPAB) { + wpa_printf(MSG_INFO, "DPP: TESTING - zero R-capabilities"); + pos[-1] = 0; + } else if (dpp_test == DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - incompatible R-capabilities"); + if ((auth->i_capab & DPP_CAPAB_ROLE_MASK) == + (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) + pos[-1] = 0; + else + pos[-1] = auth->configurator ? DPP_CAPAB_ENROLLEE : + DPP_CAPAB_CONFIGURATOR; + } +skip_r_capab: +#endif /* CONFIG_TESTING_OPTIONS */ + + if (wrapped_r_auth) { + /* {R-auth}ke */ + WPA_PUT_LE16(pos, DPP_ATTR_WRAPPED_DATA); + pos += 2; + WPA_PUT_LE16(pos, wrapped_r_auth_len); + pos += 2; + os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len); + pos += wrapped_r_auth_len; + } + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + siv_len = pos - clear; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); + if (aes_siv_encrypt(siv_key, auth->curve->hash_len, clear, siv_len, + 2, addr, len, wrapped_data) < 0) { + wpabuf_free(msg); + return NULL; + } + siv_len += AES_BLOCK_SIZE; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, siv_len); + + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, siv_len); + wpabuf_put_data(msg, wrapped_data, siv_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Authentication Response frame attributes", msg); + return msg; +} + + +static int dpp_auth_build_resp_ok(struct dpp_authentication *auth) +{ + size_t nonce_len; + size_t secret_len; + struct wpabuf *msg, *pr = NULL; + u8 r_auth[4 + DPP_MAX_HASH_LEN]; + u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE], *w_r_auth; + size_t wrapped_r_auth_len; + int ret = -1; + const u8 *r_pubkey_hash, *i_pubkey_hash, *r_nonce, *i_nonce; + enum dpp_status_error status = DPP_STATUS_OK; +#ifdef CONFIG_TESTING_OPTIONS + u8 test_hash[SHA256_MAC_LEN]; +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response"); + if (!auth->own_bi) + return -1; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_nonce_override_len > 0) { + wpa_printf(MSG_INFO, "DPP: TESTING - override R-nonce"); + nonce_len = dpp_nonce_override_len; + os_memcpy(auth->r_nonce, dpp_nonce_override, nonce_len); + } else { + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->r_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, + "DPP: Failed to generate R-nonce"); + goto fail; + } + } +#else /* CONFIG_TESTING_OPTIONS */ + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->r_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce"); + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len); + + EVP_PKEY_free(auth->own_protocol_key); +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_protocol_key_override_len) { + const struct dpp_curve_params *tmp_curve; + + wpa_printf(MSG_INFO, + "DPP: TESTING - override protocol key"); + auth->own_protocol_key = dpp_set_keypair( + &tmp_curve, dpp_protocol_key_override, + dpp_protocol_key_override_len); + } else { + auth->own_protocol_key = dpp_gen_keypair(auth->curve); + } +#else /* CONFIG_TESTING_OPTIONS */ + auth->own_protocol_key = dpp_gen_keypair(auth->curve); +#endif /* CONFIG_TESTING_OPTIONS */ + if (!auth->own_protocol_key) + goto fail; + + pr = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (!pr) + goto fail; + + /* ECDH: N = pR * PI */ + if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key, + auth->Nx, &secret_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)", + auth->Nx, auth->secret_len); + auth->Nx_len = auth->secret_len; + + if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2, + auth->curve->hash_len) < 0) + goto fail; + + if (auth->own_bi && auth->peer_bi) { + /* Mutual authentication */ + if (dpp_auth_derive_l_responder(auth) < 0) + goto fail; + } + + if (dpp_derive_bk_ke(auth) < 0) + goto fail; + + /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ + WPA_PUT_LE16(r_auth, DPP_ATTR_R_AUTH_TAG); + WPA_PUT_LE16(&r_auth[2], auth->curve->hash_len); + if (dpp_gen_r_auth(auth, r_auth + 4) < 0) + goto fail; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - R-auth mismatch"); + r_auth[4 + auth->curve->hash_len / 2] ^= 0x01; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, + r_auth, 4 + auth->curve->hash_len, + 0, NULL, NULL, wrapped_r_auth) < 0) + goto fail; + wrapped_r_auth_len = 4 + auth->curve->hash_len + AES_BLOCK_SIZE; + wpa_hexdump(MSG_DEBUG, "DPP: {R-auth}ke", + wrapped_r_auth, wrapped_r_auth_len); + w_r_auth = wrapped_r_auth; + + r_pubkey_hash = auth->own_bi->pubkey_hash; + if (auth->peer_bi) + i_pubkey_hash = auth->peer_bi->pubkey_hash; + else + i_pubkey_hash = NULL; + + i_nonce = auth->i_nonce; + r_nonce = auth->r_nonce; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); + r_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid R-Bootstrap Key Hash"); + os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + r_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); + i_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid I-Bootstrap Key Hash"); + if (i_pubkey_hash) + os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); + else + os_memset(test_hash, 0, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + i_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Proto Key"); + wpabuf_free(pr); + pr = NULL; + } else if (dpp_test == DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid R-Proto Key"); + wpabuf_free(pr); + pr = wpabuf_alloc(2 * auth->curve->prime_len); + if (!pr || dpp_test_gen_invalid_key(pr, auth->curve) < 0) + goto fail; + } else if (dpp_test == DPP_TEST_NO_R_AUTH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth"); + w_r_auth = NULL; + wrapped_r_auth_len = 0; + } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); + status = 255; + } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); + status = 254; + } else if (dpp_test == DPP_TEST_NO_R_NONCE_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-nonce"); + r_nonce = NULL; + } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); + i_nonce = NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + msg = dpp_auth_build_resp(auth, status, pr, nonce_len, + r_pubkey_hash, i_pubkey_hash, + r_nonce, i_nonce, + w_r_auth, wrapped_r_auth_len, + auth->k2); + if (!msg) + goto fail; + wpabuf_free(auth->resp_msg); + auth->resp_msg = msg; + ret = 0; +fail: + wpabuf_free(pr); + return ret; +} + + +static int dpp_auth_build_resp_status(struct dpp_authentication *auth, + enum dpp_status_error status) +{ + struct wpabuf *msg; + const u8 *r_pubkey_hash, *i_pubkey_hash, *i_nonce; +#ifdef CONFIG_TESTING_OPTIONS + u8 test_hash[SHA256_MAC_LEN]; +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!auth->own_bi) + return -1; + wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response"); + + r_pubkey_hash = auth->own_bi->pubkey_hash; + if (auth->peer_bi) + i_pubkey_hash = auth->peer_bi->pubkey_hash; + else + i_pubkey_hash = NULL; + + i_nonce = auth->i_nonce; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); + r_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid R-Bootstrap Key Hash"); + os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + r_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); + i_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid I-Bootstrap Key Hash"); + if (i_pubkey_hash) + os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); + else + os_memset(test_hash, 0, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + i_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); + status = 255; + } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); + i_nonce = NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + msg = dpp_auth_build_resp(auth, status, NULL, auth->curve->nonce_len, + r_pubkey_hash, i_pubkey_hash, + NULL, i_nonce, NULL, 0, auth->k1); + if (!msg) + return -1; + wpabuf_free(auth->resp_msg); + auth->resp_msg = msg; + return 0; +} + + +struct dpp_authentication * +dpp_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, u8 dpp_allowed_roles, + int qr_mutual, struct dpp_bootstrap_info *peer_bi, + struct dpp_bootstrap_info *own_bi, + unsigned int freq, const u8 *hdr, const u8 *attr_start, + size_t attr_len) +{ + EVP_PKEY *pi = NULL; + EVP_PKEY_CTX *ctx = NULL; + size_t secret_len; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + const u8 *wrapped_data, *i_proto, *i_nonce, *i_capab, *i_bootstrap, + *channel; + u16 wrapped_data_len, i_proto_len, i_nonce_len, i_capab_len, + i_bootstrap_len, channel_len; + struct dpp_authentication *auth = NULL; +#ifdef CONFIG_DPP2 + const u8 *version; + u16 version_len; +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_AUTH_REQ) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at Authentication Request"); + return NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Wrapped Data attribute"); + return NULL; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data", + wrapped_data, wrapped_data_len); + attr_len = wrapped_data - 4 - attr_start; + + auth = dpp_alloc_auth(dpp, msg_ctx); + if (!auth) + goto fail; + if (peer_bi && peer_bi->configurator_params && + dpp_set_configurator(auth, peer_bi->configurator_params) < 0) + goto fail; + auth->peer_bi = peer_bi; + auth->own_bi = own_bi; + auth->curve = own_bi->curve; + auth->curr_freq = freq; + + auth->peer_version = 1; /* default to the first version */ +#ifdef CONFIG_DPP2 + version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (version && DPP_VERSION > 1) { + if (version_len < 1 || version[0] == 0) { + dpp_auth_fail(auth, + "Invalid Protocol Version attribute"); + goto fail; + } + auth->peer_version = version[0]; + wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", + auth->peer_version); + } +#endif /* CONFIG_DPP2 */ + + channel = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CHANNEL, + &channel_len); + if (channel) { + int neg_freq; + + if (channel_len < 2) { + dpp_auth_fail(auth, "Too short Channel attribute"); + goto fail; + } + + neg_freq = ieee80211_chan_to_freq(NULL, channel[0], channel[1]); + wpa_printf(MSG_DEBUG, + "DPP: Initiator requested different channel for negotiation: op_class=%u channel=%u --> freq=%d", + channel[0], channel[1], neg_freq); + if (neg_freq < 0) { + dpp_auth_fail(auth, + "Unsupported Channel attribute value"); + goto fail; + } + + if (auth->curr_freq != (unsigned int) neg_freq) { + wpa_printf(MSG_DEBUG, + "DPP: Changing negotiation channel from %u MHz to %u MHz", + freq, neg_freq); + auth->curr_freq = neg_freq; + } + } + + i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY, + &i_proto_len); + if (!i_proto) { + dpp_auth_fail(auth, + "Missing required Initiator Protocol Key attribute"); + goto fail; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key", + i_proto, i_proto_len); + + /* M = bR * PI */ + pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len); + if (!pi) { + dpp_auth_fail(auth, "Invalid Initiator Protocol Key"); + goto fail; + } + dpp_debug_print_key("Peer (Initiator) Protocol Key", pi); + + if (dpp_ecdh(own_bi->pubkey, pi, auth->Mx, &secret_len) < 0) + goto fail; + auth->secret_len = secret_len; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)", + auth->Mx, auth->secret_len); + auth->Mx_len = auth->secret_len; + + if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1, + auth->curve->hash_len) < 0) + goto fail; + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->k1, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + os_memcpy(auth->i_nonce, i_nonce, i_nonce_len); + + i_capab = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_I_CAPABILITIES, + &i_capab_len); + if (!i_capab || i_capab_len < 1) { + dpp_auth_fail(auth, "Missing or invalid I-capabilities"); + goto fail; + } + auth->i_capab = i_capab[0]; + wpa_printf(MSG_DEBUG, "DPP: I-capabilities: 0x%02x", auth->i_capab); + + bin_clear_free(unwrapped, unwrapped_len); + unwrapped = NULL; + + switch (auth->i_capab & DPP_CAPAB_ROLE_MASK) { + case DPP_CAPAB_ENROLLEE: + if (!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)) { + wpa_printf(MSG_DEBUG, + "DPP: Local policy does not allow Configurator role"); + goto not_compatible; + } + wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator"); + auth->configurator = 1; + break; + case DPP_CAPAB_CONFIGURATOR: + if (!(dpp_allowed_roles & DPP_CAPAB_ENROLLEE)) { + wpa_printf(MSG_DEBUG, + "DPP: Local policy does not allow Enrollee role"); + goto not_compatible; + } + wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee"); + auth->configurator = 0; + break; + case DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE: + if (dpp_allowed_roles & DPP_CAPAB_ENROLLEE) { + wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee"); + auth->configurator = 0; + } else if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) { + wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator"); + auth->configurator = 1; + } else { + wpa_printf(MSG_DEBUG, + "DPP: Local policy does not allow Configurator/Enrollee role"); + goto not_compatible; + } + break; + default: + wpa_printf(MSG_DEBUG, "DPP: Unexpected role in I-capabilities"); + wpa_msg(auth->msg_ctx, MSG_INFO, + DPP_EVENT_FAIL "Invalid role in I-capabilities 0x%02x", + auth->i_capab & DPP_CAPAB_ROLE_MASK); + goto fail; + } + + auth->peer_protocol_key = pi; + pi = NULL; + if (qr_mutual && !peer_bi && own_bi->type == DPP_BOOTSTRAP_QR_CODE) { + char hex[SHA256_MAC_LEN * 2 + 1]; + + wpa_printf(MSG_DEBUG, + "DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time"); + if (dpp_auth_build_resp_status(auth, + DPP_STATUS_RESPONSE_PENDING) < 0) + goto fail; + i_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_I_BOOTSTRAP_KEY_HASH, + &i_bootstrap_len); + if (i_bootstrap && i_bootstrap_len == SHA256_MAC_LEN) { + auth->response_pending = 1; + os_memcpy(auth->waiting_pubkey_hash, + i_bootstrap, i_bootstrap_len); + wpa_snprintf_hex(hex, sizeof(hex), i_bootstrap, + i_bootstrap_len); + } else { + hex[0] = '\0'; + } + + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_SCAN_PEER_QR_CODE + "%s", hex); + return auth; + } + if (dpp_auth_build_resp_ok(auth) < 0) + goto fail; + + return auth; + +not_compatible: + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE + "i-capab=0x%02x", auth->i_capab); + if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) + auth->configurator = 1; + else + auth->configurator = 0; + auth->peer_protocol_key = pi; + pi = NULL; + if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0) + goto fail; + + auth->remove_on_tx_status = 1; + return auth; +fail: + bin_clear_free(unwrapped, unwrapped_len); + EVP_PKEY_free(pi); + EVP_PKEY_CTX_free(ctx); + dpp_auth_deinit(auth); + return NULL; +} + + +int dpp_notify_new_qr_code(struct dpp_authentication *auth, + struct dpp_bootstrap_info *peer_bi) +{ + if (!auth || !auth->response_pending || + os_memcmp(auth->waiting_pubkey_hash, peer_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) + return 0; + + wpa_printf(MSG_DEBUG, + "DPP: New scanned QR Code has matching public key that was needed to continue DPP Authentication exchange with " + MACSTR, MAC2STR(auth->peer_mac_addr)); + auth->peer_bi = peer_bi; + + if (dpp_auth_build_resp_ok(auth) < 0) + return -1; + + return 1; +} + + +static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth, + enum dpp_status_error status) +{ + struct wpabuf *msg; + u8 i_auth[4 + DPP_MAX_HASH_LEN]; + size_t i_auth_len; + u8 r_nonce[4 + DPP_MAX_NONCE_LEN]; + size_t r_nonce_len; + const u8 *addr[2]; + size_t len[2], attr_len; + u8 *wrapped_i_auth; + u8 *wrapped_r_nonce; + u8 *attr_start, *attr_end; + const u8 *r_pubkey_hash, *i_pubkey_hash; +#ifdef CONFIG_TESTING_OPTIONS + u8 test_hash[SHA256_MAC_LEN]; +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation"); + + i_auth_len = 4 + auth->curve->hash_len; + r_nonce_len = 4 + auth->curve->nonce_len; + /* Build DPP Authentication Confirmation frame attributes */ + attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + + 4 + i_auth_len + r_nonce_len + AES_BLOCK_SIZE; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, attr_len); + if (!msg) + goto fail; + + attr_start = wpabuf_put(msg, 0); + + r_pubkey_hash = auth->peer_bi->pubkey_hash; + if (auth->own_bi) + i_pubkey_hash = auth->own_bi->pubkey_hash; + else + i_pubkey_hash = NULL; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_STATUS_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); + goto skip_status; + } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); + status = 254; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* DPP Status */ + dpp_build_attr_status(msg, status); + +#ifdef CONFIG_TESTING_OPTIONS +skip_status: + if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); + r_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid R-Bootstrap Key Hash"); + os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + r_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); + i_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid I-Bootstrap Key Hash"); + if (i_pubkey_hash) + os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); + else + os_memset(test_hash, 0, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + i_pubkey_hash = test_hash; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Responder Bootstrapping Key Hash */ + dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); + + /* Initiator Bootstrapping Key Hash (mutual authentication) */ + dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF) + goto skip_wrapped_data; + if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF) + i_auth_len = 0; +#endif /* CONFIG_TESTING_OPTIONS */ + + attr_end = wpabuf_put(msg, 0); + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + if (status == DPP_STATUS_OK) { + /* I-auth wrapped with ke */ + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE); + wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF) + goto skip_i_auth; +#endif /* CONFIG_TESTING_OPTIONS */ + + /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] + * 1) */ + WPA_PUT_LE16(i_auth, DPP_ATTR_I_AUTH_TAG); + WPA_PUT_LE16(&i_auth[2], auth->curve->hash_len); + if (dpp_gen_i_auth(auth, i_auth + 4) < 0) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - I-auth mismatch"); + i_auth[4 + auth->curve->hash_len / 2] ^= 0x01; + } +skip_i_auth: +#endif /* CONFIG_TESTING_OPTIONS */ + if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, + i_auth, i_auth_len, + 2, addr, len, wrapped_i_auth) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke", + wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE); + } else { + /* R-nonce wrapped with k2 */ + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, r_nonce_len + AES_BLOCK_SIZE); + wrapped_r_nonce = wpabuf_put(msg, r_nonce_len + AES_BLOCK_SIZE); + + WPA_PUT_LE16(r_nonce, DPP_ATTR_R_NONCE); + WPA_PUT_LE16(&r_nonce[2], auth->curve->nonce_len); + os_memcpy(r_nonce + 4, auth->r_nonce, auth->curve->nonce_len); + + if (aes_siv_encrypt(auth->k2, auth->curve->hash_len, + r_nonce, r_nonce_len, + 2, addr, len, wrapped_r_nonce) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: {R-nonce}k2", + wrapped_r_nonce, r_nonce_len + AES_BLOCK_SIZE); + } + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Authentication Confirmation frame attributes", + msg); + if (status == DPP_STATUS_OK) + dpp_auth_success(auth); + + return msg; + +fail: + wpabuf_free(msg); + return NULL; +} + + +static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth) +{ + struct dpp_bootstrap_info *bi; + + if (auth->own_bi) + return 0; /* already generated */ + + bi = os_zalloc(sizeof(*bi)); + if (!bi) + return -1; + bi->type = DPP_BOOTSTRAP_QR_CODE; + if (dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0) < 0 || + dpp_gen_uri(bi) < 0) + goto fail; + wpa_printf(MSG_DEBUG, + "DPP: Auto-generated own bootstrapping key info: URI %s", + bi->uri); + + auth->tmp_own_bi = auth->own_bi = bi; + + return 0; +fail: + dpp_bootstrap_info_free(bi); + return -1; +} + + +struct dpp_authentication * dpp_auth_init(struct dpp_global *dpp, void *msg_ctx, + struct dpp_bootstrap_info *peer_bi, + struct dpp_bootstrap_info *own_bi, + u8 dpp_allowed_roles, + unsigned int neg_freq, + struct hostapd_hw_modes *own_modes, + u16 num_modes) +{ + struct dpp_authentication *auth; + size_t nonce_len; + size_t secret_len; + struct wpabuf *pi = NULL; + const u8 *r_pubkey_hash, *i_pubkey_hash; +#ifdef CONFIG_TESTING_OPTIONS + u8 test_hash[SHA256_MAC_LEN]; +#endif /* CONFIG_TESTING_OPTIONS */ + + auth = dpp_alloc_auth(dpp, msg_ctx); + if (!auth) + return NULL; + if (peer_bi->configurator_params && + dpp_set_configurator(auth, peer_bi->configurator_params) < 0) + goto fail; + auth->initiator = 1; + auth->waiting_auth_resp = 1; + auth->allowed_roles = dpp_allowed_roles; + auth->configurator = !!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR); + auth->peer_bi = peer_bi; + auth->own_bi = own_bi; + auth->curve = peer_bi->curve; + + if (dpp_autogen_bootstrap_key(auth) < 0 || + dpp_prepare_channel_list(auth, neg_freq, own_modes, num_modes) < 0) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_nonce_override_len > 0) { + wpa_printf(MSG_INFO, "DPP: TESTING - override I-nonce"); + nonce_len = dpp_nonce_override_len; + os_memcpy(auth->i_nonce, dpp_nonce_override, nonce_len); + } else { + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->i_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, + "DPP: Failed to generate I-nonce"); + goto fail; + } + } +#else /* CONFIG_TESTING_OPTIONS */ + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->i_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce"); + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_protocol_key_override_len) { + const struct dpp_curve_params *tmp_curve; + + wpa_printf(MSG_INFO, + "DPP: TESTING - override protocol key"); + auth->own_protocol_key = dpp_set_keypair( + &tmp_curve, dpp_protocol_key_override, + dpp_protocol_key_override_len); + } else { + auth->own_protocol_key = dpp_gen_keypair(auth->curve); + } +#else /* CONFIG_TESTING_OPTIONS */ + auth->own_protocol_key = dpp_gen_keypair(auth->curve); +#endif /* CONFIG_TESTING_OPTIONS */ + if (!auth->own_protocol_key) + goto fail; + + pi = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (!pi) + goto fail; + + /* ECDH: M = pI * BR */ + if (dpp_ecdh(auth->own_protocol_key, auth->peer_bi->pubkey, + auth->Mx, &secret_len) < 0) + goto fail; + auth->secret_len = secret_len; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)", + auth->Mx, auth->secret_len); + auth->Mx_len = auth->secret_len; + + if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1, + auth->curve->hash_len) < 0) + goto fail; + + r_pubkey_hash = auth->peer_bi->pubkey_hash; + i_pubkey_hash = auth->own_bi->pubkey_hash; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); + r_pubkey_hash = NULL; + } else if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid R-Bootstrap Key Hash"); + os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + r_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); + i_pubkey_hash = NULL; + } else if (dpp_test == DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid I-Bootstrap Key Hash"); + os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + i_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Proto Key"); + wpabuf_free(pi); + pi = NULL; + } else if (dpp_test == DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-Proto Key"); + wpabuf_free(pi); + pi = wpabuf_alloc(2 * auth->curve->prime_len); + if (!pi || dpp_test_gen_invalid_key(pi, auth->curve) < 0) + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (neg_freq && auth->num_freq == 1 && auth->freq[0] == neg_freq) + neg_freq = 0; + auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash, + i_pubkey_hash, neg_freq); + if (!auth->req_msg) + goto fail; + +out: + wpabuf_free(pi); + return auth; +fail: + dpp_auth_deinit(auth); + auth = NULL; + goto out; +} +static void +dpp_auth_resp_rx_status(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len, + const u8 *wrapped_data, u16 wrapped_data_len, + enum dpp_status_error status) +{ + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + const u8 *i_nonce, *r_capab; + u16 i_nonce_len, r_capab_len; + + if (status == DPP_STATUS_NOT_COMPATIBLE) { + wpa_printf(MSG_DEBUG, + "DPP: Responder reported incompatible roles"); + } else if (status == DPP_STATUS_RESPONSE_PENDING) { + wpa_printf(MSG_DEBUG, + "DPP: Responder reported more time needed"); + } else { + wpa_printf(MSG_DEBUG, + "DPP: Responder reported failure (status %d)", + status); + dpp_auth_fail(auth, "Responder reported failure"); + return; + } + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->k1, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) { + dpp_auth_fail(auth, "I-nonce mismatch"); + goto fail; + } + + r_capab = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_R_CAPABILITIES, + &r_capab_len); + if (!r_capab || r_capab_len < 1) { + dpp_auth_fail(auth, "Missing or invalid R-capabilities"); + goto fail; + } + auth->r_capab = r_capab[0]; + wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab); + if (status == DPP_STATUS_NOT_COMPATIBLE) { + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE + "r-capab=0x%02x", auth->r_capab); + } else if (status == DPP_STATUS_RESPONSE_PENDING) { + u8 role = auth->r_capab & DPP_CAPAB_ROLE_MASK; + + if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) || + (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) { + wpa_msg(auth->msg_ctx, MSG_INFO, + DPP_EVENT_FAIL "Unexpected role in R-capabilities 0x%02x", + role); + } else { + wpa_printf(MSG_DEBUG, + "DPP: Continue waiting for full DPP Authentication Response"); + wpa_msg(auth->msg_ctx, MSG_INFO, + DPP_EVENT_RESPONSE_PENDING "%s", + auth->tmp_own_bi ? auth->tmp_own_bi->uri : ""); + } + } +fail: + bin_clear_free(unwrapped, unwrapped_len); +} + + +struct wpabuf * +dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + EVP_PKEY *pr; + size_t secret_len; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL, *unwrapped2 = NULL; + size_t unwrapped_len = 0, unwrapped2_len = 0; + const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto, + *r_nonce, *i_nonce, *r_capab, *wrapped2, *r_auth; + u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len, + r_proto_len, r_nonce_len, i_nonce_len, r_capab_len, + wrapped2_len, r_auth_len; + u8 r_auth2[DPP_MAX_HASH_LEN]; + u8 role; +#ifdef CONFIG_DPP2 + const u8 *version; + u16 version_len; +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at Authentication Response"); + return NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!auth->initiator || !auth->peer_bi || auth->reconfig) { + dpp_auth_fail(auth, "Unexpected Authentication Response"); + return NULL; + } + + auth->waiting_auth_resp = 0; + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid required Wrapped Data attribute"); + return NULL; + } + wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data", + wrapped_data, wrapped_data_len); + + attr_len = wrapped_data - 4 - attr_start; + + r_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + dpp_auth_fail(auth, + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return NULL; + } + wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + if (os_memcmp(r_bootstrap, auth->peer_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) { + dpp_auth_fail(auth, + "Unexpected Responder Bootstrapping Key Hash value"); + wpa_hexdump(MSG_DEBUG, + "DPP: Expected Responder Bootstrapping Key Hash", + auth->peer_bi->pubkey_hash, SHA256_MAC_LEN); + return NULL; + } + + i_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_I_BOOTSTRAP_KEY_HASH, + &i_bootstrap_len); + if (i_bootstrap) { + if (i_bootstrap_len != SHA256_MAC_LEN) { + dpp_auth_fail(auth, + "Invalid Initiator Bootstrapping Key Hash attribute"); + return NULL; + } + wpa_hexdump(MSG_MSGDUMP, + "DPP: Initiator Bootstrapping Key Hash", + i_bootstrap, i_bootstrap_len); + if (!auth->own_bi || + os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) { + dpp_auth_fail(auth, + "Initiator Bootstrapping Key Hash attribute did not match"); + return NULL; + } + } else if (auth->own_bi && auth->own_bi->type == DPP_BOOTSTRAP_PKEX) { + /* PKEX bootstrapping mandates use of mutual authentication */ + dpp_auth_fail(auth, + "Missing Initiator Bootstrapping Key Hash attribute"); + return NULL; + } else if (auth->own_bi && + auth->own_bi->type == DPP_BOOTSTRAP_NFC_URI && + auth->own_bi->nfc_negotiated) { + /* NFC negotiated connection handover bootstrapping mandates + * use of mutual authentication */ + dpp_auth_fail(auth, + "Missing Initiator Bootstrapping Key Hash attribute"); + return NULL; + } + + auth->peer_version = 1; /* default to the first version */ +#ifdef CONFIG_DPP2 + version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (version && DPP_VERSION > 1) { + if (version_len < 1 || version[0] == 0) { + dpp_auth_fail(auth, + "Invalid Protocol Version attribute"); + return NULL; + } + auth->peer_version = version[0]; + wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", + auth->peer_version); + } +#endif /* CONFIG_DPP2 */ + + status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, + &status_len); + if (!status || status_len < 1) { + dpp_auth_fail(auth, + "Missing or invalid required DPP Status attribute"); + return NULL; + } + wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); + auth->auth_resp_status = status[0]; + if (status[0] != DPP_STATUS_OK) { + dpp_auth_resp_rx_status(auth, hdr, attr_start, + attr_len, wrapped_data, + wrapped_data_len, status[0]); + return NULL; + } + + if (!i_bootstrap && auth->own_bi) { + wpa_printf(MSG_DEBUG, + "DPP: Responder decided not to use mutual authentication"); + auth->own_bi = NULL; + } + + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_DIRECTION "mutual=%d", + auth->own_bi != NULL); + + r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY, + &r_proto_len); + if (!r_proto) { + dpp_auth_fail(auth, + "Missing required Responder Protocol Key attribute"); + return NULL; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key", + r_proto, r_proto_len); + + /* N = pI * PR */ + pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len); + if (!pr) { + dpp_auth_fail(auth, "Invalid Responder Protocol Key"); + return NULL; + } + dpp_debug_print_key("Peer (Responder) Protocol Key", pr); + + if (dpp_ecdh(auth->own_protocol_key, pr, auth->Nx, &secret_len) < 0) { + dpp_auth_fail(auth, "Failed to derive ECDH shared secret"); + goto fail; + } + EVP_PKEY_free(auth->peer_protocol_key); + auth->peer_protocol_key = pr; + pr = NULL; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)", + auth->Nx, auth->secret_len); + auth->Nx_len = auth->secret_len; + + if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2, + auth->curve->hash_len) < 0) + goto fail; + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->k2, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, + &r_nonce_len); + if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len); + os_memcpy(auth->r_nonce, r_nonce, r_nonce_len); + + i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) { + dpp_auth_fail(auth, "I-nonce mismatch"); + goto fail; + } + + if (auth->own_bi) { + /* Mutual authentication */ + if (dpp_auth_derive_l_initiator(auth) < 0) + goto fail; + } + + r_capab = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_R_CAPABILITIES, + &r_capab_len); + if (!r_capab || r_capab_len < 1) { + dpp_auth_fail(auth, "Missing or invalid R-capabilities"); + goto fail; + } + auth->r_capab = r_capab[0]; + wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab); + role = auth->r_capab & DPP_CAPAB_ROLE_MASK; + if ((auth->allowed_roles == + (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) && + (role == DPP_CAPAB_CONFIGURATOR || role == DPP_CAPAB_ENROLLEE)) { + /* Peer selected its role, so move from "either role" to the + * role that is compatible with peer's selection. */ + auth->configurator = role == DPP_CAPAB_ENROLLEE; + wpa_printf(MSG_DEBUG, "DPP: Acting as %s", + auth->configurator ? "Configurator" : "Enrollee"); + } else if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) || + (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) { + wpa_printf(MSG_DEBUG, "DPP: Incompatible role selection"); + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Unexpected role in R-capabilities 0x%02x", + role); + if (role != DPP_CAPAB_ENROLLEE && + role != DPP_CAPAB_CONFIGURATOR) + goto fail; + bin_clear_free(unwrapped, unwrapped_len); + auth->remove_on_tx_status = 1; + return dpp_auth_build_conf(auth, DPP_STATUS_NOT_COMPATIBLE); + } + + wrapped2 = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_WRAPPED_DATA, &wrapped2_len); + if (!wrapped2 || wrapped2_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid Secondary Wrapped Data"); + goto fail; + } + + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped2, wrapped2_len); + + if (dpp_derive_bk_ke(auth) < 0) + goto fail; + + unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE; + unwrapped2 = os_malloc(unwrapped2_len); + if (!unwrapped2) + goto fail; + if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, + wrapped2, wrapped2_len, + 0, NULL, NULL, unwrapped2) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped2, unwrapped2_len); + + if (dpp_check_attrs(unwrapped2, unwrapped2_len) < 0) { + dpp_auth_fail(auth, + "Invalid attribute in secondary unwrapped data"); + goto fail; + } + + r_auth = dpp_get_attr(unwrapped2, unwrapped2_len, DPP_ATTR_R_AUTH_TAG, + &r_auth_len); + if (!r_auth || r_auth_len != auth->curve->hash_len) { + dpp_auth_fail(auth, + "Missing or invalid Responder Authenticating Tag"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag", + r_auth, r_auth_len); + /* R-auth' = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ + if (dpp_gen_r_auth(auth, r_auth2) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: Calculated Responder Authenticating Tag", + r_auth2, r_auth_len); + if (os_memcmp(r_auth, r_auth2, r_auth_len) != 0) { + dpp_auth_fail(auth, "Mismatching Responder Authenticating Tag"); + bin_clear_free(unwrapped, unwrapped_len); + bin_clear_free(unwrapped2, unwrapped2_len); + auth->remove_on_tx_status = 1; + return dpp_auth_build_conf(auth, DPP_STATUS_AUTH_FAILURE); + } + + bin_clear_free(unwrapped, unwrapped_len); + bin_clear_free(unwrapped2, unwrapped2_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - Authentication Response in place of Confirm"); + if (dpp_auth_build_resp_ok(auth) < 0) + return NULL; + return wpabuf_dup(auth->resp_msg); + } +#endif /* CONFIG_TESTING_OPTIONS */ + + return dpp_auth_build_conf(auth, DPP_STATUS_OK); + +fail: + bin_clear_free(unwrapped, unwrapped_len); + bin_clear_free(unwrapped2, unwrapped2_len); + EVP_PKEY_free(pr); + return NULL; +} + + +static int dpp_auth_conf_rx_failure(struct dpp_authentication *auth, + const u8 *hdr, + const u8 *attr_start, size_t attr_len, + const u8 *wrapped_data, + u16 wrapped_data_len, + enum dpp_status_error status) +{ + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + const u8 *r_nonce; + u16 r_nonce_len; + + /* Authentication Confirm failure cases are expected to include + * {R-nonce}k2 in the Wrapped Data attribute. */ + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) { + dpp_auth_fail(auth, "Authentication failed"); + goto fail; + } + if (aes_siv_decrypt(auth->k2, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, + &r_nonce_len); + if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce"); + goto fail; + } + if (os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) { + wpa_hexdump(MSG_DEBUG, "DPP: Received R-nonce", + r_nonce, r_nonce_len); + wpa_hexdump(MSG_DEBUG, "DPP: Expected R-nonce", + auth->r_nonce, r_nonce_len); + dpp_auth_fail(auth, "R-nonce mismatch"); + goto fail; + } + + if (status == DPP_STATUS_NOT_COMPATIBLE) + dpp_auth_fail(auth, "Peer reported incompatible R-capab role"); + else if (status == DPP_STATUS_AUTH_FAILURE) + dpp_auth_fail(auth, "Peer reported authentication failure)"); + +fail: + bin_clear_free(unwrapped, unwrapped_len); + return -1; +} + + +int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth; + u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len, + i_auth_len; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + u8 i_auth2[DPP_MAX_HASH_LEN]; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at Authentication Confirm"); + return -1; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (auth->initiator || !auth->own_bi || !auth->waiting_auth_conf || + auth->reconfig) { + wpa_printf(MSG_DEBUG, + "DPP: initiator=%d own_bi=%d waiting_auth_conf=%d", + auth->initiator, !!auth->own_bi, + auth->waiting_auth_conf); + dpp_auth_fail(auth, "Unexpected Authentication Confirm"); + return -1; + } + + auth->waiting_auth_conf = 0; + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid required Wrapped Data attribute"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data", + wrapped_data, wrapped_data_len); + + attr_len = wrapped_data - 4 - attr_start; + + r_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + dpp_auth_fail(auth, + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + if (os_memcmp(r_bootstrap, auth->own_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) { + wpa_hexdump(MSG_DEBUG, + "DPP: Expected Responder Bootstrapping Key Hash", + auth->peer_bi->pubkey_hash, SHA256_MAC_LEN); + dpp_auth_fail(auth, + "Responder Bootstrapping Key Hash mismatch"); + return -1; + } + + i_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_I_BOOTSTRAP_KEY_HASH, + &i_bootstrap_len); + if (i_bootstrap) { + if (i_bootstrap_len != SHA256_MAC_LEN) { + dpp_auth_fail(auth, + "Invalid Initiator Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, + "DPP: Initiator Bootstrapping Key Hash", + i_bootstrap, i_bootstrap_len); + if (!auth->peer_bi || + os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) { + dpp_auth_fail(auth, + "Initiator Bootstrapping Key Hash mismatch"); + return -1; + } + } else if (auth->peer_bi) { + /* Mutual authentication and peer did not include its + * Bootstrapping Key Hash attribute. */ + dpp_auth_fail(auth, + "Missing Initiator Bootstrapping Key Hash attribute"); + return -1; + } + + status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, + &status_len); + if (!status || status_len < 1) { + dpp_auth_fail(auth, + "Missing or invalid required DPP Status attribute"); + return -1; + } + wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); + if (status[0] == DPP_STATUS_NOT_COMPATIBLE || + status[0] == DPP_STATUS_AUTH_FAILURE) + return dpp_auth_conf_rx_failure(auth, hdr, attr_start, + attr_len, wrapped_data, + wrapped_data_len, status[0]); + + if (status[0] != DPP_STATUS_OK) { + dpp_auth_fail(auth, "Authentication failed"); + return -1; + } + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + return -1; + if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + i_auth = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG, + &i_auth_len); + if (!i_auth || i_auth_len != auth->curve->hash_len) { + dpp_auth_fail(auth, + "Missing or invalid Initiator Authenticating Tag"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag", + i_auth, i_auth_len); + /* I-auth' = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ + if (dpp_gen_i_auth(auth, i_auth2) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: Calculated Initiator Authenticating Tag", + i_auth2, i_auth_len); + if (os_memcmp(i_auth, i_auth2, i_auth_len) != 0) { + dpp_auth_fail(auth, "Mismatching Initiator Authenticating Tag"); + goto fail; + } + + bin_clear_free(unwrapped, unwrapped_len); + dpp_auth_success(auth); + return 0; +fail: + bin_clear_free(unwrapped, unwrapped_len); + return -1; +} diff --git a/src/common/dpp_backup.c b/src/common/dpp_backup.c new file mode 100644 index 000000000..3b81f0964 --- /dev/null +++ b/src/common/dpp_backup.c @@ -0,0 +1,1292 @@ +/* + * DPP configurator backup + * Copyright (c) 2019-2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include +#include + +#include "utils/common.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" +#include "tls/asn1.h" +#include "dpp.h" +#include "dpp_i.h" + +#ifdef CONFIG_DPP2 + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) +/* Compatibility wrappers for older versions. */ + +static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_EC) + return NULL; + return pkey->pkey.ec; +} + +#endif + + +void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key) +{ + while (key) { + struct dpp_asymmetric_key *next = key->next; + + EVP_PKEY_free(key->csign); + EVP_PKEY_free(key->pp_key); + str_clear_free(key->config_template); + str_clear_free(key->connector_template); + os_free(key); + key = next; + } +} + + +static struct wpabuf * dpp_build_conf_params(struct dpp_configurator *conf) +{ + struct wpabuf *buf, *priv_key = NULL; + size_t len; + /* TODO: proper template values */ + const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}"; + const char *connector_template = NULL; + EC_KEY *eckey; + unsigned char *der = NULL; + int der_len; + + if (!conf->pp_key) + return NULL; + eckey = EVP_PKEY_get0_EC_KEY(conf->pp_key); + if (!eckey) + return NULL; + + EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); + der_len = i2d_ECPrivateKey(eckey, &der); + if (der_len > 0) + priv_key = wpabuf_alloc_copy(der, der_len); + OPENSSL_free(der); + if (!priv_key) + goto fail; + + len = 100 + os_strlen(conf_template); + if (connector_template) + len += os_strlen(connector_template); + if (priv_key) + len += wpabuf_len(priv_key); + buf = wpabuf_alloc(len); + if (!buf) + goto fail; + + /* + * DPPConfigurationParameters ::= SEQUENCE { + * privacyProtectionKey PrivateKey, + * configurationTemplate UTF8String, + * connectorTemplate UTF8String OPTIONAL} + */ + + /* PrivateKey ::= OCTET STRING */ + asn1_put_octet_string(buf, priv_key); + + asn1_put_utf8string(buf, conf_template); + if (connector_template) + asn1_put_utf8string(buf, connector_template); + wpabuf_clear_free(priv_key); + return asn1_encaps(buf, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); +fail: + wpabuf_clear_free(priv_key); + return NULL; +} + + +static struct wpabuf * dpp_build_attribute(struct dpp_configurator *conf) +{ + struct wpabuf *conf_params, *attr; + + /* + * aa-DPPConfigurationParameters ATTRIBUTE ::= + * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams } + * + * Attribute ::= SEQUENCE { + * type OBJECT IDENTIFIER, + * values SET SIZE(1..MAX) OF Type + */ + conf_params = dpp_build_conf_params(conf); + conf_params = asn1_encaps(conf_params, ASN1_CLASS_UNIVERSAL, + ASN1_TAG_SET); + if (!conf_params) + return NULL; + + attr = wpabuf_alloc(100 + wpabuf_len(conf_params)); + if (!attr) { + wpabuf_clear_free(conf_params); + return NULL; + } + + asn1_put_oid(attr, &asn1_dpp_config_params_oid); + wpabuf_put_buf(attr, conf_params); + wpabuf_clear_free(conf_params); + + return asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); +} + + +static struct wpabuf * dpp_build_key_alg(const struct dpp_curve_params *curve) +{ + const struct asn1_oid *oid; + struct wpabuf *params, *res; + + switch (curve->ike_group) { + case 19: + oid = &asn1_prime256v1_oid; + break; + case 20: + oid = &asn1_secp384r1_oid; + break; + case 21: + oid = &asn1_secp521r1_oid; + break; + case 28: + oid = &asn1_brainpoolP256r1_oid; + break; + case 29: + oid = &asn1_brainpoolP384r1_oid; + break; + case 30: + oid = &asn1_brainpoolP512r1_oid; + break; + default: + return NULL; + } + + params = wpabuf_alloc(20); + if (!params) + return NULL; + asn1_put_oid(params, oid); /* namedCurve */ + + res = asn1_build_alg_id(&asn1_ec_public_key_oid, params); + wpabuf_free(params); + return res; +} + + +static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth) +{ + struct wpabuf *key = NULL, *attr, *alg, *priv_key = NULL; + EC_KEY *eckey; + unsigned char *der = NULL; + int der_len; + + eckey = EVP_PKEY_get0_EC_KEY(auth->conf->csign); + if (!eckey) + return NULL; + + EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY); + der_len = i2d_ECPrivateKey(eckey, &der); + if (der_len > 0) + priv_key = wpabuf_alloc_copy(der, der_len); + OPENSSL_free(der); + + alg = dpp_build_key_alg(auth->conf->curve); + + /* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */ + attr = dpp_build_attribute(auth->conf); + attr = asn1_encaps(attr, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SET); + if (!priv_key || !attr || !alg) + goto fail; + + /* + * OneAsymmetricKey ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] Attributes OPTIONAL, + * ..., + * [[2: publicKey [1] BIT STRING OPTIONAL ]], + * ... + * } + */ + + key = wpabuf_alloc(100 + wpabuf_len(alg) + wpabuf_len(priv_key) + + wpabuf_len(attr)); + if (!key) + goto fail; + + asn1_put_integer(key, 0); /* version = v1(0) */ + + /* PrivateKeyAlgorithmIdentifier */ + wpabuf_put_buf(key, alg); + + /* PrivateKey ::= OCTET STRING */ + asn1_put_octet_string(key, priv_key); + + /* [0] Attributes OPTIONAL */ + asn1_put_hdr(key, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0, wpabuf_len(attr)); + wpabuf_put_buf(key, attr); + +fail: + wpabuf_clear_free(attr); + wpabuf_clear_free(priv_key); + wpabuf_free(alg); + + /* + * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage + * + * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey + * + * OneAsymmetricKey ::= SEQUENCE + */ + return asn1_encaps(asn1_encaps(key, + ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE), + ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); +} + + +static struct wpabuf * dpp_build_pbkdf2_alg_id(const struct wpabuf *salt, + size_t hash_len) +{ + struct wpabuf *params = NULL, *buf = NULL, *prf = NULL; + const struct asn1_oid *oid; + + /* + * PBKDF2-params ::= SEQUENCE { + * salt CHOICE { + * specified OCTET STRING, + * otherSource AlgorithmIdentifier} + * iterationCount INTEGER (1..MAX), + * keyLength INTEGER (1..MAX), + * prf AlgorithmIdentifier} + * + * salt is an 64 octet value, iterationCount is 1000, keyLength is based + * on Configurator signing key length, prf is + * id-hmacWithSHA{256,384,512} based on Configurator signing key. + */ + + if (hash_len == 32) + oid = &asn1_pbkdf2_hmac_sha256_oid; + else if (hash_len == 48) + oid = &asn1_pbkdf2_hmac_sha384_oid; + else if (hash_len == 64) + oid = &asn1_pbkdf2_hmac_sha512_oid; + else + goto fail; + prf = asn1_build_alg_id(oid, NULL); + if (!prf) + goto fail; + params = wpabuf_alloc(100 + wpabuf_len(salt) + wpabuf_len(prf)); + if (!params) + goto fail; + asn1_put_octet_string(params, salt); /* salt.specified */ + asn1_put_integer(params, 1000); /* iterationCount */ + asn1_put_integer(params, hash_len); /* keyLength */ + wpabuf_put_buf(params, prf); + params = asn1_encaps(params, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); + if (!params) + goto fail; + buf = asn1_build_alg_id(&asn1_pbkdf2_oid, params); +fail: + wpabuf_free(params); + wpabuf_free(prf); + return buf; +} + + +static struct wpabuf * +dpp_build_pw_recipient_info(struct dpp_authentication *auth, size_t hash_len, + const struct wpabuf *cont_enc_key) +{ + struct wpabuf *pwri = NULL, *enc_key = NULL, *key_der_alg = NULL, + *key_enc_alg = NULL, *salt; + u8 kek[DPP_MAX_HASH_LEN]; + u8 key[DPP_MAX_HASH_LEN]; + size_t key_len; + int res; + + salt = wpabuf_alloc(64); + if (!salt || os_get_random(wpabuf_put(salt, 64), 64) < 0) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "DPP: PBKDF2 salt", salt); + + key_len = auth->curve->hash_len; + /* password = HKDF-Expand(bk, "Enveloped Data Password", length) */ + res = dpp_hkdf_expand(key_len, auth->bk, key_len, + "Enveloped Data Password", key, key_len); + if (res < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len); + + if (dpp_pbkdf2(hash_len, key, key_len, wpabuf_head(salt), 64, 1000, + kek, hash_len)) { + wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed"); + goto fail; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2", + kek, hash_len); + + enc_key = wpabuf_alloc(hash_len + AES_BLOCK_SIZE); + if (!enc_key || + aes_siv_encrypt(kek, hash_len, wpabuf_head(cont_enc_key), + wpabuf_len(cont_enc_key), 0, NULL, NULL, + wpabuf_put(enc_key, hash_len + AES_BLOCK_SIZE)) < 0) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "DPP: encryptedKey", enc_key); + + /* + * PasswordRecipientInfo ::= SEQUENCE { + * version CMSVersion, + * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL, + * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + * encryptedKey EncryptedKey} + * + * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the + * parameters contains PBKDF2-params SEQUENCE. + */ + + key_der_alg = dpp_build_pbkdf2_alg_id(salt, hash_len); + key_enc_alg = asn1_build_alg_id(&asn1_aes_siv_cmac_aead_256_oid, NULL); + if (!key_der_alg || !key_enc_alg) + goto fail; + pwri = wpabuf_alloc(100 + wpabuf_len(key_der_alg) + + wpabuf_len(key_enc_alg) + wpabuf_len(enc_key)); + if (!pwri) + goto fail; + + /* version = 0 */ + asn1_put_integer(pwri, 0); + + /* [0] KeyDerivationAlgorithmIdentifier */ + asn1_put_hdr(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 1, 0, + wpabuf_len(key_der_alg)); + wpabuf_put_buf(pwri, key_der_alg); + + /* KeyEncryptionAlgorithmIdentifier */ + wpabuf_put_buf(pwri, key_enc_alg); + + /* EncryptedKey ::= OCTET STRING */ + asn1_put_octet_string(pwri, enc_key); + +fail: + wpabuf_clear_free(key_der_alg); + wpabuf_free(key_enc_alg); + wpabuf_free(enc_key); + wpabuf_free(salt); + forced_memzero(kek, sizeof(kek)); + return asn1_encaps(pwri, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); +} + + +static struct wpabuf * +dpp_build_recipient_info(struct dpp_authentication *auth, size_t hash_len, + const struct wpabuf *cont_enc_key) +{ + struct wpabuf *pwri; + + /* + * RecipientInfo ::= CHOICE { + * ktri KeyTransRecipientInfo, + * kari [1] KeyAgreeRecipientInfo, + * kekri [2] KEKRecipientInfo, + * pwri [3] PasswordRecipientInfo, + * ori [4] OtherRecipientInfo} + * + * Shall always use the pwri CHOICE. + */ + + pwri = dpp_build_pw_recipient_info(auth, hash_len, cont_enc_key); + return asn1_encaps(pwri, ASN1_CLASS_CONTEXT_SPECIFIC, 3); +} + + +static struct wpabuf * +dpp_build_enc_cont_info(struct dpp_authentication *auth, size_t hash_len, + const struct wpabuf *cont_enc_key) +{ + struct wpabuf *key_pkg, *enc_cont_info = NULL, *enc_cont = NULL, + *enc_alg; + const struct asn1_oid *oid; + size_t enc_cont_len; + + /* + * EncryptedContentInfo ::= SEQUENCE { + * contentType ContentType, + * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, + * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL} + */ + + if (hash_len == 32) + oid = &asn1_aes_siv_cmac_aead_256_oid; + else if (hash_len == 48) + oid = &asn1_aes_siv_cmac_aead_384_oid; + else if (hash_len == 64) + oid = &asn1_aes_siv_cmac_aead_512_oid; + else + return NULL; + + key_pkg = dpp_build_key_pkg(auth); + enc_alg = asn1_build_alg_id(oid, NULL); + if (!key_pkg || !enc_alg) + goto fail; + + wpa_hexdump_buf_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage", + key_pkg); + + enc_cont_len = wpabuf_len(key_pkg) + AES_BLOCK_SIZE; + enc_cont = wpabuf_alloc(enc_cont_len); + if (!enc_cont || + aes_siv_encrypt(wpabuf_head(cont_enc_key), wpabuf_len(cont_enc_key), + wpabuf_head(key_pkg), wpabuf_len(key_pkg), + 0, NULL, NULL, + wpabuf_put(enc_cont, enc_cont_len)) < 0) + goto fail; + + enc_cont_info = wpabuf_alloc(100 + wpabuf_len(enc_alg) + + wpabuf_len(enc_cont)); + if (!enc_cont_info) + goto fail; + + /* ContentType ::= OBJECT IDENTIFIER */ + asn1_put_oid(enc_cont_info, &asn1_dpp_asymmetric_key_package_oid); + + /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */ + wpabuf_put_buf(enc_cont_info, enc_alg); + + /* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL + * EncryptedContent ::= OCTET STRING */ + asn1_put_hdr(enc_cont_info, ASN1_CLASS_CONTEXT_SPECIFIC, 0, 0, + wpabuf_len(enc_cont)); + wpabuf_put_buf(enc_cont_info, enc_cont); + +fail: + wpabuf_clear_free(key_pkg); + wpabuf_free(enc_cont); + wpabuf_free(enc_alg); + return enc_cont_info; +} + + +static struct wpabuf * dpp_gen_random(size_t len) +{ + struct wpabuf *key; + + key = wpabuf_alloc(len); + if (!key || os_get_random(wpabuf_put(key, len), len) < 0) { + wpabuf_free(key); + key = NULL; + } + wpa_hexdump_buf_key(MSG_DEBUG, "DPP: content-encryption key", key); + return key; +} + + +struct wpabuf * dpp_build_enveloped_data(struct dpp_authentication *auth) +{ + struct wpabuf *env = NULL; + struct wpabuf *recipient_info = NULL, *enc_cont_info = NULL; + struct wpabuf *cont_enc_key = NULL; + size_t hash_len; + + if (!auth->conf) { + wpa_printf(MSG_DEBUG, + "DPP: No Configurator instance selected for the session - cannot build DPPEnvelopedData"); + return NULL; + } + + if (!auth->provision_configurator) { + wpa_printf(MSG_DEBUG, + "DPP: Configurator provisioning not allowed"); + return NULL; + } + + wpa_printf(MSG_DEBUG, "DPP: Building DPPEnvelopedData"); + + hash_len = auth->conf->curve->hash_len; + cont_enc_key = dpp_gen_random(hash_len); + if (!cont_enc_key) + goto fail; + recipient_info = dpp_build_recipient_info(auth, hash_len, cont_enc_key); + enc_cont_info = dpp_build_enc_cont_info(auth, hash_len, cont_enc_key); + if (!recipient_info || !enc_cont_info) + goto fail; + + env = wpabuf_alloc(wpabuf_len(recipient_info) + + wpabuf_len(enc_cont_info) + + 100); + if (!env) + goto fail; + + /* + * DPPEnvelopedData ::= EnvelopedData + * + * EnvelopedData ::= SEQUENCE { + * version CMSVersion, + * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + * recipientInfos RecipientInfos, + * encryptedContentInfo EncryptedContentInfo, + * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL} + * + * For DPP, version is 3, both originatorInfo and + * unprotectedAttrs are omitted, and recipientInfos contains a single + * RecipientInfo. + */ + + /* EnvelopedData.version = 3 */ + asn1_put_integer(env, 3); + + /* RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo */ + asn1_put_set(env, recipient_info); + + /* EncryptedContentInfo ::= SEQUENCE */ + asn1_put_sequence(env, enc_cont_info); + + env = asn1_encaps(env, ASN1_CLASS_UNIVERSAL, ASN1_TAG_SEQUENCE); + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: DPPEnvelopedData", env); +out: + wpabuf_clear_free(cont_enc_key); + wpabuf_clear_free(recipient_info); + wpabuf_free(enc_cont_info); + return env; +fail: + wpabuf_free(env); + env = NULL; + goto out; +} + + +struct dpp_enveloped_data { + const u8 *enc_cont; + size_t enc_cont_len; + const u8 *enc_key; + size_t enc_key_len; + const u8 *salt; + size_t pbkdf2_key_len; + size_t prf_hash_len; +}; + + +static int dpp_parse_recipient_infos(const u8 *pos, size_t len, + struct dpp_enveloped_data *data) +{ + struct asn1_hdr hdr; + const u8 *end = pos + len; + const u8 *next, *e_end; + struct asn1_oid oid; + int val; + const u8 *params; + size_t params_len; + + wpa_hexdump(MSG_MSGDUMP, "DPP: RecipientInfos", pos, len); + + /* + * RecipientInfo ::= CHOICE { + * ktri KeyTransRecipientInfo, + * kari [1] KeyAgreeRecipientInfo, + * kekri [2] KEKRecipientInfo, + * pwri [3] PasswordRecipientInfo, + * ori [4] OtherRecipientInfo} + * + * Shall always use the pwri CHOICE. + */ + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 3) { + wpa_printf(MSG_DEBUG, + "DPP: Expected CHOICE [3] (pwri) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: PasswordRecipientInfo", + hdr.payload, hdr.length); + pos = hdr.payload; + end = pos + hdr.length; + + /* + * PasswordRecipientInfo ::= SEQUENCE { + * version CMSVersion, + * keyDerivationAlgorithm [0] KeyDerivationAlgorithmIdentifier OPTIONAL, + * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + * encryptedKey EncryptedKey} + * + * version is 0, keyDerivationAlgorithm is id-PKBDF2, and the + * parameters contains PBKDF2-params SEQUENCE. + */ + + if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0) + return -1; + pos = hdr.payload; + + if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) + return -1; + if (val != 0) { + wpa_printf(MSG_DEBUG, "DPP: pwri.version != 0"); + return -1; + } + + wpa_hexdump(MSG_MSGDUMP, "DPP: Remaining PasswordRecipientInfo after version", + pos, end - pos); + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Expected keyDerivationAlgorithm [0] - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + pos = hdr.payload; + e_end = pos + hdr.length; + + /* KeyDerivationAlgorithmIdentifier ::= AlgorithmIdentifier */ + if (asn1_get_alg_id(pos, e_end - pos, &oid, ¶ms, ¶ms_len, + &next) < 0) + return -1; + if (!asn1_oid_equal(&oid, &asn1_pbkdf2_oid)) { + char buf[80]; + + asn1_oid_to_str(&oid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, + "DPP: Unexpected KeyDerivationAlgorithmIdentifier %s", + buf); + return -1; + } + + /* + * PBKDF2-params ::= SEQUENCE { + * salt CHOICE { + * specified OCTET STRING, + * otherSource AlgorithmIdentifier} + * iterationCount INTEGER (1..MAX), + * keyLength INTEGER (1..MAX), + * prf AlgorithmIdentifier} + * + * salt is an 64 octet value, iterationCount is 1000, keyLength is based + * on Configurator signing key length, prf is + * id-hmacWithSHA{256,384,512} based on Configurator signing key. + */ + if (!params || + asn1_get_sequence(params, params_len, &hdr, &e_end) < 0) + return -1; + pos = hdr.payload; + + if (asn1_get_next(pos, e_end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_OCTETSTRING) { + wpa_printf(MSG_DEBUG, + "DPP: Expected OCTETSTRING (salt.specified) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: salt.specified", + hdr.payload, hdr.length); + if (hdr.length != 64) { + wpa_printf(MSG_DEBUG, "DPP: Unexpected salt length %u", + hdr.length); + return -1; + } + data->salt = hdr.payload; + pos = hdr.payload + hdr.length; + + if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0) + return -1; + if (val != 1000) { + wpa_printf(MSG_DEBUG, "DPP: Unexpected iterationCount %d", val); + return -1; + } + + if (asn1_get_integer(pos, e_end - pos, &val, &pos) < 0) + return -1; + if (val != 32 && val != 48 && val != 64) { + wpa_printf(MSG_DEBUG, "DPP: Unexpected keyLength %d", val); + return -1; + } + data->pbkdf2_key_len = val; + + if (asn1_get_sequence(pos, e_end - pos, &hdr, NULL) < 0 || + asn1_get_oid(hdr.payload, hdr.length, &oid, &pos) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Could not parse prf"); + return -1; + } + if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha256_oid)) { + data->prf_hash_len = 32; + } else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha384_oid)) { + data->prf_hash_len = 48; + } else if (asn1_oid_equal(&oid, &asn1_pbkdf2_hmac_sha512_oid)) { + data->prf_hash_len = 64; + } else { + char buf[80]; + + asn1_oid_to_str(&oid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, "DPP: Unexpected PBKDF2-params.prf %s", + buf); + return -1; + } + + pos = next; + + /* keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier + * + * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * id-alg-AES-SIV-CMAC-aed-256, id-alg-AES-SIV-CMAC-aed-384, or + * id-alg-AES-SIV-CMAC-aed-512. */ + if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0) + return -1; + if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) && + !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) && + !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) { + char buf[80]; + + asn1_oid_to_str(&oid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, + "DPP: Unexpected KeyEncryptionAlgorithmIdentifier %s", + buf); + return -1; + } + + /* + * encryptedKey EncryptedKey + * + * EncryptedKey ::= OCTET STRING + */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_OCTETSTRING) { + wpa_printf(MSG_DEBUG, + "DPP: Expected OCTETSTRING (pwri.encryptedKey) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: pwri.encryptedKey", + hdr.payload, hdr.length); + data->enc_key = hdr.payload; + data->enc_key_len = hdr.length; + + return 0; +} + + +static int dpp_parse_encrypted_content_info(const u8 *pos, const u8 *end, + struct dpp_enveloped_data *data) +{ + struct asn1_hdr hdr; + struct asn1_oid oid; + + /* + * EncryptedContentInfo ::= SEQUENCE { + * contentType ContentType, + * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, + * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL} + */ + if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) + return -1; + wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContentInfo", + hdr.payload, hdr.length); + if (pos < end) { + wpa_hexdump(MSG_DEBUG, + "DPP: Unexpected extra data after EncryptedContentInfo", + pos, end - pos); + return -1; + } + + end = pos; + pos = hdr.payload; + + /* ContentType ::= OBJECT IDENTIFIER */ + if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Could not parse ContentType"); + return -1; + } + if (!asn1_oid_equal(&oid, &asn1_dpp_asymmetric_key_package_oid)) { + char buf[80]; + + asn1_oid_to_str(&oid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, "DPP: Unexpected ContentType %s", buf); + return -1; + } + + /* ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier */ + if (asn1_get_alg_id(pos, end - pos, &oid, NULL, NULL, &pos) < 0) + return -1; + if (!asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_256_oid) && + !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_384_oid) && + !asn1_oid_equal(&oid, &asn1_aes_siv_cmac_aead_512_oid)) { + char buf[80]; + + asn1_oid_to_str(&oid, buf, sizeof(buf)); + wpa_printf(MSG_DEBUG, + "DPP: Unexpected ContentEncryptionAlgorithmIdentifier %s", + buf); + return -1; + } + /* ignore optional parameters */ + + /* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL + * EncryptedContent ::= OCTET STRING */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Expected [0] IMPLICIT (EncryptedContent) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: EncryptedContent", + hdr.payload, hdr.length); + data->enc_cont = hdr.payload; + data->enc_cont_len = hdr.length; + return 0; +} + + +static int dpp_parse_enveloped_data(const u8 *env_data, size_t env_data_len, + struct dpp_enveloped_data *data) +{ + struct asn1_hdr hdr; + const u8 *pos, *end; + int val; + + os_memset(data, 0, sizeof(*data)); + + /* + * DPPEnvelopedData ::= EnvelopedData + * + * EnvelopedData ::= SEQUENCE { + * version CMSVersion, + * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, + * recipientInfos RecipientInfos, + * encryptedContentInfo EncryptedContentInfo, + * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL} + * + * CMSVersion ::= INTEGER + * + * RecipientInfos ::= SET SIZE (1..MAX) OF RecipientInfo + * + * For DPP, version is 3, both originatorInfo and + * unprotectedAttrs are omitted, and recipientInfos contains a single + * RecipientInfo. + */ + if (asn1_get_sequence(env_data, env_data_len, &hdr, &end) < 0) + return -1; + pos = hdr.payload; + if (end < env_data + env_data_len) { + wpa_hexdump(MSG_DEBUG, + "DPP: Unexpected extra data after DPPEnvelopedData", + end, env_data + env_data_len - end); + return -1; + } + + if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) + return -1; + if (val != 3) { + wpa_printf(MSG_DEBUG, "DPP: EnvelopedData.version != 3"); + return -1; + } + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { + wpa_printf(MSG_DEBUG, + "DPP: Expected SET (RecipientInfos) - found class %d tag 0x%x", + hdr.class, hdr.tag); + return -1; + } + + if (dpp_parse_recipient_infos(hdr.payload, hdr.length, data) < 0) + return -1; + return dpp_parse_encrypted_content_info(hdr.payload + hdr.length, end, + data); +} + + +static struct dpp_asymmetric_key * +dpp_parse_one_asymmetric_key(const u8 *buf, size_t len) +{ + struct asn1_hdr hdr; + const u8 *pos = buf, *end = buf + len, *next; + int val; + const u8 *params; + size_t params_len; + struct asn1_oid oid; + char txt[80]; + struct dpp_asymmetric_key *key; + EC_KEY *eckey; + + wpa_hexdump_key(MSG_MSGDUMP, "DPP: OneAsymmetricKey", buf, len); + + key = os_zalloc(sizeof(*key)); + if (!key) + return NULL; + + /* + * OneAsymmetricKey ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] Attributes OPTIONAL, + * ..., + * [[2: publicKey [1] BIT STRING OPTIONAL ]], + * ... + * } + */ + if (asn1_get_sequence(pos, end - pos, &hdr, &end) < 0) + goto fail; + pos = hdr.payload; + + /* Version ::= INTEGER { v1(0), v2(1) } (v1, ..., v2) */ + if (asn1_get_integer(pos, end - pos, &val, &pos) < 0) + goto fail; + if (val != 0 && val != 1) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported DPPAsymmetricKeyPackage version %d", + val); + goto fail; + } + + /* PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier */ + if (asn1_get_alg_id(pos, end - pos, &oid, ¶ms, ¶ms_len, + &pos) < 0) + goto fail; + if (!asn1_oid_equal(&oid, &asn1_ec_public_key_oid)) { + asn1_oid_to_str(&oid, txt, sizeof(txt)); + wpa_printf(MSG_DEBUG, + "DPP: Unsupported PrivateKeyAlgorithmIdentifier %s", + txt); + goto fail; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: PrivateKeyAlgorithmIdentifier params", + params, params_len); + /* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * -- implicitCurve NULL + * -- specifiedCurve SpecifiedECDomain} + */ + if (!params || asn1_get_oid(params, params_len, &oid, &next) < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Could not parse ECParameters.namedCurve"); + goto fail; + } + asn1_oid_to_str(&oid, txt, sizeof(txt)); + wpa_printf(MSG_MSGDUMP, "DPP: namedCurve %s", txt); + /* Assume the curve is identified within ECPrivateKey, so that this + * separate indication is not really needed. */ + + /* + * PrivateKey ::= OCTET STRING + * (Contains DER encoding of ECPrivateKey) + */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_OCTETSTRING) { + wpa_printf(MSG_DEBUG, + "DPP: Expected OCTETSTRING (PrivateKey) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + wpa_hexdump_key(MSG_MSGDUMP, "DPP: PrivateKey", + hdr.payload, hdr.length); + pos = hdr.payload + hdr.length; + eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length); + if (!eckey) { + wpa_printf(MSG_INFO, + "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + key->csign = EVP_PKEY_new(); + if (!key->csign || EVP_PKEY_assign_EC_KEY(key->csign, eckey) != 1) { + EC_KEY_free(eckey); + goto fail; + } + if (wpa_debug_show_keys) + dpp_debug_print_key("DPP: Received c-sign-key", key->csign); + + /* + * Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } + * + * Exactly one instance of type Attribute in OneAsymmetricKey. + */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_CONTEXT_SPECIFIC || hdr.tag != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Expected [0] Attributes - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + wpa_hexdump_key(MSG_MSGDUMP, "DPP: Attributes", + hdr.payload, hdr.length); + if (hdr.payload + hdr.length < end) { + wpa_hexdump_key(MSG_MSGDUMP, + "DPP: Ignore additional data at the end of OneAsymmetricKey", + hdr.payload + hdr.length, + end - (hdr.payload + hdr.length)); + } + pos = hdr.payload; + end = hdr.payload + hdr.length; + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { + wpa_printf(MSG_DEBUG, + "DPP: Expected SET (Attributes) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + if (hdr.payload + hdr.length < end) { + wpa_hexdump_key(MSG_MSGDUMP, + "DPP: Ignore additional data at the end of OneAsymmetricKey (after SET)", + hdr.payload + hdr.length, + end - (hdr.payload + hdr.length)); + } + pos = hdr.payload; + end = hdr.payload + hdr.length; + + /* + * OneAsymmetricKeyAttributes ATTRIBUTE ::= { + * aa-DPPConfigurationParameters, + * ... -- For local profiles + * } + * + * aa-DPPConfigurationParameters ATTRIBUTE ::= + * { TYPE DPPConfigurationParameters IDENTIFIED BY id-DPPConfigParams } + * + * Attribute ::= SEQUENCE { + * type OBJECT IDENTIFIER, + * values SET SIZE(1..MAX) OF Type + * + * Exactly one instance of ATTRIBUTE in attrValues. + */ + if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) + goto fail; + if (pos < end) { + wpa_hexdump_key(MSG_MSGDUMP, + "DPP: Ignore additional data at the end of ATTRIBUTE", + pos, end - pos); + } + end = pos; + pos = hdr.payload; + + if (asn1_get_oid(pos, end - pos, &oid, &pos) < 0) + goto fail; + if (!asn1_oid_equal(&oid, &asn1_dpp_config_params_oid)) { + asn1_oid_to_str(&oid, txt, sizeof(txt)); + wpa_printf(MSG_DEBUG, + "DPP: Unexpected Attribute identifier %s", txt); + goto fail; + } + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || hdr.tag != ASN1_TAG_SET) { + wpa_printf(MSG_DEBUG, + "DPP: Expected SET (Attribute) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + pos = hdr.payload; + end = hdr.payload + hdr.length; + + /* + * DPPConfigurationParameters ::= SEQUENCE { + * privacyProtectionKey PrivateKey, + * configurationTemplate UTF8String, + * connectorTemplate UTF8String OPTIONAL} + */ + + wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPConfigurationParameters", + pos, end - pos); + if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0) + goto fail; + if (pos < end) { + wpa_hexdump_key(MSG_MSGDUMP, + "DPP: Ignore additional data after DPPConfigurationParameters", + pos, end - pos); + } + end = pos; + pos = hdr.payload; + + /* + * PrivateKey ::= OCTET STRING + * (Contains DER encoding of ECPrivateKey) + */ + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_OCTETSTRING) { + wpa_printf(MSG_DEBUG, + "DPP: Expected OCTETSTRING (PrivateKey) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + wpa_hexdump_key(MSG_MSGDUMP, "DPP: privacyProtectionKey", + hdr.payload, hdr.length); + pos = hdr.payload + hdr.length; + eckey = d2i_ECPrivateKey(NULL, &hdr.payload, hdr.length); + if (!eckey) { + wpa_printf(MSG_INFO, + "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + key->pp_key = EVP_PKEY_new(); + if (!key->pp_key || EVP_PKEY_assign_EC_KEY(key->pp_key, eckey) != 1) { + EC_KEY_free(eckey); + goto fail; + } + if (wpa_debug_show_keys) + dpp_debug_print_key("DPP: Received privacyProtectionKey", + key->pp_key); + + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_UTF8STRING) { + wpa_printf(MSG_DEBUG, + "DPP: Expected UTF8STRING (configurationTemplate) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: configurationTemplate", + hdr.payload, hdr.length); + key->config_template = os_zalloc(hdr.length + 1); + if (!key->config_template) + goto fail; + os_memcpy(key->config_template, hdr.payload, hdr.length); + + pos = hdr.payload + hdr.length; + + if (pos < end) { + if (asn1_get_next(pos, end - pos, &hdr) < 0 || + hdr.class != ASN1_CLASS_UNIVERSAL || + hdr.tag != ASN1_TAG_UTF8STRING) { + wpa_printf(MSG_DEBUG, + "DPP: Expected UTF8STRING (connectorTemplate) - found class %d tag 0x%x", + hdr.class, hdr.tag); + goto fail; + } + wpa_hexdump_ascii_key(MSG_MSGDUMP, "DPP: connectorTemplate", + hdr.payload, hdr.length); + key->connector_template = os_zalloc(hdr.length + 1); + if (!key->connector_template) + goto fail; + os_memcpy(key->connector_template, hdr.payload, hdr.length); + } + + return key; +fail: + wpa_printf(MSG_DEBUG, "DPP: Failed to parse OneAsymmetricKey"); + dpp_free_asymmetric_key(key); + return NULL; +} + + +static struct dpp_asymmetric_key * +dpp_parse_dpp_asymmetric_key_package(const u8 *key_pkg, size_t key_pkg_len) +{ + struct asn1_hdr hdr; + const u8 *pos = key_pkg, *end = key_pkg + key_pkg_len; + struct dpp_asymmetric_key *first = NULL, *last = NULL, *key; + + wpa_hexdump_key(MSG_MSGDUMP, "DPP: DPPAsymmetricKeyPackage", + key_pkg, key_pkg_len); + + /* + * DPPAsymmetricKeyPackage ::= AsymmetricKeyPackage + * + * AsymmetricKeyPackage ::= SEQUENCE SIZE (1..MAX) OF OneAsymmetricKey + */ + while (pos < end) { + if (asn1_get_sequence(pos, end - pos, &hdr, &pos) < 0 || + !(key = dpp_parse_one_asymmetric_key(hdr.payload, + hdr.length))) { + dpp_free_asymmetric_key(first); + return NULL; + } + if (!last) { + first = last = key; + } else { + last->next = key; + last = key; + } + } + + return first; +} + + +int dpp_conf_resp_env_data(struct dpp_authentication *auth, + const u8 *env_data, size_t env_data_len) +{ + u8 key[DPP_MAX_HASH_LEN]; + size_t key_len; + u8 kek[DPP_MAX_HASH_LEN]; + u8 cont_encr_key[DPP_MAX_HASH_LEN]; + size_t cont_encr_key_len; + int res; + u8 *key_pkg; + size_t key_pkg_len; + struct dpp_enveloped_data data; + struct dpp_asymmetric_key *keys; + + wpa_hexdump(MSG_DEBUG, "DPP: DPPEnvelopedData", env_data, env_data_len); + + if (dpp_parse_enveloped_data(env_data, env_data_len, &data) < 0) + return -1; + + key_len = auth->curve->hash_len; + /* password = HKDF-Expand(bk, "Enveloped Data Password", length) */ + res = dpp_hkdf_expand(key_len, auth->bk, key_len, + "Enveloped Data Password", key, key_len); + if (res < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PBKDF2 key", key, key_len); + + if (dpp_pbkdf2(data.prf_hash_len, key, key_len, data.salt, 64, 1000, + kek, data.pbkdf2_key_len)) { + wpa_printf(MSG_DEBUG, "DPP: PBKDF2 failed"); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: key-encryption key from PBKDF2", + kek, data.pbkdf2_key_len); + + if (data.enc_key_len < AES_BLOCK_SIZE || + data.enc_key_len > sizeof(cont_encr_key) + AES_BLOCK_SIZE) { + wpa_printf(MSG_DEBUG, "DPP: Invalid encryptedKey length"); + return -1; + } + res = aes_siv_decrypt(kek, data.pbkdf2_key_len, + data.enc_key, data.enc_key_len, + 0, NULL, NULL, cont_encr_key); + forced_memzero(kek, data.pbkdf2_key_len); + if (res < 0) { + wpa_printf(MSG_DEBUG, + "DPP: AES-SIV decryption of encryptedKey failed"); + return -1; + } + cont_encr_key_len = data.enc_key_len - AES_BLOCK_SIZE; + wpa_hexdump_key(MSG_DEBUG, "DPP: content-encryption key", + cont_encr_key, cont_encr_key_len); + + if (data.enc_cont_len < AES_BLOCK_SIZE) + return -1; + key_pkg_len = data.enc_cont_len - AES_BLOCK_SIZE; + key_pkg = os_malloc(key_pkg_len); + if (!key_pkg) + return -1; + res = aes_siv_decrypt(cont_encr_key, cont_encr_key_len, + data.enc_cont, data.enc_cont_len, + 0, NULL, NULL, key_pkg); + forced_memzero(cont_encr_key, cont_encr_key_len); + if (res < 0) { + bin_clear_free(key_pkg, key_pkg_len); + wpa_printf(MSG_DEBUG, + "DPP: AES-SIV decryption of encryptedContent failed"); + return -1; + } + + keys = dpp_parse_dpp_asymmetric_key_package(key_pkg, key_pkg_len); + bin_clear_free(key_pkg, key_pkg_len); + dpp_free_asymmetric_key(auth->conf_key_pkg); + auth->conf_key_pkg = keys; + + return keys != NULL; +} + +#endif /* CONFIG_DPP2 */ diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c new file mode 100644 index 000000000..c75fc7871 --- /dev/null +++ b/src/common/dpp_crypto.c @@ -0,0 +1,3329 @@ +/* + * DPP crypto functionality + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018-2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include +#include +#include +#include +#include + +#include "utils/common.h" +#include "utils/base64.h" +#include "utils/json.h" +#include "common/ieee802_11_defs.h" +#include "crypto/crypto.h" +#include "crypto/random.h" +#include "crypto/sha384.h" +#include "crypto/sha512.h" +#include "dpp.h" +#include "dpp_i.h" + + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) +/* Compatibility wrappers for older versions. */ + +static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + sig->r = r; + sig->s = s; + return 1; +} + + +static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, + const BIGNUM **ps) +{ + if (pr) + *pr = sig->r; + if (ps) + *ps = sig->s; +} + + +static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_EC) + return NULL; + return pkey->pkey.ec; +} + +#endif + +static const struct dpp_curve_params dpp_curves[] = { + /* The mandatory to support and the default NIST P-256 curve needs to + * be the first entry on this list. */ + { "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" }, + { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" }, + { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" }, + { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" }, + { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" }, + { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" }, + { NULL, 0, 0, 0, 0, NULL, 0, NULL } +}; + + +const struct dpp_curve_params * dpp_get_curve_name(const char *name) +{ + int i; + + if (!name) + return &dpp_curves[0]; + + for (i = 0; dpp_curves[i].name; i++) { + if (os_strcmp(name, dpp_curves[i].name) == 0 || + (dpp_curves[i].jwk_crv && + os_strcmp(name, dpp_curves[i].jwk_crv) == 0)) + return &dpp_curves[i]; + } + return NULL; +} + + +const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name) +{ + int i; + + for (i = 0; dpp_curves[i].name; i++) { + if (dpp_curves[i].jwk_crv && + os_strcmp(name, dpp_curves[i].jwk_crv) == 0) + return &dpp_curves[i]; + } + return NULL; +} + + +static const struct dpp_curve_params * +dpp_get_curve_oid(const ASN1_OBJECT *poid) +{ + ASN1_OBJECT *oid; + int i; + + for (i = 0; dpp_curves[i].name; i++) { + oid = OBJ_txt2obj(dpp_curves[i].name, 0); + if (oid && OBJ_cmp(poid, oid) == 0) + return &dpp_curves[i]; + } + return NULL; +} + + +const struct dpp_curve_params * dpp_get_curve_nid(int nid) +{ + int i, tmp; + + if (!nid) + return NULL; + for (i = 0; dpp_curves[i].name; i++) { + tmp = OBJ_txt2nid(dpp_curves[i].name); + if (tmp == nid) + return &dpp_curves[i]; + } + return NULL; +} + + +const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group) +{ + int i; + + for (i = 0; dpp_curves[i].name; i++) { + if (dpp_curves[i].ike_group == group) + return &dpp_curves[i]; + } + return NULL; +} + + +void dpp_debug_print_point(const char *title, const EC_GROUP *group, + const EC_POINT *point) +{ + BIGNUM *x, *y; + BN_CTX *ctx; + char *x_str = NULL, *y_str = NULL; + + if (!wpa_debug_show_keys) + return; + + ctx = BN_CTX_new(); + x = BN_new(); + y = BN_new(); + if (!ctx || !x || !y || + EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx) != 1) + goto fail; + + x_str = BN_bn2hex(x); + y_str = BN_bn2hex(y); + if (!x_str || !y_str) + goto fail; + + wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str); + +fail: + OPENSSL_free(x_str); + OPENSSL_free(y_str); + BN_free(x); + BN_free(y); + BN_CTX_free(ctx); +} + + +void dpp_debug_print_key(const char *title, EVP_PKEY *key) +{ + EC_KEY *eckey; + BIO *out; + size_t rlen; + char *txt; + int res; + unsigned char *der = NULL; + int der_len; + const EC_GROUP *group; + const EC_POINT *point; + + out = BIO_new(BIO_s_mem()); + if (!out) + return; + + EVP_PKEY_print_private(out, key, 0, NULL); + rlen = BIO_ctrl_pending(out); + txt = os_malloc(rlen + 1); + if (txt) { + res = BIO_read(out, txt, rlen); + if (res > 0) { + txt[res] = '\0'; + wpa_printf(MSG_DEBUG, "%s: %s", title, txt); + } + os_free(txt); + } + BIO_free(out); + + eckey = EVP_PKEY_get1_EC_KEY(key); + if (!eckey) + return; + + group = EC_KEY_get0_group(eckey); + point = EC_KEY_get0_public_key(eckey); + if (group && point) + dpp_debug_print_point(title, group, point); + + der_len = i2d_ECPrivateKey(eckey, &der); + if (der_len > 0) + wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len); + OPENSSL_free(der); + if (der_len <= 0) { + der = NULL; + der_len = i2d_EC_PUBKEY(eckey, &der); + if (der_len > 0) + wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len); + OPENSSL_free(der); + } + + EC_KEY_free(eckey); +} + + +static int dpp_hash_vector(const struct dpp_curve_params *curve, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + if (curve->hash_len == 32) + return sha256_vector(num_elem, addr, len, mac); + if (curve->hash_len == 48) + return sha384_vector(num_elem, addr, len, mac); + if (curve->hash_len == 64) + return sha512_vector(num_elem, addr, len, mac); + return -1; +} + + +int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, + const char *label, u8 *out, size_t outlen) +{ + if (hash_len == 32) + return hmac_sha256_kdf(secret, secret_len, NULL, + (const u8 *) label, os_strlen(label), + out, outlen); + if (hash_len == 48) + return hmac_sha384_kdf(secret, secret_len, NULL, + (const u8 *) label, os_strlen(label), + out, outlen); + if (hash_len == 64) + return hmac_sha512_kdf(secret, secret_len, NULL, + (const u8 *) label, os_strlen(label), + out, outlen); + return -1; +} + + +int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + if (hash_len == 32) + return hmac_sha256_vector(key, key_len, num_elem, addr, len, + mac); + if (hash_len == 48) + return hmac_sha384_vector(key, key_len, num_elem, addr, len, + mac); + if (hash_len == 64) + return hmac_sha512_vector(key, key_len, num_elem, addr, len, + mac); + return -1; +} + + +static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, + const u8 *data, size_t data_len, u8 *mac) +{ + if (hash_len == 32) + return hmac_sha256(key, key_len, data, data_len, mac); + if (hash_len == 48) + return hmac_sha384(key, key_len, data, data_len, mac); + if (hash_len == 64) + return hmac_sha512(key, key_len, data, data_len, mac); + return -1; +} + + +#ifdef CONFIG_DPP2 + +static int dpp_pbkdf2_f(size_t hash_len, + const u8 *password, size_t password_len, + const u8 *salt, size_t salt_len, + unsigned int iterations, unsigned int count, u8 *digest) +{ + unsigned char tmp[DPP_MAX_HASH_LEN], tmp2[DPP_MAX_HASH_LEN]; + unsigned int i; + size_t j; + u8 count_buf[4]; + const u8 *addr[2]; + size_t len[2]; + + addr[0] = salt; + len[0] = salt_len; + addr[1] = count_buf; + len[1] = 4; + + /* F(P, S, c, i) = U1 xor U2 xor ... Uc + * U1 = PRF(P, S || i) + * U2 = PRF(P, U1) + * Uc = PRF(P, Uc-1) + */ + + WPA_PUT_BE32(count_buf, count); + if (dpp_hmac_vector(hash_len, password, password_len, 2, addr, len, + tmp)) + return -1; + os_memcpy(digest, tmp, hash_len); + + for (i = 1; i < iterations; i++) { + if (dpp_hmac(hash_len, password, password_len, tmp, hash_len, + tmp2)) + return -1; + os_memcpy(tmp, tmp2, hash_len); + for (j = 0; j < hash_len; j++) + digest[j] ^= tmp2[j]; + } + + return 0; +} + + +int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len, + const u8 *salt, size_t salt_len, unsigned int iterations, + u8 *buf, size_t buflen) +{ + unsigned int count = 0; + unsigned char *pos = buf; + size_t left = buflen, plen; + unsigned char digest[DPP_MAX_HASH_LEN]; + + while (left > 0) { + count++; + if (dpp_pbkdf2_f(hash_len, password, password_len, + salt, salt_len, iterations, count, digest)) + return -1; + plen = left > hash_len ? hash_len : left; + os_memcpy(pos, digest, plen); + pos += plen; + left -= plen; + } + + return 0; +} + +#endif /* CONFIG_DPP2 */ + + +int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len) +{ + int num_bytes, offset; + + num_bytes = BN_num_bytes(bn); + if ((size_t) num_bytes > len) + return -1; + offset = len - num_bytes; + os_memset(pos, 0, offset); + BN_bn2bin(bn, pos + offset); + return 0; +} + + +struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix) +{ + int len, res; + EC_KEY *eckey; + struct wpabuf *buf; + unsigned char *pos; + + eckey = EVP_PKEY_get1_EC_KEY(pkey); + if (!eckey) + return NULL; + EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED); + len = i2o_ECPublicKey(eckey, NULL); + if (len <= 0) { + wpa_printf(MSG_ERROR, + "DDP: Failed to determine public key encoding length"); + EC_KEY_free(eckey); + return NULL; + } + + buf = wpabuf_alloc(len); + if (!buf) { + EC_KEY_free(eckey); + return NULL; + } + + pos = wpabuf_put(buf, len); + res = i2o_ECPublicKey(eckey, &pos); + EC_KEY_free(eckey); + if (res != len) { + wpa_printf(MSG_ERROR, + "DDP: Failed to encode public key (res=%d/%d)", + res, len); + wpabuf_free(buf); + return NULL; + } + + if (!prefix) { + /* Remove 0x04 prefix to match DPP definition */ + pos = wpabuf_mhead(buf); + os_memmove(pos, pos + 1, len - 1); + buf->used--; + } + + return buf; +} + + +EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group, + const u8 *buf_x, const u8 *buf_y, + size_t len) +{ + EC_KEY *eckey = NULL; + BN_CTX *ctx; + EC_POINT *point = NULL; + BIGNUM *x = NULL, *y = NULL; + EVP_PKEY *pkey = NULL; + + ctx = BN_CTX_new(); + if (!ctx) { + wpa_printf(MSG_ERROR, "DPP: Out of memory"); + return NULL; + } + + point = EC_POINT_new(group); + x = BN_bin2bn(buf_x, len, NULL); + y = BN_bin2bn(buf_y, len, NULL); + if (!point || !x || !y) { + wpa_printf(MSG_ERROR, "DPP: Out of memory"); + goto fail; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { + wpa_printf(MSG_ERROR, + "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (!EC_POINT_is_on_curve(group, point, ctx) || + EC_POINT_is_at_infinity(group, point)) { + wpa_printf(MSG_ERROR, "DPP: Invalid point"); + goto fail; + } + dpp_debug_print_point("DPP: dpp_set_pubkey_point_group", group, point); + + eckey = EC_KEY_new(); + if (!eckey || + EC_KEY_set_group(eckey, group) != 1 || + EC_KEY_set_public_key(eckey, point) != 1) { + wpa_printf(MSG_ERROR, + "DPP: Failed to set EC_KEY: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); + + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) { + wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY"); + goto fail; + } + +out: + BN_free(x); + BN_free(y); + EC_KEY_free(eckey); + EC_POINT_free(point); + BN_CTX_free(ctx); + return pkey; +fail: + EVP_PKEY_free(pkey); + pkey = NULL; + goto out; +} + + +EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len) +{ + const EC_KEY *eckey; + const EC_GROUP *group; + EVP_PKEY *pkey = NULL; + + if (len & 1) + return NULL; + + eckey = EVP_PKEY_get0_EC_KEY(group_key); + if (!eckey) { + wpa_printf(MSG_ERROR, + "DPP: Could not get EC_KEY from group_key"); + return NULL; + } + + group = EC_KEY_get0_group(eckey); + if (group) + pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2, + len / 2); + else + wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); + + return pkey; +} + + +EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve) +{ + EVP_PKEY_CTX *kctx = NULL; + EC_KEY *ec_params = NULL; + EVP_PKEY *params = NULL, *key = NULL; + int nid; + + wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); + + nid = OBJ_txt2nid(curve->name); + if (nid == NID_undef) { + wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name); + return NULL; + } + + ec_params = EC_KEY_new_by_curve_name(nid); + if (!ec_params) { + wpa_printf(MSG_ERROR, + "DPP: Failed to generate EC_KEY parameters"); + goto fail; + } + EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE); + params = EVP_PKEY_new(); + if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) { + wpa_printf(MSG_ERROR, + "DPP: Failed to generate EVP_PKEY parameters"); + goto fail; + } + + kctx = EVP_PKEY_CTX_new(params, NULL); + if (!kctx || + EVP_PKEY_keygen_init(kctx) != 1 || + EVP_PKEY_keygen(kctx, &key) != 1) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key"); + key = NULL; + goto fail; + } + + if (wpa_debug_show_keys) + dpp_debug_print_key("Own generated key", key); + +fail: + EC_KEY_free(ec_params); + EVP_PKEY_free(params); + EVP_PKEY_CTX_free(kctx); + return key; +} + + +EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve, + const u8 *privkey, size_t privkey_len) +{ + EVP_PKEY *pkey; + EC_KEY *eckey; + const EC_GROUP *group; + int nid; + + pkey = EVP_PKEY_new(); + if (!pkey) + return NULL; + eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len); + if (!eckey) { + wpa_printf(MSG_INFO, + "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + EVP_PKEY_free(pkey); + return NULL; + } + group = EC_KEY_get0_group(eckey); + if (!group) { + EC_KEY_free(eckey); + EVP_PKEY_free(pkey); + return NULL; + } + nid = EC_GROUP_get_curve_name(group); + *curve = dpp_get_curve_nid(nid); + if (!*curve) { + wpa_printf(MSG_INFO, + "DPP: Unsupported curve (nid=%d) in pre-assigned key", + nid); + EC_KEY_free(eckey); + EVP_PKEY_free(pkey); + return NULL; + } + + if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { + EC_KEY_free(eckey); + EVP_PKEY_free(pkey); + return NULL; + } + return pkey; +} + + +typedef struct { + /* AlgorithmIdentifier ecPublicKey with optional parameters present + * as an OID identifying the curve */ + X509_ALGOR *alg; + /* Compressed format public key per ANSI X9.63 */ + ASN1_BIT_STRING *pub_key; +} DPP_BOOTSTRAPPING_KEY; + +ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = { + ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR), + ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY); + +IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY); + + +static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key) +{ + unsigned char *der = NULL; + int der_len; + const EC_KEY *eckey; + struct wpabuf *ret = NULL; + size_t len; + const EC_GROUP *group; + const EC_POINT *point; + BN_CTX *ctx; + DPP_BOOTSTRAPPING_KEY *bootstrap = NULL; + int nid; + + ctx = BN_CTX_new(); + eckey = EVP_PKEY_get0_EC_KEY(key); + if (!ctx || !eckey) + goto fail; + + group = EC_KEY_get0_group(eckey); + point = EC_KEY_get0_public_key(eckey); + if (!group || !point) + goto fail; + dpp_debug_print_point("DPP: bootstrap public key", group, point); + nid = EC_GROUP_get_curve_name(group); + + bootstrap = DPP_BOOTSTRAPPING_KEY_new(); + if (!bootstrap || + X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC), + V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1) + goto fail; + + len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, + NULL, 0, ctx); + if (len == 0) + goto fail; + + der = OPENSSL_malloc(len); + if (!der) + goto fail; + len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, + der, len, ctx); + + OPENSSL_free(bootstrap->pub_key->data); + bootstrap->pub_key->data = der; + der = NULL; + bootstrap->pub_key->length = len; + /* No unused bits */ + bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; + + der_len = i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der); + if (der_len <= 0) { + wpa_printf(MSG_ERROR, + "DDP: Failed to build DER encoded public key"); + goto fail; + } + + ret = wpabuf_alloc_copy(der, der_len); +fail: + DPP_BOOTSTRAPPING_KEY_free(bootstrap); + OPENSSL_free(der); + BN_CTX_free(ctx); + return ret; +} + + +int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) +{ + struct wpabuf *der; + int res; + + der = dpp_bootstrap_key_der(bi->pubkey); + if (!der) + return -1; + wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", + der); + res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)); + if (res < 0) + wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); + wpabuf_free(der); + return res; +} + + +int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, + const u8 *privkey, size_t privkey_len) +{ + char *base64 = NULL; + char *pos, *end; + size_t len; + struct wpabuf *der = NULL; + + bi->curve = dpp_get_curve_name(curve); + if (!bi->curve) { + wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve); + return -1; + } + + if (privkey) + bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len); + else + bi->pubkey = dpp_gen_keypair(bi->curve); + if (!bi->pubkey) + goto fail; + bi->own = 1; + + der = dpp_bootstrap_key_der(bi->pubkey); + if (!der) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", + der); + + if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); + goto fail; + } + + base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len); + wpabuf_free(der); + der = NULL; + if (!base64) + goto fail; + pos = base64; + end = pos + len; + for (;;) { + pos = os_strchr(pos, '\n'); + if (!pos) + break; + os_memmove(pos, pos + 1, end - pos); + } + os_free(bi->pk); + bi->pk = base64; + return 0; +fail: + os_free(base64); + wpabuf_free(der); + return -1; +} + + +int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + const char *info = "first intermediate key"; + int res; + + /* k1 = HKDF(<>, "first intermediate key", M.x) */ + + /* HKDF-Extract(<>, M.x) */ + os_memset(salt, 0, hash_len); + if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len); + os_memset(prk, 0, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)", + k1, hash_len); + return 0; +} + + +int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + const char *info = "second intermediate key"; + int res; + + /* k2 = HKDF(<>, "second intermediate key", N.x) */ + + /* HKDF-Extract(<>, N.x) */ + os_memset(salt, 0, hash_len); + res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk); + if (res < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len); + os_memset(prk, 0, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)", + k2, hash_len); + return 0; +} + + +int dpp_derive_bk_ke(struct dpp_authentication *auth) +{ + unsigned int hash_len = auth->curve->hash_len; + size_t nonce_len = auth->curve->nonce_len; + u8 nonces[2 * DPP_MAX_NONCE_LEN]; + const char *info_ke = "DPP Key"; + int res; + const u8 *addr[3]; + size_t len[3]; + size_t num_elem = 0; + + if (!auth->Mx_len || !auth->Nx_len) { + wpa_printf(MSG_DEBUG, + "DPP: Mx/Nx not available - cannot derive ke"); + return -1; + } + + /* bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */ + os_memcpy(nonces, auth->i_nonce, nonce_len); + os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len); + addr[num_elem] = auth->Mx; + len[num_elem] = auth->Mx_len; + num_elem++; + addr[num_elem] = auth->Nx; + len[num_elem] = auth->Nx_len; + num_elem++; + if (auth->peer_bi && auth->own_bi) { + if (!auth->Lx_len) { + wpa_printf(MSG_DEBUG, + "DPP: Lx not available - cannot derive ke"); + return -1; + } + addr[num_elem] = auth->Lx; + len[num_elem] = auth->secret_len; + num_elem++; + } + res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len, + num_elem, addr, len, auth->bk); + if (res < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, + "DPP: bk = HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x])", + auth->bk, hash_len); + + /* ke = HKDF-Expand(bk, "DPP Key", length) */ + res = dpp_hkdf_expand(hash_len, auth->bk, hash_len, info_ke, auth->ke, + hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, + "DPP: ke = HKDF-Expand(bk, \"DPP Key\", length)", + auth->ke, hash_len); + + return 0; +} + + +int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, u8 *secret, size_t *secret_len) +{ + EVP_PKEY_CTX *ctx; + int ret = -1; + + ERR_clear_error(); + *secret_len = 0; + + ctx = EVP_PKEY_CTX_new(own, NULL); + if (!ctx) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + + if (EVP_PKEY_derive_init(ctx) != 1) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive_init failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (EVP_PKEY_derive_set_peer(ctx, peer) != 1) { + wpa_printf(MSG_ERROR, + "DPP: EVP_PKEY_derive_set_peet failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (EVP_PKEY_derive(ctx, NULL, secret_len) != 1) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive(NULL) failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { + u8 buf[200]; + int level = *secret_len > 200 ? MSG_ERROR : MSG_DEBUG; + + /* It looks like OpenSSL can return unexpectedly large buffer + * need for shared secret from EVP_PKEY_derive(NULL) in some + * cases. For example, group 19 has shown cases where secret_len + * is set to 72 even though the actual length ends up being + * updated to 32 when EVP_PKEY_derive() is called with a buffer + * for the value. Work around this by trying to fetch the value + * and continue if it is within supported range even when the + * initial buffer need is claimed to be larger. */ + wpa_printf(level, + "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()", + (int) *secret_len); + if (*secret_len > 200) + goto fail; + if (EVP_PKEY_derive(ctx, buf, secret_len) != 1) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { + wpa_printf(MSG_ERROR, + "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()", + (int) *secret_len); + goto fail; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: Unexpected secret_len change", + buf, *secret_len); + os_memcpy(secret, buf, *secret_len); + forced_memzero(buf, sizeof(buf)); + goto done; + } + + if (EVP_PKEY_derive(ctx, secret, secret_len) != 1) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + +done: + ret = 0; + +fail: + EVP_PKEY_CTX_free(ctx); + return ret; +} + + +int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, + const u8 *data, size_t data_len) +{ + const u8 *addr[2]; + size_t len[2]; + + addr[0] = data; + len[0] = data_len; + if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0) + return -1; + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", + bi->pubkey_hash, SHA256_MAC_LEN); + + addr[0] = (const u8 *) "chirp"; + len[0] = 5; + addr[1] = data; + len[1] = data_len; + if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0) + return -1; + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)", + bi->pubkey_hash_chirp, SHA256_MAC_LEN); + + return 0; +} + + +int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, + const u8 *data, size_t data_len) +{ + EVP_PKEY *pkey; + const unsigned char *p; + int res; + X509_PUBKEY *pub = NULL; + ASN1_OBJECT *ppkalg; + const unsigned char *pk; + int ppklen; + X509_ALGOR *pa; +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20800000L) + ASN1_OBJECT *pa_oid; +#else + const ASN1_OBJECT *pa_oid; +#endif + const void *pval; + int ptype; + const ASN1_OBJECT *poid; + char buf[100]; + + if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); + return -1; + } + + /* DER encoded ASN.1 SubjectPublicKeyInfo + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * subjectPublicKey = compressed format public key per ANSI X9.63 + * algorithm = ecPublicKey (1.2.840.10045.2.1) + * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g., + * prime256v1 (1.2.840.10045.3.1.7) + */ + + p = data; + pkey = d2i_PUBKEY(NULL, &p, data_len); + + if (!pkey) { + wpa_printf(MSG_DEBUG, + "DPP: Could not parse URI public-key SubjectPublicKeyInfo"); + return -1; + } + + if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) { + wpa_printf(MSG_DEBUG, + "DPP: SubjectPublicKeyInfo does not describe an EC key"); + EVP_PKEY_free(pkey); + return -1; + } + + res = X509_PUBKEY_set(&pub, pkey); + if (res != 1) { + wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey"); + goto fail; + } + + res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub); + if (res != 1) { + wpa_printf(MSG_DEBUG, + "DPP: Could not extract SubjectPublicKeyInfo parameters"); + goto fail; + } + res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0); + if (res < 0 || (size_t) res >= sizeof(buf)) { + wpa_printf(MSG_DEBUG, + "DPP: Could not extract SubjectPublicKeyInfo algorithm"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf); + if (os_strcmp(buf, "id-ecPublicKey") != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported SubjectPublicKeyInfo algorithm"); + goto fail; + } + + X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa); + if (ptype != V_ASN1_OBJECT) { + wpa_printf(MSG_DEBUG, + "DPP: SubjectPublicKeyInfo parameters did not contain an OID"); + goto fail; + } + poid = pval; + res = OBJ_obj2txt(buf, sizeof(buf), poid, 0); + if (res < 0 || (size_t) res >= sizeof(buf)) { + wpa_printf(MSG_DEBUG, + "DPP: Could not extract SubjectPublicKeyInfo parameters OID"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf); + bi->curve = dpp_get_curve_oid(poid); + if (!bi->curve) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported SubjectPublicKeyInfo curve: %s", + buf); + goto fail; + } + + wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen); + + X509_PUBKEY_free(pub); + bi->pubkey = pkey; + return 0; +fail: + X509_PUBKEY_free(pub); + EVP_PKEY_free(pkey); + return -1; +} + + +static struct wpabuf * +dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, + const u8 *prot_hdr, u16 prot_hdr_len, + const EVP_MD **ret_md) +{ + struct json_token *root, *token; + struct wpabuf *kid = NULL; + + root = json_parse((const char *) prot_hdr, prot_hdr_len); + if (!root) { + wpa_printf(MSG_DEBUG, + "DPP: JSON parsing failed for JWS Protected Header"); + goto fail; + } + + if (root->type != JSON_OBJECT) { + wpa_printf(MSG_DEBUG, + "DPP: JWS Protected Header root is not an object"); + goto fail; + } + + token = json_get_member(root, "typ"); + if (!token || token->type != JSON_STRING) { + wpa_printf(MSG_DEBUG, "DPP: No typ string value found"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s", + token->string); + if (os_strcmp(token->string, "dppCon") != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported JWS Protected Header typ=%s", + token->string); + goto fail; + } + + token = json_get_member(root, "alg"); + if (!token || token->type != JSON_STRING) { + wpa_printf(MSG_DEBUG, "DPP: No alg string value found"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s", + token->string); + if (os_strcmp(token->string, curve->jws_alg) != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)", + token->string, curve->jws_alg); + goto fail; + } + if (os_strcmp(token->string, "ES256") == 0 || + os_strcmp(token->string, "BS256") == 0) + *ret_md = EVP_sha256(); + else if (os_strcmp(token->string, "ES384") == 0 || + os_strcmp(token->string, "BS384") == 0) + *ret_md = EVP_sha384(); + else if (os_strcmp(token->string, "ES512") == 0 || + os_strcmp(token->string, "BS512") == 0) + *ret_md = EVP_sha512(); + else + *ret_md = NULL; + if (!*ret_md) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported JWS Protected Header alg=%s", + token->string); + goto fail; + } + + kid = json_get_member_base64url(root, "kid"); + if (!kid) { + wpa_printf(MSG_DEBUG, "DPP: No kid string value found"); + goto fail; + } + wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)", + kid); + +fail: + json_free(root); + return kid; +} + + +static int dpp_check_pubkey_match(EVP_PKEY *pub, struct wpabuf *r_hash) +{ + struct wpabuf *uncomp; + int res; + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[1]; + size_t len[1]; + + if (wpabuf_len(r_hash) != SHA256_MAC_LEN) + return -1; + uncomp = dpp_get_pubkey_point(pub, 1); + if (!uncomp) + return -1; + addr[0] = wpabuf_head(uncomp); + len[0] = wpabuf_len(uncomp); + wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key", + addr[0], len[0]); + res = sha256_vector(1, addr, len, hash); + wpabuf_free(uncomp); + if (res < 0) + return -1; + if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Received hash value does not match calculated public key hash value"); + wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash", + hash, SHA256_MAC_LEN); + return -1; + } + return 0; +} + + +enum dpp_status_error +dpp_process_signed_connector(struct dpp_signed_connector_info *info, + EVP_PKEY *csign_pub, const char *connector) +{ + enum dpp_status_error ret = 255; + const char *pos, *end, *signed_start, *signed_end; + struct wpabuf *kid = NULL; + unsigned char *prot_hdr = NULL, *signature = NULL; + size_t prot_hdr_len = 0, signature_len = 0; + const EVP_MD *sign_md = NULL; + unsigned char *der = NULL; + int der_len; + int res; + EVP_MD_CTX *md_ctx = NULL; + ECDSA_SIG *sig = NULL; + BIGNUM *r = NULL, *s = NULL; + const struct dpp_curve_params *curve; + const EC_KEY *eckey; + const EC_GROUP *group; + int nid; + + eckey = EVP_PKEY_get0_EC_KEY(csign_pub); + if (!eckey) + goto fail; + group = EC_KEY_get0_group(eckey); + if (!group) + goto fail; + nid = EC_GROUP_get_curve_name(group); + curve = dpp_get_curve_nid(nid); + if (!curve) + goto fail; + wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv); + os_memset(info, 0, sizeof(*info)); + + signed_start = pos = connector; + end = os_strchr(pos, '.'); + if (!end) { + wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len); + if (!prot_hdr) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to base64url decode signedConnector JWS Protected Header"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, + "DPP: signedConnector - JWS Protected Header", + prot_hdr, prot_hdr_len); + kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &sign_md); + if (!kid) { + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + if (wpabuf_len(kid) != SHA256_MAC_LEN) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)", + (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + + pos = end + 1; + end = os_strchr(pos, '.'); + if (!end) { + wpa_printf(MSG_DEBUG, + "DPP: Missing dot(2) in signedConnector"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + signed_end = end - 1; + info->payload = base64_url_decode(pos, end - pos, &info->payload_len); + if (!info->payload) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to base64url decode signedConnector JWS Payload"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, + "DPP: signedConnector - JWS Payload", + info->payload, info->payload_len); + pos = end + 1; + signature = base64_url_decode(pos, os_strlen(pos), &signature_len); + if (!signature) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to base64url decode signedConnector signature"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature", + signature, signature_len); + + if (dpp_check_pubkey_match(csign_pub, kid) < 0) { + ret = DPP_STATUS_NO_MATCH; + goto fail; + } + + if (signature_len & 0x01) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected signedConnector signature length (%d)", + (int) signature_len); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + + /* JWS Signature encodes the signature (r,s) as two octet strings. Need + * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */ + r = BN_bin2bn(signature, signature_len / 2, NULL); + s = BN_bin2bn(signature + signature_len / 2, signature_len / 2, NULL); + sig = ECDSA_SIG_new(); + if (!r || !s || !sig || ECDSA_SIG_set0(sig, r, s) != 1) + goto fail; + r = NULL; + s = NULL; + + der_len = i2d_ECDSA_SIG(sig, &der); + if (der_len <= 0) { + wpa_printf(MSG_DEBUG, "DPP: Could not DER encode signature"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: DER encoded signature", der, der_len); + md_ctx = EVP_MD_CTX_create(); + if (!md_ctx) + goto fail; + + ERR_clear_error(); + if (EVP_DigestVerifyInit(md_ctx, NULL, sign_md, NULL, csign_pub) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyInit failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (EVP_DigestVerifyUpdate(md_ctx, signed_start, + signed_end - signed_start + 1) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestVerifyUpdate failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + res = EVP_DigestVerifyFinal(md_ctx, der, der_len); + if (res != 1) { + wpa_printf(MSG_DEBUG, + "DPP: EVP_DigestVerifyFinal failed (res=%d): %s", + res, ERR_error_string(ERR_get_error(), NULL)); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + + ret = DPP_STATUS_OK; +fail: + EVP_MD_CTX_destroy(md_ctx); + os_free(prot_hdr); + wpabuf_free(kid); + os_free(signature); + ECDSA_SIG_free(sig); + BN_free(r); + BN_free(s); + OPENSSL_free(der); + return ret; +} + + +enum dpp_status_error +dpp_check_signed_connector(struct dpp_signed_connector_info *info, + const u8 *csign_key, size_t csign_key_len, + const u8 *peer_connector, size_t peer_connector_len) +{ + const unsigned char *p; + EVP_PKEY *csign = NULL; + char *signed_connector = NULL; + enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR; + + p = csign_key; + csign = d2i_PUBKEY(NULL, &p, csign_key_len); + if (!csign) { + wpa_printf(MSG_ERROR, + "DPP: Failed to parse local C-sign-key information"); + goto fail; + } + + wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector", + peer_connector, peer_connector_len); + signed_connector = os_malloc(peer_connector_len + 1); + if (!signed_connector) + goto fail; + os_memcpy(signed_connector, peer_connector, peer_connector_len); + signed_connector[peer_connector_len] = '\0'; + res = dpp_process_signed_connector(info, csign, signed_connector); +fail: + os_free(signed_connector); + EVP_PKEY_free(csign); + return res; +} + + +int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth) +{ + struct wpabuf *pix, *prx, *bix, *brx; + const u8 *addr[7]; + size_t len[7]; + size_t i, num_elem = 0; + size_t nonce_len; + u8 zero = 0; + int res = -1; + + /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ + nonce_len = auth->curve->nonce_len; + + if (auth->initiator) { + pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + if (auth->own_bi) + bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + else + bix = NULL; + brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + } else { + pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (auth->peer_bi) + bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + else + bix = NULL; + brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + } + if (!pix || !prx || !brx) + goto fail; + + addr[num_elem] = auth->i_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = auth->r_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = wpabuf_head(pix); + len[num_elem] = wpabuf_len(pix) / 2; + num_elem++; + + addr[num_elem] = wpabuf_head(prx); + len[num_elem] = wpabuf_len(prx) / 2; + num_elem++; + + if (bix) { + addr[num_elem] = wpabuf_head(bix); + len[num_elem] = wpabuf_len(bix) / 2; + num_elem++; + } + + addr[num_elem] = wpabuf_head(brx); + len[num_elem] = wpabuf_len(brx) / 2; + num_elem++; + + addr[num_elem] = &zero; + len[num_elem] = 1; + num_elem++; + + wpa_printf(MSG_DEBUG, "DPP: R-auth hash components"); + for (i = 0; i < num_elem; i++) + wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); + res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth); + if (res == 0) + wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth, + auth->curve->hash_len); +fail: + wpabuf_free(pix); + wpabuf_free(prx); + wpabuf_free(bix); + wpabuf_free(brx); + return res; +} + + +int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth) +{ + struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL; + const u8 *addr[7]; + size_t len[7]; + size_t i, num_elem = 0; + size_t nonce_len; + u8 one = 1; + int res = -1; + + /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ + nonce_len = auth->curve->nonce_len; + + if (auth->initiator) { + pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + if (auth->own_bi) + bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + else + bix = NULL; + if (!auth->peer_bi) + goto fail; + brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + } else { + pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (auth->peer_bi) + bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + else + bix = NULL; + if (!auth->own_bi) + goto fail; + brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + } + if (!pix || !prx || !brx) + goto fail; + + addr[num_elem] = auth->r_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = auth->i_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = wpabuf_head(prx); + len[num_elem] = wpabuf_len(prx) / 2; + num_elem++; + + addr[num_elem] = wpabuf_head(pix); + len[num_elem] = wpabuf_len(pix) / 2; + num_elem++; + + addr[num_elem] = wpabuf_head(brx); + len[num_elem] = wpabuf_len(brx) / 2; + num_elem++; + + if (bix) { + addr[num_elem] = wpabuf_head(bix); + len[num_elem] = wpabuf_len(bix) / 2; + num_elem++; + } + + addr[num_elem] = &one; + len[num_elem] = 1; + num_elem++; + + wpa_printf(MSG_DEBUG, "DPP: I-auth hash components"); + for (i = 0; i < num_elem; i++) + wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); + res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth); + if (res == 0) + wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth, + auth->curve->hash_len); +fail: + wpabuf_free(pix); + wpabuf_free(prx); + wpabuf_free(bix); + wpabuf_free(brx); + return res; +} + + +int dpp_auth_derive_l_responder(struct dpp_authentication *auth) +{ + const EC_GROUP *group; + EC_POINT *l = NULL; + const EC_KEY *BI, *bR, *pR; + const EC_POINT *BI_point; + BN_CTX *bnctx; + BIGNUM *lx, *sum, *q; + const BIGNUM *bR_bn, *pR_bn; + int ret = -1; + + /* L = ((bR + pR) modulo q) * BI */ + + bnctx = BN_CTX_new(); + sum = BN_new(); + q = BN_new(); + lx = BN_new(); + if (!bnctx || !sum || !q || !lx) + goto fail; + BI = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey); + if (!BI) + goto fail; + BI_point = EC_KEY_get0_public_key(BI); + group = EC_KEY_get0_group(BI); + if (!group) + goto fail; + + bR = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey); + pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key); + if (!bR || !pR) + goto fail; + bR_bn = EC_KEY_get0_private_key(bR); + pR_bn = EC_KEY_get0_private_key(pR); + if (!bR_bn || !pR_bn) + goto fail; + if (EC_GROUP_get_order(group, q, bnctx) != 1 || + BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1) + goto fail; + l = EC_POINT_new(group); + if (!l || + EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL, + bnctx) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); + auth->Lx_len = auth->secret_len; + ret = 0; +fail: + EC_POINT_clear_free(l); + BN_clear_free(lx); + BN_clear_free(sum); + BN_free(q); + BN_CTX_free(bnctx); + return ret; +} + + +int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) +{ + const EC_GROUP *group; + EC_POINT *l = NULL, *sum = NULL; + const EC_KEY *bI, *BR, *PR; + const EC_POINT *BR_point, *PR_point; + BN_CTX *bnctx; + BIGNUM *lx; + const BIGNUM *bI_bn; + int ret = -1; + + /* L = bI * (BR + PR) */ + + bnctx = BN_CTX_new(); + lx = BN_new(); + if (!bnctx || !lx) + goto fail; + BR = EVP_PKEY_get0_EC_KEY(auth->peer_bi->pubkey); + PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key); + if (!BR || !PR) + goto fail; + BR_point = EC_KEY_get0_public_key(BR); + PR_point = EC_KEY_get0_public_key(PR); + + bI = EVP_PKEY_get0_EC_KEY(auth->own_bi->pubkey); + if (!bI) + goto fail; + group = EC_KEY_get0_group(bI); + bI_bn = EC_KEY_get0_private_key(bI); + if (!group || !bI_bn) + goto fail; + sum = EC_POINT_new(group); + l = EC_POINT_new(group); + if (!sum || !l || + EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 || + EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL, + bnctx) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); + auth->Lx_len = auth->secret_len; + ret = 0; +fail: + EC_POINT_clear_free(l); + EC_POINT_clear_free(sum); + BN_clear_free(lx); + BN_CTX_free(bnctx); + return ret; +} + + +int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + const char *info = "DPP PMK"; + int res; + + /* PMK = HKDF(<>, "DPP PMK", N.x) */ + + /* HKDF-Extract(<>, N.x) */ + os_memset(salt, 0, hash_len); + if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len); + os_memset(prk, 0, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)", + pmk, hash_len); + return 0; +} + + +int dpp_derive_pmkid(const struct dpp_curve_params *curve, + EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid) +{ + struct wpabuf *nkx, *pkx; + int ret = -1, res; + const u8 *addr[2]; + size_t len[2]; + u8 hash[SHA256_MAC_LEN]; + + /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */ + nkx = dpp_get_pubkey_point(own_key, 0); + pkx = dpp_get_pubkey_point(peer_key, 0); + if (!nkx || !pkx) + goto fail; + addr[0] = wpabuf_head(nkx); + len[0] = wpabuf_len(nkx) / 2; + addr[1] = wpabuf_head(pkx); + len[1] = wpabuf_len(pkx) / 2; + if (len[0] != len[1]) + goto fail; + if (os_memcmp(addr[0], addr[1], len[0]) > 0) { + addr[0] = wpabuf_head(pkx); + addr[1] = wpabuf_head(nkx); + } + wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]); + res = sha256_vector(2, addr, len, hash); + if (res < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN); + os_memcpy(pmkid, hash, PMKID_LEN); + wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN); + ret = 0; +fail: + wpabuf_free(nkx); + wpabuf_free(pkx); + return ret; +} + + +/* Role-specific elements for PKEX */ + +/* NIST P-256 */ +static const u8 pkex_init_x_p256[32] = { + 0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b, + 0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54, + 0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07, + 0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25 + }; +static const u8 pkex_init_y_p256[32] = { + 0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b, + 0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc, + 0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45, + 0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4 + }; +static const u8 pkex_resp_x_p256[32] = { + 0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39, + 0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f, + 0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f, + 0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76 +}; +static const u8 pkex_resp_y_p256[32] = { + 0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19, + 0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1, + 0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a, + 0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67 +}; + +/* NIST P-384 */ +static const u8 pkex_init_x_p384[48] = { + 0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa, + 0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68, + 0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53, + 0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac, + 0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12, + 0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3 +}; +static const u8 pkex_init_y_p384[48] = { + 0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29, + 0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56, + 0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7, + 0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6, + 0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94, + 0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18 +}; +static const u8 pkex_resp_x_p384[48] = { + 0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98, + 0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97, + 0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92, + 0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44, + 0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf, + 0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf +}; +static const u8 pkex_resp_y_p384[48] = { + 0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c, + 0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c, + 0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3, + 0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1, + 0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63, + 0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06 +}; + +/* NIST P-521 */ +static const u8 pkex_init_x_p521[66] = { + 0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23, + 0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0, + 0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76, + 0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5, + 0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38, + 0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01, + 0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e, + 0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d, + 0x97, 0x76 +}; +static const u8 pkex_init_y_p521[66] = { + 0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59, + 0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99, + 0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b, + 0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd, + 0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f, + 0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf, + 0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02, + 0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d, + 0x03, 0xa8 +}; +static const u8 pkex_resp_x_p521[66] = { + 0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a, + 0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44, + 0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f, + 0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb, + 0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48, + 0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e, + 0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a, + 0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97, + 0x84, 0xb4 +}; +static const u8 pkex_resp_y_p521[66] = { + 0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d, + 0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20, + 0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3, + 0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84, + 0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9, + 0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2, + 0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80, + 0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53, + 0xce, 0xe1 +}; + +/* Brainpool P-256r1 */ +static const u8 pkex_init_x_bp_p256r1[32] = { + 0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10, + 0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca, + 0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75, + 0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8 +}; +static const u8 pkex_init_y_bp_p256r1[32] = { + 0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd, + 0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30, + 0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe, + 0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b +}; +static const u8 pkex_resp_x_bp_p256r1[32] = { + 0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f, + 0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a, + 0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a, + 0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3 +}; +static const u8 pkex_resp_y_bp_p256r1[32] = { + 0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd, + 0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2, + 0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e, + 0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64 +}; + +/* Brainpool P-384r1 */ +static const u8 pkex_init_x_bp_p384r1[48] = { + 0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd, + 0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19, + 0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06, + 0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62, + 0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30, + 0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe +}; +static const u8 pkex_init_y_bp_p384r1[48] = { + 0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99, + 0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86, + 0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32, + 0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9, + 0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e, + 0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52 +}; +static const u8 pkex_resp_x_bp_p384r1[48] = { + 0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0, + 0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25, + 0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b, + 0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71, + 0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce, + 0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c +}; +static const u8 pkex_resp_y_bp_p384r1[48] = { + 0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65, + 0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04, + 0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70, + 0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c, + 0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb, + 0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1 +}; + +/* Brainpool P-512r1 */ +static const u8 pkex_init_x_bp_p512r1[64] = { + 0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c, + 0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51, + 0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc, + 0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95, + 0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d, + 0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff, + 0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc, + 0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f +}; +static const u8 pkex_init_y_bp_p512r1[64] = { + 0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94, + 0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8, + 0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3, + 0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45, + 0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e, + 0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58, + 0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71, + 0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99 +}; +static const u8 pkex_resp_x_bp_p512r1[64] = { + 0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72, + 0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76, + 0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19, + 0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e, + 0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9, + 0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88, + 0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29, + 0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e +}; +static const u8 pkex_resp_y_bp_p512r1[64] = { + 0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81, + 0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68, + 0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa, + 0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d, + 0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c, + 0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09, + 0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56, + 0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7 +}; + + +static EVP_PKEY * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, + int init) +{ + EC_GROUP *group; + size_t len = curve->prime_len; + const u8 *x, *y; + EVP_PKEY *res; + + switch (curve->ike_group) { + case 19: + x = init ? pkex_init_x_p256 : pkex_resp_x_p256; + y = init ? pkex_init_y_p256 : pkex_resp_y_p256; + break; + case 20: + x = init ? pkex_init_x_p384 : pkex_resp_x_p384; + y = init ? pkex_init_y_p384 : pkex_resp_y_p384; + break; + case 21: + x = init ? pkex_init_x_p521 : pkex_resp_x_p521; + y = init ? pkex_init_y_p521 : pkex_resp_y_p521; + break; + case 28: + x = init ? pkex_init_x_bp_p256r1 : pkex_resp_x_bp_p256r1; + y = init ? pkex_init_y_bp_p256r1 : pkex_resp_y_bp_p256r1; + break; + case 29: + x = init ? pkex_init_x_bp_p384r1 : pkex_resp_x_bp_p384r1; + y = init ? pkex_init_y_bp_p384r1 : pkex_resp_y_bp_p384r1; + break; + case 30: + x = init ? pkex_init_x_bp_p512r1 : pkex_resp_x_bp_p512r1; + y = init ? pkex_init_y_bp_p512r1 : pkex_resp_y_bp_p512r1; + break; + default: + return NULL; + } + + group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); + if (!group) + return NULL; + res = dpp_set_pubkey_point_group(group, x, y, len); + EC_GROUP_free(group); + return res; +} + + +EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, + const u8 *mac_init, const char *code, + const char *identifier, BN_CTX *bnctx, + EC_GROUP **ret_group) +{ + u8 hash[DPP_MAX_HASH_LEN]; + const u8 *addr[3]; + size_t len[3]; + unsigned int num_elem = 0; + EC_POINT *Qi = NULL; + EVP_PKEY *Pi = NULL; + const EC_KEY *Pi_ec; + const EC_POINT *Pi_point; + BIGNUM *hash_bn = NULL; + const EC_GROUP *group = NULL; + EC_GROUP *group2 = NULL; + + /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ + + wpa_printf(MSG_DEBUG, "DPP: MAC-Initiator: " MACSTR, MAC2STR(mac_init)); + addr[num_elem] = mac_init; + len[num_elem] = ETH_ALEN; + num_elem++; + if (identifier) { + wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", + identifier); + addr[num_elem] = (const u8 *) identifier; + len[num_elem] = os_strlen(identifier); + num_elem++; + } + wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); + addr[num_elem] = (const u8 *) code; + len[num_elem] = os_strlen(code); + num_elem++; + if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: H(MAC-Initiator | [identifier |] code)", + hash, curve->hash_len); + Pi = dpp_pkex_get_role_elem(curve, 1); + if (!Pi) + goto fail; + dpp_debug_print_key("DPP: Pi", Pi); + Pi_ec = EVP_PKEY_get0_EC_KEY(Pi); + if (!Pi_ec) + goto fail; + Pi_point = EC_KEY_get0_public_key(Pi_ec); + + group = EC_KEY_get0_group(Pi_ec); + if (!group) + goto fail; + group2 = EC_GROUP_dup(group); + if (!group2) + goto fail; + Qi = EC_POINT_new(group2); + if (!Qi) { + EC_GROUP_free(group2); + goto fail; + } + hash_bn = BN_bin2bn(hash, curve->hash_len, NULL); + if (!hash_bn || + EC_POINT_mul(group2, Qi, NULL, Pi_point, hash_bn, bnctx) != 1) + goto fail; + if (EC_POINT_is_at_infinity(group, Qi)) { + wpa_printf(MSG_INFO, "DPP: Qi is the point-at-infinity"); + goto fail; + } + dpp_debug_print_point("DPP: Qi", group, Qi); +out: + EVP_PKEY_free(Pi); + BN_clear_free(hash_bn); + if (ret_group && Qi) + *ret_group = group2; + else + EC_GROUP_free(group2); + return Qi; +fail: + EC_POINT_free(Qi); + Qi = NULL; + goto out; +} + + +EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, + const u8 *mac_resp, const char *code, + const char *identifier, BN_CTX *bnctx, + EC_GROUP **ret_group) +{ + u8 hash[DPP_MAX_HASH_LEN]; + const u8 *addr[3]; + size_t len[3]; + unsigned int num_elem = 0; + EC_POINT *Qr = NULL; + EVP_PKEY *Pr = NULL; + const EC_KEY *Pr_ec; + const EC_POINT *Pr_point; + BIGNUM *hash_bn = NULL; + const EC_GROUP *group = NULL; + EC_GROUP *group2 = NULL; + + /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */ + + wpa_printf(MSG_DEBUG, "DPP: MAC-Responder: " MACSTR, MAC2STR(mac_resp)); + addr[num_elem] = mac_resp; + len[num_elem] = ETH_ALEN; + num_elem++; + if (identifier) { + wpa_printf(MSG_DEBUG, "DPP: code identifier: %s", + identifier); + addr[num_elem] = (const u8 *) identifier; + len[num_elem] = os_strlen(identifier); + num_elem++; + } + wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: code", code, os_strlen(code)); + addr[num_elem] = (const u8 *) code; + len[num_elem] = os_strlen(code); + num_elem++; + if (dpp_hash_vector(curve, num_elem, addr, len, hash) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: H(MAC-Responder | [identifier |] code)", + hash, curve->hash_len); + Pr = dpp_pkex_get_role_elem(curve, 0); + if (!Pr) + goto fail; + dpp_debug_print_key("DPP: Pr", Pr); + Pr_ec = EVP_PKEY_get0_EC_KEY(Pr); + if (!Pr_ec) + goto fail; + Pr_point = EC_KEY_get0_public_key(Pr_ec); + + group = EC_KEY_get0_group(Pr_ec); + if (!group) + goto fail; + group2 = EC_GROUP_dup(group); + if (!group2) + goto fail; + Qr = EC_POINT_new(group2); + if (!Qr) { + EC_GROUP_free(group2); + goto fail; + } + hash_bn = BN_bin2bn(hash, curve->hash_len, NULL); + if (!hash_bn || + EC_POINT_mul(group2, Qr, NULL, Pr_point, hash_bn, bnctx) != 1) + goto fail; + if (EC_POINT_is_at_infinity(group, Qr)) { + wpa_printf(MSG_INFO, "DPP: Qr is the point-at-infinity"); + goto fail; + } + dpp_debug_print_point("DPP: Qr", group, Qr); +out: + EVP_PKEY_free(Pr); + BN_clear_free(hash_bn); + if (ret_group && Qr) + *ret_group = group2; + else + EC_GROUP_free(group2); + return Qr; +fail: + EC_POINT_free(Qr); + Qr = NULL; + goto out; +} + + +int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp, + const u8 *Mx, size_t Mx_len, + const u8 *Nx, size_t Nx_len, + const char *code, + const u8 *Kx, size_t Kx_len, + u8 *z, unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + int res; + u8 *info, *pos; + size_t info_len; + + /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) + */ + + /* HKDF-Extract(<>, IKM=K.x) */ + os_memset(salt, 0, hash_len); + if (dpp_hmac(hash_len, salt, hash_len, Kx, Kx_len, prk) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", + prk, hash_len); + info_len = 2 * ETH_ALEN + Mx_len + Nx_len + os_strlen(code); + info = os_malloc(info_len); + if (!info) + return -1; + pos = info; + os_memcpy(pos, mac_init, ETH_ALEN); + pos += ETH_ALEN; + os_memcpy(pos, mac_resp, ETH_ALEN); + pos += ETH_ALEN; + os_memcpy(pos, Mx, Mx_len); + pos += Mx_len; + os_memcpy(pos, Nx, Nx_len); + pos += Nx_len; + os_memcpy(pos, code, os_strlen(code)); + + /* HKDF-Expand(PRK, info, L) */ + if (hash_len == 32) + res = hmac_sha256_kdf(prk, hash_len, NULL, info, info_len, + z, hash_len); + else if (hash_len == 48) + res = hmac_sha384_kdf(prk, hash_len, NULL, info, info_len, + z, hash_len); + else if (hash_len == 64) + res = hmac_sha512_kdf(prk, hash_len, NULL, info, info_len, + z, hash_len); + else + res = -1; + os_free(info); + os_memset(prk, 0, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: z = HKDF-Expand(PRK, info, L)", + z, hash_len); + return 0; +} + + +int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, + const u8 *net_access_key, + size_t net_access_key_len, + struct json_token *peer_net_access_key) +{ + BN_CTX *bnctx = NULL; + EVP_PKEY *own_key = NULL, *peer_key = NULL; + BIGNUM *sum = NULL, *q = NULL, *mx = NULL; + EC_POINT *m = NULL; + const EC_KEY *cR, *pR; + const EC_GROUP *group; + const BIGNUM *cR_bn, *pR_bn; + const EC_POINT *CI_point; + const EC_KEY *CI; + u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; + u8 prk[DPP_MAX_HASH_LEN]; + const struct dpp_curve_params *curve; + int res = -1; + u8 nonces[2 * DPP_MAX_NONCE_LEN]; + + own_key = dpp_set_keypair(&auth->curve, net_access_key, + net_access_key_len); + if (!own_key) { + dpp_auth_fail(auth, "Failed to parse own netAccessKey"); + goto fail; + } + + peer_key = dpp_parse_jwk(peer_net_access_key, &curve); + if (!peer_key) + goto fail; + dpp_debug_print_key("DPP: Received netAccessKey", peer_key); + + if (auth->curve != curve) { + wpa_printf(MSG_DEBUG, + "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", + auth->curve->name, curve->name); + goto fail; + } + + auth->own_protocol_key = dpp_gen_keypair(curve); + if (!auth->own_protocol_key) + goto fail; + + if (random_get_bytes(auth->e_nonce, auth->curve->nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce"); + goto fail; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: E-nonce", + auth->e_nonce, auth->curve->nonce_len); + + /* M = { cR + pR } * CI */ + cR = EVP_PKEY_get0_EC_KEY(own_key); + pR = EVP_PKEY_get0_EC_KEY(auth->own_protocol_key); + if (!pR) + goto fail; + group = EC_KEY_get0_group(pR); + bnctx = BN_CTX_new(); + sum = BN_new(); + mx = BN_new(); + q = BN_new(); + m = EC_POINT_new(group); + if (!cR || !bnctx || !sum || !mx || !q || !m) + goto fail; + cR_bn = EC_KEY_get0_private_key(cR); + pR_bn = EC_KEY_get0_private_key(pR); + if (!cR_bn || !pR_bn) + goto fail; + CI = EVP_PKEY_get0_EC_KEY(peer_key); + CI_point = EC_KEY_get0_public_key(CI); + if (EC_GROUP_get_order(group, q, bnctx) != 1 || + BN_mod_add(sum, cR_bn, pR_bn, q, bnctx) != 1 || + EC_POINT_mul(group, m, NULL, CI_point, sum, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, m, mx, NULL, + bnctx) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (dpp_bn2bin_pad(mx, Mx, curve->prime_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); + + /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */ + + /* HKDF-Extract(C-nonce | E-nonce, M.x) */ + os_memcpy(nonces, auth->c_nonce, curve->nonce_len); + os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len); + if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len, + Mx, curve->prime_len, prk) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); + + /* HKDF-Expand(PRK, "dpp reconfig key", L) */ + if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, + "dpp reconfig key", auth->ke, curve->hash_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)", + auth->ke, curve->hash_len); + + res = 0; + EVP_PKEY_free(auth->reconfig_old_protocol_key); + auth->reconfig_old_protocol_key = own_key; + own_key = NULL; +fail: + forced_memzero(prk, sizeof(prk)); + forced_memzero(Mx, sizeof(Mx)); + EC_POINT_clear_free(m); + BN_free(q); + BN_clear_free(mx); + BN_clear_free(sum); + EVP_PKEY_free(own_key); + EVP_PKEY_free(peer_key); + BN_CTX_free(bnctx); + return res; +} + + +int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, + const u8 *r_proto, u16 r_proto_len, + struct json_token *net_access_key) +{ + BN_CTX *bnctx = NULL; + EVP_PKEY *pr = NULL, *peer_key = NULL; + EC_POINT *sum = NULL, *m = NULL; + BIGNUM *mx = NULL; + const EC_KEY *cI, *CR, *PR; + const EC_GROUP *group; + const EC_POINT *CR_point, *PR_point; + const BIGNUM *cI_bn; + u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; + u8 prk[DPP_MAX_HASH_LEN]; + int res = -1; + const struct dpp_curve_params *curve; + u8 nonces[2 * DPP_MAX_NONCE_LEN]; + + pr = dpp_set_pubkey_point(auth->conf->connector_key, + r_proto, r_proto_len); + if (!pr) { + dpp_auth_fail(auth, "Invalid Responder Protocol Key"); + goto fail; + } + dpp_debug_print_key("Peer (Responder) Protocol Key", pr); + EVP_PKEY_free(auth->peer_protocol_key); + auth->peer_protocol_key = pr; + pr = NULL; + + peer_key = dpp_parse_jwk(net_access_key, &curve); + if (!peer_key) + goto fail; + dpp_debug_print_key("DPP: Received netAccessKey", peer_key); + if (auth->curve != curve) { + wpa_printf(MSG_DEBUG, + "DPP: Mismatching netAccessKey curves (own=%s != peer=%s)", + auth->curve->name, curve->name); + goto fail; + } + + /* M = cI * { CR + PR } */ + cI = EVP_PKEY_get0_EC_KEY(auth->conf->connector_key); + cI_bn = EC_KEY_get0_private_key(cI); + group = EC_KEY_get0_group(cI); + bnctx = BN_CTX_new(); + sum = EC_POINT_new(group); + m = EC_POINT_new(group); + mx = BN_new(); + CR = EVP_PKEY_get0_EC_KEY(peer_key); + PR = EVP_PKEY_get0_EC_KEY(auth->peer_protocol_key); + CR_point = EC_KEY_get0_public_key(CR); + PR_point = EC_KEY_get0_public_key(PR); + if (!bnctx || !sum || !m || !mx || + EC_POINT_add(group, sum, CR_point, PR_point, bnctx) != 1 || + EC_POINT_mul(group, m, NULL, sum, cI_bn, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, m, mx, NULL, + bnctx) != 1 || + dpp_bn2bin_pad(mx, Mx, curve->prime_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: M.x", Mx, curve->prime_len); + + /* ke = HKDF(C-nonce | E-nonce, "dpp reconfig key", M.x) */ + + /* HKDF-Extract(C-nonce | E-nonce, M.x) */ + os_memcpy(nonces, auth->c_nonce, curve->nonce_len); + os_memcpy(&nonces[curve->nonce_len], auth->e_nonce, curve->nonce_len); + if (dpp_hmac(curve->hash_len, nonces, 2 * curve->nonce_len, + Mx, curve->prime_len, prk) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK", prk, curve->hash_len); + + /* HKDF-Expand(PRK, "dpp reconfig key", L) */ + if (dpp_hkdf_expand(curve->hash_len, prk, curve->hash_len, + "dpp reconfig key", auth->ke, curve->hash_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: ke = HKDF(C-nonce | E-nonce, \"dpp reconfig key\", M.x)", + auth->ke, curve->hash_len); + + res = 0; +fail: + forced_memzero(prk, sizeof(prk)); + forced_memzero(Mx, sizeof(Mx)); + EVP_PKEY_free(pr); + EVP_PKEY_free(peer_key); + EC_POINT_clear_free(sum); + EC_POINT_clear_free(m); + BN_clear_free(mx); + BN_CTX_free(bnctx); + return res; +} + + +static char * +dpp_build_jws_prot_hdr(struct dpp_configurator *conf, size_t *signed1_len) +{ + struct wpabuf *jws_prot_hdr; + char *signed1; + + jws_prot_hdr = wpabuf_alloc(100); + if (!jws_prot_hdr) + return NULL; + json_start_object(jws_prot_hdr, NULL); + json_add_string(jws_prot_hdr, "typ", "dppCon"); + json_value_sep(jws_prot_hdr); + json_add_string(jws_prot_hdr, "kid", conf->kid); + json_value_sep(jws_prot_hdr); + json_add_string(jws_prot_hdr, "alg", conf->curve->jws_alg); + json_end_object(jws_prot_hdr); + signed1 = base64_url_encode(wpabuf_head(jws_prot_hdr), + wpabuf_len(jws_prot_hdr), + signed1_len); + wpabuf_free(jws_prot_hdr); + return signed1; +} + + +static char * +dpp_build_conn_signature(struct dpp_configurator *conf, + const char *signed1, size_t signed1_len, + const char *signed2, size_t signed2_len, + size_t *signed3_len) +{ + const struct dpp_curve_params *curve; + char *signed3 = NULL; + unsigned char *signature = NULL; + const unsigned char *p; + size_t signature_len; + EVP_MD_CTX *md_ctx = NULL; + ECDSA_SIG *sig = NULL; + char *dot = "."; + const EVP_MD *sign_md; + const BIGNUM *r, *s; + + curve = conf->curve; + if (curve->hash_len == SHA256_MAC_LEN) { + sign_md = EVP_sha256(); + } else if (curve->hash_len == SHA384_MAC_LEN) { + sign_md = EVP_sha384(); + } else if (curve->hash_len == SHA512_MAC_LEN) { + sign_md = EVP_sha512(); + } else { + wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); + goto fail; + } + + md_ctx = EVP_MD_CTX_create(); + if (!md_ctx) + goto fail; + + ERR_clear_error(); + if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL, conf->csign) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 || + EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 || + EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + signature = os_malloc(signature_len); + if (!signature) + goto fail; + if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)", + signature, signature_len); + /* Convert to raw coordinates r,s */ + p = signature; + sig = d2i_ECDSA_SIG(NULL, &p, signature_len); + if (!sig) + goto fail; + ECDSA_SIG_get0(sig, &r, &s); + if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 || + dpp_bn2bin_pad(s, signature + curve->prime_len, + curve->prime_len) < 0) + goto fail; + signature_len = 2 * curve->prime_len; + wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)", + signature, signature_len); + signed3 = base64_url_encode(signature, signature_len, signed3_len); +fail: + EVP_MD_CTX_destroy(md_ctx); + ECDSA_SIG_free(sig); + os_free(signature); + return signed3; +} + +char * dpp_sign_connector(struct dpp_configurator *conf, + const struct wpabuf *dppcon) +{ + char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL; + char *signed_conn = NULL, *pos; + size_t signed1_len, signed2_len, signed3_len; + + signed1 = dpp_build_jws_prot_hdr(conf, &signed1_len); + signed2 = base64_url_encode(wpabuf_head(dppcon), wpabuf_len(dppcon), + &signed2_len); + if (!signed1 || !signed2) + goto fail; + + signed3 = dpp_build_conn_signature(conf, signed1, signed1_len, + signed2, signed2_len, &signed3_len); + if (!signed3) + goto fail; + + signed_conn = os_malloc(signed1_len + signed2_len + signed3_len + 3); + if (!signed_conn) + goto fail; + pos = signed_conn; + os_memcpy(pos, signed1, signed1_len); + pos += signed1_len; + *pos++ = '.'; + os_memcpy(pos, signed2, signed2_len); + pos += signed2_len; + *pos++ = '.'; + os_memcpy(pos, signed3, signed3_len); + pos += signed3_len; + *pos = '\0'; + +fail: + os_free(signed1); + os_free(signed2); + os_free(signed3); + return signed_conn; +} + + +#ifdef CONFIG_DPP2 + +struct dpp_pfs * dpp_pfs_init(const u8 *net_access_key, + size_t net_access_key_len) +{ + struct wpabuf *pub = NULL; + EVP_PKEY *own_key; + struct dpp_pfs *pfs; + + pfs = os_zalloc(sizeof(*pfs)); + if (!pfs) + return NULL; + + own_key = dpp_set_keypair(&pfs->curve, net_access_key, + net_access_key_len); + if (!own_key) { + wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); + goto fail; + } + EVP_PKEY_free(own_key); + + pfs->ecdh = crypto_ecdh_init(pfs->curve->ike_group); + if (!pfs->ecdh) + goto fail; + + pub = crypto_ecdh_get_pubkey(pfs->ecdh, 0); + pub = wpabuf_zeropad(pub, pfs->curve->prime_len); + if (!pub) + goto fail; + + pfs->ie = wpabuf_alloc(5 + wpabuf_len(pub)); + if (!pfs->ie) + goto fail; + wpabuf_put_u8(pfs->ie, WLAN_EID_EXTENSION); + wpabuf_put_u8(pfs->ie, 1 + 2 + wpabuf_len(pub)); + wpabuf_put_u8(pfs->ie, WLAN_EID_EXT_OWE_DH_PARAM); + wpabuf_put_le16(pfs->ie, pfs->curve->ike_group); + wpabuf_put_buf(pfs->ie, pub); + wpabuf_free(pub); + wpa_hexdump_buf(MSG_DEBUG, "DPP: Diffie-Hellman Parameter element", + pfs->ie); + + return pfs; +fail: + wpabuf_free(pub); + dpp_pfs_free(pfs); + return NULL; +} + + +int dpp_pfs_process(struct dpp_pfs *pfs, const u8 *peer_ie, size_t peer_ie_len) +{ + if (peer_ie_len < 2) + return -1; + if (WPA_GET_LE16(peer_ie) != pfs->curve->ike_group) { + wpa_printf(MSG_DEBUG, "DPP: Peer used different group for PFS"); + return -1; + } + + pfs->secret = crypto_ecdh_set_peerkey(pfs->ecdh, 0, peer_ie + 2, + peer_ie_len - 2); + pfs->secret = wpabuf_zeropad(pfs->secret, pfs->curve->prime_len); + if (!pfs->secret) { + wpa_printf(MSG_DEBUG, "DPP: Invalid peer DH public key"); + return -1; + } + wpa_hexdump_buf_key(MSG_DEBUG, "DPP: DH shared secret", pfs->secret); + return 0; +} + + +void dpp_pfs_free(struct dpp_pfs *pfs) +{ + if (!pfs) + return; + crypto_ecdh_deinit(pfs->ecdh); + wpabuf_free(pfs->ie); + wpabuf_clear_free(pfs->secret); + os_free(pfs); +} + + +struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name) +{ + X509_REQ *req = NULL; + struct wpabuf *buf = NULL; + unsigned char *der; + int der_len; + EVP_PKEY *key; + const EVP_MD *sign_md; + unsigned int hash_len = auth->curve->hash_len; + EC_KEY *eckey; + BIO *out = NULL; + u8 cp[DPP_CP_LEN]; + char *password; + size_t password_len; + int res; + + /* TODO: use auth->csrattrs */ + + /* TODO: support generation of a new private key if csrAttrs requests + * a specific group to be used */ + key = auth->own_protocol_key; + + eckey = EVP_PKEY_get1_EC_KEY(key); + if (!eckey) + goto fail; + der = NULL; + der_len = i2d_ECPrivateKey(eckey, &der); + if (der_len <= 0) + goto fail; + wpabuf_free(auth->priv_key); + auth->priv_key = wpabuf_alloc_copy(der, der_len); + OPENSSL_free(der); + if (!auth->priv_key) + goto fail; + + req = X509_REQ_new(); + if (!req || !X509_REQ_set_pubkey(req, key)) + goto fail; + + if (name) { + X509_NAME *n; + + n = X509_REQ_get_subject_name(req); + if (!n) + goto fail; + + if (X509_NAME_add_entry_by_txt( + n, "CN", MBSTRING_UTF8, + (const unsigned char *) name, -1, -1, 0) != 1) + goto fail; + } + + /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ + if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, + "CSR challengePassword", cp, DPP_CP_LEN) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)", + cp, DPP_CP_LEN); + password = base64_encode_no_lf(cp, DPP_CP_LEN, &password_len); + forced_memzero(cp, DPP_CP_LEN); + if (!password) + goto fail; + + res = X509_REQ_add1_attr_by_NID(req, NID_pkcs9_challengePassword, + V_ASN1_UTF8STRING, + (const unsigned char *) password, + password_len); + bin_clear_free(password, password_len); + if (!res) + goto fail; + + /* TODO */ + + /* TODO: hash func selection based on csrAttrs */ + if (hash_len == SHA256_MAC_LEN) { + sign_md = EVP_sha256(); + } else if (hash_len == SHA384_MAC_LEN) { + sign_md = EVP_sha384(); + } else if (hash_len == SHA512_MAC_LEN) { + sign_md = EVP_sha512(); + } else { + wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); + goto fail; + } + + if (!X509_REQ_sign(req, key, sign_md)) + goto fail; + + der = NULL; + der_len = i2d_X509_REQ(req, &der); + if (der_len < 0) + goto fail; + buf = wpabuf_alloc_copy(der, der_len); + OPENSSL_free(der); + + wpa_hexdump_buf(MSG_DEBUG, "DPP: CSR", buf); + +fail: + BIO_free_all(out); + X509_REQ_free(req); + return buf; +} + + +struct wpabuf * dpp_pkcs7_certs(const struct wpabuf *pkcs7) +{ +#ifdef OPENSSL_IS_BORINGSSL + CBS pkcs7_cbs; +#else /* OPENSSL_IS_BORINGSSL */ + PKCS7 *p7 = NULL; + const unsigned char *p = wpabuf_head(pkcs7); +#endif /* OPENSSL_IS_BORINGSSL */ + STACK_OF(X509) *certs; + int i, num; + BIO *out = NULL; + size_t rlen; + struct wpabuf *pem = NULL; + int res; + +#ifdef OPENSSL_IS_BORINGSSL + certs = sk_X509_new_null(); + if (!certs) + goto fail; + CBS_init(&pkcs7_cbs, wpabuf_head(pkcs7), wpabuf_len(pkcs7)); + if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) { + wpa_printf(MSG_INFO, "DPP: Could not parse PKCS#7 object: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } +#else /* OPENSSL_IS_BORINGSSL */ + p7 = d2i_PKCS7(NULL, &p, wpabuf_len(pkcs7)); + if (!p7) { + wpa_printf(MSG_INFO, "DPP: Could not parse PKCS#7 object: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + switch (OBJ_obj2nid(p7->type)) { + case NID_pkcs7_signed: + certs = p7->d.sign->cert; + break; + case NID_pkcs7_signedAndEnveloped: + certs = p7->d.signed_and_enveloped->cert; + break; + default: + certs = NULL; + break; + } +#endif /* OPENSSL_IS_BORINGSSL */ + + if (!certs || ((num = sk_X509_num(certs)) == 0)) { + wpa_printf(MSG_INFO, + "DPP: No certificates found in PKCS#7 object"); + goto fail; + } + + out = BIO_new(BIO_s_mem()); + if (!out) + goto fail; + + for (i = 0; i < num; i++) { + X509 *cert = sk_X509_value(certs, i); + + PEM_write_bio_X509(out, cert); + } + + rlen = BIO_ctrl_pending(out); + pem = wpabuf_alloc(rlen); + if (!pem) + goto fail; + res = BIO_read(out, wpabuf_put(pem, 0), rlen); + if (res <= 0) { + wpabuf_free(pem); + pem = NULL; + goto fail; + } + wpabuf_put(pem, res); + +fail: +#ifdef OPENSSL_IS_BORINGSSL + if (certs) + sk_X509_pop_free(certs, X509_free); +#else /* OPENSSL_IS_BORINGSSL */ + PKCS7_free(p7); +#endif /* OPENSSL_IS_BORINGSSL */ + if (out) + BIO_free_all(out); + + return pem; +} + + +int dpp_validate_csr(struct dpp_authentication *auth, const struct wpabuf *csr) +{ + X509_REQ *req; + const unsigned char *pos; + EVP_PKEY *pkey; + int res, loc, ret = -1; + X509_ATTRIBUTE *attr; + ASN1_TYPE *type; + ASN1_STRING *str; + unsigned char *utf8 = NULL; + unsigned char *cp = NULL; + size_t cp_len; + u8 exp_cp[DPP_CP_LEN]; + unsigned int hash_len = auth->curve->hash_len; + + pos = wpabuf_head(csr); + req = d2i_X509_REQ(NULL, &pos, wpabuf_len(csr)); + if (!req) { + wpa_printf(MSG_DEBUG, "DPP: Failed to parse CSR"); + return -1; + } + + pkey = X509_REQ_get_pubkey(req); + if (!pkey) { + wpa_printf(MSG_DEBUG, "DPP: Failed to get public key from CSR"); + goto fail; + } + + res = X509_REQ_verify(req, pkey); + EVP_PKEY_free(pkey); + if (res != 1) { + wpa_printf(MSG_DEBUG, + "DPP: CSR does not have a valid signature"); + goto fail; + } + + loc = X509_REQ_get_attr_by_NID(req, NID_pkcs9_challengePassword, -1); + if (loc < 0) { + wpa_printf(MSG_DEBUG, + "DPP: CSR does not include challengePassword"); + goto fail; + } + + attr = X509_REQ_get_attr(req, loc); + if (!attr) { + wpa_printf(MSG_DEBUG, + "DPP: Could not get challengePassword attribute"); + goto fail; + } + + type = X509_ATTRIBUTE_get0_type(attr, 0); + if (!type) { + wpa_printf(MSG_DEBUG, + "DPP: Could not get challengePassword attribute type"); + goto fail; + } + + res = ASN1_TYPE_get(type); + /* This is supposed to be UTF8String, but allow other strings as well + * since challengePassword is using ASCII (base64 encoded). */ + if (res != V_ASN1_UTF8STRING && res != V_ASN1_PRINTABLESTRING && + res != V_ASN1_IA5STRING) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected challengePassword attribute type %d", + res); + goto fail; + } + + str = X509_ATTRIBUTE_get0_data(attr, 0, res, NULL); + if (!str) { + wpa_printf(MSG_DEBUG, + "DPP: Could not get ASN.1 string for challengePassword"); + goto fail; + } + + res = ASN1_STRING_to_UTF8(&utf8, str); + if (res < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Could not get UTF8 version of challengePassword"); + goto fail; + } + + cp = base64_decode((const char *) utf8, res, &cp_len); + OPENSSL_free(utf8); + if (!cp) { + wpa_printf(MSG_DEBUG, + "DPP: Could not base64 decode challengePassword"); + goto fail; + } + if (cp_len != DPP_CP_LEN) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected cp length (%zu) in CSR challengePassword", + cp_len); + goto fail; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: cp from CSR challengePassword", + cp, cp_len); + + /* cp = HKDF-Expand(bk, "CSR challengePassword", 64) */ + if (dpp_hkdf_expand(hash_len, auth->bk, hash_len, + "CSR challengePassword", exp_cp, DPP_CP_LEN) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, + "DPP: cp = HKDF-Expand(bk, \"CSR challengePassword\", 64)", + exp_cp, DPP_CP_LEN); + if (os_memcmp_const(cp, exp_cp, DPP_CP_LEN) != 0) { + wpa_printf(MSG_DEBUG, + "DPP: CSR challengePassword does not match calculated cp"); + goto fail; + } + + ret = 0; +fail: + os_free(cp); + X509_REQ_free(req); + return ret; +} + + +struct dpp_reconfig_id * dpp_gen_reconfig_id(const u8 *csign_key, + size_t csign_key_len, + const u8 *pp_key, + size_t pp_key_len) +{ + const unsigned char *p; + EVP_PKEY *csign = NULL, *ppkey = NULL; + struct dpp_reconfig_id *id = NULL; + BN_CTX *ctx = NULL; + BIGNUM *bn = NULL, *q = NULL; + const EC_KEY *eckey; + const EC_GROUP *group; + EC_POINT *e_id = NULL; + + p = csign_key; + csign = d2i_PUBKEY(NULL, &p, csign_key_len); + if (!csign) + goto fail; + + if (!pp_key) + goto fail; + p = pp_key; + ppkey = d2i_PUBKEY(NULL, &p, pp_key_len); + if (!ppkey) + goto fail; + + eckey = EVP_PKEY_get0_EC_KEY(csign); + if (!eckey) + goto fail; + group = EC_KEY_get0_group(eckey); + if (!group) + goto fail; + + e_id = EC_POINT_new(group); + ctx = BN_CTX_new(); + bn = BN_new(); + q = BN_new(); + if (!e_id || !ctx || !bn || !q || + !EC_GROUP_get_order(group, q, ctx) || + !BN_rand_range(bn, q) || + !EC_POINT_mul(group, e_id, bn, NULL, NULL, ctx)) + goto fail; + + dpp_debug_print_point("DPP: Generated random point E-id", group, e_id); + + id = os_zalloc(sizeof(*id)); + if (!id) + goto fail; + id->group = group; + id->e_id = e_id; + e_id = NULL; + id->csign = csign; + csign = NULL; + id->pp_key = ppkey; + ppkey = NULL; +fail: + EC_POINT_free(e_id); + EVP_PKEY_free(csign); + EVP_PKEY_free(ppkey); + BN_clear_free(bn); + BN_CTX_free(ctx); + return id; +} + + +static EVP_PKEY * dpp_pkey_from_point(const EC_GROUP *group, + const EC_POINT *point) +{ + EC_KEY *eckey; + EVP_PKEY *pkey = NULL; + + eckey = EC_KEY_new(); + if (!eckey || + EC_KEY_set_group(eckey, group) != 1 || + EC_KEY_set_public_key(eckey, point) != 1) { + wpa_printf(MSG_ERROR, + "DPP: Failed to set EC_KEY: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); + + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) { + wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY"); + EVP_PKEY_free(pkey); + pkey = NULL; + goto fail; + } + +fail: + EC_KEY_free(eckey); + return pkey; +} + + +int dpp_update_reconfig_id(struct dpp_reconfig_id *id) +{ + BN_CTX *ctx = NULL; + BIGNUM *bn = NULL, *q = NULL; + EC_POINT *e_prime_id = NULL, *a_nonce = NULL; + int ret = -1; + const EC_KEY *pp; + const EC_POINT *pp_point; + + pp = EVP_PKEY_get0_EC_KEY(id->pp_key); + if (!pp) + goto fail; + pp_point = EC_KEY_get0_public_key(pp); + e_prime_id = EC_POINT_new(id->group); + a_nonce = EC_POINT_new(id->group); + ctx = BN_CTX_new(); + bn = BN_new(); + q = BN_new(); + /* Generate random 0 <= a-nonce < q + * A-NONCE = a-nonce * G + * E'-id = E-id + a-nonce * P_pk */ + if (!pp_point || !e_prime_id || !a_nonce || !ctx || !bn || !q || + !EC_GROUP_get_order(id->group, q, ctx) || + !BN_rand_range(bn, q) || /* bn = a-nonce */ + !EC_POINT_mul(id->group, a_nonce, bn, NULL, NULL, ctx) || + !EC_POINT_mul(id->group, e_prime_id, NULL, pp_point, bn, ctx) || + !EC_POINT_add(id->group, e_prime_id, id->e_id, e_prime_id, ctx)) + goto fail; + + dpp_debug_print_point("DPP: Generated A-NONCE", id->group, a_nonce); + dpp_debug_print_point("DPP: Encrypted E-id to E'-id", + id->group, e_prime_id); + + EVP_PKEY_free(id->a_nonce); + EVP_PKEY_free(id->e_prime_id); + id->a_nonce = dpp_pkey_from_point(id->group, a_nonce); + id->e_prime_id = dpp_pkey_from_point(id->group, e_prime_id); + if (!id->a_nonce || !id->e_prime_id) + goto fail; + + ret = 0; + +fail: + EC_POINT_free(e_prime_id); + EC_POINT_free(a_nonce); + BN_clear_free(bn); + BN_CTX_free(ctx); + return ret; +} + + +void dpp_free_reconfig_id(struct dpp_reconfig_id *id) +{ + if (id) { + EC_POINT_clear_free(id->e_id); + EVP_PKEY_free(id->csign); + EVP_PKEY_free(id->a_nonce); + EVP_PKEY_free(id->e_prime_id); + EVP_PKEY_free(id->pp_key); + os_free(id); + } +} + + +EC_POINT * dpp_decrypt_e_id(EVP_PKEY *ppkey, EVP_PKEY *a_nonce, + EVP_PKEY *e_prime_id) +{ + const EC_KEY *pp_ec, *a_nonce_ec, *e_prime_id_ec; + const BIGNUM *pp_bn; + const EC_GROUP *group; + EC_POINT *e_id = NULL; + const EC_POINT *a_nonce_point, *e_prime_id_point; + BN_CTX *ctx = NULL; + + if (!ppkey) + return NULL; + + /* E-id = E'-id - s_C * A-NONCE */ + pp_ec = EVP_PKEY_get0_EC_KEY(ppkey); + a_nonce_ec = EVP_PKEY_get0_EC_KEY(a_nonce); + e_prime_id_ec = EVP_PKEY_get0_EC_KEY(e_prime_id); + if (!pp_ec || !a_nonce_ec || !e_prime_id_ec) + return NULL; + pp_bn = EC_KEY_get0_private_key(pp_ec); + group = EC_KEY_get0_group(pp_ec); + a_nonce_point = EC_KEY_get0_public_key(a_nonce_ec); + e_prime_id_point = EC_KEY_get0_public_key(e_prime_id_ec); + ctx = BN_CTX_new(); + if (!pp_bn || !group || !a_nonce_point || !e_prime_id_point || !ctx) + goto fail; + e_id = EC_POINT_new(group); + if (!e_id || + !EC_POINT_mul(group, e_id, NULL, a_nonce_point, pp_bn, ctx) || + !EC_POINT_invert(group, e_id, ctx) || + !EC_POINT_add(group, e_id, e_prime_id_point, e_id, ctx)) { + EC_POINT_clear_free(e_id); + goto fail; + } + + dpp_debug_print_point("DPP: Decrypted E-id", group, e_id); + +fail: + BN_CTX_free(ctx); + return e_id; +} + +#endif /* CONFIG_DPP2 */ + + +#ifdef CONFIG_TESTING_OPTIONS + +int dpp_test_gen_invalid_key(struct wpabuf *msg, + const struct dpp_curve_params *curve) +{ + BN_CTX *ctx; + BIGNUM *x, *y; + int ret = -1; + EC_GROUP *group; + EC_POINT *point; + + group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); + if (!group) + return -1; + + ctx = BN_CTX_new(); + point = EC_POINT_new(group); + x = BN_new(); + y = BN_new(); + if (!ctx || !point || !x || !y) + goto fail; + + if (BN_rand(x, curve->prime_len * 8, 0, 0) != 1) + goto fail; + + /* Generate a random y coordinate that results in a point that is not + * on the curve. */ + for (;;) { + if (BN_rand(y, curve->prime_len * 8, 0, 0) != 1) + goto fail; + + if (EC_POINT_set_affine_coordinates_GFp(group, point, x, y, + ctx) != 1) { +#if OPENSSL_VERSION_NUMBER >= 0x10100000L || defined(OPENSSL_IS_BORINGSSL) + /* Unlike older OpenSSL versions, OpenSSL 1.1.1 and BoringSSL + * return an error from EC_POINT_set_affine_coordinates_GFp() + * when the point is not on the curve. */ + break; +#else /* >=1.1.0 or OPENSSL_IS_BORINGSSL */ + goto fail; +#endif /* >= 1.1.0 or OPENSSL_IS_BORINGSSL */ + } + + if (!EC_POINT_is_on_curve(group, point, ctx)) + break; + } + + if (dpp_bn2bin_pad(x, wpabuf_put(msg, curve->prime_len), + curve->prime_len) < 0 || + dpp_bn2bin_pad(y, wpabuf_put(msg, curve->prime_len), + curve->prime_len) < 0) + goto fail; + + ret = 0; +fail: + if (ret < 0) + wpa_printf(MSG_INFO, "DPP: Failed to generate invalid key"); + BN_free(x); + BN_free(y); + EC_POINT_free(point); + BN_CTX_free(ctx); + EC_GROUP_free(group); + + return ret; +} + + +char * dpp_corrupt_connector_signature(const char *connector) +{ + char *tmp, *pos, *signed3 = NULL; + unsigned char *signature = NULL; + size_t signature_len = 0, signed3_len; + + tmp = os_zalloc(os_strlen(connector) + 5); + if (!tmp) + goto fail; + os_memcpy(tmp, connector, os_strlen(connector)); + + pos = os_strchr(tmp, '.'); + if (!pos) + goto fail; + + pos = os_strchr(pos + 1, '.'); + if (!pos) + goto fail; + pos++; + + wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s", + pos); + signature = base64_url_decode(pos, os_strlen(pos), &signature_len); + if (!signature || signature_len == 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature", + signature, signature_len); + signature[signature_len - 1] ^= 0x01; + wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature", + signature, signature_len); + signed3 = base64_url_encode(signature, signature_len, &signed3_len); + if (!signed3) + goto fail; + os_memcpy(pos, signed3, signed3_len); + pos[signed3_len] = '\0'; + wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s", + pos); + +out: + os_free(signature); + os_free(signed3); + return tmp; +fail: + os_free(tmp); + tmp = NULL; + goto out; +} + +#endif /* CONFIG_TESTING_OPTIONS */ diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h new file mode 100644 index 000000000..af12467a5 --- /dev/null +++ b/src/common/dpp_i.h @@ -0,0 +1,160 @@ +/* + * DPP module internal definitions + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018-2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DPP_I_H +#define DPP_I_H + +#ifdef CONFIG_DPP + +struct dpp_global { + void *msg_ctx; + struct dl_list bootstrap; /* struct dpp_bootstrap_info */ + struct dl_list configurator; /* struct dpp_configurator */ +#ifdef CONFIG_DPP2 + struct dl_list controllers; /* struct dpp_relay_controller */ + struct dpp_controller *controller; + struct dl_list tcp_init; /* struct dpp_connection */ + void *cb_ctx; + int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); + void (*remove_bi)(void *ctx, struct dpp_bootstrap_info *bi); +#endif /* CONFIG_DPP2 */ +}; + +/* dpp.c */ + +void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status); +void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, const u8 *hash); +unsigned int dpp_next_id(struct dpp_global *dpp); +struct wpabuf * dpp_build_conn_status(enum dpp_status_error result, + const u8 *ssid, size_t ssid_len, + const char *channel_list); +struct json_token * dpp_parse_own_connector(const char *own_connector); +int dpp_connector_match_groups(struct json_token *own_root, + struct json_token *peer_root, bool reconfig); +int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key, + const char *kid, const struct dpp_curve_params *curve); +EVP_PKEY * dpp_parse_jwk(struct json_token *jwk, + const struct dpp_curve_params **key_curve); +int dpp_prepare_channel_list(struct dpp_authentication *auth, + unsigned int neg_freq, + struct hostapd_hw_modes *own_modes, u16 num_modes); +void dpp_auth_fail(struct dpp_authentication *auth, const char *txt); +int dpp_gen_uri(struct dpp_bootstrap_info *bi); +void dpp_write_adv_proto(struct wpabuf *buf); +void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query); + +/* dpp_backup.c */ + +void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key); +struct wpabuf * dpp_build_enveloped_data(struct dpp_authentication *auth); +int dpp_conf_resp_env_data(struct dpp_authentication *auth, + const u8 *env_data, size_t env_data_len); + +/* dpp_crypto.c */ + +struct dpp_signed_connector_info { + unsigned char *payload; + size_t payload_len; +}; + +enum dpp_status_error +dpp_process_signed_connector(struct dpp_signed_connector_info *info, + EVP_PKEY *csign_pub, const char *connector); +enum dpp_status_error +dpp_check_signed_connector(struct dpp_signed_connector_info *info, + const u8 *csign_key, size_t csign_key_len, + const u8 *peer_connector, size_t peer_connector_len); +const struct dpp_curve_params * dpp_get_curve_name(const char *name); +const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name); +const struct dpp_curve_params * dpp_get_curve_nid(int nid); +const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group); +int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, + const u8 *data, size_t data_len); +struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix); +EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group, + const u8 *buf_x, const u8 *buf_y, + size_t len); +EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, const u8 *buf, size_t len); +int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len); +int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, + const char *label, u8 *out, size_t outlen); +int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac); +int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, u8 *secret, size_t *secret_len); +void dpp_debug_print_point(const char *title, const EC_GROUP *group, + const EC_POINT *point); +void dpp_debug_print_key(const char *title, EVP_PKEY *key); +int dpp_pbkdf2(size_t hash_len, const u8 *password, size_t password_len, + const u8 *salt, size_t salt_len, unsigned int iterations, + u8 *buf, size_t buflen); +int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, + const u8 *data, size_t data_len); +int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi); +int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, + const u8 *privkey, size_t privkey_len); +EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve, + const u8 *privkey, size_t privkey_len); +EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve); +int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len); +int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len); +int dpp_derive_bk_ke(struct dpp_authentication *auth); +int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth); +int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth); +int dpp_auth_derive_l_responder(struct dpp_authentication *auth); +int dpp_auth_derive_l_initiator(struct dpp_authentication *auth); +int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len); +int dpp_derive_pmkid(const struct dpp_curve_params *curve, + EVP_PKEY *own_key, EVP_PKEY *peer_key, u8 *pmkid); +EC_POINT * dpp_pkex_derive_Qi(const struct dpp_curve_params *curve, + const u8 *mac_init, const char *code, + const char *identifier, BN_CTX *bnctx, + EC_GROUP **ret_group); +EC_POINT * dpp_pkex_derive_Qr(const struct dpp_curve_params *curve, + const u8 *mac_resp, const char *code, + const char *identifier, BN_CTX *bnctx, + EC_GROUP **ret_group); +int dpp_pkex_derive_z(const u8 *mac_init, const u8 *mac_resp, + const u8 *Mx, size_t Mx_len, + const u8 *Nx, size_t Nx_len, + const char *code, + const u8 *Kx, size_t Kx_len, + u8 *z, unsigned int hash_len); +int dpp_reconfig_derive_ke_responder(struct dpp_authentication *auth, + const u8 *net_access_key, + size_t net_access_key_len, + struct json_token *peer_net_access_key); +int dpp_reconfig_derive_ke_initiator(struct dpp_authentication *auth, + const u8 *r_proto, u16 r_proto_len, + struct json_token *net_access_key); +EC_POINT * dpp_decrypt_e_id(EVP_PKEY *ppkey, EVP_PKEY *a_nonce, + EVP_PKEY *e_prime_id); +char * dpp_sign_connector(struct dpp_configurator *conf, + const struct wpabuf *dppcon); +int dpp_test_gen_invalid_key(struct wpabuf *msg, + const struct dpp_curve_params *curve); + +struct dpp_reconfig_id { + const EC_GROUP *group; + EC_POINT *e_id; /* E-id */ + EVP_PKEY *csign; + EVP_PKEY *a_nonce; /* A-NONCE */ + EVP_PKEY *e_prime_id; /* E'-id */ + EVP_PKEY *pp_key; +}; + +/* dpp_tcp.c */ + +void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx, + void *timeout_ctx); +void dpp_tcp_init_flush(struct dpp_global *dpp); +void dpp_relay_flush_controllers(struct dpp_global *dpp); + +#endif /* CONFIG_DPP */ +#endif /* DPP_I_H */ diff --git a/src/common/dpp_pkex.c b/src/common/dpp_pkex.c new file mode 100644 index 000000000..807ab7d0a --- /dev/null +++ b/src/common/dpp_pkex.c @@ -0,0 +1,1324 @@ +/* + * DPP PKEX functionality + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018-2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include +#include + +#include "utils/common.h" +#include "common/wpa_ctrl.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" +#include "crypto/crypto.h" +#include "dpp.h" +#include "dpp_i.h" + + +#ifdef CONFIG_TESTING_OPTIONS +u8 dpp_pkex_own_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; +u8 dpp_pkex_peer_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; +u8 dpp_pkex_ephemeral_key_override[600]; +size_t dpp_pkex_ephemeral_key_override_len = 0; +#endif /* CONFIG_TESTING_OPTIONS */ + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) +/* Compatibility wrappers for older versions. */ + +static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_EC) + return NULL; + return pkey->pkey.ec; +} + +#endif + + +static struct wpabuf * dpp_pkex_build_exchange_req(struct dpp_pkex *pkex) +{ + const EC_KEY *X_ec; + const EC_POINT *X_point; + BN_CTX *bnctx = NULL; + EC_GROUP *group = NULL; + EC_POINT *Qi = NULL, *M = NULL; + struct wpabuf *M_buf = NULL; + BIGNUM *Mx = NULL, *My = NULL; + struct wpabuf *msg = NULL; + size_t attr_len; + const struct dpp_curve_params *curve = pkex->own_bi->curve; + + wpa_printf(MSG_DEBUG, "DPP: Build PKEX Exchange Request"); + + /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ + bnctx = BN_CTX_new(); + if (!bnctx) + goto fail; + Qi = dpp_pkex_derive_Qi(curve, pkex->own_mac, pkex->code, + pkex->identifier, bnctx, &group); + if (!Qi) + goto fail; + + /* Generate a random ephemeral keypair x/X */ +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_pkex_ephemeral_key_override_len) { + const struct dpp_curve_params *tmp_curve; + + wpa_printf(MSG_INFO, + "DPP: TESTING - override ephemeral key x/X"); + pkex->x = dpp_set_keypair(&tmp_curve, + dpp_pkex_ephemeral_key_override, + dpp_pkex_ephemeral_key_override_len); + } else { + pkex->x = dpp_gen_keypair(curve); + } +#else /* CONFIG_TESTING_OPTIONS */ + pkex->x = dpp_gen_keypair(curve); +#endif /* CONFIG_TESTING_OPTIONS */ + if (!pkex->x) + goto fail; + + /* M = X + Qi */ + X_ec = EVP_PKEY_get0_EC_KEY(pkex->x); + if (!X_ec) + goto fail; + X_point = EC_KEY_get0_public_key(X_ec); + if (!X_point) + goto fail; + dpp_debug_print_point("DPP: X", group, X_point); + M = EC_POINT_new(group); + Mx = BN_new(); + My = BN_new(); + if (!M || !Mx || !My || + EC_POINT_add(group, M, X_point, Qi, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1) + goto fail; + dpp_debug_print_point("DPP: M", group, M); + + /* Initiator -> Responder: group, [identifier,] M */ + attr_len = 4 + 2; + if (pkex->identifier) + attr_len += 4 + os_strlen(pkex->identifier); + attr_len += 4 + 2 * curve->prime_len; + msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_REQ, attr_len); + if (!msg) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_FINITE_CYCLIC_GROUP_PKEX_EXCHANGE_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Finite Cyclic Group"); + goto skip_finite_cyclic_group; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Finite Cyclic Group attribute */ + wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP); + wpabuf_put_le16(msg, 2); + wpabuf_put_le16(msg, curve->ike_group); + +#ifdef CONFIG_TESTING_OPTIONS +skip_finite_cyclic_group: +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Code Identifier attribute */ + if (pkex->identifier) { + wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER); + wpabuf_put_le16(msg, os_strlen(pkex->identifier)); + wpabuf_put_str(msg, pkex->identifier); + } + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key"); + goto out; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* M in Encrypted Key attribute */ + wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY); + wpabuf_put_le16(msg, 2 * curve->prime_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key"); + if (dpp_test_gen_invalid_key(msg, curve) < 0) + goto fail; + goto out; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (dpp_bn2bin_pad(Mx, wpabuf_put(msg, curve->prime_len), + curve->prime_len) < 0 || + dpp_bn2bin_pad(Mx, pkex->Mx, curve->prime_len) < 0 || + dpp_bn2bin_pad(My, wpabuf_put(msg, curve->prime_len), + curve->prime_len) < 0) + goto fail; + +out: + wpabuf_free(M_buf); + EC_POINT_free(M); + EC_POINT_free(Qi); + BN_clear_free(Mx); + BN_clear_free(My); + BN_CTX_free(bnctx); + EC_GROUP_free(group); + return msg; +fail: + wpa_printf(MSG_INFO, "DPP: Failed to build PKEX Exchange Request"); + wpabuf_free(msg); + msg = NULL; + goto out; +} + + +static void dpp_pkex_fail(struct dpp_pkex *pkex, const char *txt) +{ + wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt); +} + + +struct dpp_pkex * dpp_pkex_init(void *msg_ctx, struct dpp_bootstrap_info *bi, + const u8 *own_mac, + const char *identifier, + const char *code) +{ + struct dpp_pkex *pkex; + +#ifdef CONFIG_TESTING_OPTIONS + if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) { + wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR, + MAC2STR(dpp_pkex_own_mac_override)); + own_mac = dpp_pkex_own_mac_override; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + pkex = os_zalloc(sizeof(*pkex)); + if (!pkex) + return NULL; + pkex->msg_ctx = msg_ctx; + pkex->initiator = 1; + pkex->own_bi = bi; + os_memcpy(pkex->own_mac, own_mac, ETH_ALEN); + if (identifier) { + pkex->identifier = os_strdup(identifier); + if (!pkex->identifier) + goto fail; + } + pkex->code = os_strdup(code); + if (!pkex->code) + goto fail; + pkex->exchange_req = dpp_pkex_build_exchange_req(pkex); + if (!pkex->exchange_req) + goto fail; + return pkex; +fail: + dpp_pkex_free(pkex); + return NULL; +} + + +static struct wpabuf * +dpp_pkex_build_exchange_resp(struct dpp_pkex *pkex, + enum dpp_status_error status, + const BIGNUM *Nx, const BIGNUM *Ny) +{ + struct wpabuf *msg = NULL; + size_t attr_len; + const struct dpp_curve_params *curve = pkex->own_bi->curve; + + /* Initiator -> Responder: DPP Status, [identifier,] N */ + attr_len = 4 + 1; + if (pkex->identifier) + attr_len += 4 + os_strlen(pkex->identifier); + attr_len += 4 + 2 * curve->prime_len; + msg = dpp_alloc_msg(DPP_PA_PKEX_EXCHANGE_RESP, attr_len); + if (!msg) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_STATUS_PKEX_EXCHANGE_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); + goto skip_status; + } + + if (dpp_test == DPP_TEST_INVALID_STATUS_PKEX_EXCHANGE_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); + status = 255; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* DPP Status */ + dpp_build_attr_status(msg, status); + +#ifdef CONFIG_TESTING_OPTIONS +skip_status: +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Code Identifier attribute */ + if (pkex->identifier) { + wpabuf_put_le16(msg, DPP_ATTR_CODE_IDENTIFIER); + wpabuf_put_le16(msg, os_strlen(pkex->identifier)); + wpabuf_put_str(msg, pkex->identifier); + } + + if (status != DPP_STATUS_OK) + goto skip_encrypted_key; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Encrypted Key"); + goto skip_encrypted_key; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* N in Encrypted Key attribute */ + wpabuf_put_le16(msg, DPP_ATTR_ENCRYPTED_KEY); + wpabuf_put_le16(msg, 2 * curve->prime_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_INVALID_ENCRYPTED_KEY_PKEX_EXCHANGE_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Encrypted Key"); + if (dpp_test_gen_invalid_key(msg, curve) < 0) + goto fail; + goto skip_encrypted_key; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (dpp_bn2bin_pad(Nx, wpabuf_put(msg, curve->prime_len), + curve->prime_len) < 0 || + dpp_bn2bin_pad(Nx, pkex->Nx, curve->prime_len) < 0 || + dpp_bn2bin_pad(Ny, wpabuf_put(msg, curve->prime_len), + curve->prime_len) < 0) + goto fail; + +skip_encrypted_key: + if (status == DPP_STATUS_BAD_GROUP) { + /* Finite Cyclic Group attribute */ + wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP); + wpabuf_put_le16(msg, 2); + wpabuf_put_le16(msg, curve->ike_group); + } + + return msg; +fail: + wpabuf_free(msg); + return NULL; +} + + +static int dpp_pkex_identifier_match(const u8 *attr_id, u16 attr_id_len, + const char *identifier) +{ + if (!attr_id && identifier) { + wpa_printf(MSG_DEBUG, + "DPP: No PKEX code identifier received, but expected one"); + return 0; + } + + if (attr_id && !identifier) { + wpa_printf(MSG_DEBUG, + "DPP: PKEX code identifier received, but not expecting one"); + return 0; + } + + if (attr_id && identifier && + (os_strlen(identifier) != attr_id_len || + os_memcmp(identifier, attr_id, attr_id_len) != 0)) { + wpa_printf(MSG_DEBUG, "DPP: PKEX code identifier mismatch"); + return 0; + } + + return 1; +} + + +struct dpp_pkex * dpp_pkex_rx_exchange_req(void *msg_ctx, + struct dpp_bootstrap_info *bi, + const u8 *own_mac, + const u8 *peer_mac, + const char *identifier, + const char *code, + const u8 *buf, size_t len) +{ + const u8 *attr_group, *attr_id, *attr_key; + u16 attr_group_len, attr_id_len, attr_key_len; + const struct dpp_curve_params *curve = bi->curve; + u16 ike_group; + struct dpp_pkex *pkex = NULL; + EC_POINT *Qi = NULL, *Qr = NULL, *M = NULL, *X = NULL, *N = NULL; + BN_CTX *bnctx = NULL; + EC_GROUP *group = NULL; + BIGNUM *Mx = NULL, *My = NULL; + const EC_KEY *Y_ec; + EC_KEY *X_ec = NULL; + const EC_POINT *Y_point; + BIGNUM *Nx = NULL, *Ny = NULL; + u8 Kx[DPP_MAX_SHARED_SECRET_LEN]; + size_t Kx_len; + int res; + + if (bi->pkex_t >= PKEX_COUNTER_T_LIMIT) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "PKEX counter t limit reached - ignore message"); + return NULL; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) { + wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR, + MAC2STR(dpp_pkex_peer_mac_override)); + peer_mac = dpp_pkex_peer_mac_override; + } + if (!is_zero_ether_addr(dpp_pkex_own_mac_override)) { + wpa_printf(MSG_INFO, "DPP: TESTING - own_mac override " MACSTR, + MAC2STR(dpp_pkex_own_mac_override)); + own_mac = dpp_pkex_own_mac_override; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + attr_id_len = 0; + attr_id = dpp_get_attr(buf, len, DPP_ATTR_CODE_IDENTIFIER, + &attr_id_len); + if (!dpp_pkex_identifier_match(attr_id, attr_id_len, identifier)) + return NULL; + + attr_group = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, + &attr_group_len); + if (!attr_group || attr_group_len != 2) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid Finite Cyclic Group attribute"); + return NULL; + } + ike_group = WPA_GET_LE16(attr_group); + if (ike_group != curve->ike_group) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Mismatching PKEX curve: peer=%u own=%u", + ike_group, curve->ike_group); + pkex = os_zalloc(sizeof(*pkex)); + if (!pkex) + goto fail; + pkex->own_bi = bi; + pkex->failed = 1; + pkex->exchange_resp = dpp_pkex_build_exchange_resp( + pkex, DPP_STATUS_BAD_GROUP, NULL, NULL); + if (!pkex->exchange_resp) + goto fail; + return pkex; + } + + /* M in Encrypted Key attribute */ + attr_key = dpp_get_attr(buf, len, DPP_ATTR_ENCRYPTED_KEY, + &attr_key_len); + if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2 || + attr_key_len / 2 > DPP_MAX_SHARED_SECRET_LEN) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing Encrypted Key attribute"); + return NULL; + } + + /* Qi = H(MAC-Initiator | [identifier |] code) * Pi */ + bnctx = BN_CTX_new(); + if (!bnctx) + goto fail; + Qi = dpp_pkex_derive_Qi(curve, peer_mac, code, identifier, bnctx, + &group); + if (!Qi) + goto fail; + + /* X' = M - Qi */ + X = EC_POINT_new(group); + M = EC_POINT_new(group); + Mx = BN_bin2bn(attr_key, attr_key_len / 2, NULL); + My = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL); + if (!X || !M || !Mx || !My || + EC_POINT_set_affine_coordinates_GFp(group, M, Mx, My, bnctx) != 1 || + EC_POINT_is_at_infinity(group, M) || + !EC_POINT_is_on_curve(group, M, bnctx) || + EC_POINT_invert(group, Qi, bnctx) != 1 || + EC_POINT_add(group, X, M, Qi, bnctx) != 1 || + EC_POINT_is_at_infinity(group, X) || + !EC_POINT_is_on_curve(group, X, bnctx)) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Invalid Encrypted Key value"); + bi->pkex_t++; + goto fail; + } + dpp_debug_print_point("DPP: M", group, M); + dpp_debug_print_point("DPP: X'", group, X); + + pkex = os_zalloc(sizeof(*pkex)); + if (!pkex) + goto fail; + pkex->t = bi->pkex_t; + pkex->msg_ctx = msg_ctx; + pkex->own_bi = bi; + os_memcpy(pkex->own_mac, own_mac, ETH_ALEN); + os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); + if (identifier) { + pkex->identifier = os_strdup(identifier); + if (!pkex->identifier) + goto fail; + } + pkex->code = os_strdup(code); + if (!pkex->code) + goto fail; + + os_memcpy(pkex->Mx, attr_key, attr_key_len / 2); + + X_ec = EC_KEY_new(); + if (!X_ec || + EC_KEY_set_group(X_ec, group) != 1 || + EC_KEY_set_public_key(X_ec, X) != 1) + goto fail; + pkex->x = EVP_PKEY_new(); + if (!pkex->x || + EVP_PKEY_set1_EC_KEY(pkex->x, X_ec) != 1) + goto fail; + + /* Qr = H(MAC-Responder | | [identifier | ] code) * Pr */ + Qr = dpp_pkex_derive_Qr(curve, own_mac, code, identifier, bnctx, NULL); + if (!Qr) + goto fail; + + /* Generate a random ephemeral keypair y/Y */ +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_pkex_ephemeral_key_override_len) { + const struct dpp_curve_params *tmp_curve; + + wpa_printf(MSG_INFO, + "DPP: TESTING - override ephemeral key y/Y"); + pkex->y = dpp_set_keypair(&tmp_curve, + dpp_pkex_ephemeral_key_override, + dpp_pkex_ephemeral_key_override_len); + } else { + pkex->y = dpp_gen_keypair(curve); + } +#else /* CONFIG_TESTING_OPTIONS */ + pkex->y = dpp_gen_keypair(curve); +#endif /* CONFIG_TESTING_OPTIONS */ + if (!pkex->y) + goto fail; + + /* N = Y + Qr */ + Y_ec = EVP_PKEY_get0_EC_KEY(pkex->y); + if (!Y_ec) + goto fail; + Y_point = EC_KEY_get0_public_key(Y_ec); + if (!Y_point) + goto fail; + dpp_debug_print_point("DPP: Y", group, Y_point); + N = EC_POINT_new(group); + Nx = BN_new(); + Ny = BN_new(); + if (!N || !Nx || !Ny || + EC_POINT_add(group, N, Y_point, Qr, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1) + goto fail; + dpp_debug_print_point("DPP: N", group, N); + + pkex->exchange_resp = dpp_pkex_build_exchange_resp(pkex, DPP_STATUS_OK, + Nx, Ny); + if (!pkex->exchange_resp) + goto fail; + + /* K = y * X' */ + if (dpp_ecdh(pkex->y, pkex->x, Kx, &Kx_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)", + Kx, Kx_len); + + /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) + */ + res = dpp_pkex_derive_z(pkex->peer_mac, pkex->own_mac, + pkex->Mx, curve->prime_len, + pkex->Nx, curve->prime_len, pkex->code, + Kx, Kx_len, pkex->z, curve->hash_len); + os_memset(Kx, 0, Kx_len); + if (res < 0) + goto fail; + + pkex->exchange_done = 1; + +out: + BN_CTX_free(bnctx); + EC_POINT_free(Qi); + EC_POINT_free(Qr); + BN_free(Mx); + BN_free(My); + BN_free(Nx); + BN_free(Ny); + EC_POINT_free(M); + EC_POINT_free(N); + EC_POINT_free(X); + EC_KEY_free(X_ec); + EC_GROUP_free(group); + return pkex; +fail: + wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request processing failed"); + dpp_pkex_free(pkex); + pkex = NULL; + goto out; +} + + +static struct wpabuf * +dpp_pkex_build_commit_reveal_req(struct dpp_pkex *pkex, + const struct wpabuf *A_pub, const u8 *u) +{ + const struct dpp_curve_params *curve = pkex->own_bi->curve; + struct wpabuf *msg = NULL; + size_t clear_len, attr_len; + struct wpabuf *clear = NULL; + u8 *wrapped; + u8 octet; + const u8 *addr[2]; + size_t len[2]; + + /* {A, u, [bootstrapping info]}z */ + clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len; + clear = wpabuf_alloc(clear_len); + attr_len = 4 + clear_len + AES_BLOCK_SIZE; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_REQ, attr_len); + if (!clear || !msg) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key"); + goto skip_bootstrap_key; + } + if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key"); + wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); + wpabuf_put_le16(clear, 2 * curve->prime_len); + if (dpp_test_gen_invalid_key(clear, curve) < 0) + goto fail; + goto skip_bootstrap_key; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* A in Bootstrap Key attribute */ + wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); + wpabuf_put_le16(clear, wpabuf_len(A_pub)); + wpabuf_put_buf(clear, A_pub); + +#ifdef CONFIG_TESTING_OPTIONS +skip_bootstrap_key: + if (dpp_test == DPP_TEST_NO_I_AUTH_TAG_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Auth tag"); + goto skip_i_auth_tag; + } + if (dpp_test == DPP_TEST_I_AUTH_TAG_MISMATCH_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - I-Auth tag mismatch"); + wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG); + wpabuf_put_le16(clear, curve->hash_len); + wpabuf_put_data(clear, u, curve->hash_len - 1); + wpabuf_put_u8(clear, u[curve->hash_len - 1] ^ 0x01); + goto skip_i_auth_tag; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* u in I-Auth tag attribute */ + wpabuf_put_le16(clear, DPP_ATTR_I_AUTH_TAG); + wpabuf_put_le16(clear, curve->hash_len); + wpabuf_put_data(clear, u, curve->hash_len); + +#ifdef CONFIG_TESTING_OPTIONS +skip_i_auth_tag: + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); + goto skip_wrapped_data; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = DPP_HDR_LEN; + octet = 0; + addr[1] = &octet; + len[1] = sizeof(octet); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + + wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); + if (aes_siv_encrypt(pkex->z, curve->hash_len, + wpabuf_head(clear), wpabuf_len(clear), + 2, addr, len, wrapped) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + +out: + wpabuf_free(clear); + return msg; + +fail: + wpabuf_free(msg); + msg = NULL; + goto out; +} + + +struct wpabuf * dpp_pkex_rx_exchange_resp(struct dpp_pkex *pkex, + const u8 *peer_mac, + const u8 *buf, size_t buflen) +{ + const u8 *attr_status, *attr_id, *attr_key, *attr_group; + u16 attr_status_len, attr_id_len, attr_key_len, attr_group_len; + EC_GROUP *group = NULL; + BN_CTX *bnctx = NULL; + struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL; + const struct dpp_curve_params *curve = pkex->own_bi->curve; + EC_POINT *Qr = NULL, *Y = NULL, *N = NULL; + BIGNUM *Nx = NULL, *Ny = NULL; + EC_KEY *Y_ec = NULL; + size_t Jx_len, Kx_len; + u8 Jx[DPP_MAX_SHARED_SECRET_LEN], Kx[DPP_MAX_SHARED_SECRET_LEN]; + const u8 *addr[4]; + size_t len[4]; + u8 u[DPP_MAX_HASH_LEN]; + int res; + + if (pkex->failed || pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator) + return NULL; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_PKEX_EXCHANGE_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at PKEX Exchange Response"); + pkex->failed = 1; + return NULL; + } + + if (!is_zero_ether_addr(dpp_pkex_peer_mac_override)) { + wpa_printf(MSG_INFO, "DPP: TESTING - peer_mac override " MACSTR, + MAC2STR(dpp_pkex_peer_mac_override)); + peer_mac = dpp_pkex_peer_mac_override; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + os_memcpy(pkex->peer_mac, peer_mac, ETH_ALEN); + + attr_status = dpp_get_attr(buf, buflen, DPP_ATTR_STATUS, + &attr_status_len); + if (!attr_status || attr_status_len != 1) { + dpp_pkex_fail(pkex, "No DPP Status attribute"); + return NULL; + } + wpa_printf(MSG_DEBUG, "DPP: Status %u", attr_status[0]); + + if (attr_status[0] == DPP_STATUS_BAD_GROUP) { + attr_group = dpp_get_attr(buf, buflen, + DPP_ATTR_FINITE_CYCLIC_GROUP, + &attr_group_len); + if (attr_group && attr_group_len == 2) { + wpa_msg(pkex->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Peer indicated mismatching PKEX group - proposed %u", + WPA_GET_LE16(attr_group)); + return NULL; + } + } + + if (attr_status[0] != DPP_STATUS_OK) { + dpp_pkex_fail(pkex, "PKEX failed (peer indicated failure)"); + return NULL; + } + + attr_id_len = 0; + attr_id = dpp_get_attr(buf, buflen, DPP_ATTR_CODE_IDENTIFIER, + &attr_id_len); + if (!dpp_pkex_identifier_match(attr_id, attr_id_len, + pkex->identifier)) { + dpp_pkex_fail(pkex, "PKEX code identifier mismatch"); + return NULL; + } + + /* N in Encrypted Key attribute */ + attr_key = dpp_get_attr(buf, buflen, DPP_ATTR_ENCRYPTED_KEY, + &attr_key_len); + if (!attr_key || attr_key_len & 0x01 || attr_key_len < 2) { + dpp_pkex_fail(pkex, "Missing Encrypted Key attribute"); + return NULL; + } + + /* Qr = H(MAC-Responder | [identifier |] code) * Pr */ + bnctx = BN_CTX_new(); + if (!bnctx) + goto fail; + Qr = dpp_pkex_derive_Qr(curve, pkex->peer_mac, pkex->code, + pkex->identifier, bnctx, &group); + if (!Qr) + goto fail; + + /* Y' = N - Qr */ + Y = EC_POINT_new(group); + N = EC_POINT_new(group); + Nx = BN_bin2bn(attr_key, attr_key_len / 2, NULL); + Ny = BN_bin2bn(attr_key + attr_key_len / 2, attr_key_len / 2, NULL); + if (!Y || !N || !Nx || !Ny || + EC_POINT_set_affine_coordinates_GFp(group, N, Nx, Ny, bnctx) != 1 || + EC_POINT_is_at_infinity(group, N) || + !EC_POINT_is_on_curve(group, N, bnctx) || + EC_POINT_invert(group, Qr, bnctx) != 1 || + EC_POINT_add(group, Y, N, Qr, bnctx) != 1 || + EC_POINT_is_at_infinity(group, Y) || + !EC_POINT_is_on_curve(group, Y, bnctx)) { + dpp_pkex_fail(pkex, "Invalid Encrypted Key value"); + pkex->t++; + goto fail; + } + dpp_debug_print_point("DPP: N", group, N); + dpp_debug_print_point("DPP: Y'", group, Y); + + pkex->exchange_done = 1; + + /* ECDH: J = a * Y' */ + Y_ec = EC_KEY_new(); + if (!Y_ec || + EC_KEY_set_group(Y_ec, group) != 1 || + EC_KEY_set_public_key(Y_ec, Y) != 1) + goto fail; + pkex->y = EVP_PKEY_new(); + if (!pkex->y || + EVP_PKEY_set1_EC_KEY(pkex->y, Y_ec) != 1) + goto fail; + if (dpp_ecdh(pkex->own_bi->pubkey, pkex->y, Jx, &Jx_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)", + Jx, Jx_len); + + /* u = HMAC(J.x, MAC-Initiator | A.x | Y'.x | X.x) */ + A_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0); + Y_pub = dpp_get_pubkey_point(pkex->y, 0); + X_pub = dpp_get_pubkey_point(pkex->x, 0); + if (!A_pub || !Y_pub || !X_pub) + goto fail; + addr[0] = pkex->own_mac; + len[0] = ETH_ALEN; + addr[1] = wpabuf_head(A_pub); + len[1] = wpabuf_len(A_pub) / 2; + addr[2] = wpabuf_head(Y_pub); + len[2] = wpabuf_len(Y_pub) / 2; + addr[3] = wpabuf_head(X_pub); + len[3] = wpabuf_len(X_pub) / 2; + if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: u", u, curve->hash_len); + + /* K = x * Y' */ + if (dpp_ecdh(pkex->x, pkex->y, Kx, &Kx_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (K.x)", + Kx, Kx_len); + + /* z = HKDF(<>, MAC-Initiator | MAC-Responder | M.x | N.x | code, K.x) + */ + res = dpp_pkex_derive_z(pkex->own_mac, pkex->peer_mac, + pkex->Mx, curve->prime_len, + attr_key /* N.x */, attr_key_len / 2, + pkex->code, Kx, Kx_len, + pkex->z, curve->hash_len); + os_memset(Kx, 0, Kx_len); + if (res < 0) + goto fail; + + msg = dpp_pkex_build_commit_reveal_req(pkex, A_pub, u); + if (!msg) + goto fail; + +out: + wpabuf_free(A_pub); + wpabuf_free(X_pub); + wpabuf_free(Y_pub); + EC_POINT_free(Qr); + EC_POINT_free(Y); + EC_POINT_free(N); + BN_free(Nx); + BN_free(Ny); + EC_KEY_free(Y_ec); + BN_CTX_free(bnctx); + EC_GROUP_free(group); + return msg; +fail: + wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response processing failed"); + goto out; +} + + +static struct wpabuf * +dpp_pkex_build_commit_reveal_resp(struct dpp_pkex *pkex, + const struct wpabuf *B_pub, const u8 *v) +{ + const struct dpp_curve_params *curve = pkex->own_bi->curve; + struct wpabuf *msg = NULL; + const u8 *addr[2]; + size_t len[2]; + u8 octet; + u8 *wrapped; + struct wpabuf *clear = NULL; + size_t clear_len, attr_len; + + /* {B, v [bootstrapping info]}z */ + clear_len = 4 + 2 * curve->prime_len + 4 + curve->hash_len; + clear = wpabuf_alloc(clear_len); + attr_len = 4 + clear_len + AES_BLOCK_SIZE; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_PKEX_COMMIT_REVEAL_RESP, attr_len); + if (!clear || !msg) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_BOOTSTRAP_KEY_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Bootstrap Key"); + goto skip_bootstrap_key; + } + if (dpp_test == DPP_TEST_INVALID_BOOTSTRAP_KEY_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Bootstrap Key"); + wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); + wpabuf_put_le16(clear, 2 * curve->prime_len); + if (dpp_test_gen_invalid_key(clear, curve) < 0) + goto fail; + goto skip_bootstrap_key; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* B in Bootstrap Key attribute */ + wpabuf_put_le16(clear, DPP_ATTR_BOOTSTRAP_KEY); + wpabuf_put_le16(clear, wpabuf_len(B_pub)); + wpabuf_put_buf(clear, B_pub); + +#ifdef CONFIG_TESTING_OPTIONS +skip_bootstrap_key: + if (dpp_test == DPP_TEST_NO_R_AUTH_TAG_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth tag"); + goto skip_r_auth_tag; + } + if (dpp_test == DPP_TEST_R_AUTH_TAG_MISMATCH_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - R-Auth tag mismatch"); + wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG); + wpabuf_put_le16(clear, curve->hash_len); + wpabuf_put_data(clear, v, curve->hash_len - 1); + wpabuf_put_u8(clear, v[curve->hash_len - 1] ^ 0x01); + goto skip_r_auth_tag; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* v in R-Auth tag attribute */ + wpabuf_put_le16(clear, DPP_ATTR_R_AUTH_TAG); + wpabuf_put_le16(clear, curve->hash_len); + wpabuf_put_data(clear, v, curve->hash_len); + +#ifdef CONFIG_TESTING_OPTIONS +skip_r_auth_tag: + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); + goto skip_wrapped_data; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = DPP_HDR_LEN; + octet = 1; + addr[1] = &octet; + len[1] = sizeof(octet); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + + wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); + if (aes_siv_encrypt(pkex->z, curve->hash_len, + wpabuf_head(clear), wpabuf_len(clear), + 2, addr, len, wrapped) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + +out: + wpabuf_free(clear); + return msg; + +fail: + wpabuf_free(msg); + msg = NULL; + goto out; +} + + +struct wpabuf * dpp_pkex_rx_commit_reveal_req(struct dpp_pkex *pkex, + const u8 *hdr, + const u8 *buf, size_t buflen) +{ + const struct dpp_curve_params *curve = pkex->own_bi->curve; + size_t Jx_len, Lx_len; + u8 Jx[DPP_MAX_SHARED_SECRET_LEN]; + u8 Lx[DPP_MAX_SHARED_SECRET_LEN]; + const u8 *wrapped_data, *b_key, *peer_u; + u16 wrapped_data_len, b_key_len, peer_u_len = 0; + const u8 *addr[4]; + size_t len[4]; + u8 octet; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + struct wpabuf *msg = NULL, *A_pub = NULL, *X_pub = NULL, *Y_pub = NULL; + struct wpabuf *B_pub = NULL; + u8 u[DPP_MAX_HASH_LEN], v[DPP_MAX_HASH_LEN]; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_REQ) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at PKEX CR Request"); + pkex->failed = 1; + return NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!pkex->exchange_done || pkex->failed || + pkex->t >= PKEX_COUNTER_T_LIMIT || pkex->initiator) + goto fail; + + wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_pkex_fail(pkex, + "Missing or invalid required Wrapped Data attribute"); + goto fail; + } + + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + octet = 0; + addr[1] = &octet; + len[1] = sizeof(octet); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + if (aes_siv_decrypt(pkex->z, curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_pkex_fail(pkex, + "AES-SIV decryption failed - possible PKEX code mismatch"); + pkex->failed = 1; + pkex->t++; + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data"); + goto fail; + } + + b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY, + &b_key_len); + if (!b_key || b_key_len != 2 * curve->prime_len) { + dpp_pkex_fail(pkex, "No valid peer bootstrapping key found"); + goto fail; + } + pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key, + b_key_len); + if (!pkex->peer_bootstrap_key) { + dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid"); + goto fail; + } + dpp_debug_print_key("DPP: Peer bootstrap public key", + pkex->peer_bootstrap_key); + + /* ECDH: J' = y * A' */ + if (dpp_ecdh(pkex->y, pkex->peer_bootstrap_key, Jx, &Jx_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (J.x)", + Jx, Jx_len); + + /* u' = HMAC(J'.x, MAC-Initiator | A'.x | Y.x | X'.x) */ + A_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0); + Y_pub = dpp_get_pubkey_point(pkex->y, 0); + X_pub = dpp_get_pubkey_point(pkex->x, 0); + if (!A_pub || !Y_pub || !X_pub) + goto fail; + addr[0] = pkex->peer_mac; + len[0] = ETH_ALEN; + addr[1] = wpabuf_head(A_pub); + len[1] = wpabuf_len(A_pub) / 2; + addr[2] = wpabuf_head(Y_pub); + len[2] = wpabuf_len(Y_pub) / 2; + addr[3] = wpabuf_head(X_pub); + len[3] = wpabuf_len(X_pub) / 2; + if (dpp_hmac_vector(curve->hash_len, Jx, Jx_len, 4, addr, len, u) < 0) + goto fail; + + peer_u = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG, + &peer_u_len); + if (!peer_u || peer_u_len != curve->hash_len || + os_memcmp(peer_u, u, curve->hash_len) != 0) { + dpp_pkex_fail(pkex, "No valid u (I-Auth tag) found"); + wpa_hexdump(MSG_DEBUG, "DPP: Calculated u'", + u, curve->hash_len); + wpa_hexdump(MSG_DEBUG, "DPP: Received u", peer_u, peer_u_len); + pkex->t++; + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: Valid u (I-Auth tag) received"); + + /* ECDH: L = b * X' */ + if (dpp_ecdh(pkex->own_bi->pubkey, pkex->x, Lx, &Lx_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)", + Lx, Lx_len); + + /* v = HMAC(L.x, MAC-Responder | B.x | X'.x | Y.x) */ + B_pub = dpp_get_pubkey_point(pkex->own_bi->pubkey, 0); + if (!B_pub) + goto fail; + addr[0] = pkex->own_mac; + len[0] = ETH_ALEN; + addr[1] = wpabuf_head(B_pub); + len[1] = wpabuf_len(B_pub) / 2; + addr[2] = wpabuf_head(X_pub); + len[2] = wpabuf_len(X_pub) / 2; + addr[3] = wpabuf_head(Y_pub); + len[3] = wpabuf_len(Y_pub) / 2; + if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: v", v, curve->hash_len); + + msg = dpp_pkex_build_commit_reveal_resp(pkex, B_pub, v); + if (!msg) + goto fail; + +out: + os_free(unwrapped); + wpabuf_free(A_pub); + wpabuf_free(B_pub); + wpabuf_free(X_pub); + wpabuf_free(Y_pub); + return msg; +fail: + wpa_printf(MSG_DEBUG, + "DPP: PKEX Commit-Reveal Request processing failed"); + goto out; +} + + +int dpp_pkex_rx_commit_reveal_resp(struct dpp_pkex *pkex, const u8 *hdr, + const u8 *buf, size_t buflen) +{ + const struct dpp_curve_params *curve = pkex->own_bi->curve; + const u8 *wrapped_data, *b_key, *peer_v; + u16 wrapped_data_len, b_key_len, peer_v_len = 0; + const u8 *addr[4]; + size_t len[4]; + u8 octet; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + int ret = -1; + u8 v[DPP_MAX_HASH_LEN]; + size_t Lx_len; + u8 Lx[DPP_MAX_SHARED_SECRET_LEN]; + struct wpabuf *B_pub = NULL, *X_pub = NULL, *Y_pub = NULL; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_PKEX_CR_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at PKEX CR Response"); + pkex->failed = 1; + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!pkex->exchange_done || pkex->failed || + pkex->t >= PKEX_COUNTER_T_LIMIT || !pkex->initiator) + goto fail; + + wrapped_data = dpp_get_attr(buf, buflen, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_pkex_fail(pkex, + "Missing or invalid required Wrapped Data attribute"); + goto fail; + } + + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + octet = 1; + addr[1] = &octet; + len[1] = sizeof(octet); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + if (aes_siv_decrypt(pkex->z, curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_pkex_fail(pkex, + "AES-SIV decryption failed - possible PKEX code mismatch"); + pkex->t++; + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_pkex_fail(pkex, "Invalid attribute in unwrapped data"); + goto fail; + } + + b_key = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_BOOTSTRAP_KEY, + &b_key_len); + if (!b_key || b_key_len != 2 * curve->prime_len) { + dpp_pkex_fail(pkex, "No valid peer bootstrapping key found"); + goto fail; + } + pkex->peer_bootstrap_key = dpp_set_pubkey_point(pkex->x, b_key, + b_key_len); + if (!pkex->peer_bootstrap_key) { + dpp_pkex_fail(pkex, "Peer bootstrapping key is invalid"); + goto fail; + } + dpp_debug_print_key("DPP: Peer bootstrap public key", + pkex->peer_bootstrap_key); + + /* ECDH: L' = x * B' */ + if (dpp_ecdh(pkex->x, pkex->peer_bootstrap_key, Lx, &Lx_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (L.x)", + Lx, Lx_len); + + /* v' = HMAC(L.x, MAC-Responder | B'.x | X.x | Y'.x) */ + B_pub = dpp_get_pubkey_point(pkex->peer_bootstrap_key, 0); + X_pub = dpp_get_pubkey_point(pkex->x, 0); + Y_pub = dpp_get_pubkey_point(pkex->y, 0); + if (!B_pub || !X_pub || !Y_pub) + goto fail; + addr[0] = pkex->peer_mac; + len[0] = ETH_ALEN; + addr[1] = wpabuf_head(B_pub); + len[1] = wpabuf_len(B_pub) / 2; + addr[2] = wpabuf_head(X_pub); + len[2] = wpabuf_len(X_pub) / 2; + addr[3] = wpabuf_head(Y_pub); + len[3] = wpabuf_len(Y_pub) / 2; + if (dpp_hmac_vector(curve->hash_len, Lx, Lx_len, 4, addr, len, v) < 0) + goto fail; + + peer_v = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_AUTH_TAG, + &peer_v_len); + if (!peer_v || peer_v_len != curve->hash_len || + os_memcmp(peer_v, v, curve->hash_len) != 0) { + dpp_pkex_fail(pkex, "No valid v (R-Auth tag) found"); + wpa_hexdump(MSG_DEBUG, "DPP: Calculated v'", + v, curve->hash_len); + wpa_hexdump(MSG_DEBUG, "DPP: Received v", peer_v, peer_v_len); + pkex->t++; + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: Valid v (R-Auth tag) received"); + + ret = 0; +out: + wpabuf_free(B_pub); + wpabuf_free(X_pub); + wpabuf_free(Y_pub); + os_free(unwrapped); + return ret; +fail: + goto out; +} + + +struct dpp_bootstrap_info * +dpp_pkex_finish(struct dpp_global *dpp, struct dpp_pkex *pkex, const u8 *peer, + unsigned int freq) +{ + struct dpp_bootstrap_info *bi; + + bi = os_zalloc(sizeof(*bi)); + if (!bi) + return NULL; + bi->id = dpp_next_id(dpp); + bi->type = DPP_BOOTSTRAP_PKEX; + os_memcpy(bi->mac_addr, peer, ETH_ALEN); + bi->num_freq = 1; + bi->freq[0] = freq; + bi->curve = pkex->own_bi->curve; + bi->pubkey = pkex->peer_bootstrap_key; + pkex->peer_bootstrap_key = NULL; + if (dpp_bootstrap_key_hash(bi) < 0) { + dpp_bootstrap_info_free(bi); + return NULL; + } + dpp_pkex_free(pkex); + dl_list_add(&dpp->bootstrap, &bi->list); + return bi; +} + + +void dpp_pkex_free(struct dpp_pkex *pkex) +{ + if (!pkex) + return; + + os_free(pkex->identifier); + os_free(pkex->code); + EVP_PKEY_free(pkex->x); + EVP_PKEY_free(pkex->y); + EVP_PKEY_free(pkex->peer_bootstrap_key); + wpabuf_free(pkex->exchange_req); + wpabuf_free(pkex->exchange_resp); + os_free(pkex); +} diff --git a/src/common/dpp_reconfig.c b/src/common/dpp_reconfig.c new file mode 100644 index 000000000..c4a027363 --- /dev/null +++ b/src/common/dpp_reconfig.c @@ -0,0 +1,958 @@ +/* + * DPP reconfiguration + * Copyright (c) 2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include +#include + +#include "utils/common.h" +#include "utils/json.h" +#include "crypto/crypto.h" +#include "crypto/random.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" +#include "dpp.h" +#include "dpp_i.h" + + +#ifdef CONFIG_DPP2 + +static void dpp_build_attr_csign_key_hash(struct wpabuf *msg, const u8 *hash) +{ + if (hash) { + wpa_printf(MSG_DEBUG, "DPP: Configurator C-sign key Hash"); + wpabuf_put_le16(msg, DPP_ATTR_C_SIGN_KEY_HASH); + wpabuf_put_le16(msg, SHA256_MAC_LEN); + wpabuf_put_data(msg, hash, SHA256_MAC_LEN); + } +} + + +struct wpabuf * dpp_build_reconfig_announcement(const u8 *csign_key, + size_t csign_key_len, + const u8 *net_access_key, + size_t net_access_key_len, + struct dpp_reconfig_id *id) +{ + struct wpabuf *msg = NULL; + EVP_PKEY *csign = NULL; + const unsigned char *p; + struct wpabuf *uncomp; + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[1]; + size_t len[1]; + int res; + size_t attr_len; + const struct dpp_curve_params *own_curve; + EVP_PKEY *own_key; + struct wpabuf *a_nonce = NULL, *e_id = NULL; + + wpa_printf(MSG_DEBUG, "DPP: Build Reconfig Announcement frame"); + + own_key = dpp_set_keypair(&own_curve, net_access_key, + net_access_key_len); + if (!own_key) { + wpa_printf(MSG_ERROR, "DPP: Failed to parse own netAccessKey"); + goto fail; + } + + p = csign_key; + csign = d2i_PUBKEY(NULL, &p, csign_key_len); + if (!csign) { + wpa_printf(MSG_ERROR, + "DPP: Failed to parse local C-sign-key information"); + goto fail; + } + + uncomp = dpp_get_pubkey_point(csign, 1); + EVP_PKEY_free(csign); + if (!uncomp) + goto fail; + addr[0] = wpabuf_head(uncomp); + len[0] = wpabuf_len(uncomp); + wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed C-sign key", addr[0], len[0]); + res = sha256_vector(1, addr, len, hash); + wpabuf_free(uncomp); + if (res < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: kid = SHA256(uncompressed C-sign key)", + hash, SHA256_MAC_LEN); + + if (dpp_update_reconfig_id(id) < 0) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate E'-id"); + goto fail; + } + + a_nonce = dpp_get_pubkey_point(id->a_nonce, 0); + e_id = dpp_get_pubkey_point(id->e_prime_id, 0); + if (!a_nonce || !e_id) + goto fail; + + attr_len = 4 + SHA256_MAC_LEN; + attr_len += 4 + 2; + attr_len += 4 + wpabuf_len(a_nonce); + attr_len += 4 + wpabuf_len(e_id); + msg = dpp_alloc_msg(DPP_PA_RECONFIG_ANNOUNCEMENT, attr_len); + if (!msg) + goto fail; + + /* Configurator C-sign key Hash */ + dpp_build_attr_csign_key_hash(msg, hash); + + /* Finite Cyclic Group attribute */ + wpa_printf(MSG_DEBUG, "DPP: Finite Cyclic Group: %u", + own_curve->ike_group); + wpabuf_put_le16(msg, DPP_ATTR_FINITE_CYCLIC_GROUP); + wpabuf_put_le16(msg, 2); + wpabuf_put_le16(msg, own_curve->ike_group); + + /* A-NONCE */ + wpabuf_put_le16(msg, DPP_ATTR_A_NONCE); + wpabuf_put_le16(msg, wpabuf_len(a_nonce)); + wpabuf_put_buf(msg, a_nonce); + + /* E'-id */ + wpabuf_put_le16(msg, DPP_ATTR_E_PRIME_ID); + wpabuf_put_le16(msg, wpabuf_len(e_id)); + wpabuf_put_buf(msg, e_id); + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Reconfig Announcement frame attributes", msg); +fail: + wpabuf_free(a_nonce); + wpabuf_free(e_id); + EVP_PKEY_free(own_key); + return msg; +} + + +static struct wpabuf * dpp_reconfig_build_req(struct dpp_authentication *auth) +{ + struct wpabuf *msg; + size_t attr_len; + + /* Build DPP Reconfig Authentication Request frame attributes */ + attr_len = 4 + 1 + 4 + 1 + 4 + os_strlen(auth->conf->connector) + + 4 + auth->curve->nonce_len; + msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_REQ, attr_len); + if (!msg) + return NULL; + + /* Transaction ID */ + wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, auth->transaction_id); + + /* Protocol Version */ + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + + /* DPP Connector */ + wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); + wpabuf_put_le16(msg, os_strlen(auth->conf->connector)); + wpabuf_put_str(msg, auth->conf->connector); + + /* C-nonce */ + wpabuf_put_le16(msg, DPP_ATTR_CONFIGURATOR_NONCE); + wpabuf_put_le16(msg, auth->curve->nonce_len); + wpabuf_put_data(msg, auth->c_nonce, auth->curve->nonce_len); + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Reconfig Authentication Request frame attributes", + msg); + + return msg; +} + + +static int +dpp_configurator_build_own_connector(struct dpp_configurator *conf, + const struct dpp_curve_params *curve) +{ + struct wpabuf *dppcon = NULL; + int ret = -1; + + if (conf->connector) + return 0; /* already generated */ + + wpa_printf(MSG_DEBUG, + "DPP: Sign own Configurator Connector for reconfiguration with curve %s", + conf->curve->name); + conf->connector_key = dpp_gen_keypair(curve); + if (!conf->connector_key) + goto fail; + + /* Connector (JSON dppCon object) */ + dppcon = wpabuf_alloc(1000 + 2 * curve->prime_len * 4 / 3); + if (!dppcon) + goto fail; + json_start_object(dppcon, NULL); + json_start_array(dppcon, "groups"); + json_start_object(dppcon, NULL); + json_add_string(dppcon, "groupId", "*"); + json_value_sep(dppcon); + json_add_string(dppcon, "netRole", "configurator"); + json_end_object(dppcon); + json_end_array(dppcon); + json_value_sep(dppcon); + if (dpp_build_jwk(dppcon, "netAccessKey", conf->connector_key, NULL, + curve) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK"); + goto fail; + } + json_end_object(dppcon); + wpa_printf(MSG_DEBUG, "DPP: dppCon: %s", + (const char *) wpabuf_head(dppcon)); + + conf->connector = dpp_sign_connector(conf, dppcon); + if (!conf->connector) + goto fail; + wpa_printf(MSG_DEBUG, "DPP: signedConnector: %s", conf->connector); + + ret = 0; +fail: + wpabuf_free(dppcon); + return ret; +} + + +struct dpp_authentication * +dpp_reconfig_init(struct dpp_global *dpp, void *msg_ctx, + struct dpp_configurator *conf, unsigned int freq, u16 group, + const u8 *a_nonce_attr, size_t a_nonce_len, + const u8 *e_id_attr, size_t e_id_len) +{ + struct dpp_authentication *auth; + const struct dpp_curve_params *curve; + EVP_PKEY *a_nonce, *e_prime_id; + EC_POINT *e_id; + + curve = dpp_get_curve_ike_group(group); + if (!curve) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported group %u - cannot reconfigure", + group); + return NULL; + } + + if (!a_nonce_attr) { + wpa_printf(MSG_INFO, "DPP: Missing required A-NONCE attribute"); + return NULL; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: A-NONCE", a_nonce_attr, a_nonce_len); + a_nonce = dpp_set_pubkey_point(conf->csign, a_nonce_attr, a_nonce_len); + if (!a_nonce) { + wpa_printf(MSG_INFO, "DPP: Invalid A-NONCE"); + return NULL; + } + dpp_debug_print_key("A-NONCE", a_nonce); + + if (!e_id_attr) { + wpa_printf(MSG_INFO, "DPP: Missing required E'-id attribute"); + return NULL; + } + e_prime_id = dpp_set_pubkey_point(conf->csign, e_id_attr, e_id_len); + if (!e_prime_id) { + wpa_printf(MSG_INFO, "DPP: Invalid E'-id"); + EVP_PKEY_free(a_nonce); + return NULL; + } + dpp_debug_print_key("E'-id", e_prime_id); + e_id = dpp_decrypt_e_id(conf->pp_key, a_nonce, e_prime_id); + EVP_PKEY_free(a_nonce); + EVP_PKEY_free(e_prime_id); + if (!e_id) { + wpa_printf(MSG_INFO, "DPP: Could not decrypt E'-id"); + return NULL; + } + /* TODO: could use E-id to determine whether reconfiguration with this + * Enrollee has already been started and is waiting for updated + * configuration instead of replying again before such configuration + * becomes available */ + EC_POINT_clear_free(e_id); + + auth = dpp_alloc_auth(dpp, msg_ctx); + if (!auth) + return NULL; + + auth->conf = conf; + auth->reconfig = 1; + auth->initiator = 1; + auth->waiting_auth_resp = 1; + auth->allowed_roles = DPP_CAPAB_CONFIGURATOR; + auth->configurator = 1; + auth->curve = curve; + auth->transaction_id = 1; + if (freq && dpp_prepare_channel_list(auth, freq, NULL, 0) < 0) + goto fail; + + if (dpp_configurator_build_own_connector(conf, curve) < 0) + goto fail; + + if (random_get_bytes(auth->c_nonce, auth->curve->nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate C-nonce"); + goto fail; + } + + auth->reconfig_req_msg = dpp_reconfig_build_req(auth); + if (!auth->reconfig_req_msg) + goto fail; + +out: + return auth; +fail: + dpp_auth_deinit(auth); + auth = NULL; + goto out; +} + + +static int dpp_reconfig_build_resp(struct dpp_authentication *auth, + const char *own_connector, + struct wpabuf *conn_status) +{ + struct wpabuf *msg = NULL, *clear, *pr = NULL; + u8 *attr_start, *attr_end; + size_t clear_len, attr_len, len[2]; + const u8 *addr[2]; + u8 *wrapped; + int res = -1; + + /* Build DPP Reconfig Authentication Response frame attributes */ + clear_len = 4 + auth->curve->nonce_len + + 4 + wpabuf_len(conn_status); + clear = wpabuf_alloc(clear_len); + if (!clear) + goto fail; + + /* C-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_CONFIGURATOR_NONCE); + wpabuf_put_le16(clear, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->c_nonce, auth->curve->nonce_len); + + /* Connection Status (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_CONN_STATUS); + wpabuf_put_le16(clear, wpabuf_len(conn_status)); + wpabuf_put_buf(clear, conn_status); + + pr = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (!pr) + goto fail; + + attr_len = 4 + 1 + 4 + 1 + + 4 + os_strlen(own_connector) + + 4 + auth->curve->nonce_len + + 4 + wpabuf_len(pr) + + 4 + wpabuf_len(clear) + AES_BLOCK_SIZE; + msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_RESP, attr_len); + if (!msg) + goto fail; + + attr_start = wpabuf_put(msg, 0); + + /* Transaction ID */ + wpabuf_put_le16(msg, DPP_ATTR_TRANSACTION_ID); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, auth->transaction_id); + + /* Protocol Version */ + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + + /* R-Connector */ + wpabuf_put_le16(msg, DPP_ATTR_CONNECTOR); + wpabuf_put_le16(msg, os_strlen(own_connector)); + wpabuf_put_str(msg, own_connector); + + /* E-nonce */ + wpabuf_put_le16(msg, DPP_ATTR_ENROLLEE_NONCE); + wpabuf_put_le16(msg, auth->curve->nonce_len); + wpabuf_put_data(msg, auth->e_nonce, auth->curve->nonce_len); + + /* Responder Protocol Key (Pr) */ + wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY); + wpabuf_put_le16(msg, wpabuf_len(pr)); + wpabuf_put_buf(msg, pr); + + attr_end = wpabuf_put(msg, 0); + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + /* Wrapped Data: {C-nonce, E-nonce, Connection Status}ke */ + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + + wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); + if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, + wpabuf_head(clear), wpabuf_len(clear), + 2, addr, len, wrapped) < 0) + goto fail; + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Reconfig Authentication Response frame attributes", + msg); + + wpabuf_free(auth->reconfig_resp_msg); + auth->reconfig_resp_msg = msg; + + res = 0; +out: + wpabuf_free(clear); + wpabuf_free(pr); + return res; +fail: + wpabuf_free(msg); + goto out; +} + + +struct dpp_authentication * +dpp_reconfig_auth_req_rx(struct dpp_global *dpp, void *msg_ctx, + const char *own_connector, + const u8 *net_access_key, size_t net_access_key_len, + const u8 *csign_key, size_t csign_key_len, + unsigned int freq, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + struct dpp_authentication *auth = NULL; + const u8 *trans_id, *version, *i_connector, *c_nonce; + u16 trans_id_len, version_len, i_connector_len, c_nonce_len; + struct dpp_signed_connector_info info; + enum dpp_status_error res; + struct json_token *root = NULL, *own_root = NULL, *token; + unsigned char *own_conn = NULL; + struct wpabuf *conn_status = NULL; + + os_memset(&info, 0, sizeof(info)); + + trans_id = dpp_get_attr(attr_start, attr_len, DPP_ATTR_TRANSACTION_ID, + &trans_id_len); + if (!trans_id || trans_id_len != 1) { + wpa_printf(MSG_DEBUG, + "DPP: Peer did not include Transaction ID"); + goto fail; + } + + version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (!version || version_len < 1 || version[0] < 2) { + wpa_printf(MSG_DEBUG, + "DPP: Missing or invalid Protocol Version attribute"); + goto fail; + } + + i_connector = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CONNECTOR, + &i_connector_len); + if (!i_connector) { + wpa_printf(MSG_DEBUG, "DPP: Missing I-Connector attribute"); + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, "DPP: I-Connector", + i_connector, i_connector_len); + + c_nonce = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len); + if (!c_nonce || c_nonce_len > DPP_MAX_NONCE_LEN) { + wpa_printf(MSG_DEBUG, + "DPP: Missing or invalid C-nonce attribute"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len); + + res = dpp_check_signed_connector(&info, csign_key, csign_key_len, + i_connector, i_connector_len); + if (res != DPP_STATUS_OK) { + wpa_printf(MSG_DEBUG, "DPP: Invalid I-Connector"); + goto fail; + } + + root = json_parse((const char *) info.payload, info.payload_len); + own_root = dpp_parse_own_connector(own_connector); + if (!root || !own_root || + !dpp_connector_match_groups(own_root, root, true)) { + wpa_printf(MSG_DEBUG, + "DPP: I-Connector does not include compatible group netrole with own connector"); + goto fail; + } + + token = json_get_member(root, "expiry"); + if (token && token->type == JSON_STRING && + dpp_key_expired(token->string, NULL)) { + wpa_printf(MSG_DEBUG, + "DPP: I-Connector (netAccessKey) has expired"); + goto fail; + } + + token = json_get_member(root, "netAccessKey"); + if (!token || token->type != JSON_OBJECT) { + wpa_printf(MSG_DEBUG, "DPP: No netAccessKey object found"); + goto fail; + } + + auth = dpp_alloc_auth(dpp, msg_ctx); + if (!auth) + return NULL; + + auth->reconfig = 1; + auth->allowed_roles = DPP_CAPAB_ENROLLEE; + if (dpp_prepare_channel_list(auth, freq, NULL, 0) < 0) + goto fail; + + auth->transaction_id = trans_id[0]; + + auth->peer_version = version[0]; + wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", + auth->peer_version); + + os_memcpy(auth->c_nonce, c_nonce, c_nonce_len); + + if (dpp_reconfig_derive_ke_responder(auth, net_access_key, + net_access_key_len, token) < 0) + goto fail; + + if (c_nonce_len != auth->curve->nonce_len) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected C-nonce length %u (curve nonce len %zu)", + c_nonce_len, auth->curve->nonce_len); + goto fail; + } + + /* Build Connection Status object */ + /* TODO: Get appropriate result value */ + /* TODO: ssid64 and channelList */ + conn_status = dpp_build_conn_status(DPP_STATUS_NO_AP, NULL, 0, NULL); + if (!conn_status) + goto fail; + + if (dpp_reconfig_build_resp(auth, own_connector, conn_status) < 0) + goto fail; + +out: + os_free(info.payload); + os_free(own_conn); + json_free(root); + json_free(own_root); + wpabuf_free(conn_status); + return auth; +fail: + dpp_auth_deinit(auth); + auth = NULL; + goto out; +} + + +struct wpabuf * +dpp_reconfig_build_conf(struct dpp_authentication *auth) +{ + struct wpabuf *msg = NULL, *clear; + u8 *attr_start, *attr_end; + size_t clear_len, attr_len, len[2]; + const u8 *addr[2]; + u8 *wrapped; + u8 flags; + + /* Build DPP Reconfig Authentication Confirm frame attributes */ + clear_len = 4 + 1 + 4 + 1 + 2 * (4 + auth->curve->nonce_len) + + 4 + 1; + clear = wpabuf_alloc(clear_len); + if (!clear) + goto fail; + + /* Transaction ID */ + wpabuf_put_le16(clear, DPP_ATTR_TRANSACTION_ID); + wpabuf_put_le16(clear, 1); + wpabuf_put_u8(clear, auth->transaction_id); + + /* Protocol Version */ + wpabuf_put_le16(clear, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(clear, 1); + wpabuf_put_u8(clear, auth->peer_version); + + /* C-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_CONFIGURATOR_NONCE); + wpabuf_put_le16(clear, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->c_nonce, auth->curve->nonce_len); + + /* E-nonce (wrapped) */ + wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); + wpabuf_put_le16(clear, auth->curve->nonce_len); + wpabuf_put_data(clear, auth->e_nonce, auth->curve->nonce_len); + + /* Reconfig-Flags (wrapped) */ + flags = DPP_CONFIG_REPLACEKEY; + wpabuf_put_le16(clear, DPP_ATTR_RECONFIG_FLAGS); + wpabuf_put_le16(clear, 1); + wpabuf_put_u8(clear, flags); + + attr_len = 4 + wpabuf_len(clear) + AES_BLOCK_SIZE; + attr_len += 4 + 1; + msg = dpp_alloc_msg(DPP_PA_RECONFIG_AUTH_CONF, attr_len); + if (!msg) + goto fail; + + attr_start = wpabuf_put(msg, 0); + + /* DPP Status */ + dpp_build_attr_status(msg, DPP_STATUS_OK); + + attr_end = wpabuf_put(msg, 0); + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + /* Wrapped Data */ + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + + wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); + if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, + wpabuf_head(clear), wpabuf_len(clear), + 2, addr, len, wrapped) < 0) + goto fail; + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Reconfig Authentication Confirm frame attributes", + msg); + +out: + wpabuf_free(clear); + return msg; +fail: + wpabuf_free(msg); + msg = NULL; + goto out; +} + + +struct wpabuf * +dpp_reconfig_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + const u8 *trans_id, *version, *r_connector, *r_proto, *wrapped_data, + *c_nonce, *e_nonce, *conn_status; + u16 trans_id_len, version_len, r_connector_len, r_proto_len, + wrapped_data_len, c_nonce_len, e_nonce_len, conn_status_len; + struct wpabuf *conf = NULL; + char *signed_connector = NULL; + struct dpp_signed_connector_info info; + enum dpp_status_error res; + struct json_token *root = NULL, *token, *conn_status_json = NULL; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + + os_memset(&info, 0, sizeof(info)); + + if (!auth->reconfig || !auth->configurator) + goto fail; + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid required Wrapped Data attribute"); + goto fail; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data", + wrapped_data, wrapped_data_len); + attr_len = wrapped_data - 4 - attr_start; + + trans_id = dpp_get_attr(attr_start, attr_len, DPP_ATTR_TRANSACTION_ID, + &trans_id_len); + if (!trans_id || trans_id_len != 1) { + dpp_auth_fail(auth, "Peer did not include Transaction ID"); + goto fail; + } + if (trans_id[0] != auth->transaction_id) { + dpp_auth_fail(auth, "Transaction ID mismatch"); + goto fail; + } + + version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (!version || version_len < 1 || version[0] < 2) { + dpp_auth_fail(auth, + "Missing or invalid Protocol Version attribute"); + goto fail; + } + auth->peer_version = version[0]; + wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", + auth->peer_version); + + r_connector = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CONNECTOR, + &r_connector_len); + if (!r_connector) { + dpp_auth_fail(auth, " Missing R-Connector attribute"); + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, "DPP: R-Connector", + r_connector, r_connector_len); + + e_nonce = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_ENROLLEE_NONCE, &e_nonce_len); + if (!e_nonce || e_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid E-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", e_nonce, e_nonce_len); + os_memcpy(auth->e_nonce, e_nonce, e_nonce_len); + + r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY, + &r_proto_len); + if (!r_proto) { + dpp_auth_fail(auth, + "Missing required Responder Protocol Key attribute"); + goto fail; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key", + r_proto, r_proto_len); + + signed_connector = os_malloc(r_connector_len + 1); + if (!signed_connector) + goto fail; + os_memcpy(signed_connector, r_connector, r_connector_len); + signed_connector[r_connector_len] = '\0'; + + res = dpp_process_signed_connector(&info, auth->conf->csign, + signed_connector); + if (res != DPP_STATUS_OK) { + dpp_auth_fail(auth, "Invalid R-Connector"); + goto fail; + } + + root = json_parse((const char *) info.payload, info.payload_len); + if (!root) { + dpp_auth_fail(auth, "Invalid Connector payload"); + goto fail; + } + + /* Do not check netAccessKey expiration for reconfiguration to allow + * expired Connector to be updated. */ + + token = json_get_member(root, "netAccessKey"); + if (!token || token->type != JSON_OBJECT) { + dpp_auth_fail(auth, "No netAccessKey object found"); + goto fail; + } + + if (dpp_reconfig_derive_ke_initiator(auth, r_proto, r_proto_len, + token) < 0) + goto fail; + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + c_nonce = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len); + if (!c_nonce || c_nonce_len != auth->curve->nonce_len || + os_memcmp(c_nonce, auth->c_nonce, c_nonce_len) != 0) { + dpp_auth_fail(auth, "Missing or invalid C-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len); + + conn_status = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_CONN_STATUS, &conn_status_len); + if (!conn_status) { + dpp_auth_fail(auth, "Missing Connection Status attribute"); + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, "DPP: connStatus", + conn_status, conn_status_len); + + conn_status_json = json_parse((const char *) conn_status, + conn_status_len); + if (!conn_status_json) { + dpp_auth_fail(auth, "Could not parse connStatus"); + goto fail; + } + /* TODO: use connStatus information */ + + conf = dpp_reconfig_build_conf(auth); + if (conf) + auth->reconfig_success = true; + +out: + json_free(root); + json_free(conn_status_json); + bin_clear_free(unwrapped, unwrapped_len); + os_free(info.payload); + os_free(signed_connector); + return conf; +fail: + wpabuf_free(conf); + conf = NULL; + goto out; +} + + +int dpp_reconfig_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + const u8 *trans_id, *version, *wrapped_data, *c_nonce, *e_nonce, + *reconfig_flags, *status; + u16 trans_id_len, version_len, wrapped_data_len, c_nonce_len, + e_nonce_len, reconfig_flags_len, status_len; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + int res = -1; + u8 flags; + + if (!auth->reconfig || auth->configurator) + goto fail; + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid required Wrapped Data attribute"); + goto fail; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data", + wrapped_data, wrapped_data_len); + attr_len = wrapped_data - 4 - attr_start; + + status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, + &status_len); + if (!status || status_len < 1) { + dpp_auth_fail(auth, + "Missing or invalid required DPP Status attribute"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); + if (status[0] != DPP_STATUS_OK) { + dpp_auth_fail(auth, + "Reconfiguration did not complete successfully"); + goto fail; + } + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + trans_id = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_TRANSACTION_ID, &trans_id_len); + if (!trans_id || trans_id_len != 1 || + trans_id[0] != auth->transaction_id) { + dpp_auth_fail(auth, + "Peer did not include valid Transaction ID"); + goto fail; + } + + version = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_PROTOCOL_VERSION, &version_len); + if (!version || version_len < 1 || version[0] != DPP_VERSION) { + dpp_auth_fail(auth, + "Missing or invalid Protocol Version attribute"); + goto fail; + } + + c_nonce = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_CONFIGURATOR_NONCE, &c_nonce_len); + if (!c_nonce || c_nonce_len != auth->curve->nonce_len || + os_memcmp(c_nonce, auth->c_nonce, c_nonce_len) != 0) { + dpp_auth_fail(auth, "Missing or invalid C-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: C-nonce", c_nonce, c_nonce_len); + + e_nonce = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_ENROLLEE_NONCE, &e_nonce_len); + if (!e_nonce || e_nonce_len != auth->curve->nonce_len || + os_memcmp(e_nonce, auth->e_nonce, e_nonce_len) != 0) { + dpp_auth_fail(auth, "Missing or invalid E-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", e_nonce, e_nonce_len); + + reconfig_flags = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_RECONFIG_FLAGS, + &reconfig_flags_len); + if (!reconfig_flags || reconfig_flags_len < 1) { + dpp_auth_fail(auth, "Missing or invalid Reconfig-Flags"); + goto fail; + } + flags = reconfig_flags[0] & BIT(0); + wpa_printf(MSG_DEBUG, "DPP: Reconfig Flags connectorKey=%u", flags); + auth->reconfig_connector_key = flags; + + auth->reconfig_success = true; + res = 0; +fail: + bin_clear_free(unwrapped, unwrapped_len); + return res; +} + +#endif /* CONFIG_DPP2 */ diff --git a/src/common/dpp_tcp.c b/src/common/dpp_tcp.c new file mode 100644 index 000000000..7e330d689 --- /dev/null +++ b/src/common/dpp_tcp.c @@ -0,0 +1,1794 @@ +/* + * DPP over TCP + * Copyright (c) 2019-2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include + +#include "utils/common.h" +#include "utils/ip_addr.h" +#include "utils/eloop.h" +#include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" +#include "dpp.h" +#include "dpp_i.h" + +#ifdef CONFIG_DPP2 + +struct dpp_connection { + struct dl_list list; + struct dpp_controller *ctrl; + struct dpp_relay_controller *relay; + struct dpp_global *global; + struct dpp_authentication *auth; + void *msg_ctx; + void *cb_ctx; + int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); + int sock; + u8 mac_addr[ETH_ALEN]; + unsigned int freq; + u8 msg_len[4]; + size_t msg_len_octets; + struct wpabuf *msg; + struct wpabuf *msg_out; + size_t msg_out_pos; + unsigned int read_eloop:1; + unsigned int write_eloop:1; + unsigned int on_tcp_tx_complete_gas_done:1; + unsigned int on_tcp_tx_complete_remove:1; + unsigned int on_tcp_tx_complete_auth_ok:1; + unsigned int gas_comeback_in_progress:1; + u8 gas_dialog_token; + char *name; + enum dpp_netrole netrole; +}; + +/* Remote Controller */ +struct dpp_relay_controller { + struct dl_list list; + struct dpp_global *global; + u8 pkhash[SHA256_MAC_LEN]; + struct hostapd_ip_addr ipaddr; + void *msg_ctx; + void *cb_ctx; + void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg, + size_t len); + void (*gas_resp_tx)(void *ctx, const u8 *addr, u8 dialog_token, + int prot, struct wpabuf *buf); + struct dl_list conn; /* struct dpp_connection */ +}; + +/* Local Controller */ +struct dpp_controller { + struct dpp_global *global; + u8 allowed_roles; + int qr_mutual; + int sock; + struct dl_list conn; /* struct dpp_connection */ + char *configurator_params; + enum dpp_netrole netrole; + void *msg_ctx; + void *cb_ctx; + int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); +}; + +static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx); +static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx); +static void dpp_controller_auth_success(struct dpp_connection *conn, + int initiator); +static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx); +static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx); + + +static void dpp_connection_free(struct dpp_connection *conn) +{ + if (conn->sock >= 0) { + wpa_printf(MSG_DEBUG, "DPP: Close Controller socket %d", + conn->sock); + eloop_unregister_sock(conn->sock, EVENT_TYPE_READ); + eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE); + close(conn->sock); + } + eloop_cancel_timeout(dpp_controller_conn_status_result_wait_timeout, + conn, NULL); + eloop_cancel_timeout(dpp_tcp_build_csr, conn, NULL); + eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL); + wpabuf_free(conn->msg); + wpabuf_free(conn->msg_out); + dpp_auth_deinit(conn->auth); + os_free(conn->name); + os_free(conn); +} + + +static void dpp_connection_remove(struct dpp_connection *conn) +{ + dl_list_del(&conn->list); + dpp_connection_free(conn); +} + + +int dpp_relay_add_controller(struct dpp_global *dpp, + struct dpp_relay_config *config) +{ + struct dpp_relay_controller *ctrl; + + if (!dpp) + return -1; + + ctrl = os_zalloc(sizeof(*ctrl)); + if (!ctrl) + return -1; + dl_list_init(&ctrl->conn); + ctrl->global = dpp; + os_memcpy(&ctrl->ipaddr, config->ipaddr, sizeof(*config->ipaddr)); + os_memcpy(ctrl->pkhash, config->pkhash, SHA256_MAC_LEN); + ctrl->msg_ctx = config->msg_ctx; + ctrl->cb_ctx = config->cb_ctx; + ctrl->tx = config->tx; + ctrl->gas_resp_tx = config->gas_resp_tx; + dl_list_add(&dpp->controllers, &ctrl->list); + return 0; +} + + +static struct dpp_relay_controller * +dpp_relay_controller_get(struct dpp_global *dpp, const u8 *pkhash) +{ + struct dpp_relay_controller *ctrl; + + if (!dpp) + return NULL; + + dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller, + list) { + if (os_memcmp(pkhash, ctrl->pkhash, SHA256_MAC_LEN) == 0) + return ctrl; + } + + return NULL; +} + + +static void dpp_controller_gas_done(struct dpp_connection *conn) +{ + struct dpp_authentication *auth = conn->auth; + + if (auth->waiting_csr) { + wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR"); + conn->on_tcp_tx_complete_gas_done = 0; + return; + } + + if (auth->peer_version >= 2 && + auth->conf_resp_status == DPP_STATUS_OK) { + wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result"); + auth->waiting_conf_result = 1; + return; + } + + wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT); + dpp_connection_remove(conn); +} + + +static int dpp_tcp_send(struct dpp_connection *conn) +{ + int res; + + if (!conn->msg_out) { + eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE); + conn->write_eloop = 0; + return -1; + } + res = send(conn->sock, + wpabuf_head_u8(conn->msg_out) + conn->msg_out_pos, + wpabuf_len(conn->msg_out) - conn->msg_out_pos, 0); + if (res < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to send buffer: %s", + strerror(errno)); + dpp_connection_remove(conn); + return -1; + } + + conn->msg_out_pos += res; + if (wpabuf_len(conn->msg_out) > conn->msg_out_pos) { + wpa_printf(MSG_DEBUG, + "DPP: %u/%u bytes of message sent to Controller", + (unsigned int) conn->msg_out_pos, + (unsigned int) wpabuf_len(conn->msg_out)); + if (!conn->write_eloop && + eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, + dpp_conn_tx_ready, conn, NULL) == 0) + conn->write_eloop = 1; + return 1; + } + + wpa_printf(MSG_DEBUG, "DPP: Full message sent over TCP"); + wpabuf_free(conn->msg_out); + conn->msg_out = NULL; + conn->msg_out_pos = 0; + eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE); + conn->write_eloop = 0; + if (!conn->read_eloop && + eloop_register_sock(conn->sock, EVENT_TYPE_READ, + dpp_controller_rx, conn, NULL) == 0) + conn->read_eloop = 1; + if (conn->on_tcp_tx_complete_remove) { + dpp_connection_remove(conn); + } else if (conn->auth && (conn->ctrl || conn->auth->configurator) && + conn->on_tcp_tx_complete_gas_done) { + dpp_controller_gas_done(conn); + } else if (conn->on_tcp_tx_complete_auth_ok) { + conn->on_tcp_tx_complete_auth_ok = 0; + dpp_controller_auth_success(conn, 1); + } + + return 0; +} + + +static int dpp_tcp_send_msg(struct dpp_connection *conn, + const struct wpabuf *msg) +{ + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = wpabuf_alloc(4 + wpabuf_len(msg) - 1); + if (!conn->msg_out) + return -1; + wpabuf_put_be32(conn->msg_out, wpabuf_len(msg) - 1); + wpabuf_put_data(conn->msg_out, wpabuf_head_u8(msg) + 1, + wpabuf_len(msg) - 1); + + if (dpp_tcp_send(conn) == 1) { + if (!conn->write_eloop) { + if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, + dpp_conn_tx_ready, + conn, NULL) < 0) + return -1; + conn->write_eloop = 1; + } + } + + return 0; +} + + +static void dpp_controller_start_gas_client(struct dpp_connection *conn) +{ + struct dpp_authentication *auth = conn->auth; + struct wpabuf *buf; + const char *dpp_name; + + dpp_name = conn->name ? conn->name : "Test"; + buf = dpp_build_conf_req_helper(auth, dpp_name, conn->netrole, NULL, + NULL); + if (!buf) { + wpa_printf(MSG_DEBUG, + "DPP: No configuration request data available"); + return; + } + + dpp_tcp_send_msg(conn, buf); + wpabuf_free(buf); +} + + +static void dpp_controller_auth_success(struct dpp_connection *conn, + int initiator) +{ + struct dpp_authentication *auth = conn->auth; + + if (!auth) + return; + + wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded"); + wpa_msg(conn->msg_ctx, MSG_INFO, + DPP_EVENT_AUTH_SUCCESS "init=%d", initiator); +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at Authentication Confirm"); + if (auth->configurator) { + /* Prevent GAS response */ + auth->auth_success = 0; + } + return; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!auth->configurator) + dpp_controller_start_gas_client(conn); +} + + +static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx) +{ + struct dpp_connection *conn = eloop_ctx; + + wpa_printf(MSG_DEBUG, "DPP: TCP socket %d ready for TX", sock); + dpp_tcp_send(conn); +} + + +static int dpp_ipaddr_to_sockaddr(struct sockaddr *addr, socklen_t *addrlen, + const struct hostapd_ip_addr *ipaddr, + int port) +{ + struct sockaddr_in *dst; +#ifdef CONFIG_IPV6 + struct sockaddr_in6 *dst6; +#endif /* CONFIG_IPV6 */ + + switch (ipaddr->af) { + case AF_INET: + dst = (struct sockaddr_in *) addr; + os_memset(dst, 0, sizeof(*dst)); + dst->sin_family = AF_INET; + dst->sin_addr.s_addr = ipaddr->u.v4.s_addr; + dst->sin_port = htons(port); + *addrlen = sizeof(*dst); + break; +#ifdef CONFIG_IPV6 + case AF_INET6: + dst6 = (struct sockaddr_in6 *) addr; + os_memset(dst6, 0, sizeof(*dst6)); + dst6->sin6_family = AF_INET6; + os_memcpy(&dst6->sin6_addr, &ipaddr->u.v6, + sizeof(struct in6_addr)); + dst6->sin6_port = htons(port); + *addrlen = sizeof(*dst6); + break; +#endif /* CONFIG_IPV6 */ + default: + return -1; + } + + return 0; +} + + +static struct dpp_connection * +dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src, + unsigned int freq) +{ + struct dpp_connection *conn; + struct sockaddr_storage addr; + socklen_t addrlen; + char txt[100]; + + if (dl_list_len(&ctrl->conn) >= 15) { + wpa_printf(MSG_DEBUG, + "DPP: Too many ongoing Relay connections to the Controller - cannot start a new one"); + return NULL; + } + + if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &addr, &addrlen, + &ctrl->ipaddr, DPP_TCP_PORT) < 0) + return NULL; + + conn = os_zalloc(sizeof(*conn)); + if (!conn) + return NULL; + + conn->global = ctrl->global; + conn->relay = ctrl; + conn->msg_ctx = ctrl->msg_ctx; + conn->cb_ctx = ctrl->global->cb_ctx; + os_memcpy(conn->mac_addr, src, ETH_ALEN); + conn->freq = freq; + + conn->sock = socket(AF_INET, SOCK_STREAM, 0); + if (conn->sock < 0) + goto fail; + wpa_printf(MSG_DEBUG, "DPP: TCP relay socket %d connection to %s", + conn->sock, hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt))); + + if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { + wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", + strerror(errno)); + goto fail; + } + + if (connect(conn->sock, (struct sockaddr *) &addr, addrlen) < 0) { + if (errno != EINPROGRESS) { + wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s", + strerror(errno)); + goto fail; + } + + /* + * Continue connecting in the background; eloop will call us + * once the connection is ready (or failed). + */ + } + + if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, + dpp_conn_tx_ready, conn, NULL) < 0) + goto fail; + conn->write_eloop = 1; + + /* TODO: eloop timeout to clear a connection if it does not complete + * properly */ + + dl_list_add(&ctrl->conn, &conn->list); + return conn; +fail: + dpp_connection_free(conn); + return NULL; +} + + +static struct wpabuf * dpp_tcp_encaps(const u8 *hdr, const u8 *buf, size_t len) +{ + struct wpabuf *msg; + + msg = wpabuf_alloc(4 + 1 + DPP_HDR_LEN + len); + if (!msg) + return NULL; + wpabuf_put_be32(msg, 1 + DPP_HDR_LEN + len); + wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC); + wpabuf_put_data(msg, hdr, DPP_HDR_LEN); + wpabuf_put_data(msg, buf, len); + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg); + return msg; +} + + +static int dpp_relay_tx(struct dpp_connection *conn, const u8 *hdr, + const u8 *buf, size_t len) +{ + u8 type = hdr[DPP_HDR_LEN - 1]; + + wpa_printf(MSG_DEBUG, + "DPP: Continue already established Relay/Controller connection for this session"); + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = dpp_tcp_encaps(hdr, buf, len); + if (!conn->msg_out) { + dpp_connection_remove(conn); + return -1; + } + + /* TODO: for proto ver 1, need to do remove connection based on GAS Resp + * TX status */ + if (type == DPP_PA_CONFIGURATION_RESULT) + conn->on_tcp_tx_complete_remove = 1; + dpp_tcp_send(conn); + return 0; +} + + +int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr, + const u8 *buf, size_t len, unsigned int freq, + const u8 *i_bootstrap, const u8 *r_bootstrap) +{ + struct dpp_relay_controller *ctrl; + struct dpp_connection *conn; + u8 type = hdr[DPP_HDR_LEN - 1]; + + /* Check if there is an already started session for this peer and if so, + * continue that session (send this over TCP) and return 0. + */ + if (type != DPP_PA_PEER_DISCOVERY_REQ && + type != DPP_PA_PEER_DISCOVERY_RESP && + type != DPP_PA_PRESENCE_ANNOUNCEMENT && + type != DPP_PA_RECONFIG_ANNOUNCEMENT) { + dl_list_for_each(ctrl, &dpp->controllers, + struct dpp_relay_controller, list) { + dl_list_for_each(conn, &ctrl->conn, + struct dpp_connection, list) { + if (os_memcmp(src, conn->mac_addr, + ETH_ALEN) == 0) + return dpp_relay_tx(conn, hdr, buf, len); + } + } + } + + if (type == DPP_PA_PRESENCE_ANNOUNCEMENT || + type == DPP_PA_RECONFIG_ANNOUNCEMENT) { + /* TODO: Could send this to all configured Controllers. For now, + * only the first Controller is supported. */ + ctrl = dl_list_first(&dpp->controllers, + struct dpp_relay_controller, list); + } else { + if (!r_bootstrap) + return -1; + ctrl = dpp_relay_controller_get(dpp, r_bootstrap); + } + if (!ctrl) + return -1; + + wpa_printf(MSG_DEBUG, + "DPP: Authentication Request for a configured Controller"); + conn = dpp_relay_new_conn(ctrl, src, freq); + if (!conn) + return -1; + + conn->msg_out = dpp_tcp_encaps(hdr, buf, len); + if (!conn->msg_out) { + dpp_connection_remove(conn); + return -1; + } + /* Message will be sent in dpp_conn_tx_ready() */ + + return 0; +} + + +int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data, + size_t data_len) +{ + struct dpp_relay_controller *ctrl; + struct dpp_connection *conn, *found = NULL; + struct wpabuf *msg; + + /* Check if there is a successfully completed authentication for this + * and if so, continue that session (send this over TCP) and return 0. + */ + dl_list_for_each(ctrl, &dpp->controllers, + struct dpp_relay_controller, list) { + if (found) + break; + dl_list_for_each(conn, &ctrl->conn, + struct dpp_connection, list) { + if (os_memcmp(src, conn->mac_addr, + ETH_ALEN) == 0) { + found = conn; + break; + } + } + } + + if (!found) + return -1; + + msg = wpabuf_alloc(4 + 1 + data_len); + if (!msg) + return -1; + wpabuf_put_be32(msg, 1 + data_len); + wpabuf_put_u8(msg, WLAN_PA_GAS_INITIAL_REQ); + wpabuf_put_data(msg, data, data_len); + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg); + + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = msg; + dpp_tcp_send(conn); + return 0; +} + + +static void dpp_controller_free(struct dpp_controller *ctrl) +{ + struct dpp_connection *conn, *tmp; + + if (!ctrl) + return; + + dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection, + list) + dpp_connection_remove(conn); + + if (ctrl->sock >= 0) { + close(ctrl->sock); + eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ); + } + os_free(ctrl->configurator_params); + os_free(ctrl); +} + + +static int dpp_controller_rx_auth_req(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, size_t len) +{ + const u8 *r_bootstrap, *i_bootstrap; + u16 r_bootstrap_len, i_bootstrap_len; + struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL; + + if (!conn->ctrl) + return 0; + + wpa_printf(MSG_DEBUG, "DPP: Authentication Request"); + + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + wpa_printf(MSG_INFO, + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + + i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH, + &i_bootstrap_len); + if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) { + wpa_printf(MSG_INFO, + "Missing or invalid required Initiator Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash", + i_bootstrap, i_bootstrap_len); + + /* Try to find own and peer bootstrapping key matches based on the + * received hash values */ + dpp_bootstrap_find_pair(conn->ctrl->global, i_bootstrap, r_bootstrap, + &own_bi, &peer_bi); + if (!own_bi) { + wpa_printf(MSG_INFO, + "No matching own bootstrapping key found - ignore message"); + return -1; + } + + if (conn->auth) { + wpa_printf(MSG_INFO, + "Already in DPP authentication exchange - ignore new one"); + return 0; + } + + conn->auth = dpp_auth_req_rx(conn->ctrl->global, conn->msg_ctx, + conn->ctrl->allowed_roles, + conn->ctrl->qr_mutual, + peer_bi, own_bi, -1, hdr, buf, len); + if (!conn->auth) { + wpa_printf(MSG_DEBUG, "DPP: No response generated"); + return -1; + } + + if (dpp_set_configurator(conn->auth, + conn->ctrl->configurator_params) < 0) { + dpp_connection_remove(conn); + return -1; + } + + return dpp_tcp_send_msg(conn, conn->auth->resp_msg); +} + + +static int dpp_controller_rx_auth_resp(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, size_t len) +{ + struct dpp_authentication *auth = conn->auth; + struct wpabuf *msg; + int res; + + if (!auth) + return -1; + + wpa_printf(MSG_DEBUG, "DPP: Authentication Response"); + + msg = dpp_auth_resp_rx(auth, hdr, buf, len); + if (!msg) { + if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) { + wpa_printf(MSG_DEBUG, + "DPP: Start wait for full response"); + return 0; + } + wpa_printf(MSG_DEBUG, "DPP: No confirm generated"); + dpp_connection_remove(conn); + return -1; + } + + conn->on_tcp_tx_complete_auth_ok = 1; + res = dpp_tcp_send_msg(conn, msg); + wpabuf_free(msg); + return res; +} + + +static int dpp_controller_rx_auth_conf(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, size_t len) +{ + struct dpp_authentication *auth = conn->auth; + + wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation"); + + if (!auth) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Authentication in progress - drop"); + return -1; + } + + if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Authentication failed"); + return -1; + } + + dpp_controller_auth_success(conn, 0); + return 0; +} + + +void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx, + void *timeout_ctx) +{ + struct dpp_connection *conn = eloop_ctx; + + if (!conn->auth->waiting_conf_result) + return; + + wpa_printf(MSG_DEBUG, + "DPP: Timeout while waiting for Connection Status Result"); + wpa_msg(conn->msg_ctx, MSG_INFO, + DPP_EVENT_CONN_STATUS_RESULT "timeout"); + dpp_connection_remove(conn); +} + + +static int dpp_controller_rx_conf_result(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, + size_t len) +{ + struct dpp_authentication *auth = conn->auth; + enum dpp_status_error status; + void *msg_ctx = conn->msg_ctx; + + if (!conn->ctrl && (!auth || !auth->configurator)) + return 0; + + wpa_printf(MSG_DEBUG, "DPP: Configuration Result"); + + if (!auth || !auth->waiting_conf_result) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Configuration waiting for result - drop"); + return -1; + } + + status = dpp_conf_result_rx(auth, hdr, buf, len); + if (status == DPP_STATUS_OK && auth->send_conn_status) { + wpa_msg(msg_ctx, MSG_INFO, + DPP_EVENT_CONF_SENT "wait_conn_status=1"); + wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result"); + eloop_cancel_timeout( + dpp_controller_conn_status_result_wait_timeout, + conn, NULL); + eloop_register_timeout( + 16, 0, dpp_controller_conn_status_result_wait_timeout, + conn, NULL); + return 0; + } + if (status == DPP_STATUS_OK) + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT); + else + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED); + return -1; /* to remove the completed connection */ +} + + +static int dpp_controller_rx_conn_status_result(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, + size_t len) +{ + struct dpp_authentication *auth = conn->auth; + enum dpp_status_error status; + u8 ssid[SSID_MAX_LEN]; + size_t ssid_len = 0; + char *channel_list = NULL; + + if (!conn->ctrl) + return 0; + + wpa_printf(MSG_DEBUG, "DPP: Connection Status Result"); + + if (!auth || !auth->waiting_conn_status_result) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Configuration waiting for connection status result - drop"); + return -1; + } + + status = dpp_conn_status_result_rx(auth, hdr, buf, len, + ssid, &ssid_len, &channel_list); + wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT + "result=%d ssid=%s channel_list=%s", + status, wpa_ssid_txt(ssid, ssid_len), + channel_list ? channel_list : "N/A"); + os_free(channel_list); + return -1; /* to remove the completed connection */ +} + + +static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, + size_t len) +{ + const u8 *r_bootstrap; + u16 r_bootstrap_len; + struct dpp_bootstrap_info *peer_bi; + struct dpp_authentication *auth; + struct dpp_global *dpp = conn->ctrl->global; + + if (conn->auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Presence Announcement during ongoing Authentication"); + return -1; + } + + wpa_printf(MSG_DEBUG, "DPP: Presence Announcement"); + + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + peer_bi = dpp_bootstrap_find_chirp(dpp, r_bootstrap); + if (!peer_bi) { + wpa_printf(MSG_DEBUG, + "DPP: No matching bootstrapping information found"); + return -1; + } + + auth = dpp_auth_init(dpp, conn->msg_ctx, peer_bi, NULL, + DPP_CAPAB_CONFIGURATOR, -1, NULL, 0); + if (!auth) + return -1; + if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) { + dpp_auth_deinit(auth); + dpp_connection_remove(conn); + return -1; + } + + conn->auth = auth; + return dpp_tcp_send_msg(conn, conn->auth->req_msg); +} + + +static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, + size_t len) +{ + const u8 *csign_hash, *fcgroup, *a_nonce, *e_id; + u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len; + struct dpp_configurator *conf; + struct dpp_global *dpp = conn->ctrl->global; + struct dpp_authentication *auth; + u16 group; + + if (conn->auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Reconfig Announcement during ongoing Authentication"); + return -1; + } + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement"); + + csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH, + &csign_hash_len); + if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) { + wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Configurator C-sign key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)", + csign_hash, csign_hash_len); + conf = dpp_configurator_find_kid(dpp, csign_hash); + if (!conf) { + wpa_printf(MSG_DEBUG, + "DPP: No matching Configurator information found"); + return -1; + } + + fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, + &fcgroup_len); + if (!fcgroup || fcgroup_len != 2) { + wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Finite Cyclic Group attribute"); + return -1; + } + group = WPA_GET_LE16(fcgroup); + wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); + + a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len); + e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len); + + auth = dpp_reconfig_init(dpp, conn->msg_ctx, conf, 0, group, + a_nonce, a_nonce_len, e_id, e_id_len); + if (!auth) + return -1; + if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) { + dpp_auth_deinit(auth); + return -1; + } + + conn->auth = auth; + return dpp_tcp_send_msg(conn, auth->reconfig_req_msg); +} + + +static int dpp_controller_rx_reconfig_auth_resp(struct dpp_connection *conn, + const u8 *hdr, const u8 *buf, + size_t len) +{ + struct dpp_authentication *auth = conn->auth; + struct wpabuf *conf; + int res; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response"); + + if (!auth || !auth->reconfig || !auth->configurator) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Reconfig Authentication in progress - drop"); + return -1; + } + + conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len); + if (!conf) + return -1; + + res = dpp_tcp_send_msg(conn, conf); + wpabuf_free(conf); + return res; +} + + +static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg, + size_t len) +{ + const u8 *pos, *end; + u8 type; + + wpa_printf(MSG_DEBUG, "DPP: Received DPP Action frame over TCP"); + pos = msg; + end = msg + len; + + if (end - pos < DPP_HDR_LEN || + WPA_GET_BE24(pos) != OUI_WFA || + pos[3] != DPP_OUI_TYPE) { + wpa_printf(MSG_DEBUG, "DPP: Unrecognized header"); + return -1; + } + + if (pos[4] != 1) { + wpa_printf(MSG_DEBUG, "DPP: Unsupported Crypto Suite %u", + pos[4]); + return -1; + } + type = pos[5]; + wpa_printf(MSG_DEBUG, "DPP: Received message type %u", type); + pos += DPP_HDR_LEN; + + wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes", + pos, end - pos); + if (dpp_check_attrs(pos, end - pos) < 0) + return -1; + + if (conn->relay) { + wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN"); + conn->relay->tx(conn->relay->cb_ctx, conn->mac_addr, + conn->freq, msg, len); + return 0; + } + + switch (type) { + case DPP_PA_AUTHENTICATION_REQ: + return dpp_controller_rx_auth_req(conn, msg, pos, end - pos); + case DPP_PA_AUTHENTICATION_RESP: + return dpp_controller_rx_auth_resp(conn, msg, pos, end - pos); + case DPP_PA_AUTHENTICATION_CONF: + return dpp_controller_rx_auth_conf(conn, msg, pos, end - pos); + case DPP_PA_CONFIGURATION_RESULT: + return dpp_controller_rx_conf_result(conn, msg, pos, end - pos); + case DPP_PA_CONNECTION_STATUS_RESULT: + return dpp_controller_rx_conn_status_result(conn, msg, pos, + end - pos); + case DPP_PA_PRESENCE_ANNOUNCEMENT: + return dpp_controller_rx_presence_announcement(conn, msg, pos, + end - pos); + case DPP_PA_RECONFIG_ANNOUNCEMENT: + return dpp_controller_rx_reconfig_announcement(conn, msg, pos, + end - pos); + case DPP_PA_RECONFIG_AUTH_RESP: + return dpp_controller_rx_reconfig_auth_resp(conn, msg, pos, + end - pos); + default: + /* TODO: missing messages types */ + wpa_printf(MSG_DEBUG, + "DPP: Unsupported frame subtype %d", type); + return -1; + } +} + + +static int dpp_tcp_send_comeback_delay(struct dpp_connection *conn, u8 action) +{ + struct wpabuf *buf; + size_t len = 18; + + if (action == WLAN_PA_GAS_COMEBACK_RESP) + len++; + + buf = wpabuf_alloc(4 + len); + if (!buf) + return -1; + + wpabuf_put_be32(buf, len); + + wpabuf_put_u8(buf, action); + wpabuf_put_u8(buf, conn->gas_dialog_token); + wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); + if (action == WLAN_PA_GAS_COMEBACK_RESP) + wpabuf_put_u8(buf, 0); + wpabuf_put_le16(buf, 500); /* GAS Comeback Delay */ + + dpp_write_adv_proto(buf); + wpabuf_put_le16(buf, 0); /* Query Response Length */ + + /* Send Config Response over TCP */ + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf); + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = buf; + dpp_tcp_send(conn); + return 0; +} + + +static int dpp_tcp_send_gas_resp(struct dpp_connection *conn, u8 action, + struct wpabuf *resp) +{ + struct wpabuf *buf; + size_t len; + + if (!resp) + return -1; + + len = 18 + wpabuf_len(resp); + if (action == WLAN_PA_GAS_COMEBACK_RESP) + len++; + + buf = wpabuf_alloc(4 + len); + if (!buf) { + wpabuf_free(resp); + return -1; + } + + wpabuf_put_be32(buf, len); + + wpabuf_put_u8(buf, action); + wpabuf_put_u8(buf, conn->gas_dialog_token); + wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS); + if (action == WLAN_PA_GAS_COMEBACK_RESP) + wpabuf_put_u8(buf, 0); + wpabuf_put_le16(buf, 0); /* GAS Comeback Delay */ + + dpp_write_adv_proto(buf); + dpp_write_gas_query(buf, resp); + wpabuf_free(resp); + + /* Send Config Response over TCP; GAS fragmentation is taken care of by + * the Relay */ + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf); + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = buf; + conn->on_tcp_tx_complete_gas_done = 1; + dpp_tcp_send(conn); + return 0; +} + + +static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg, + size_t len) +{ + const u8 *pos, *end, *next; + const u8 *adv_proto; + u16 slen; + struct wpabuf *resp; + struct dpp_authentication *auth = conn->auth; + + if (len < 1 + 2) + return -1; + + wpa_printf(MSG_DEBUG, + "DPP: Received DPP Configuration Request over TCP"); + + if (!auth || (!conn->ctrl && !auth->configurator) || + (!auth->auth_success && !auth->reconfig_success)) { + wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); + return -1; + } + + pos = msg; + end = msg + len; + + conn->gas_dialog_token = *pos++; + adv_proto = pos++; + slen = *pos++; + if (*adv_proto != WLAN_EID_ADV_PROTO || + slen > end - pos || slen < 2) + return -1; + + next = pos + slen; + pos++; /* skip QueryRespLenLimit and PAME-BI */ + + if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC || + pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA || + pos[5] != DPP_OUI_TYPE || pos[6] != 0x01) + return -1; + + pos = next; + /* Query Request */ + if (end - pos < 2) + return -1; + slen = WPA_GET_LE16(pos); + pos += 2; + if (slen > end - pos) + return -1; + + resp = dpp_conf_req_rx(auth, pos, slen); + if (!resp && auth->waiting_cert) { + wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready"); + conn->gas_comeback_in_progress = 1; + return dpp_tcp_send_comeback_delay(conn, + WLAN_PA_GAS_INITIAL_RESP); + } + + return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_INITIAL_RESP, resp); +} + + +static int dpp_controller_rx_gas_comeback_req(struct dpp_connection *conn, + const u8 *msg, size_t len) +{ + u8 dialog_token; + struct dpp_authentication *auth = conn->auth; + struct wpabuf *resp; + + if (len < 1) + return -1; + + wpa_printf(MSG_DEBUG, + "DPP: Received DPP Configuration Request over TCP (comeback)"); + + if (!auth || (!conn->ctrl && !auth->configurator) || + (!auth->auth_success && !auth->reconfig_success) || + !conn->gas_comeback_in_progress) { + wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); + return -1; + } + + dialog_token = msg[0]; + if (dialog_token != conn->gas_dialog_token) { + wpa_printf(MSG_DEBUG, "DPP: Dialog token mismatch (%u != %u)", + dialog_token, conn->gas_dialog_token); + return -1; + } + + if (!auth->conf_resp_tcp) { + wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready"); + return dpp_tcp_send_comeback_delay(conn, + WLAN_PA_GAS_COMEBACK_RESP); + } + + wpa_printf(MSG_DEBUG, + "DPP: Configuration response is ready to be sent out"); + resp = auth->conf_resp_tcp; + auth->conf_resp_tcp = NULL; + return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_COMEBACK_RESP, resp); +} + + +static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx) +{ + struct dpp_connection *conn = eloop_ctx; + struct dpp_authentication *auth = conn->auth; + + if (!auth || !auth->csrattrs) + return; + + wpa_printf(MSG_DEBUG, "DPP: Build CSR"); + wpabuf_free(auth->csr); + /* TODO: Additional information needed for CSR based on csrAttrs */ + auth->csr = dpp_build_csr(auth, conn->name ? conn->name : "Test"); + if (!auth->csr) { + dpp_connection_remove(conn); + return; + } + + dpp_controller_start_gas_client(conn); +} + + +static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp) +{ + struct dpp_authentication *auth = conn->auth; + int res; + struct wpabuf *msg; + enum dpp_status_error status; + + wpa_printf(MSG_DEBUG, + "DPP: Configuration Response for local stack from TCP"); + + if (auth) + res = dpp_conf_resp_rx(auth, resp); + else + res = -1; + wpabuf_free(resp); + if (res == -2) { + wpa_printf(MSG_DEBUG, "DPP: CSR needed"); + eloop_register_timeout(0, 0, dpp_tcp_build_csr, conn, NULL); + return 0; + } + if (res < 0) { + wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); + return -1; + } + + if (conn->process_conf_obj) + res = conn->process_conf_obj(conn->cb_ctx, auth); + else + res = 0; + + if (auth->peer_version < 2 || auth->conf_resp_status != DPP_STATUS_OK) + return -1; + + wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result"); + status = res < 0 ? DPP_STATUS_CONFIG_REJECTED : DPP_STATUS_OK; + msg = dpp_build_conf_result(auth, status); + if (!msg) + return -1; + + conn->on_tcp_tx_complete_remove = 1; + res = dpp_tcp_send_msg(conn, msg); + wpabuf_free(msg); + + /* This exchange will be terminated in the TX status handler */ + + return res; +} + + +static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx) +{ + struct dpp_connection *conn = eloop_ctx; + struct dpp_authentication *auth = conn->auth; + struct wpabuf *msg; + + if (!auth) + return; + + wpa_printf(MSG_DEBUG, "DPP: Send GAS Comeback Request"); + msg = wpabuf_alloc(4 + 2); + if (!msg) + return; + wpabuf_put_be32(msg, 2); + wpabuf_put_u8(msg, WLAN_PA_GAS_COMEBACK_REQ); + wpabuf_put_u8(msg, conn->gas_dialog_token); + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg); + + wpabuf_free(conn->msg_out); + conn->msg_out_pos = 0; + conn->msg_out = msg; + dpp_tcp_send(conn); +} + + +static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg, + size_t len, bool comeback) +{ + struct wpabuf *buf; + u8 dialog_token; + const u8 *pos, *end, *next, *adv_proto; + u16 status, slen, comeback_delay; + + if (len < 5 + 2 + (comeback ? 1 : 0)) + return -1; + + wpa_printf(MSG_DEBUG, + "DPP: Received DPP Configuration Response over TCP"); + + pos = msg; + end = msg + len; + + dialog_token = *pos++; + status = WPA_GET_LE16(pos); + if (status != WLAN_STATUS_SUCCESS) { + wpa_printf(MSG_DEBUG, "DPP: Unexpected Status Code %u", status); + return -1; + } + pos += 2; + if (comeback) + pos++; /* ignore Fragment ID */ + comeback_delay = WPA_GET_LE16(pos); + pos += 2; + + adv_proto = pos++; + slen = *pos++; + if (*adv_proto != WLAN_EID_ADV_PROTO || + slen > end - pos || slen < 2) + return -1; + + next = pos + slen; + pos++; /* skip QueryRespLenLimit and PAME-BI */ + + if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC || + pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA || + pos[5] != DPP_OUI_TYPE || pos[6] != 0x01) + return -1; + + pos = next; + /* Query Response */ + if (end - pos < 2) + return -1; + slen = WPA_GET_LE16(pos); + pos += 2; + if (slen > end - pos) + return -1; + + if (comeback_delay) { + unsigned int secs, usecs; + + conn->gas_dialog_token = dialog_token; + secs = (comeback_delay * 1024) / 1000000; + usecs = comeback_delay * 1024 - secs * 1000000; + wpa_printf(MSG_DEBUG, "DPP: Comeback delay: %u", + comeback_delay); + eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL); + eloop_register_timeout(secs, usecs, dpp_tcp_gas_query_comeback, + conn, NULL); + return 0; + } + + buf = wpabuf_alloc(slen); + if (!buf) + return -1; + wpabuf_put_data(buf, pos, slen); + + if (!conn->relay && + (!conn->ctrl || (conn->ctrl->allowed_roles & DPP_CAPAB_ENROLLEE))) + return dpp_tcp_rx_gas_resp(conn, buf); + + if (!conn->relay) { + wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); + wpabuf_free(buf); + return -1; + } + wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN"); + conn->relay->gas_resp_tx(conn->relay->cb_ctx, conn->mac_addr, + dialog_token, 0, buf); + + return 0; +} + + +static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx) +{ + struct dpp_connection *conn = eloop_ctx; + int res; + const u8 *pos; + + wpa_printf(MSG_DEBUG, "DPP: TCP data available for reading (sock %d)", + sd); + + if (conn->msg_len_octets < 4) { + u32 msglen; + + res = recv(sd, &conn->msg_len[conn->msg_len_octets], + 4 - conn->msg_len_octets, 0); + if (res < 0) { + wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", + strerror(errno)); + dpp_connection_remove(conn); + return; + } + if (res == 0) { + wpa_printf(MSG_DEBUG, + "DPP: No more data available over TCP"); + dpp_connection_remove(conn); + return; + } + wpa_printf(MSG_DEBUG, + "DPP: Received %d/%d octet(s) of message length field", + res, (int) (4 - conn->msg_len_octets)); + conn->msg_len_octets += res; + + if (conn->msg_len_octets < 4) { + wpa_printf(MSG_DEBUG, + "DPP: Need %d more octets of message length field", + (int) (4 - conn->msg_len_octets)); + return; + } + + msglen = WPA_GET_BE32(conn->msg_len); + wpa_printf(MSG_DEBUG, "DPP: Message length: %u", msglen); + if (msglen > 65535) { + wpa_printf(MSG_INFO, "DPP: Unexpectedly long message"); + dpp_connection_remove(conn); + return; + } + + wpabuf_free(conn->msg); + conn->msg = wpabuf_alloc(msglen); + } + + if (!conn->msg) { + wpa_printf(MSG_DEBUG, + "DPP: No buffer available for receiving the message"); + dpp_connection_remove(conn); + return; + } + + wpa_printf(MSG_DEBUG, "DPP: Need %u more octets of message payload", + (unsigned int) wpabuf_tailroom(conn->msg)); + + res = recv(sd, wpabuf_put(conn->msg, 0), wpabuf_tailroom(conn->msg), 0); + if (res < 0) { + wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", strerror(errno)); + dpp_connection_remove(conn); + return; + } + if (res == 0) { + wpa_printf(MSG_DEBUG, "DPP: No more data available over TCP"); + dpp_connection_remove(conn); + return; + } + wpa_printf(MSG_DEBUG, "DPP: Received %d octets", res); + wpabuf_put(conn->msg, res); + + if (wpabuf_tailroom(conn->msg) > 0) { + wpa_printf(MSG_DEBUG, + "DPP: Need %u more octets of message payload", + (unsigned int) wpabuf_tailroom(conn->msg)); + return; + } + + conn->msg_len_octets = 0; + wpa_hexdump_buf(MSG_DEBUG, "DPP: Received TCP message", conn->msg); + if (wpabuf_len(conn->msg) < 1) { + dpp_connection_remove(conn); + return; + } + + pos = wpabuf_head(conn->msg); + switch (*pos) { + case WLAN_PA_VENDOR_SPECIFIC: + if (dpp_controller_rx_action(conn, pos + 1, + wpabuf_len(conn->msg) - 1) < 0) + dpp_connection_remove(conn); + break; + case WLAN_PA_GAS_INITIAL_REQ: + if (dpp_controller_rx_gas_req(conn, pos + 1, + wpabuf_len(conn->msg) - 1) < 0) + dpp_connection_remove(conn); + break; + case WLAN_PA_GAS_INITIAL_RESP: + case WLAN_PA_GAS_COMEBACK_RESP: + if (dpp_rx_gas_resp(conn, pos + 1, + wpabuf_len(conn->msg) - 1, + *pos == WLAN_PA_GAS_COMEBACK_RESP) < 0) + dpp_connection_remove(conn); + break; + case WLAN_PA_GAS_COMEBACK_REQ: + if (dpp_controller_rx_gas_comeback_req( + conn, pos + 1, wpabuf_len(conn->msg) - 1) < 0) + dpp_connection_remove(conn); + break; + default: + wpa_printf(MSG_DEBUG, "DPP: Ignore unsupported message type %u", + *pos); + break; + } +} + + +static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx) +{ + struct dpp_controller *ctrl = eloop_ctx; + struct sockaddr_in addr; + socklen_t addr_len = sizeof(addr); + int fd; + struct dpp_connection *conn; + + wpa_printf(MSG_DEBUG, "DPP: New TCP connection"); + + fd = accept(ctrl->sock, (struct sockaddr *) &addr, &addr_len); + if (fd < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to accept new connection: %s", + strerror(errno)); + return; + } + wpa_printf(MSG_DEBUG, "DPP: Connection from %s:%d", + inet_ntoa(addr.sin_addr), ntohs(addr.sin_port)); + + conn = os_zalloc(sizeof(*conn)); + if (!conn) + goto fail; + + conn->global = ctrl->global; + conn->ctrl = ctrl; + conn->msg_ctx = ctrl->msg_ctx; + conn->cb_ctx = ctrl->cb_ctx; + conn->process_conf_obj = ctrl->process_conf_obj; + conn->sock = fd; + conn->netrole = ctrl->netrole; + + if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { + wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", + strerror(errno)); + goto fail; + } + + if (eloop_register_sock(conn->sock, EVENT_TYPE_READ, + dpp_controller_rx, conn, NULL) < 0) + goto fail; + conn->read_eloop = 1; + + /* TODO: eloop timeout to expire connections that do not complete in + * reasonable time */ + dl_list_add(&ctrl->conn, &conn->list); + return; + +fail: + close(fd); + os_free(conn); +} + + +int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth, + const struct hostapd_ip_addr *addr, int port, const char *name, + enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx, + int (*process_conf_obj)(void *ctx, + struct dpp_authentication *auth)) +{ + struct dpp_connection *conn; + struct sockaddr_storage saddr; + socklen_t addrlen; + const u8 *hdr, *pos, *end; + char txt[100]; + + wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d", + hostapd_ip_txt(addr, txt, sizeof(txt)), port); + if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen, + addr, port) < 0) { + dpp_auth_deinit(auth); + return -1; + } + + conn = os_zalloc(sizeof(*conn)); + if (!conn) { + dpp_auth_deinit(auth); + return -1; + } + + conn->msg_ctx = msg_ctx; + conn->cb_ctx = cb_ctx; + conn->process_conf_obj = process_conf_obj; + conn->name = os_strdup(name ? name : "Test"); + conn->netrole = netrole; + conn->global = dpp; + conn->auth = auth; + conn->sock = socket(AF_INET, SOCK_STREAM, 0); + if (conn->sock < 0) + goto fail; + + if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) { + wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s", + strerror(errno)); + goto fail; + } + + if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) { + if (errno != EINPROGRESS) { + wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s", + strerror(errno)); + goto fail; + } + + /* + * Continue connecting in the background; eloop will call us + * once the connection is ready (or failed). + */ + } + + if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE, + dpp_conn_tx_ready, conn, NULL) < 0) + goto fail; + conn->write_eloop = 1; + + hdr = wpabuf_head(auth->req_msg); + end = hdr + wpabuf_len(auth->req_msg); + hdr += 2; /* skip Category and Actiom */ + pos = hdr + DPP_HDR_LEN; + conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos); + if (!conn->msg_out) + goto fail; + /* Message will be sent in dpp_conn_tx_ready() */ + + /* TODO: eloop timeout to clear a connection if it does not complete + * properly */ + dl_list_add(&dpp->tcp_init, &conn->list); + return 0; +fail: + dpp_connection_free(conn); + return -1; +} + + +int dpp_controller_start(struct dpp_global *dpp, + struct dpp_controller_config *config) +{ + struct dpp_controller *ctrl; + int on = 1; + struct sockaddr_in sin; + int port; + + if (!dpp || dpp->controller) + return -1; + + ctrl = os_zalloc(sizeof(*ctrl)); + if (!ctrl) + return -1; + ctrl->global = dpp; + if (config->configurator_params) + ctrl->configurator_params = + os_strdup(config->configurator_params); + dl_list_init(&ctrl->conn); + ctrl->allowed_roles = config->allowed_roles; + ctrl->qr_mutual = config->qr_mutual; + ctrl->netrole = config->netrole; + ctrl->msg_ctx = config->msg_ctx; + ctrl->cb_ctx = config->cb_ctx; + ctrl->process_conf_obj = config->process_conf_obj; + + ctrl->sock = socket(AF_INET, SOCK_STREAM, 0); + if (ctrl->sock < 0) + goto fail; + + if (setsockopt(ctrl->sock, SOL_SOCKET, SO_REUSEADDR, + &on, sizeof(on)) < 0) { + wpa_printf(MSG_DEBUG, + "DPP: setsockopt(SO_REUSEADDR) failed: %s", + strerror(errno)); + /* try to continue anyway */ + } + + if (fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0) { + wpa_printf(MSG_INFO, "DPP: fnctl(O_NONBLOCK) failed: %s", + strerror(errno)); + goto fail; + } + + /* TODO: IPv6 */ + os_memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = INADDR_ANY; + port = config->tcp_port ? config->tcp_port : DPP_TCP_PORT; + sin.sin_port = htons(port); + if (bind(ctrl->sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + wpa_printf(MSG_INFO, + "DPP: Failed to bind Controller TCP port: %s", + strerror(errno)); + goto fail; + } + if (listen(ctrl->sock, 10 /* max backlog */) < 0 || + fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0 || + eloop_register_sock(ctrl->sock, EVENT_TYPE_READ, + dpp_controller_tcp_cb, ctrl, NULL)) + goto fail; + + dpp->controller = ctrl; + wpa_printf(MSG_DEBUG, "DPP: Controller started on TCP port %d", port); + return 0; +fail: + dpp_controller_free(ctrl); + return -1; +} + + +void dpp_controller_stop(struct dpp_global *dpp) +{ + if (dpp) { + dpp_controller_free(dpp->controller); + dpp->controller = NULL; + } +} + + +static bool dpp_tcp_peer_id_match(struct dpp_authentication *auth, + unsigned int id) +{ + return auth && + ((auth->peer_bi && auth->peer_bi->id == id) || + (auth->tmp_peer_bi && auth->tmp_peer_bi->id == id)); +} + + +static struct dpp_authentication * dpp_tcp_get_auth(struct dpp_global *dpp, + unsigned int id) +{ + struct dpp_connection *conn; + + dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) { + if (dpp_tcp_peer_id_match(conn->auth, id)) + return conn->auth; + } + + return NULL; +} + + +struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp, + unsigned int id) +{ + struct dpp_controller *ctrl = dpp->controller; + struct dpp_connection *conn; + + if (!ctrl) + return dpp_tcp_get_auth(dpp, id); + + dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) { + if (dpp_tcp_peer_id_match(conn->auth, id)) + return conn->auth; + } + + return dpp_tcp_get_auth(dpp, id); +} + + +void dpp_controller_new_qr_code(struct dpp_global *dpp, + struct dpp_bootstrap_info *bi) +{ + struct dpp_controller *ctrl = dpp->controller; + struct dpp_connection *conn; + + if (!ctrl) + return; + + dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) { + struct dpp_authentication *auth = conn->auth; + + if (!auth->response_pending || + dpp_notify_new_qr_code(auth, bi) != 1) + continue; + wpa_printf(MSG_DEBUG, + "DPP: Sending out pending authentication response"); + dpp_tcp_send_msg(conn, conn->auth->resp_msg); + } +} + + +void dpp_tcp_init_flush(struct dpp_global *dpp) +{ + struct dpp_connection *conn, *tmp; + + dl_list_for_each_safe(conn, tmp, &dpp->tcp_init, struct dpp_connection, + list) + dpp_connection_remove(conn); +} + + +static void dpp_relay_controller_free(struct dpp_relay_controller *ctrl) +{ + struct dpp_connection *conn, *tmp; + + dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection, + list) + dpp_connection_remove(conn); + os_free(ctrl); +} + + +void dpp_relay_flush_controllers(struct dpp_global *dpp) +{ + struct dpp_relay_controller *ctrl, *tmp; + + if (!dpp) + return; + + dl_list_for_each_safe(ctrl, tmp, &dpp->controllers, + struct dpp_relay_controller, list) { + dl_list_del(&ctrl->list); + dpp_relay_controller_free(ctrl); + } +} + +#endif /* CONFIG_DPP2 */ diff --git a/src/common/gas_server.c b/src/common/gas_server.c index ca46758ce..c000aeb60 100644 --- a/src/common/gas_server.c +++ b/src/common/gas_server.c @@ -1,6 +1,7 @@ /* * Generic advertisement service (GAS) server * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2020, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -23,8 +24,9 @@ struct gas_server_handler { struct dl_list list; u8 adv_proto_id[MAX_ADV_PROTO_ID_LEN]; u8 adv_proto_id_len; - struct wpabuf * (*req_cb)(void *ctx, const u8 *sa, - const u8 *query, size_t query_len); + struct wpabuf * (*req_cb)(void *ctx, void *resp_ctx, const u8 *sa, + const u8 *query, size_t query_len, + u16 *comeback_delay); void (*status_cb)(void *ctx, struct wpabuf *resp, int ok); void *ctx; struct gas_server *gas; @@ -39,6 +41,7 @@ struct gas_server_response { u8 dst[ETH_ALEN]; u8 dialog_token; struct gas_server_handler *handler; + u16 comeback_delay; }; struct gas_server { @@ -61,7 +64,8 @@ static void gas_server_response_timeout(void *eloop_ctx, void *user_ctx) response, MAC2STR(response->dst), response->dialog_token, response->freq, response->frag_id, (unsigned long) response->offset, - (unsigned long) wpabuf_len(response->resp)); + (unsigned long) (response->resp ? + wpabuf_len(response->resp) : 0)); response->handler->status_cb(response->handler->ctx, response->resp, 0); response->resp = NULL; @@ -83,30 +87,29 @@ static void gas_server_free_response(struct gas_server_response *response) static void gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler, + struct gas_server_response *response, const u8 *da, int freq, u8 dialog_token, - struct wpabuf *query_resp) + struct wpabuf *query_resp, u16 comeback_delay) { size_t max_len = (freq > 56160) ? 928 : 1400; size_t hdr_len = 24 + 2 + 5 + 3 + handler->adv_proto_id_len + 2; size_t resp_frag_len; struct wpabuf *resp; - u16 comeback_delay; - struct gas_server_response *response; - if (!query_resp) - return; - - response = os_zalloc(sizeof(*response)); - if (!response) { - wpabuf_free(query_resp); + if (comeback_delay == 0 && !query_resp) { + gas_server_free_response(response); return; } - wpa_printf(MSG_DEBUG, "DPP: Allocated GAS response @%p", response); + response->freq = freq; response->handler = handler; os_memcpy(response->dst, da, ETH_ALEN); response->dialog_token = dialog_token; - if (hdr_len + wpabuf_len(query_resp) > max_len) { + if (comeback_delay) { + /* Need more time to prepare the response */ + resp_frag_len = 0; + response->comeback_delay = comeback_delay; + } else if (hdr_len + wpabuf_len(query_resp) > max_len) { /* Need to use comeback to initiate fragmentation */ comeback_delay = 1; resp_frag_len = 0; @@ -135,10 +138,12 @@ gas_server_send_resp(struct gas_server *gas, struct gas_server_handler *handler, /* Query Response Length */ wpabuf_put_le16(resp, resp_frag_len); - if (!comeback_delay) + if (!comeback_delay && query_resp) wpabuf_put_buf(resp, query_resp); - if (comeback_delay) { + if (comeback_delay && !query_resp) { + wpa_printf(MSG_DEBUG, "GAS: No response available yet"); + } else if (comeback_delay) { wpa_printf(MSG_DEBUG, "GAS: Need to fragment query response"); } else { @@ -165,6 +170,7 @@ gas_server_rx_initial_req(struct gas_server *gas, const u8 *da, const u8 *sa, u16 query_req_len; struct gas_server_handler *handler; struct wpabuf *resp; + struct gas_server_response *response; wpa_hexdump(MSG_MSGDUMP, "GAS: Received GAS Initial Request frame", data, len); @@ -210,8 +216,15 @@ gas_server_rx_initial_req(struct gas_server *gas, const u8 *da, const u8 *sa, pos, end - pos); } + response = os_zalloc(sizeof(*response)); + if (!response) + return -1; + + wpa_printf(MSG_DEBUG, "DPP: Allocated GAS response @%p", response); dl_list_for_each(handler, &gas->handlers, struct gas_server_handler, list) { + u16 comeback_delay = 0; + if (adv_proto_len < 1 + handler->adv_proto_id_len || os_memcmp(adv_proto + 1, handler->adv_proto_id, handler->adv_proto_id_len) != 0) @@ -219,17 +232,22 @@ gas_server_rx_initial_req(struct gas_server *gas, const u8 *da, const u8 *sa, wpa_printf(MSG_DEBUG, "GAS: Calling handler for the requested Advertisement Protocol ID"); - resp = handler->req_cb(handler->ctx, sa, query_req, - query_req_len); + resp = handler->req_cb(handler->ctx, response, sa, query_req, + query_req_len, &comeback_delay); wpa_hexdump_buf(MSG_MSGDUMP, "GAS: Response from the handler", resp); - gas_server_send_resp(gas, handler, sa, freq, dialog_token, - resp); + if (comeback_delay) + wpa_printf(MSG_DEBUG, + "GAS: Handler requested comeback delay: %u TU", + comeback_delay); + gas_server_send_resp(gas, handler, response, sa, freq, + dialog_token, resp, comeback_delay); return 0; } wpa_printf(MSG_DEBUG, "GAS: No registered handler for the requested Advertisement Protocol ID"); + gas_server_free_response(response); return -1; } @@ -243,6 +261,31 @@ gas_server_handle_rx_comeback_req(struct gas_server_response *response) size_t hdr_len = 24 + 2 + 6 + 3 + handler->adv_proto_id_len + 2; size_t remaining, resp_frag_len; struct wpabuf *resp; + unsigned int wait_time = 0; + + if (!response->resp) { + resp = gas_build_comeback_resp(response->dialog_token, + WLAN_STATUS_SUCCESS, 0, 0, + response->comeback_delay, + handler->adv_proto_id_len); + if (!resp) { + dl_list_del(&response->list); + gas_server_free_response(response); + return; + } + + /* Advertisement Protocol element */ + wpabuf_put_u8(resp, WLAN_EID_ADV_PROTO); + wpabuf_put_u8(resp, 1 + handler->adv_proto_id_len); /* Length */ + wpabuf_put_u8(resp, 0x7f); + /* Advertisement Protocol ID */ + wpabuf_put_data(resp, handler->adv_proto_id, + handler->adv_proto_id_len); + + /* Query Response Length */ + wpabuf_put_le16(resp, 0); + goto send_resp; + } remaining = wpabuf_len(response->resp) - response->offset; if (hdr_len + remaining > max_len) @@ -279,8 +322,11 @@ gas_server_handle_rx_comeback_req(struct gas_server_response *response) response->offset += resp_frag_len; - gas->tx(gas->ctx, response->freq, response->dst, resp, - remaining > resp_frag_len ? 2000 : 0); + if (remaining > resp_frag_len) + wait_time = 2000; + +send_resp: + gas->tx(gas->ctx, response->freq, response->dst, resp, wait_time); wpabuf_free(resp); } @@ -359,12 +405,19 @@ int gas_server_rx(struct gas_server *gas, const u8 *da, const u8 *sa, static void gas_server_handle_tx_status(struct gas_server_response *response, int ack) { - if (ack && response->offset < wpabuf_len(response->resp)) { + if (ack && response->resp && + response->offset < wpabuf_len(response->resp)) { wpa_printf(MSG_DEBUG, "GAS: More fragments remaining - keep pending entry"); return; } + if (ack && !response->resp && response->comeback_delay) { + wpa_printf(MSG_DEBUG, + "GAS: Waiting for response - keep pending entry"); + return; + } + if (!ack) wpa_printf(MSG_DEBUG, "GAS: No ACK received - drop pending entry"); @@ -415,6 +468,27 @@ void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data, } +int gas_server_set_resp(struct gas_server *gas, void *resp_ctx, + struct wpabuf *resp) +{ + struct gas_server_response *tmp, *response = NULL; + + dl_list_for_each(tmp, &gas->responses, struct gas_server_response, + list) { + if (tmp == resp_ctx) { + response = tmp; + break; + } + } + + if (!response || response->resp) + return -1; + + response->resp = resp; + return 0; +} + + struct gas_server * gas_server_init(void *ctx, void (*tx)(void *ctx, int freq, const u8 *da, @@ -461,8 +535,9 @@ void gas_server_deinit(struct gas_server *gas) int gas_server_register(struct gas_server *gas, const u8 *adv_proto_id, u8 adv_proto_id_len, struct wpabuf * - (*req_cb)(void *ctx, const u8 *sa, - const u8 *query, size_t query_len), + (*req_cb)(void *ctx, void *resp_ctx, const u8 *sa, + const u8 *query, size_t query_len, + u16 *comeback_delay), void (*status_cb)(void *ctx, struct wpabuf *resp, int ok), void *ctx) diff --git a/src/common/gas_server.h b/src/common/gas_server.h index 299f529f7..2611ddedc 100644 --- a/src/common/gas_server.h +++ b/src/common/gas_server.h @@ -1,6 +1,7 @@ /* * Generic advertisement service (GAS) server * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2020, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -22,8 +23,9 @@ void gas_server_deinit(struct gas_server *gas); int gas_server_register(struct gas_server *gas, const u8 *adv_proto_id, u8 adv_proto_id_len, struct wpabuf * - (*req_cb)(void *ctx, const u8 *sa, - const u8 *query, size_t query_len), + (*req_cb)(void *ctx, void *resp_ctx, const u8 *sa, + const u8 *query, size_t query_len, + u16 *comeback_delay), void (*status_cb)(void *ctx, struct wpabuf *resp, int ok), void *ctx); @@ -32,6 +34,8 @@ int gas_server_rx(struct gas_server *gas, const u8 *da, const u8 *sa, int freq); void gas_server_tx_status(struct gas_server *gas, const u8 *dst, const u8 *data, size_t data_len, int ack); +int gas_server_set_resp(struct gas_server *gas, void *resp_ctx, + struct wpabuf *resp); #else /* CONFIG_GAS_SERVER */ diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c index 4f1c4935a..511e68f9e 100644 --- a/src/common/hw_features_common.c +++ b/src/common/hw_features_common.c @@ -415,7 +415,7 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, return -1; } - if (center_idx_to_bw_6ghz(channel) != 0) { + if (center_idx_to_bw_6ghz(channel) < 0) { wpa_printf(MSG_ERROR, "Invalid control channel for 6 GHz band"); return -1; @@ -475,13 +475,46 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, return 0; } - if (data->vht_enabled) switch (oper_chwidth) { + if (data->he_enabled) switch (oper_chwidth) { case CHANWIDTH_USE_HT: - if (center_segment1 || - (center_segment0 != 0 && - 5000 + center_segment0 * 5 != data->center_freq1 && - 2407 + center_segment0 * 5 != data->center_freq1)) + if (mode == HOSTAPD_MODE_IEEE80211G && sec_channel_offset) { + if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & + HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G)) { + wpa_printf(MSG_ERROR, + "40 MHz channel width is not supported in 2.4 GHz"); + return -1; + } + break; + } + /* fall through */ + case CHANWIDTH_80MHZ: + if (mode == HOSTAPD_MODE_IEEE80211A) { + if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & + HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G)) { + wpa_printf(MSG_ERROR, + "40/80 MHz channel width is not supported in 5/6 GHz"); + return -1; + } + } + break; + case CHANWIDTH_80P80MHZ: + if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & + HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G)) { + wpa_printf(MSG_ERROR, + "80+80 MHz channel width is not supported in 5/6 GHz"); return -1; + } + break; + case CHANWIDTH_160MHZ: + if (!(he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & + HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)) { + wpa_printf(MSG_ERROR, + "160 MHz channel width is not supported in 5 / 6GHz"); + return -1; + } + break; + } else if (data->vht_enabled) switch (oper_chwidth) { + case CHANWIDTH_USE_HT: break; case CHANWIDTH_80P80MHZ: if (!(vht_caps & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) { @@ -489,9 +522,38 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, "80+80 channel width is not supported!"); return -1; } - if (center_segment1 == center_segment0 + 4 || - center_segment1 == center_segment0 - 4) + /* fall through */ + case CHANWIDTH_80MHZ: + break; + case CHANWIDTH_160MHZ: + if (!(vht_caps & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | + VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) { + wpa_printf(MSG_ERROR, + "160 MHz channel width is not supported!"); return -1; + } + break; + } + + if (data->he_enabled || data->vht_enabled) switch (oper_chwidth) { + case CHANWIDTH_USE_HT: + if (center_segment1 || + (center_segment0 != 0 && + 5000 + center_segment0 * 5 != data->center_freq1 && + 2407 + center_segment0 * 5 != data->center_freq1)) { + wpa_printf(MSG_ERROR, + "20/40 MHz: center segment 0 (=%d) and center freq 1 (=%d) not in sync", + center_segment0, data->center_freq1); + return -1; + } + break; + case CHANWIDTH_80P80MHZ: + if (center_segment1 == center_segment0 + 4 || + center_segment1 == center_segment0 - 4) { + wpa_printf(MSG_ERROR, + "80+80 MHz: center segment 1 only 20 MHz apart"); + return -1; + } data->center_freq2 = 5000 + center_segment1 * 5; /* fall through */ case CHANWIDTH_80MHZ: @@ -500,8 +562,11 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, center_segment1) || (oper_chwidth == CHANWIDTH_80P80MHZ && !center_segment1) || - !sec_channel_offset) + !sec_channel_offset) { + wpa_printf(MSG_ERROR, + "80/80+80 MHz: center segment 1 wrong or no second channel offset"); return -1; + } if (!center_segment0) { if (channel <= 48) center_segment0 = 42; @@ -527,22 +592,25 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, center_segment0 == channel - 2 || center_segment0 == channel - 6) data->center_freq1 = 5000 + center_segment0 * 5; - else + else { + wpa_printf(MSG_ERROR, + "Wrong coupling between HT and VHT/HE channel setting"); return -1; + } } break; case CHANWIDTH_160MHZ: data->bandwidth = 160; - if (!(vht_caps & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | - VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) { + if (center_segment1) { wpa_printf(MSG_ERROR, - "160MHZ channel width is not supported!"); + "160 MHz: center segment 1 should not be set"); return -1; } - if (center_segment1) - return -1; - if (!sec_channel_offset) + if (!sec_channel_offset) { + wpa_printf(MSG_ERROR, + "160 MHz: second channel offset not set"); return -1; + } /* * Note: HT/VHT config and params are coupled. Check if * HT40 channel band is in VHT160 channel band configuration. @@ -556,8 +624,11 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data, center_segment0 == channel - 10 || center_segment0 == channel - 14) data->center_freq1 = 5000 + center_segment0 * 5; - else + else { + wpa_printf(MSG_ERROR, + "160 MHz: HT40 channel band is not in 160 MHz band"); return -1; + } break; } diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c index 36005d75f..c90e04ce7 100644 --- a/src/common/ieee802_11_common.c +++ b/src/common/ieee802_11_common.c @@ -130,6 +130,16 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, elems->multi_ap = pos; elems->multi_ap_len = elen; break; + case OWE_OUI_TYPE: + /* OWE Transition Mode element */ + break; + case DPP_CC_OUI_TYPE: + /* DPP Configurator Connectivity element */ + break; + case SAE_PK_OUI_TYPE: + elems->sae_pk = pos + 4; + elems->sae_pk_len = elen - 4; + break; default: wpa_printf(MSG_MSGDUMP, "Unknown WFA " "information element ignored " @@ -206,6 +216,8 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen, ext_id = *pos++; elen--; + elems->frag_ies.last_eid_ext = 0; + switch (ext_id) { case WLAN_EID_EXT_ASSOC_DELAY_INFO: if (elen != 1) @@ -245,9 +257,9 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen, elems->key_delivery = pos; elems->key_delivery_len = elen; break; - case WLAN_EID_EXT_FILS_WRAPPED_DATA: - elems->fils_wrapped_data = pos; - elems->fils_wrapped_data_len = elen; + case WLAN_EID_EXT_WRAPPED_DATA: + elems->wrapped_data = pos; + elems->wrapped_data_len = elen; break; case WLAN_EID_EXT_FILS_PUBLIC_KEY: if (elen < 1) @@ -286,6 +298,11 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen, elems->short_ssid_list = pos; elems->short_ssid_list_len = elen; break; + case WLAN_EID_EXT_HE_6GHZ_BAND_CAP: + if (elen < sizeof(struct ieee80211_he_6ghz_band_cap)) + break; + elems->he_6ghz_band_cap = pos; + break; default: if (show_errors) { wpa_printf(MSG_MSGDUMP, @@ -295,10 +312,39 @@ static int ieee802_11_parse_extension(const u8 *pos, size_t elen, return -1; } + if (elen == 254) + elems->frag_ies.last_eid_ext = ext_id; + return 0; } +static void ieee802_11_parse_fragment(struct frag_ies_info *frag_ies, + const u8 *pos, u8 elen) +{ + if (frag_ies->n_frags >= MAX_NUM_FRAG_IES_SUPPORTED) { + wpa_printf(MSG_MSGDUMP, "Too many element fragments - skip"); + return; + } + + /* + * Note: while EID == 0 is a valid ID (SSID IE), it should not be + * fragmented. + */ + if (!frag_ies->last_eid) { + wpa_printf(MSG_MSGDUMP, + "Fragment without a valid last element - skip"); + return; + } + + frag_ies->frags[frag_ies->n_frags].ie = pos; + frag_ies->frags[frag_ies->n_frags].ie_len = elen; + frag_ies->frags[frag_ies->n_frags].eid = frag_ies->last_eid; + frag_ies->frags[frag_ies->n_frags].eid_ext = frag_ies->last_eid_ext; + frag_ies->n_frags++; +} + + /** * ieee802_11_parse_elems - Parse information elements in management frames * @start: Pointer to the start of IEs @@ -331,6 +377,11 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, elen); break; } + if (elems->ssid) { + wpa_printf(MSG_MSGDUMP, + "Ignored duplicated SSID element"); + break; + } elems->ssid = pos; elems->ssid_len = elen; break; @@ -515,8 +566,13 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, elems->dils = pos; elems->dils_len = elen; break; + case WLAN_EID_S1G_CAPABILITIES: + if (elen < 15) + break; + elems->s1g_capab = pos; + break; case WLAN_EID_FRAGMENT: - /* TODO */ + ieee802_11_parse_fragment(&elems->frag_ies, pos, elen); break; case WLAN_EID_EXTENSION: if (ieee802_11_parse_extension(pos, elen, elems, @@ -532,6 +588,12 @@ ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, id, elen); break; } + + if (id != WLAN_EID_FRAGMENT && elen == 255) + elems->frag_ies.last_eid = id; + + if (id == WLAN_EID_EXTENSION && !elems->frag_ies.last_eid_ext) + elems->frag_ies.last_eid = 0; } if (!for_each_element_completed(elem, start, len)) { @@ -710,6 +772,98 @@ int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[], } +/* convert floats with one decimal place to value*10 int, i.e., + * "1.5" will return 15 + */ +static int hostapd_config_read_int10(const char *value) +{ + int i, d; + char *pos; + + i = atoi(value); + pos = os_strchr(value, '.'); + d = 0; + if (pos) { + pos++; + if (*pos >= '0' && *pos <= '9') + d = *pos - '0'; + } + + return i * 10 + d; +} + + +static int valid_cw(int cw) +{ + return (cw == 1 || cw == 3 || cw == 7 || cw == 15 || cw == 31 || + cw == 63 || cw == 127 || cw == 255 || cw == 511 || cw == 1023 || + cw == 2047 || cw == 4095 || cw == 8191 || cw == 16383 || + cw == 32767); +} + + +int hostapd_config_tx_queue(struct hostapd_tx_queue_params tx_queue[], + const char *name, const char *val) +{ + int num; + const char *pos; + struct hostapd_tx_queue_params *queue; + + /* skip 'tx_queue_' prefix */ + pos = name + 9; + if (os_strncmp(pos, "data", 4) == 0 && + pos[4] >= '0' && pos[4] <= '9' && pos[5] == '_') { + num = pos[4] - '0'; + pos += 6; + } else if (os_strncmp(pos, "after_beacon_", 13) == 0 || + os_strncmp(pos, "beacon_", 7) == 0) { + wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); + return 0; + } else { + wpa_printf(MSG_ERROR, "Unknown tx_queue name '%s'", pos); + return -1; + } + + if (num >= NUM_TX_QUEUES) { + /* for backwards compatibility, do not trigger failure */ + wpa_printf(MSG_INFO, "DEPRECATED: '%s' not used", name); + return 0; + } + + queue = &tx_queue[num]; + + if (os_strcmp(pos, "aifs") == 0) { + queue->aifs = atoi(val); + if (queue->aifs < 0 || queue->aifs > 255) { + wpa_printf(MSG_ERROR, "Invalid AIFS value %d", + queue->aifs); + return -1; + } + } else if (os_strcmp(pos, "cwmin") == 0) { + queue->cwmin = atoi(val); + if (!valid_cw(queue->cwmin)) { + wpa_printf(MSG_ERROR, "Invalid cwMin value %d", + queue->cwmin); + return -1; + } + } else if (os_strcmp(pos, "cwmax") == 0) { + queue->cwmax = atoi(val); + if (!valid_cw(queue->cwmax)) { + wpa_printf(MSG_ERROR, "Invalid cwMax value %d", + queue->cwmax); + return -1; + } + } else if (os_strcmp(pos, "burst") == 0) { + queue->burst = hostapd_config_read_int10(val); + } else { + wpa_printf(MSG_ERROR, "Unknown queue field '%s'", pos); + return -1; + } + + return 0; +} + + enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel) { u8 op_class; @@ -880,16 +1034,35 @@ enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, return HOSTAPD_MODE_IEEE80211A; } - if (freq > 5940 && freq <= 7105) { - int bw; - u8 idx = (freq - 5940) / 5; - - bw = center_idx_to_bw_6ghz(idx); - if (bw < 0) + if (freq > 5950 && freq <= 7115) { + if ((freq - 5950) % 5) return NUM_HOSTAPD_MODES; - *channel = idx; - *op_class = 131 + bw; + switch (chanwidth) { + case CHANWIDTH_80MHZ: + *op_class = 133; + break; + case CHANWIDTH_160MHZ: + *op_class = 134; + break; + case CHANWIDTH_80P80MHZ: + *op_class = 135; + break; + default: + if (sec_channel) + *op_class = 132; + else + *op_class = 131; + break; + } + + *channel = (freq - 5950) / 5; + return HOSTAPD_MODE_IEEE80211A; + } + + if (freq == 5935) { + *op_class = 136; + *channel = (freq - 5925) / 5; return HOSTAPD_MODE_IEEE80211A; } @@ -1269,7 +1442,11 @@ static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan) case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */ if (chan < 1 || chan > 233) return -1; - return 5940 + chan * 5; + return 5950 + chan * 5; + case 136: /* UHB channels, 20 MHz: 2 */ + if (chan == 2) + return 5935; + return -1; case 180: /* 60 GHz band, channels 1..8 */ if (chan < 1 || chan > 8) return -1; @@ -1613,7 +1790,9 @@ const char * status2str(u16 status) S2S(FILS_AUTHENTICATION_FAILURE) S2S(UNKNOWN_AUTHENTICATION_SERVER) S2S(UNKNOWN_PASSWORD_IDENTIFIER) + S2S(DENIED_HE_NOT_SUPPORTED) S2S(SAE_HASH_TO_ELEMENT) + S2S(SAE_PK) } return "UNKNOWN"; #undef S2S @@ -1711,8 +1890,12 @@ const struct oper_class_map global_op_class[] = { */ { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211A, 129, 50, 114, 16, BW160, P2P_SUPP }, - { HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP }, - { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 131, 1, 233, 4, BW20, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 132, 1, 233, 8, BW40, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 133, 1, 233, 16, BW80, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 134, 1, 233, 32, BW160, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 135, 1, 233, 16, BW80P80, NO_P2P_SUPP }, + { HOSTAPD_MODE_IEEE80211A, 136, 2, 2, 4, BW20, NO_P2P_SUPP }, /* * IEEE Std 802.11ad-2012 and P802.ay/D5.0 60 GHz operating classes. @@ -1723,6 +1906,12 @@ const struct oper_class_map global_op_class[] = { { HOSTAPD_MODE_IEEE80211AD, 181, 9, 13, 1, BW4320, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211AD, 182, 17, 20, 1, BW6480, P2P_SUPP }, { HOSTAPD_MODE_IEEE80211AD, 183, 25, 27, 1, BW8640, P2P_SUPP }, + + /* Keep the operating class 130 as the last entry as a workaround for + * the OneHundredAndThirty Delimiter value used in the Supported + * Operating Classes element to indicate the end of the Operating + * Classes field. */ + { HOSTAPD_MODE_IEEE80211A, 130, 36, 161, 4, BW80P80, P2P_SUPP }, { -1, 0, 0, 0, 0, BW20, NO_P2P_SUPP } }; @@ -2020,6 +2209,7 @@ int oper_class_bw_to_int(const struct oper_class_map *map) switch (map->bw) { case BW20: return 20; + case BW40: case BW40PLUS: case BW40MINUS: return 40; @@ -2055,41 +2245,44 @@ int center_idx_to_bw_6ghz(u8 idx) } -int is_6ghz_freq(int freq) +bool is_6ghz_freq(int freq) { - if (freq < 5940 || freq > 7105) - return 0; + if (freq < 5935 || freq > 7115) + return false; - if (center_idx_to_bw_6ghz((freq - 5940) / 5) < 0) - return 0; + if (freq == 5935) + return true; - return 1; + if (center_idx_to_bw_6ghz((freq - 5950) / 5) < 0) + return false; + + return true; } -int is_6ghz_op_class(u8 op_class) +bool is_6ghz_op_class(u8 op_class) { - return op_class >= 131 && op_class <= 135; + return op_class >= 131 && op_class <= 136; } -int is_6ghz_psc_frequency(int freq) +bool is_6ghz_psc_frequency(int freq) { int i; - if (!is_6ghz_freq(freq)) - return 0; - if ((((freq - 5940) / 5) & 0x3) != 0x1) - return 0; + if (!is_6ghz_freq(freq) || freq == 5935) + return false; + if ((((freq - 5950) / 5) & 0x3) != 0x1) + return false; - i = (freq - 5940 + 55) % 80; + i = (freq - 5950 + 55) % 80; if (i == 0) - i = (freq - 5940 + 55) / 80; + i = (freq - 5950 + 55) / 80; if (i >= 1 && i <= 15) - return 1; + return true; - return 0; + return false; } @@ -2320,6 +2513,8 @@ int op_class_to_bandwidth(u8 op_class) case 134: /* UHB channels, 160 MHz: 15, 47, 79.. */ case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */ return 160; + case 136: /* UHB channels, 20 MHz: 2 */ + return 20; case 180: /* 60 GHz band, channels 1..8 */ return 2160; case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */ @@ -2380,6 +2575,8 @@ int op_class_to_ch_width(u8 op_class) return CHANWIDTH_160MHZ; case 135: /* UHB channels, 80+80 MHz: 7, 23, 39.. */ return CHANWIDTH_80P80MHZ; + case 136: /* UHB channels, 20 MHz: 2 */ + return CHANWIDTH_USE_HT; case 180: /* 60 GHz band, channels 1..8 */ return CHANWIDTH_2160MHZ; case 181: /* 60 GHz band, EDMG CB2, channels 9..15 */ @@ -2391,3 +2588,78 @@ int op_class_to_ch_width(u8 op_class) } return CHANWIDTH_USE_HT; } + + +struct wpabuf * ieee802_11_defrag_data(struct ieee802_11_elems *elems, + u8 eid, u8 eid_ext, + const u8 *data, u8 len) +{ + struct frag_ies_info *frag_ies = &elems->frag_ies; + struct wpabuf *buf; + unsigned int i; + + if (!elems || !data || !len) + return NULL; + + buf = wpabuf_alloc_copy(data, len); + if (!buf) + return NULL; + + for (i = 0; i < frag_ies->n_frags; i++) { + int ret; + + if (frag_ies->frags[i].eid != eid || + frag_ies->frags[i].eid_ext != eid_ext) + continue; + + ret = wpabuf_resize(&buf, frag_ies->frags[i].ie_len); + if (ret < 0) { + wpabuf_free(buf); + return NULL; + } + + /* Copy only the fragment data (without the EID and length) */ + wpabuf_put_data(buf, frag_ies->frags[i].ie, + frag_ies->frags[i].ie_len); + } + + return buf; +} + + +struct wpabuf * ieee802_11_defrag(struct ieee802_11_elems *elems, + u8 eid, u8 eid_ext) +{ + const u8 *data; + u8 len; + + /* + * TODO: Defragmentation mechanism can be supported for all IEs. For now + * handle only those that are used (or use ieee802_11_defrag_data()). + */ + switch (eid) { + case WLAN_EID_EXTENSION: + switch (eid_ext) { + case WLAN_EID_EXT_FILS_HLP_CONTAINER: + data = elems->fils_hlp; + len = elems->fils_hlp_len; + break; + case WLAN_EID_EXT_WRAPPED_DATA: + data = elems->wrapped_data; + len = elems->wrapped_data_len; + break; + default: + wpa_printf(MSG_DEBUG, + "Defragmentation not supported. eid_ext=%u", + eid_ext); + return NULL; + } + break; + default: + wpa_printf(MSG_DEBUG, + "Defragmentation not supported. eid=%u", eid); + return NULL; + } + + return ieee802_11_defrag_data(elems, eid, eid_ext, data, len); +} diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h index d13316969..6bbe3b7a3 100644 --- a/src/common/ieee802_11_common.h +++ b/src/common/ieee802_11_common.h @@ -21,6 +21,7 @@ struct element { struct hostapd_hw_modes; #define MAX_NOF_MB_IES_SUPPORTED 5 +#define MAX_NUM_FRAG_IES_SUPPORTED 3 struct mb_ies_info { struct { @@ -30,6 +31,21 @@ struct mb_ies_info { u8 nof_ies; }; +struct frag_ies_info { + struct { + u8 eid; + u8 eid_ext; + const u8 *ie; + u8 ie_len; + } frags[MAX_NUM_FRAG_IES_SUPPORTED]; + + u8 n_frags; + + /* the last parsed element ID and element extension ID */ + u8 last_eid; + u8 last_eid_ext; +}; + /* Parsed Information Elements */ struct ieee802_11_elems { const u8 *ssid; @@ -85,7 +101,7 @@ struct ieee802_11_elems { const u8 *fils_hlp; const u8 *fils_ip_addr_assign; const u8 *key_delivery; - const u8 *fils_wrapped_data; + const u8 *wrapped_data; const u8 *fils_pk; const u8 *fils_nonce; const u8 *owe_dh; @@ -97,6 +113,9 @@ struct ieee802_11_elems { const u8 *he_capabilities; const u8 *he_operation; const u8 *short_ssid_list; + const u8 *he_6ghz_band_cap; + const u8 *sae_pk; + const u8 *s1g_capab; u8 ssid_len; u8 supp_rates_len; @@ -138,7 +157,7 @@ struct ieee802_11_elems { u8 fils_hlp_len; u8 fils_ip_addr_assign_len; u8 key_delivery_len; - u8 fils_wrapped_data_len; + u8 wrapped_data_len; u8 fils_pk_len; u8 owe_dh_len; u8 power_capab_len; @@ -149,8 +168,10 @@ struct ieee802_11_elems { u8 he_capabilities_len; u8 he_operation_len; u8 short_ssid_list_len; + u8 sae_pk_len; struct mb_ies_info mb_ies; + struct frag_ies_info frag_ies; }; typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; @@ -174,6 +195,18 @@ struct hostapd_wmm_ac_params { int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[], const char *name, const char *val); + +struct hostapd_tx_queue_params { + int aifs; + int cwmin; + int cwmax; + int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */ +}; + +#define NUM_TX_QUEUES 4 + +int hostapd_config_tx_queue(struct hostapd_tx_queue_params queue[], + const char *name, const char *val); enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel); int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan); enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, @@ -200,8 +233,8 @@ struct oper_class_map { u8 min_chan; u8 max_chan; u8 inc; - enum { BW20, BW40PLUS, BW40MINUS, BW80, BW2160, BW160, BW80P80, BW4320, - BW6480, BW8640} bw; + enum { BW20, BW40PLUS, BW40MINUS, BW40, BW80, BW2160, BW160, BW80P80, + BW4320, BW6480, BW8640} bw; enum { P2P_SUPP, NO_P2P_SUPP } p2p; }; @@ -226,9 +259,9 @@ u8 country_to_global_op_class(const char *country, u8 op_class); const struct oper_class_map * get_oper_class(const char *country, u8 op_class); int oper_class_bw_to_int(const struct oper_class_map *map); int center_idx_to_bw_6ghz(u8 idx); -int is_6ghz_freq(int freq); -int is_6ghz_op_class(u8 op_class); -int is_6ghz_psc_frequency(int freq); +bool is_6ghz_freq(int freq); +bool is_6ghz_op_class(u8 op_class); +bool is_6ghz_psc_frequency(int freq); int ieee802_11_parse_candidate_list(const char *pos, u8 *nei_rep, size_t nei_rep_len); @@ -293,4 +326,10 @@ void hostapd_encode_edmg_chan(int edmg_enable, u8 edmg_channel, int ieee802_edmg_is_allowed(struct ieee80211_edmg_config allowed, struct ieee80211_edmg_config requested); +struct wpabuf * ieee802_11_defrag_data(struct ieee802_11_elems *elems, + u8 eid, u8 eid_ext, + const u8 *data, u8 len); +struct wpabuf * ieee802_11_defrag(struct ieee802_11_elems *elems, + u8 eid, u8 eid_ext); + #endif /* IEEE802_11_COMMON_H */ diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index ad4ef1a33..9518a7afe 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -204,7 +204,9 @@ #define WLAN_STATUS_FILS_AUTHENTICATION_FAILURE 112 #define WLAN_STATUS_UNKNOWN_AUTHENTICATION_SERVER 113 #define WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER 123 +#define WLAN_STATUS_DENIED_HE_NOT_SUPPORTED 124 #define WLAN_STATUS_SAE_HASH_TO_ELEMENT 126 +#define WLAN_STATUS_SAE_PK 127 /* Reason codes (IEEE Std 802.11-2016, 9.4.1.7, Table 9-45) */ #define WLAN_REASON_UNSPECIFIED 1 @@ -441,7 +443,10 @@ #define WLAN_EID_DEVICE_LOCATION 204 #define WLAN_EID_WHITE_SPACE_MAP 205 #define WLAN_EID_FTM_PARAMETERS 206 +#define WLAN_EID_S1G_BCN_COMPAT 213 +#define WLAN_EID_S1G_CAPABILITIES 217 #define WLAN_EID_VENDOR_SPECIFIC 221 +#define WLAN_EID_S1G_OPERATION 232 #define WLAN_EID_CAG_NUMBER 237 #define WLAN_EID_AP_CSN 239 #define WLAN_EID_FILS_INDICATION 240 @@ -458,7 +463,7 @@ #define WLAN_EID_EXT_FILS_HLP_CONTAINER 5 #define WLAN_EID_EXT_FILS_IP_ADDR_ASSIGN 6 #define WLAN_EID_EXT_KEY_DELIVERY 7 -#define WLAN_EID_EXT_FILS_WRAPPED_DATA 8 +#define WLAN_EID_EXT_WRAPPED_DATA 8 #define WLAN_EID_EXT_FTM_SYNC_INFO 9 #define WLAN_EID_EXT_EXTENDED_REQUEST 10 #define WLAN_EID_EXT_ESTIMATED_SERVICE_PARAMS 11 @@ -473,8 +478,11 @@ #define WLAN_EID_EXT_SPATIAL_REUSE 39 #define WLAN_EID_EXT_OCV_OCI 54 #define WLAN_EID_EXT_SHORT_SSID_LIST 58 +#define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59 #define WLAN_EID_EXT_EDMG_CAPABILITIES 61 #define WLAN_EID_EXT_EDMG_OPERATION 62 +#define WLAN_EID_EXT_MSCS_DESCRIPTOR 88 +#define WLAN_EID_EXT_TCLAS_MASK 89 #define WLAN_EID_EXT_REJECTED_GROUPS 92 #define WLAN_EID_EXT_ANTI_CLOGGING_TOKEN 93 @@ -558,11 +566,15 @@ #define WLAN_EXT_CAPAB_COMPLETE_NON_TX_BSSID_PROFILE 80 #define WLAN_EXT_CAPAB_SAE_PW_ID 81 #define WLAN_EXT_CAPAB_SAE_PW_ID_EXCLUSIVELY 82 +#define WLAN_EXT_CAPAB_BEACON_PROTECTION 84 +#define WLAN_EXT_CAPAB_MSCS 85 +#define WLAN_EXT_CAPAB_SAE_PK_EXCLUSIVELY 88 /* Extended RSN Capabilities */ /* bits 0-3: Field length (n-1) */ #define WLAN_RSNX_CAPAB_PROTECTED_TWT 4 #define WLAN_RSNX_CAPAB_SAE_H2E 5 +#define WLAN_RSNX_CAPAB_SAE_PK 6 /* Action frame categories (IEEE Std 802.11-2016, 9.4.1.11, Table 9-76) */ #define WLAN_ACTION_SPECTRUM_MGMT 0 @@ -1315,6 +1327,10 @@ struct ieee80211_ampe_ie { #define OWE_IE_VENDOR_TYPE 0x506f9a1c #define OWE_OUI_TYPE 28 #define MULTI_AP_OUI_TYPE 0x1B +#define DPP_CC_IE_VENDOR_TYPE 0x506f9a1e +#define DPP_CC_OUI_TYPE 0x1e +#define SAE_PK_IE_VENDOR_TYPE 0x506f9a1f +#define SAE_PK_OUI_TYPE 0x1f #define MULTI_AP_SUB_ELEM_TYPE 0x06 #define MULTI_AP_TEAR_DOWN BIT(4) @@ -1874,7 +1890,15 @@ enum wnm_sleep_mode_response_status { /* WNM-Sleep Mode subelement IDs */ enum wnm_sleep_mode_subelement_id { WNM_SLEEP_SUBELEM_GTK = 0, - WNM_SLEEP_SUBELEM_IGTK = 1 + WNM_SLEEP_SUBELEM_IGTK = 1, + WNM_SLEEP_SUBELEM_BIGTK = 2, +}; + +/* WNM notification type (IEEE P802.11-REVmd/D3.0, Table 9-430) */ +enum wnm_notification_Type { + WNM_NOTIF_TYPE_FIRMWARE_UPDATE = 0, + WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE = 2, + WNM_NOTIF_TYPE_VENDOR_SPECIFIC = 221, }; /* Channel Switch modes (802.11h) */ @@ -2090,7 +2114,7 @@ enum phy_type { PHY_TYPE_VHT = 9, }; -/* IEEE P802.11-REVmc/D5.0, 9.4.2.37 - Neighbor Report element */ +/* IEEE P802.11-REVmd/D3.0, 9.4.2.36 - Neighbor Report element */ /* BSSID Information Field */ #define NEI_REP_BSSID_INFO_AP_NOT_REACH BIT(0) #define NEI_REP_BSSID_INFO_AP_UNKNOWN_REACH BIT(1) @@ -2107,6 +2131,7 @@ enum phy_type { #define NEI_REP_BSSID_INFO_HT BIT(11) #define NEI_REP_BSSID_INFO_VHT BIT(12) #define NEI_REP_BSSID_INFO_FTM BIT(13) +#define NEI_REP_BSSID_INFO_HE BIT(14) /* * IEEE P802.11-REVmc/D5.0 Table 9-152 - HT/VHT Operation Information @@ -2133,12 +2158,53 @@ struct ieee80211_he_operation { le32 he_oper_params; /* HE Operation Parameters[3] and * BSS Color Information[1] */ le16 he_mcs_nss_set; - u8 vht_op_info_chwidth; - u8 vht_op_info_chan_center_freq_seg0_idx; - u8 vht_op_info_chan_center_freq_seg1_idx; - /* Followed by conditional MaxBSSID Indicator subfield (u8) */ + /* Followed by conditional VHT Operation Information (3 octets), + * Max Co-Hosted BSSID Indicator subfield (1 octet), and/or 6 GHz + * Operation Information subfield (5 octets). */ } STRUCT_PACKED; +/* IEEE P802.11ax/D6.0, Figure 9-787k - 6 GHz Operation Information field */ +struct ieee80211_he_6ghz_oper_info { + u8 primary_chan; + u8 control; + u8 chan_center_freq_seg0; + u8 chan_center_freq_seg1; + u8 min_rate; +} STRUCT_PACKED; + +#define HE_6GHZ_OPER_INFO_CTRL_CHAN_WIDTH_MASK (BIT(0) | BIT(1)) +#define HE_6GHZ_OPER_INFO_CTRL_DUP_BEACON BIT(2) + +/* IEEE P802.11ax/D6.0, 9.4.2.261 HE 6 GHz Band Capabilities element */ +struct ieee80211_he_6ghz_band_cap { + /* Minimum MPDU Start Spacing B0..B2 + * Maximum A-MPDU Length Exponent B3..B5 + * Maximum MPDU Length B6..B7 */ + le16 capab; +} STRUCT_PACKED; + +#define HE_6GHZ_BAND_CAP_MIN_MPDU_START (BIT(0) | BIT(1) | BIT(2)) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_16K BIT(3) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_32K BIT(4) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_64K (BIT(3) | BIT(4)) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_128K BIT(5) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_256K (BIT(3) | BIT(5)) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_512K (BIT(4) | BIT(5)) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_1024K (BIT(3) | BIT(4) | BIT(5)) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_MASK (BIT(3) | BIT(4) | BIT(5)) +#define HE_6GHZ_BAND_CAP_MAX_AMPDU_LEN_EXP_SHIFT 3 +#define HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_7991 BIT(6) +#define HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_11454 BIT(7) +#define HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_MASK (BIT(6) | BIT(7)) +#define HE_6GHZ_BAND_CAP_MAX_MPDU_LEN_SHIFT 6 +#define HE_6GHZ_BAND_CAP_SMPS_MASK (BIT(9) | BIT(10)) +#define HE_6GHZ_BAND_CAP_SMPS_STATIC 0 +#define HE_6GHZ_BAND_CAP_SMPS_DYNAMIC BIT(9) +#define HE_6GHZ_BAND_CAP_SMPS_DISABLED (BIT(9) | BIT(10)) +#define HE_6GHZ_BAND_CAP_RD_RESPONDER BIT(11) +#define HE_6GHZ_BAND_CAP_RX_ANTPAT_CONS BIT(12) +#define HE_6GHZ_BAND_CAP_TX_ANTPAT_CONS BIT(13) + /* * IEEE P802.11ax/D4.0, 9.4.2.246 Spatial Reuse Parameter Set element */ @@ -2156,6 +2222,8 @@ struct ieee80211_spatial_reuse { /* HE Capabilities Information defines */ +#define HE_MACCAP_TWT_RESPONDER ((u8) BIT(2)) + #define HE_PHYCAP_CHANNEL_WIDTH_SET_IDX 0 #define HE_PHYCAP_CHANNEL_WIDTH_MASK ((u8) (BIT(1) | BIT(2) | \ BIT(3) | BIT(4))) @@ -2198,7 +2266,7 @@ struct ieee80211_spatial_reuse { #define HE_OPERATION_BSS_COLOR_MASK ((u32) (BIT(24) | BIT(25) | \ BIT(26) | BIT(27) | \ BIT(28) | BIT(29))) -#define HE_OPERATION_PARTIAL_BSS_COLOR ((u32) BIT(30)) +#define HE_OPERATION_BSS_COLOR_PARTIAL ((u32) BIT(30)) #define HE_OPERATION_BSS_COLOR_DISABLED ((u32) BIT(31)) #define HE_OPERATION_BSS_COLOR_OFFSET 24 @@ -2278,4 +2346,25 @@ enum edmg_bw_config { /* DPP Public Action frame identifiers - OUI_WFA */ #define DPP_OUI_TYPE 0x1A +/* Robust AV streaming Action field values */ +enum robust_av_streaming_action { + ROBUST_AV_SCS_REQ = 0, + ROBUST_AV_SCS_RESP = 1, + ROBUST_AV_GROUP_MEMBERSHIP_REQ = 2, + ROBUST_AV_GROUP_MEMBERSHIP_RESP = 3, + ROBUST_AV_MSCS_REQ = 4, + ROBUST_AV_MSCS_RESP = 5, +}; + +enum scs_request_type { + SCS_REQ_ADD = 0, + SCS_REQ_REMOVE = 1, + SCS_REQ_CHANGE = 2, +}; + +/* Optional subelement IDs for MSCS Descriptor element */ +enum mscs_description_subelem { + MCSC_SUBELEM_STATUS = 1, +}; + #endif /* IEEE802_11_DEFS_H */ diff --git a/src/common/ocv.c b/src/common/ocv.c index 06badfbfb..c9dc14fa6 100644 --- a/src/common/ocv.c +++ b/src/common/ocv.c @@ -45,6 +45,8 @@ int ocv_derive_all_parameters(struct oci_info *oci) oci->sec_channel = 1; else if (op_class_map->bw == BW40MINUS) oci->sec_channel = -1; + else if (op_class_map->bw == BW40) + oci->sec_channel = (((oci->channel - 1) / 4) % 2) ? -1 : 1; return 0; } @@ -95,23 +97,24 @@ int ocv_insert_extended_oci(struct wpa_channel_info *ci, u8 *pos) } -int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, - struct wpa_channel_info *ci, int tx_chanwidth, - int tx_seg1_idx) +enum oci_verify_result +ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, + struct wpa_channel_info *ci, int tx_chanwidth, + int tx_seg1_idx) { struct oci_info oci; if (!oci_ie) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: did not receive mandatory OCI"); - return -1; + "did not receive mandatory OCI"); + return OCI_NOT_FOUND; } if (oci_ie_len != 3) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: received OCI of unexpected length (%d)", + "received OCI of unexpected length (%d)", (int) oci_ie_len); - return -1; + return OCI_INVALID_LENGTH; } os_memset(&oci, 0, sizeof(oci)); @@ -120,25 +123,25 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, oci.seg1_idx = oci_ie[2]; if (ocv_derive_all_parameters(&oci) != 0) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: unable to interpret received OCI"); - return -1; + "unable to interpret received OCI"); + return OCI_PARSE_ERROR; } /* Primary frequency used to send frames to STA must match the STA's */ if ((int) ci->frequency != oci.freq) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: primary channel mismatch in received OCI (we use %d but receiver is using %d)", + "primary channel mismatch in received OCI (we use %d but receiver is using %d)", ci->frequency, oci.freq); - return -1; + return OCI_PRIMARY_FREQ_MISMATCH; } /* We shouldn't transmit with a higher bandwidth than the STA supports */ if (tx_chanwidth > oci.chanwidth) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: channel bandwidth mismatch in received OCI (we use %d but receiver only supports %d)", + "channel bandwidth mismatch in received OCI (we use %d but receiver only supports %d)", tx_chanwidth, oci.chanwidth); - return -1; + return OCI_CHANNEL_WIDTH_MISMATCH; } /* @@ -150,9 +153,9 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, if (tx_chanwidth == 40 && ci->frequency < 2500 && ci->sec_channel != oci.sec_channel) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: secondary channel mismatch in received OCI (we use %d but receiver is using %d)", + "secondary channel mismatch in received OCI (we use %d but receiver is using %d)", ci->sec_channel, oci.sec_channel); - return -1; + return OCI_SECONDARY_FREQ_MISMATCH; } /* @@ -163,10 +166,10 @@ int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, ci->chanwidth == CHAN_WIDTH_80P80) && tx_seg1_idx != oci.seg1_idx) { os_snprintf(ocv_errorstr, sizeof(ocv_errorstr), - "OCV failed: frequency segment 1 mismatch in received OCI (we use %d but receiver is using %d)", + "frequency segment 1 mismatch in received OCI (we use %d but receiver is using %d)", tx_seg1_idx, oci.seg1_idx); - return -1; + return OCI_SEG_1_INDEX_MISMATCH; } - return 0; + return OCI_SUCCESS; } diff --git a/src/common/ocv.h b/src/common/ocv.h index 6379d9d06..7fa4522c1 100644 --- a/src/common/ocv.h +++ b/src/common/ocv.h @@ -27,14 +27,21 @@ struct oci_info { #define OCV_OCI_EXTENDED_LEN (3 + OCV_OCI_LEN) #define OCV_OCI_KDE_LEN (2 + RSN_SELECTOR_LEN + OCV_OCI_LEN) +enum oci_verify_result { + OCI_SUCCESS, OCI_NOT_FOUND, OCI_INVALID_LENGTH, OCI_PARSE_ERROR, + OCI_PRIMARY_FREQ_MISMATCH, OCI_CHANNEL_WIDTH_MISMATCH, + OCI_SECONDARY_FREQ_MISMATCH, OCI_SEG_1_INDEX_MISMATCH +}; + extern char ocv_errorstr[256]; int ocv_derive_all_parameters(struct oci_info *oci); int ocv_insert_oci(struct wpa_channel_info *ci, u8 **argpos); int ocv_insert_oci_kde(struct wpa_channel_info *ci, u8 **argpos); int ocv_insert_extended_oci(struct wpa_channel_info *ci, u8 *pos); -int ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, - struct wpa_channel_info *ci, int tx_chanwidth, - int tx_seg1_idx); +enum oci_verify_result +ocv_verify_tx_params(const u8 *oci_ie, size_t oci_ie_len, + struct wpa_channel_info *ci, int tx_chanwidth, + int tx_seg1_idx); #endif /* OCV_H */ diff --git a/src/common/privsep_commands.h b/src/common/privsep_commands.h index b85c6c347..d2c4bbd5e 100644 --- a/src/common/privsep_commands.h +++ b/src/common/privsep_commands.h @@ -82,6 +82,7 @@ struct privsep_cmd_set_key { size_t seq_len; u8 key[32]; size_t key_len; + enum key_flag key_flag; }; enum privsep_event { diff --git a/src/common/qca-vendor.h b/src/common/qca-vendor.h index 44d4e6902..28a93d7b8 100644 --- a/src/common/qca-vendor.h +++ b/src/common/qca-vendor.h @@ -1,7 +1,7 @@ /* * Qualcomm Atheros OUI and vendor specific assignments * Copyright (c) 2014-2017, Qualcomm Atheros, Inc. - * Copyright (c) 2018-2019, The Linux Foundation + * Copyright (c) 2018-2020, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -174,6 +174,22 @@ enum qca_radiotap_vendor_ids { * to notify the connected station's status. The attributes for this * command are defined in enum qca_wlan_vendor_attr_link_properties. * + * @QCA_NL80211_VENDOR_SUBCMD_SETBAND: Command to configure the enabled band(s) + * to the driver. This command sets the band(s) through either the + * attribute QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE or + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK (or both). + * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE refers enum qca_set_band as unsigned + * integer values and QCA_WLAN_VENDOR_ATTR_SETBAND_MASK refers it as 32 + * bit unsigned bitmask values. The allowed values for + * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE are limited to QCA_SETBAND_AUTO, + * QCA_SETBAND_5G, and QCA_SETBAND_2G. Other values/bitmasks are valid for + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. The attribute + * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE is deprecated and the recommendation + * is to use the QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. If the both attributes + * are included for backwards compatibility, the configurations through + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK will take the precedence with drivers + * that support both attributes. + * * @QCA_NL80211_VENDOR_SUBCMD_ACS_POLICY: This command is used to configure * DFS policy and channel hint for ACS operation. This command uses the * attributes defined in enum qca_wlan_vendor_attr_acs_config and @@ -646,6 +662,44 @@ enum qca_radiotap_vendor_ids { * code immediately prior to triggering cfg80211_disconnected(). The * attributes used with this event are defined in enum * qca_wlan_vendor_attr_driver_disconnect_reason. + * + * @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC: This vendor subcommand is used to + * add/delete TSPEC for each AC. One command is for one specific AC only. + * This command can only be used in STA mode and the STA must be + * associated with an AP when the command is issued. Uses attributes + * defined in enum qca_wlan_vendor_attr_config_tspec. + * + * @QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT: Vendor subcommand to configure TWT. + * Uses attributes defined in enum qca_wlan_vendor_attr_config_twt. + * + * @QCA_NL80211_VENDOR_SUBCMD_GETBAND: Command to get the enabled band(s) from + * the driver. The band configurations obtained are referred through + * QCA_WLAN_VENDOR_ATTR_SETBAND_MASK. + * + * @QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS: Vendor subcommand/event for medium + * assessment. + * Uses attributes defined in enum qca_wlan_vendor_attr_medium_assess. + * + * @QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID: This acts as a vendor event and is + * used to update SSID information in hostapd when it is updated in the + * driver. Uses the attribute NL80211_ATTR_SSID. + * + * @QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS: This vendor subcommand is used by + * the driver to send opaque data from the firmware to userspace. The + * driver sends an event to userspace whenever such data is received from + * the firmware. + * + * QCA_WLAN_VENDOR_ATTR_CONFIG_GENERIC_DATA is used as the attribute to + * send this opaque data for this event. + * + * The format of the opaque data is specific to the particular firmware + * version and there is no guarantee of the format remaining same. + * + * @QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS: This acts as an event. + * The host driver selects Tx VDEV, and notifies user. The attributes + * used with this event are defined in enum + * qca_wlan_vendor_attr_mbssid_tx_vdev_status. + * */ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_UNSPEC = 0, @@ -825,6 +879,13 @@ enum qca_nl80211_vendor_subcmds { QCA_NL80211_VENDOR_SUBCMD_GET_SAR_LIMITS_EVENT = 187, QCA_NL80211_VENDOR_SUBCMD_UPDATE_STA_INFO = 188, QCA_NL80211_VENDOR_SUBCMD_DRIVER_DISCONNECT_REASON = 189, + QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC = 190, + QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT = 191, + QCA_NL80211_VENDOR_SUBCMD_GETBAND = 192, + QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS = 193, + QCA_NL80211_VENDOR_SUBCMD_UPDATE_SSID = 194, + QCA_NL80211_VENDOR_SUBCMD_WIFI_FW_STATS = 195, + QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS = 196, }; enum qca_wlan_vendor_attr { @@ -855,7 +916,11 @@ enum qca_wlan_vendor_attr { QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_2_4_BAND = 10, /* Unsigned 32-bit value */ QCA_WLAN_VENDOR_ATTR_MAX_CONCURRENT_CHANNELS_5_0_BAND = 11, - /* Unsigned 32-bit value from enum qca_set_band. */ + /* Unsigned 32-bit value from enum qca_set_band. The allowed values for + * this attribute are limited to QCA_SETBAND_AUTO, QCA_SETBAND_5G, and + * QCA_SETBAND_2G. This attribute is deprecated. Recommendation is to + * use QCA_WLAN_VENDOR_ATTR_SETBAND_MASK instead. + */ QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE = 12, /* Dummy (NOP) attribute for 64 bit padding */ QCA_WLAN_VENDOR_ATTR_PAD = 13, @@ -1018,6 +1083,15 @@ enum qca_wlan_vendor_attr { */ QCA_WLAN_VENDOR_ATTR_FW_STATE = 42, + /* Unsigned 32-bitmask value from enum qca_set_band. Substitutes the + * attribute QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE for which only a subset + * of single values from enum qca_set_band are valid. This attribute + * uses bitmask combinations to define the respective allowed band + * combinations and this attributes takes precedence over + * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE if both attributes are included. + */ + QCA_WLAN_VENDOR_ATTR_SETBAND_MASK = 43, + /* keep last */ QCA_WLAN_VENDOR_ATTR_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_MAX = QCA_WLAN_VENDOR_ATTR_AFTER_LAST - 1, @@ -1279,6 +1353,15 @@ enum qca_wlan_vendor_attr_p2p_listen_offload { * Note: If the driver supports the 6 GHz band, the event sent from the driver * includes this attribute along with * QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED: Flag attribute. + * Used with command to notify the driver of EDMG request for ACS + * operation. + * + * @QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL: Optional (u8). + * Used with event to notify the EDMG channel number selected in ACS + * operation. + * EDMG primary channel is indicated by QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL */ enum qca_wlan_vendor_attr_acs_offload { QCA_WLAN_VENDOR_ATTR_ACS_CHANNEL_INVALID = 0, @@ -1297,6 +1380,8 @@ enum qca_wlan_vendor_attr_acs_offload { QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY = 13, QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_FREQUENCY = 14, QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_FREQUENCY = 15, + QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED = 16, + QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL = 17, /* keep last */ QCA_WLAN_VENDOR_ATTR_ACS_AFTER_LAST, @@ -1360,6 +1445,19 @@ enum qca_wlan_vendor_acs_hw_mode { * %QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL and * %QCA_WLAN_VENDOR_ATTR_THERMAL_COMPLETION_WINDOW attributes from * userspace. + * @QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R: Device supports Adaptive 11r. + * With Adaptive 11r feature, access points advertise the vendor + * specific IEs and MDE but do not include FT AKM in the RSNE. + * The Adaptive 11r supported stations are expected to identify + * such vendor specific IEs and connect to the AP in FT mode though + * the profile is configured in non-FT mode. + * The driver-based SME cases also need to have this support for + * Adaptive 11r to handle the connection and roaming scenarios. + * This flag indicates the support for the same to the user space. + * @QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS: Device supports + * concurrent network sessions on different Wi-Fi bands. This feature + * capability is attributed to the hardware's capability to support + * the same (e.g., DBS). * @NUM_QCA_WLAN_VENDOR_FEATURES: Number of assigned feature bits */ enum qca_wlan_vendor_features { @@ -1375,6 +1473,8 @@ enum qca_wlan_vendor_features { QCA_WLAN_VENDOR_FEATURE_11AX = 9, QCA_WLAN_VENDOR_FEATURE_6GHZ_SUPPORT = 10, QCA_WLAN_VENDOR_FEATURE_THERMAL_CONFIG = 11, + QCA_WLAN_VENDOR_FEATURE_ADAPTIVE_11R = 12, + QCA_WLAN_VENDOR_FEATURE_CONCURRENT_BAND_SESSIONS = 13, NUM_QCA_WLAN_VENDOR_FEATURES /* keep last */ }; @@ -1554,9 +1654,10 @@ enum qca_iface_type { }; enum qca_set_band { - QCA_SETBAND_AUTO, - QCA_SETBAND_5G, - QCA_SETBAND_2G, + QCA_SETBAND_AUTO = 0, + QCA_SETBAND_5G = BIT(0), + QCA_SETBAND_2G = BIT(1), + QCA_SETBAND_6G = BIT(2), }; /** @@ -1684,6 +1785,8 @@ enum qca_vendor_attr_wisa_cmd { * (not including the Element ID Extension field). Please note that the * draft is still work in progress and this element payload is subject to * change. + * + * @QCA_VENDOR_ELEM_ALLPLAY: Allplay element */ enum qca_vendor_element_id { QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST = 0, @@ -1692,6 +1795,7 @@ enum qca_vendor_element_id { QCA_VENDOR_ELEM_RAPS = 3, QCA_VENDOR_ELEM_MU_EDCA_PARAMS = 4, QCA_VENDOR_ELEM_BSS_COLOR_CHANGE = 5, + QCA_VENDOR_ELEM_ALLPLAY = 6, }; /** @@ -1716,6 +1820,9 @@ enum qca_vendor_element_id { * randomisation * @QCA_WLAN_VENDOR_ATTR_SCAN_BSSID: 6-byte MAC address representing the * specific BSSID to scan for. + * @QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME: Unsigned 64-bit dwell time in + * microseconds. This is a common value which applies across all + * frequencies specified by QCA_WLAN_VENDOR_ATTR_SCAN_FREQUENCIES. */ enum qca_wlan_vendor_attr_scan { QCA_WLAN_VENDOR_ATTR_SCAN_INVALID_PARAM = 0, @@ -1730,6 +1837,7 @@ enum qca_wlan_vendor_attr_scan { QCA_WLAN_VENDOR_ATTR_SCAN_MAC = 9, QCA_WLAN_VENDOR_ATTR_SCAN_MAC_MASK = 10, QCA_WLAN_VENDOR_ATTR_SCAN_BSSID = 11, + QCA_WLAN_VENDOR_ATTR_SCAN_DWELL_TIME = 12, QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SCAN_MAX = QCA_WLAN_VENDOR_ATTR_SCAN_AFTER_LAST - 1 @@ -2084,7 +2192,7 @@ enum qca_wlan_vendor_attr_config { * take the union of IEs from both of these interfaces and send in * further disassoc/deauth frames. */ - QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES = 58, + QCA_WLAN_VENDOR_ATTR_CONFIG_DISCONNECT_IES = 58, /* 8-bit unsigned value for ELNA bypass. * 1-Enable, 0-Disable @@ -2096,7 +2204,193 @@ enum qca_wlan_vendor_attr_config { * scenarios where STA cannot honor the Beacon Report Request from AP. * 1-Enable, 0-Disable. */ - QCA_WLAN_VENDOR_ATTR_BEACON_REPORT_FAIL = 60, + QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL = 60, + + /* 8-bit unsigned value. This attribute enables/disables the host driver + * to send roam reason information in the Reassociation Request frame to + * the target AP when roaming within the same ESS. + * 1-Enable, 0-Disable. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ROAM_REASON = 61, + + /* 32-bit unsigned value to configure different PHY modes to the + * driver/firmware. The possible values are defined in + * enum qca_wlan_vendor_phy_mode. The configuration will be reset to + * default value, i.e., QCA_WLAN_VENDOR_PHY_MODE_AUTO upon restarting + * the driver. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE = 62, + + /* 8-bit unsigned value to configure the maximum supported channel width + * for STA mode. If this value is configured when STA is in connected + * state, it should not exceed the negotiated channel width. If it is + * configured when STA is in disconnected state, the configured value + * will take effect for the next immediate connection. + * Possible values are: + * NL80211_CHAN_WIDTH_20 + * NL80211_CHAN_WIDTH_40 + * NL80211_CHAN_WIDTH_80 + * NL80211_CHAN_WIDTH_80P80 + * NL80211_CHAN_WIDTH_160 + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_WIDTH = 63, + + /* 8-bit unsigned value to enable/disable dynamic bandwidth adjustment. + * This attribute is only applicable for STA mode. When dynamic + * bandwidth adjustment is disabled, STA will use static channel width + * the value of which is negotiated during connection. + * 1-enable (default), 0-disable + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_DYNAMIC_BW = 64, + + /* 8-bit unsigned value to configure the maximum number of subframes of + * TX MSDU for aggregation. Possible values are 0-31. When set to 0, + * it is decided by the hardware. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TX_MSDU_AGGREGATION = 65, + + /* 8-bit unsigned value to configure the maximum number of subframes of + * RX MSDU for aggregation. Possible values are 0-31. When set to 0, + * it is decided by the hardware. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_MSDU_AGGREGATION = 66, + + /* 8-bit unsigned value. This attribute is used to dynamically + * enable/disable the LDPC capability of the device. When configured in + * the disconnected state, the updated configuration will be considered + * for the immediately following connection attempt. If this + * configuration is modified while the device is in the connected state, + * the LDPC TX will be updated with this configuration immediately, + * while the LDPC RX configuration update will take place starting from + * the subsequent association attempt. + * 1-Enable, 0-Disable. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_LDPC = 67, + + /* 8-bit unsigned value. This attribute is used to dynamically + * enable/disable the TX STBC capability of the device. When configured + * in the disconnected state, the updated configuration will be + * considered for the immediately following connection attempt. If the + * connection is formed with TX STBC enabled and if this configuration + * is disabled during that association, the TX will be impacted + * immediately. Further connection attempts will disable TX STBC. + * However, enabling the TX STBC for a connected session with disabled + * capability is not allowed and will fail. + * 1-Enable, 0-Disable. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TX_STBC = 68, + + /* 8-bit unsigned value. This attribute is used to dynamically + * enable/disable the RX STBC capability of the device. When configured + * in the disconnected state, the updated configuration will be + * considered for the immediately following connection attempt. If the + * configuration is modified in the connected state, there will be no + * impact for the current association, but further connection attempts + * will use the updated configuration. + * 1-Enable, 0-Disable. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_STBC = 69, + + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of spatial streams. When configured in the disconnected + * state, the updated configuration will be considered for the + * immediately following connection attempt. If the NSS is updated after + * the connection, the updated NSS value is notified to the peer using + * the Operating Mode Notification/Spatial Multiplexing Power Save + * frame. The updated NSS value after the connection shall not be + * greater than the one negotiated during the connection. Any such + * higher value configuration shall be returned with a failure. + * Only symmetric NSS configuration (such as 2X2 or 1X1) can be done + * using this attribute. QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS and + * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attributes shall be used to + * configure the asymmetric NSS configuration (such as 1X2). + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_NSS = 70, + /* 8-bit unsigned value to trigger Optimized Power Management: + * 1-Enable, 0-Disable + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_OPTIMIZED_POWER_MANAGEMENT = 71, + + /* 8-bit unsigned value. This attribute takes the QoS/access category + * value represented by the enum qca_wlan_ac_type and expects the driver + * to upgrade the UDP frames to this access category. The value of + * QCA_WLAN_AC_ALL is invalid for this attribute. This will override the + * DSCP value configured in the frame with the intention to only upgrade + * the access category. That said, it is not intended to downgrade the + * access category for the frames. + * Set the value to QCA_WLAN_AC_BK if the QoS upgrade needs to be + * disabled, as BK is of the lowest priority and an upgrade to it does + * not result in any changes for the frames. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_UDP_QOS_UPGRADE = 72, + + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of chains to be used for transmitting data. This + * configuration is allowed only when in connected state and will be + * effective until disconnected. The driver rejects this configuration + * if the number of spatial streams being used in the current connection + * cannot be supported by this configuration. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_TX_CHAINS = 73, + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of chains to be used for receiving data. This + * configuration is allowed only when in connected state and will be + * effective until disconnected. The driver rejects this configuration + * if the number of spatial streams being used in the current connection + * cannot be supported by this configuration. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_NUM_RX_CHAINS = 74, + + /* 8-bit unsigned value to configure ANI setting type. + * See &enum qca_wlan_ani_setting for possible values. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_SETTING = 75, + /* 32-bit signed value to configure ANI level. This is used when + * ANI settings type is &QCA_WLAN_ANI_SETTING_FIXED. + * The set and get of ANI level with &QCA_WLAN_ANI_SETTING_AUTO + * is invalid, the driver will return a failure. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_ANI_LEVEL = 76, + + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of spatial streams used for transmitting the data. When + * configured in the disconnected state, the configured value will + * be considered for the following connection attempt. + * If the NSS is updated after the connection, the updated NSS value + * is notified to the peer using the Operating Mode Notification/Spatial + * Multiplexing Power Save frame. + * The TX NSS value configured after the connection shall not be greater + * than the value negotiated during the connection. Any such higher + * value configuration shall be treated as invalid configuration by + * the driver. This attribute shall be configured along with + * QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute to define the symmetric + * configuration (such as 2X2 or 1X1) or the asymmetric + * configuration (such as 1X2). + * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along + * with this QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute the driver + * will update the TX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS = 77, + + /* 8-bit unsigned value. This attribute is used to dynamically configure + * the number of spatial streams used for receiving the data. When + * configured in the disconnected state, the configured value will + * be considered for the following connection attempt. + * If the NSS is updated after the connection, the updated NSS value + * is notified to the peer using the Operating Mode Notification/Spatial + * Multiplexing Power Save frame. + * The RX NSS value configured after the connection shall not be greater + * than the value negotiated during the connection. Any such higher + * value configuration shall be treated as invalid configuration by + * the driver. This attribute shall be configured along with + * QCA_WLAN_VENDOR_ATTR_CONFIG_TX_NSS attribute to define the symmetric + * configuration (such as 2X2 or 1X1) or the asymmetric + * configuration (such as 1X2). + * If QCA_WLAN_VENDOR_ATTR_CONFIG_NSS attribute is also provided along + * with this QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS attribute the driver + * will update the RX NSS based on QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS. + */ + QCA_WLAN_VENDOR_ATTR_CONFIG_RX_NSS = 78, /* keep last */ QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST, @@ -2104,6 +2398,24 @@ enum qca_wlan_vendor_attr_config { QCA_WLAN_VENDOR_ATTR_CONFIG_AFTER_LAST - 1, }; +/* Compatibility defines for previously used incorrect enum + * qca_wlan_vendor_attr_config names. These values should not be used in any + * new implementation. */ +#define QCA_WLAN_VENDOR_ATTR_DISCONNECT_IES \ + QCA_WLAN_VENDOR_ATTR_CONFIG_DISCONNECT_IES +#define QCA_WLAN_VENDOR_ATTR_BEACON_REPORT_FAIL \ + QCA_WLAN_VENDOR_ATTR_CONFIG_BEACON_REPORT_FAIL + +/** + * enum qca_wlan_ani_setting - ANI setting type + * @QCA_WLAN_ANI_SETTING_AUTO: Automatically determine ANI level + * @QCA_WLAN_ANI_SETTING_FIXED: Fix ANI level to the dBm parameter + */ +enum qca_wlan_ani_setting { + QCA_WLAN_ANI_SETTING_AUTO = 0, + QCA_WLAN_ANI_SETTING_FIXED = 1, +}; + /** * enum qca_wlan_vendor_attr_sap_config - Parameters for AP configuration * @@ -2159,19 +2471,87 @@ enum qca_wlan_vendor_attr_sap_conditional_chan_switch { /** * enum qca_wlan_gpio_attr - Parameters for GPIO configuration + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND: Required (u32) + * value to specify the GPIO command. Please refer to enum qca_gpio_cmd_type + * for the available values. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM: Required (u32) + * value to specify the GPIO number. + * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG or %QCA_WLAN_VENDOR_GPIO_OUTPUT. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE: Required (u32) + * value to specify the GPIO output level. Please refer to enum qca_gpio_value + * for the available values. + * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_OUTPUT. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE: Optional (u32) + * value to specify the GPIO pull type. Please refer to enum qca_gpio_pull_type + * for the available values. + * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG and + * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG + * attribute is present. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE: Optional (u32) + * value to specify the GPIO interrupt mode. Please refer to enum + * qca_gpio_interrupt_mode for the available values. + * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG and + * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG + * attribute is present. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR: Optional (u32) + * value to specify the GPIO direction. Please refer to enum qca_gpio_direction + * for the available values. + * This is required, when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG and + * %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG attribute is not present. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG + * attribute is present. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG: Optional (u32) + * Value to specify the mux config. Meaning of a given value is dependent + * on the target chipset and GPIO pin. Must be of the range 0-15. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to 0. + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE: Optional (u32) + * Value to specify the drive, refer to enum qca_gpio_drive. + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG. Defaults to QCA_WLAN_GPIO_DRIVE_2MA(0). + * + * @QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG: Optional (flag) + * Optional when %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND is + * %QCA_WLAN_VENDOR_GPIO_CONFIG. When present this attribute signals that all + * other parameters for the given GPIO will be obtained from internal + * configuration. Only %QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM must be + * specified to indicate the GPIO pin being configured. */ enum qca_wlan_gpio_attr { QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INVALID = 0, /* Unsigned 32-bit attribute for GPIO command */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_COMMAND = 1, /* Unsigned 32-bit attribute for GPIO PIN number to configure */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PINNUM = 2, /* Unsigned 32-bit attribute for GPIO value to configure */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_VALUE = 3, /* Unsigned 32-bit attribute for GPIO pull type */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_PULL_TYPE = 4, /* Unsigned 32-bit attribute for GPIO interrupt mode */ - QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE, + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTR_MODE = 5, + /* Unsigned 32-bit attribute for GPIO direction to configure */ + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DIR = 6, + /* Unsigned 32-bit attribute for GPIO mux config */ + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_MUX_CONFIG = 7, + /* Unsigned 32-bit attribute for GPIO drive */ + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_DRIVE = 8, + /* Flag attribute for using internal GPIO configuration */ + QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_INTERNAL_CONFIG = 9, /* keep last */ QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST, @@ -2179,6 +2559,97 @@ enum qca_wlan_gpio_attr { QCA_WLAN_VENDOR_ATTR_GPIO_PARAM_LAST - 1 }; +/** + * enum gpio_cmd_type - GPIO configuration command type + * @QCA_WLAN_VENDOR_GPIO_CONFIG: Set GPIO configuration info + * @QCA_WLAN_VENDOR_GPIO_OUTPUT: Set GPIO output level + */ +enum qca_gpio_cmd_type { + QCA_WLAN_VENDOR_GPIO_CONFIG = 0, + QCA_WLAN_VENDOR_GPIO_OUTPUT = 1, +}; + +/** + * enum qca_gpio_pull_type - GPIO pull type + * @QCA_WLAN_GPIO_PULL_NONE: Set GPIO pull type to none + * @QCA_WLAN_GPIO_PULL_UP: Set GPIO pull up + * @QCA_WLAN_GPIO_PULL_DOWN: Set GPIO pull down + */ +enum qca_gpio_pull_type { + QCA_WLAN_GPIO_PULL_NONE = 0, + QCA_WLAN_GPIO_PULL_UP = 1, + QCA_WLAN_GPIO_PULL_DOWN = 2, + QCA_WLAN_GPIO_PULL_MAX, +}; + +/** + * enum qca_gpio_direction - GPIO direction + * @QCA_WLAN_GPIO_INPUT: Set GPIO as input mode + * @QCA_WLAN_GPIO_OUTPUT: Set GPIO as output mode + * @QCA_WLAN_GPIO_VALUE_MAX: Invalid value + */ +enum qca_gpio_direction { + QCA_WLAN_GPIO_INPUT = 0, + QCA_WLAN_GPIO_OUTPUT = 1, + QCA_WLAN_GPIO_DIR_MAX, +}; + +/** + * enum qca_gpio_value - GPIO Value + * @QCA_WLAN_GPIO_LEVEL_LOW: set gpio output level to low + * @QCA_WLAN_GPIO_LEVEL_HIGH: set gpio output level to high + * @QCA_WLAN_GPIO_LEVEL_MAX: Invalid value + */ +enum qca_gpio_value { + QCA_WLAN_GPIO_LEVEL_LOW = 0, + QCA_WLAN_GPIO_LEVEL_HIGH = 1, + QCA_WLAN_GPIO_LEVEL_MAX, +}; + +/** + * enum gpio_interrupt_mode - GPIO interrupt mode + * @QCA_WLAN_GPIO_INTMODE_DISABLE: Disable interrupt trigger + * @QCA_WLAN_GPIO_INTMODE_RISING_EDGE: Interrupt with GPIO rising edge trigger + * @QCA_WLAN_GPIO_INTMODE_FALLING_EDGE: Interrupt with GPIO falling edge trigger + * @QCA_WLAN_GPIO_INTMODE_BOTH_EDGE: Interrupt with GPIO both edge trigger + * @QCA_WLAN_GPIO_INTMODE_LEVEL_LOW: Interrupt with GPIO level low trigger + * @QCA_WLAN_GPIO_INTMODE_LEVEL_HIGH: Interrupt with GPIO level high trigger + * @QCA_WLAN_GPIO_INTMODE_MAX: Invalid value + */ +enum qca_gpio_interrupt_mode { + QCA_WLAN_GPIO_INTMODE_DISABLE = 0, + QCA_WLAN_GPIO_INTMODE_RISING_EDGE = 1, + QCA_WLAN_GPIO_INTMODE_FALLING_EDGE = 2, + QCA_WLAN_GPIO_INTMODE_BOTH_EDGE = 3, + QCA_WLAN_GPIO_INTMODE_LEVEL_LOW = 4, + QCA_WLAN_GPIO_INTMODE_LEVEL_HIGH = 5, + QCA_WLAN_GPIO_INTMODE_MAX, +}; + +/** + * enum qca_gpio_drive - GPIO drive + * @QCA_WLAN_GPIO_DRIVE_2MA: drive 2MA + * @QCA_WLAN_GPIO_DRIVE_4MA: drive 4MA + * @QCA_WLAN_GPIO_DRIVE_6MA: drive 6MA + * @QCA_WLAN_GPIO_DRIVE_8MA: drive 8MA + * @QCA_WLAN_GPIO_DRIVE_10MA: drive 10MA + * @QCA_WLAN_GPIO_DRIVE_12MA: drive 12MA + * @QCA_WLAN_GPIO_DRIVE_14MA: drive 14MA + * @QCA_WLAN_GPIO_DRIVE_16MA: drive 16MA + * @QCA_WLAN_GPIO_DRIVE_MAX: invalid GPIO drive + */ +enum qca_gpio_drive { + QCA_WLAN_GPIO_DRIVE_2MA = 0, + QCA_WLAN_GPIO_DRIVE_4MA = 1, + QCA_WLAN_GPIO_DRIVE_6MA = 2, + QCA_WLAN_GPIO_DRIVE_8MA = 3, + QCA_WLAN_GPIO_DRIVE_10MA = 4, + QCA_WLAN_GPIO_DRIVE_12MA = 5, + QCA_WLAN_GPIO_DRIVE_14MA = 6, + QCA_WLAN_GPIO_DRIVE_16MA = 7, + QCA_WLAN_GPIO_DRIVE_MAX, +}; + /** * qca_wlan_set_qdepth_thresh_attr - Parameters for setting * MSDUQ depth threshold per peer per tid in the target @@ -3267,7 +3738,7 @@ enum qca_wlan_vendor_attr_ll_stats_results { QCA_WLAN_VENDOR_ATTR_LL_STATS_NUM_RADIOS = 66, /* Signifies the nested list of channel attributes - * QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_INFO_* + * QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_* */ QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO = 67, @@ -3329,6 +3800,17 @@ enum qca_wlan_vendor_attr_ll_stats_results { */ QCA_WLAN_VENDOR_ATTR_LL_STATS_WMM_AC_PENDING_MSDU = 83, + /* u32 value representing total time in milliseconds for which the radio + * is transmitting on this channel. This attribute will be nested + * within QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_TX_TIME = 84, + /* u32 value representing total time in milliseconds for which the radio + * is receiving all 802.11 frames intended for this device on this + * channel. This attribute will be nested within + * QCA_WLAN_VENDOR_ATTR_LL_STATS_CH_INFO. + */ + QCA_WLAN_VENDOR_ATTR_LL_STATS_CHANNEL_RX_TIME = 85, /* keep last */ QCA_WLAN_VENDOR_ATTR_LL_STATS_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_LL_STATS_MAX = @@ -3676,6 +4158,30 @@ enum qca_vendor_attr_scan_freq_list_scheme { QCA_ATTR_ROAM_CONTROL_SCAN_FREQ_LIST_SCHEME_AFTER_LAST - 1, }; +/** + * enum qca_roam_scan_scheme: Scan scheme + * + * @QCA_ROAM_SCAN_SCHEME_NO_SCAN: No frequencies specified to scan. + * Indicates the driver to not scan on a Roam Trigger scenario, but + * disconnect. E.g., on a BTM request from the AP the driver/firmware shall + * disconnect from the current connected AP by notifying a failure + * code in the BTM response. + * + * @QCA_ROAM_SCAN_SCHEME_PARTIAL_SCAN: Indicates the driver/firmware to + * trigger partial frequency scans. These frequencies are the ones learned + * or maintained by the driver based on the probability of finding the + * BSSIDs in the ESS for which the roaming is triggered. + * + * @QCA_ROAM_SCAN_SCHEME_FULL_SCAN: Indicates the driver/firmware to + * trigger the scan on all the valid frequencies to find better + * candidates to roam. + */ +enum qca_roam_scan_scheme { + QCA_ROAM_SCAN_SCHEME_NO_SCAN = 0, + QCA_ROAM_SCAN_SCHEME_PARTIAL_SCAN = 1, + QCA_ROAM_SCAN_SCHEME_FULL_SCAN = 2, +}; + /* * enum qca_vendor_roam_triggers: Bitmap of roaming triggers * @@ -3696,6 +4202,18 @@ enum qca_vendor_attr_scan_freq_list_scheme { * when BTM Request frame is received from the connected AP. * @QCA_ROAM_TRIGGER_REASON_BSS_LOAD: Set if the roam has to be triggered * when the channel utilization is goes above the configured threshold. + * @QCA_ROAM_TRIGGER_REASON_USER_TRIGGER: Set if the roam has to be triggered + * based on the request from the user (space). + * @QCA_ROAM_TRIGGER_REASON_DEAUTH: Set if the roam has to be triggered when + * device receives Deauthentication/Disassociation frame from connected AP. + * @QCA_ROAM_TRIGGER_REASON_IDLE: Set if the roam has to be triggered when the + * device is in idle state (no TX/RX) and suspend mode, if the current RSSI + * is determined to be a poor one. + * @QCA_ROAM_TRIGGER_REASON_TX_FAILURES: Set if the roam has to be triggered + * based on continuous TX Data frame failures to the connected AP. + * @QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN: Set if the roam has to be triggered + * based on the scan results obtained from an external scan (not triggered + * to aim roaming). * * Set the corresponding roam trigger reason bit to consider it for roam * trigger. @@ -3711,6 +4229,11 @@ enum qca_vendor_roam_triggers { QCA_ROAM_TRIGGER_REASON_DENSE = 1 << 5, QCA_ROAM_TRIGGER_REASON_BTM = 1 << 6, QCA_ROAM_TRIGGER_REASON_BSS_LOAD = 1 << 7, + QCA_ROAM_TRIGGER_REASON_USER_TRIGGER = 1 << 8, + QCA_ROAM_TRIGGER_REASON_DEAUTH = 1 << 9, + QCA_ROAM_TRIGGER_REASON_IDLE = 1 << 10, + QCA_ROAM_TRIGGER_REASON_TX_FAILURES = 1 << 11, + QCA_ROAM_TRIGGER_REASON_EXTERNAL_SCAN = 1 << 12, }; /** @@ -3867,6 +4390,40 @@ enum qca_vendor_attr_roam_candidate_selection_criteria { * * Clears the selection criteria configured in the driver when specified * with clear command. + * + * @QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME: Unsigned 32-bit value. + * Represents value of the scan frequency scheme from enum + * qca_roam_scan_scheme. + * It's an optional attribute. If this attribute is not configured, the + * driver shall proceed with default behavior. + * + * @QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD: Signed 32-bit value in dBm, + * signifying the RSSI threshold of the current connected AP, indicating + * the driver to trigger roam only when the current connected AP's RSSI + * is less than this threshold. + * + * @QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD: Signed 32-bit value in dBm, + * signifying the RSSI threshold of the candidate AP, indicating + * the driver to trigger roam only to the candidate AP with RSSI + * better than this threshold. + * + * @QCA_ATTR_ROAM_CONTROL_USER_REASON: Unsigned 32-bit value. Represents the + * user defined reason code to be sent to the AP in response to AP's + * request to trigger the roam if the roaming cannot be triggered. + * Applies to all the scenarios of AP assisted roaming (e.g., BTM). + * + * @QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS: Unsigned 32-bit value. + * Carries a bitmap of the roam triggers specified in + * enum qca_vendor_roam_triggers. + * Represents the roam triggers for which the specific scan scheme from + * enum qca_roam_scan_scheme has to be applied. + * It's an optional attribute. If this attribute is not configured, but + * QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME is specified, the scan scheme + * specified through QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME is applicable for + * all the roams. + * If both QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME and + * QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS are not specified, the + * driver shall proceed with the default behavior. */ enum qca_vendor_attr_roam_control { QCA_ATTR_ROAM_CONTROL_ENABLE = 1, @@ -3877,6 +4434,11 @@ enum qca_vendor_attr_roam_control { QCA_ATTR_ROAM_CONTROL_FULL_SCAN_PERIOD = 6, QCA_ATTR_ROAM_CONTROL_TRIGGERS = 7, QCA_ATTR_ROAM_CONTROL_SELECTION_CRITERIA = 8, + QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME = 9, + QCA_ATTR_ROAM_CONTROL_CONNECTED_RSSI_THRESHOLD = 10, + QCA_ATTR_ROAM_CONTROL_CANDIDATE_RSSI_THRESHOLD = 11, + QCA_ATTR_ROAM_CONTROL_USER_REASON = 12, + QCA_ATTR_ROAM_CONTROL_SCAN_SCHEME_TRIGGERS = 13, /* keep last */ QCA_ATTR_ROAM_CONTROL_AFTER_LAST, @@ -3896,7 +4458,7 @@ enum qca_vendor_attr_roam_control { * Represents the Request ID for the specific set of commands. * This also helps to map specific set of commands to the respective * ID / client. e.g., helps to identify the user entity configuring the - * Blacklist BSSID and accordingly clear the respective ones with the + * ignored BSSIDs and accordingly clear the respective ones with the * matching ID. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_WHITE_LIST_SSID_NUM_NETWORKS: Unsigned @@ -3963,17 +4525,18 @@ enum qca_vendor_attr_roam_control { * the BSSID for the purpose of comparing it with other roam candidate. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS: Nested attribute, - * represents the BSSIDs to get blacklisted for roaming. + * represents the BSSIDs to get ignored for roaming. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID: Unsigned - * 32-bit value, represents the number of blacklisted BSSIDs. + * 32-bit value, represents the number of ignored BSSIDs. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID: 6-byte MAC - * address representing the Blacklisted BSSID. + * address representing the ignored BSSID. * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT: Flag attribute, - * indicates this BSSID blacklist as a hint to the driver. The driver can - * select this BSSID in the worst case (when no other BSSIDs are better). + * indicates this request to ignore the BSSID as a hint to the driver. The + * driver can select this BSSID in the worst case (when no other BSSIDs are + * better). * * @QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL: Nested attribute to * set/get/clear the roam control config as @@ -4008,11 +4571,11 @@ enum qca_wlan_vendor_attr_roaming_config_params { QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_BSSID = 16, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_LAZY_ROAM_RSSI_MODIFIER = 17, - /* Attribute for set_blacklist bssid params */ + /* Attribute for setting ignored BSSID parameters */ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS = 18, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_NUM_BSSID = 19, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_BSSID = 20, - /* Flag attribute indicates this BSSID blacklist as a hint */ + /* Flag attribute indicates this entry as a hint */ QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS_HINT = 21, QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_CONTROL = 22, @@ -4048,9 +4611,9 @@ enum qca_wlan_vendor_attr_roaming_config_params { * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PREFS to set the BSSID * preference. * - * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID: Sets the Blacklist - * BSSIDs. Refers QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS to - * set the same. + * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_SET_BLACKLIST_BSSID: Sets the list of BSSIDs + * to ignore in roaming decision. Uses + * QCA_WLAN_VENDOR_ATTR_ROAMING_PARAM_SET_BSSID_PARAMS to set the list. * * @QCA_WLAN_VENDOR_ROAMING_SUBCMD_CONTROL_SET: Command to set the * roam control config to the driver with the attribute @@ -4712,9 +5275,9 @@ enum qca_wlan_vendor_channel_prop_flags_ext { QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DISALLOW_ADHOC = 1 << 6, /* Station only channel */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_DISALLOW_HOSTAP = 1 << 7, - /* DFS radar history for slave device (STA mode) */ + /* DFS radar history for client device (STA mode) */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_HISTORY_RADAR = 1 << 8, - /* DFS CAC valid for slave device (STA mode) */ + /* DFS CAC valid for client device (STA mode) */ QCA_WLAN_VENDOR_CHANNEL_PROP_FLAG_EXT_CAC_VALID = 1 << 9, }; @@ -5437,8 +6000,12 @@ enum qca_wlan_vendor_attr_spectral_scan { * QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_AGILE * Center frequency (in MHz) of the span of interest or * for convenience, center frequency (in MHz) of any channel - * in the span of interest. If agile spectral scan is initiated - * without setting a valid frequency it returns the error code + * in the span of interest. For 80+80 MHz agile spectral scan + * request it represents center frequency (in MHz) of the primary + * 80 MHz span or for convenience, center frequency (in MHz) of any + * channel in the primary 80 MHz span. If agile spectral scan is + * initiated without setting a valid frequency it returns the + * error code * (QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED). * u32 attribute. */ @@ -5465,6 +6032,20 @@ enum qca_wlan_vendor_attr_spectral_scan { * 1-enable, 0-disable */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG = 28, + /* This specifies the frequency span over which spectral scan would be + * carried out. Its value depends on the value of + * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE and the relation is as + * follows. + * QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_NORMAL + * Not applicable. Spectral scan would happen in the operating span. + * QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_AGILE + * This attribute is applicable only for agile spectral scan + * requests in 80+80 MHz mode. It represents center frequency (in + * MHz) of the secondary 80 MHz span or for convenience, center + * frequency (in MHz) of any channel in the secondary 80 MHz span. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2 = 29, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX = @@ -5555,6 +6136,26 @@ enum qca_wlan_vendor_attr_spectral_cap { * for 80+80 MHz mode. */ QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_80_80 = 13, + /* Number of spectral detectors used for scan in 20 MHz. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_20_MHZ = 14, + /* Number of spectral detectors used for scan in 40 MHz. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_40_MHZ = 15, + /* Number of spectral detectors used for scan in 80 MHz. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80_MHZ = 16, + /* Number of spectral detectors used for scan in 160 MHz. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_160_MHZ = 17, + /* Number of spectral detectors used for scan in 80+80 MHz. + * u32 attribute. + */ + QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80P80_MHZ = 18, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX = @@ -5704,6 +6305,47 @@ enum qca_wlan_vendor_hang_reason { QCA_WLAN_HANG_DXE_FAILURE = 12, /* WMI pending commands exceed the maximum count */ QCA_WLAN_HANG_WMI_EXCEED_MAX_PENDING_CMDS = 13, + /* Timeout for peer STA connection accept command's response from the + * FW in AP mode. This command is triggered when a STA (peer) connects + * to AP (DUT). + */ + QCA_WLAN_HANG_AP_STA_CONNECT_REQ_TIMEOUT = 14, + /* Timeout for the AP connection accept command's response from the FW + * in STA mode. This command is triggered when the STA (DUT) connects + * to an AP (peer). + */ + QCA_WLAN_HANG_STA_AP_CONNECT_REQ_TIMEOUT = 15, + /* Timeout waiting for the response to the MAC HW mode change command + * sent to FW as a part of MAC mode switch among DBS (Dual Band + * Simultaneous), SCC (Single Channel Concurrency), and MCC (Multi + * Channel Concurrency) mode. + */ + QCA_WLAN_HANG_MAC_HW_MODE_CHANGE_TIMEOUT = 16, + /* Timeout waiting for the response from FW to configure the MAC HW's + * mode. This operation is to configure the single/two MACs in either + * SCC/MCC/DBS mode. + */ + QCA_WLAN_HANG_MAC_HW_MODE_CONFIG_TIMEOUT = 17, + /* Timeout waiting for response of VDEV start command from the FW */ + QCA_WLAN_HANG_VDEV_START_RESPONSE_TIMED_OUT = 18, + /* Timeout waiting for response of VDEV restart command from the FW */ + QCA_WLAN_HANG_VDEV_RESTART_RESPONSE_TIMED_OUT = 19, + /* Timeout waiting for response of VDEV stop command from the FW */ + QCA_WLAN_HANG_VDEV_STOP_RESPONSE_TIMED_OUT = 20, + /* Timeout waiting for response of VDEV delete command from the FW */ + QCA_WLAN_HANG_VDEV_DELETE_RESPONSE_TIMED_OUT = 21, + /* Timeout waiting for response of peer all delete request command to + * the FW on a specific VDEV. + */ + QCA_WLAN_HANG_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT = 22, + /* WMI sequence mismatch between WMI command and Tx completion */ + QCA_WLAN_HANG_WMI_BUF_SEQUENCE_MISMATCH = 23, + /* Write to Device HAL register failed */ + QCA_WLAN_HANG_REG_WRITE_FAILURE = 24, + /* No credit left to send the wow_wakeup_from_sleep to firmware */ + QCA_WLAN_HANG_SUSPEND_NO_CREDIT = 25, + /* Bus failure */ + QCA_WLAN_HANG_BUS_FAILURE = 26, }; /** @@ -5716,6 +6358,12 @@ enum qca_wlan_vendor_attr_hang { * qca_wlan_vendor_hang_reason. */ QCA_WLAN_VENDOR_ATTR_HANG_REASON = 1, + /* The binary blob data associated with the hang reason specified by + * QCA_WLAN_VENDOR_ATTR_HANG_REASON. This binary data is expected to + * contain the required dump to analyze the reason for the hang. + * NLA_BINARY attribute, the max size is 1024 bytes. + */ + QCA_WLAN_VENDOR_ATTR_HANG_REASON_DATA = 2, QCA_WLAN_VENDOR_ATTR_HANG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_HANG_MAX = @@ -6364,8 +7012,9 @@ enum qca_wlan_vendor_attr_wake_stats { /** * enum qca_wlan_vendor_thermal_level - Defines various thermal levels - * configured by userspace to the driver/firmware. The values will be - * encapsulated in QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL attribute. + * configured by userspace to the driver/firmware. + * The values can be encapsulated in QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL or + * QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_LEVEL attribute. * The driver/firmware takes actions requested by userspace such as throttling * wifi TX etc. in order to mitigate high temperature. * @@ -6399,8 +7048,9 @@ enum qca_wlan_vendor_attr_thermal_cmd { */ QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE = 1, /* Userspace uses this attribute to configure thermal level to the - * driver/firmware. Used in request, u32 attribute, possible values - * are defined in enum qca_wlan_vendor_thermal_level. + * driver/firmware, or get thermal level from the driver/firmware. + * Used in request or response, u32 attribute, + * possible values are defined in enum qca_wlan_vendor_thermal_level. */ QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL = 2, /* Userspace uses this attribute to configure the time in which the @@ -6438,6 +7088,9 @@ enum qca_wlan_vendor_attr_thermal_cmd { * resume action. * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL: Configure thermal level to * the driver/firmware. + * @QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL: Request to get the current + * thermal level from the driver/firmware. The driver should respond with a + * thermal level defined in enum qca_wlan_vendor_thermal_level. */ enum qca_wlan_vendor_attr_thermal_cmd_type { QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_PARAMS, @@ -6445,6 +7098,7 @@ enum qca_wlan_vendor_attr_thermal_cmd_type { QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SUSPEND, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_RESUME, QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL, + QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_GET_LEVEL, }; /** @@ -6527,6 +7181,11 @@ enum qca_wlan_vendor_attr_thermal_event { * NLA_FLAG attribute. */ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_RESUME_COMPLETE, + /* Thermal level from the driver. + * u32 attribute. Possible values are defined in + * enum qca_wlan_vendor_thermal_level. + */ + QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_LEVEL = 3, /* keep last */ QCA_WLAN_VENDOR_ATTR_THERMAL_EVENT_AFTER_LAST, @@ -6740,6 +7399,72 @@ enum qca_wlan_vendor_attr_he_omi_tx { QCA_WLAN_VENDOR_ATTR_HE_OMI_AFTER_LAST - 1, }; + /** + * enum qca_wlan_vendor_phy_mode - Different PHY modes + * These values are used with %QCA_WLAN_VENDOR_ATTR_CONFIG_PHY_MODE. + * + * @QCA_WLAN_VENDOR_PHY_MODE_AUTO: autoselect + * @QCA_WLAN_VENDOR_PHY_MODE_2G_AUTO: 2.4 GHz 802.11b/g/n/ax autoselect + * @QCA_WLAN_VENDOR_PHY_MODE_5G_AUTO: 5 GHz 802.11a/n/ac/ax autoselect + * @QCA_WLAN_VENDOR_PHY_MODE_11A: 5 GHz, OFDM + * @QCA_WLAN_VENDOR_PHY_MODE_11B: 2.4 GHz, CCK + * @QCA_WLAN_VENDOR_PHY_MODE_11G: 2.4 GHz, OFDM + * @QCA_WLAN_VENDOR_PHY_MODE_11AGN: Support 802.11n in both 2.4 GHz and 5 GHz + * @QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20: 2.4 GHz, HT20 + * @QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS: 2.4 GHz, HT40 (ext ch +1) + * @QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS: 2.4 GHz, HT40 (ext ch -1) + * @QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40: 2.4 GHz, Auto HT40 + * @QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20: 5 GHz, HT20 + * @QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS: 5 GHz, HT40 (ext ch +1) + * @QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS: 5 GHz, HT40 (ext ch -1) + * @QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40: 5 GHz, Auto HT40 + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20: 5 GHz, VHT20 + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS: 5 GHz, VHT40 (Ext ch +1) + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS: 5 GHz VHT40 (Ext ch -1) + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40: 5 GHz, VHT40 + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80: 5 GHz, VHT80 + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80: 5 GHz, VHT80+80 + * @QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160: 5 GHz, VHT160 + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20: HE20 + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40: HE40 + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS: HE40 (ext ch +1) + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS: HE40 (ext ch -1) + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80: HE80 + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80: HE 80P80 + * @QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160: HE160 + */ +enum qca_wlan_vendor_phy_mode { + QCA_WLAN_VENDOR_PHY_MODE_AUTO = 0, + QCA_WLAN_VENDOR_PHY_MODE_2G_AUTO = 1, + QCA_WLAN_VENDOR_PHY_MODE_5G_AUTO = 2, + QCA_WLAN_VENDOR_PHY_MODE_11A = 3, + QCA_WLAN_VENDOR_PHY_MODE_11B = 4, + QCA_WLAN_VENDOR_PHY_MODE_11G = 5, + QCA_WLAN_VENDOR_PHY_MODE_11AGN = 6, + QCA_WLAN_VENDOR_PHY_MODE_11NG_HT20 = 7, + QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40PLUS = 8, + QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40MINUS = 9, + QCA_WLAN_VENDOR_PHY_MODE_11NG_HT40 = 10, + QCA_WLAN_VENDOR_PHY_MODE_11NA_HT20 = 11, + QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40PLUS = 12, + QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40MINUS = 13, + QCA_WLAN_VENDOR_PHY_MODE_11NA_HT40 = 14, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT20 = 15, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40PLUS = 16, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40MINUS = 17, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT40 = 18, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80 = 19, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT80P80 = 20, + QCA_WLAN_VENDOR_PHY_MODE_11AC_VHT160 = 21, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE20 = 22, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40 = 23, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40PLUS = 24, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE40MINUS = 25, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80 = 26, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE80P80 = 27, + QCA_WLAN_VENDOR_PHY_MODE_11AX_HE160 = 28, +}; + /* Attributes for data used by * QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION */ @@ -7023,12 +7748,169 @@ enum qca_wlan_vendor_attr_wifi_test_config { */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_HE_TWT_REQ_SUPPORT = 37, + /* 8-bit unsigned value to configure protection for Management + * frames when PMF is enabled for the association. + * This attribute is used to configure the testbed device. + * 0-use the correct key, 1-use an incorrect key, 2-disable protection. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_PMF_PROTECTION = 38, + + /* Flag attribute to inject Disassociation frame to the connected AP. + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_DISASSOC_TX = 39, + + /* 8-bit unsigned value to configure an override for the RSNXE Used + * subfield in the MIC control field of the FTE in FT Reassociation + * Request frame. + * 0 - Default behavior, 1 - override with 1, 2 - override with 0. + * This attribute is used to configure the testbed device. + * This attribute can be configured only when STA is in associated state + * and the configuration is valid until the disconnection. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FT_REASSOCREQ_RSNXE_USED = 40, + + /* 8-bit unsigned value to configure the driver to ignore CSA (Channel + * Switch Announcement) when STA is in connected state. + * 0 - Default behavior, 1 - Ignore CSA. + * This attribute is used to configure the testbed device. + * This attribute can be configured only when STA is in associated state + * and the configuration is valid until the disconnection. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_CSA = 41, + + /* Nested attribute values required to configure OCI (Operating Channel + * Information). Attributes defined in enum + * qca_wlan_vendor_attr_oci_override are nested within this attribute. + * This attribute is used to configure the testbed device. + * This attribute can be configured only when STA is in associated state + * and the configuration is valid until the disconnection. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE = 42, + + /* 8-bit unsigned value to configure the driver/firmware to ignore SA + * Query timeout. If this configuration is enabled STA shall not send + * Deauthentication frmae when SA Query times out (mainly, after a + * channel switch when OCV is enabled). + * 0 - Default behavior, 1 - Ignore SA Query timeout. + * This attribute is used to configure the testbed device. + * This attribute can be configured only when STA is in associated state + * and the configuration is valid until the disconnection. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_IGNORE_SA_QUERY_TIMEOUT = 43, + + /* 8-bit unsigned value to configure the driver/firmware to start or + * stop transmitting FILS discovery frames. + * 0 - Stop transmitting FILS discovery frames + * 1 - Start transmitting FILS discovery frames + * This attribute is used to configure the testbed device. + * This attribute can be configured only in AP mode and the + * configuration is valid until AP restart. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FILS_DISCOVERY_FRAMES_TX = 44, + + /* 8-bit unsigned value to configure the driver/firmware to enable or + * disable full bandwidth UL MU-MIMO subfield in the HE PHY capabilities + * information field. + * 0 - Disable full bandwidth UL MU-MIMO subfield + * 1 - Enable full bandwidth UL MU-MIMO subfield + * This attribute is used to configure the testbed device. + */ + QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_FULL_BW_UL_MU_MIMO = 45, + /* keep last */ QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_MAX = QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_AFTER_LAST - 1, }; +/** + * enum qca_wlan_twt_operation - Operation of the config TWT request + * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION. + * + * @QCA_WLAN_TWT_SET: Setup a TWT session. Required parameters are configured + * through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_setup. + * + * @QCA_WLAN_TWT_GET: Get the configured TWT parameters. Required parameters are + * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_setup. + * + * @QCA_WLAN_TWT_TERMINATE: Terminate the TWT session. Required parameters are + * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup. + * This terminate can either get triggered by the user space or can as well be + * a notification from the firmware if it initiates a terminate. + * + * @QCA_WLAN_TWT_SUSPEND: Suspend the TWT session. Required parameters are + * obtained through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_setup. Valid only after the TWT session is setup. + * + * @QCA_WLAN_TWT_RESUME: Resume the TWT session. Required parameters are + * configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the enum + * qca_wlan_vendor_attr_twt_resume. Valid only after the TWT session is setup. + * This can as well be a notification from the firmware on a QCA_WLAN_TWT_NUDGE + * request. + * + * @QCA_WLAN_TWT_NUDGE: Suspend and resume the TWT session. TWT nudge is a + * combination of suspend and resume in a single request. Required parameters + * are configured through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. Refers the + * enum qca_wlan_vendor_attr_twt_nudge. Valid only after the TWT session is + * setup. + * + * @QCA_WLAN_TWT_GET_STATS: Get the TWT session traffic statistics information. + * Refers the enum qca_wlan_vendor_attr_twt_stats. Valid only after the TWT + * session is setup. + * + * @QCA_WLAN_TWT_CLEAR_STATS: Clear TWT session traffic statistics information. + * Valid only after the TWT session is setup. + * + * @QCA_WLAN_TWT_GET_CAPABILITIES: Get TWT capabilities of this device and its + * peer. Refers the enum qca_wlan_vendor_attr_twt_capability. It's a synchronous + * operation, i.e., the capabilities are obtained in the corresponding + * vendor command reply to the user space. + * + * @QCA_WLAN_TWT_SETUP_READY_NOTIFY: Notify userspace that the firmare is + * ready for a new TWT session setup after it issued a TWT teardown. + */ +enum qca_wlan_twt_operation { + QCA_WLAN_TWT_SET = 0, + QCA_WLAN_TWT_GET = 1, + QCA_WLAN_TWT_TERMINATE = 2, + QCA_WLAN_TWT_SUSPEND = 3, + QCA_WLAN_TWT_RESUME = 4, + QCA_WLAN_TWT_NUDGE = 5, + QCA_WLAN_TWT_GET_STATS = 6, + QCA_WLAN_TWT_CLEAR_STATS = 7, + QCA_WLAN_TWT_GET_CAPABILITIES = 8, + QCA_WLAN_TWT_SETUP_READY_NOTIFY = 9, +}; + +/** + * enum qca_wlan_vendor_attr_config_twt: Defines attributes used by + * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION: u8 attribute. Specify the TWT + * operation of this request. Possible values are defined in enum + * qca_wlan_twt_operation. The parameters for the respective operation is + * specified through QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS: Nested attribute representing the + * parameters configured for TWT. These parameters are represented by + * enum qca_wlan_vendor_attr_twt_setup, enum qca_wlan_vendor_attr_twt_resume, + * or enum qca_wlan_vendor_attr_twt_stats based on the operation. + */ +enum qca_wlan_vendor_attr_config_twt { + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_OPERATION = 1, + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_PARAMS = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_MAX = + QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_AFTER_LAST - 1, +}; + /** * enum qca_wlan_vendor_attr_bss_filter - Used by the vendor command * QCA_NL80211_VENDOR_SUBCMD_BSS_FILTER. @@ -7176,11 +8058,25 @@ enum qca_wlan_vendor_attr_nan_params { QCA_WLAN_VENDOR_ATTR_NAN_PARAMS_AFTER_LAST - 1 }; +/** + * qca_wlan_twt_setup_state: Represents the TWT session states. + * + * QCA_WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED: TWT session not established. + * QCA_WLAN_TWT_SETUP_STATE_ACTIVE: TWT session is active. + * QCA_WLAN_TWT_SETUP_STATE_SUSPEND: TWT session is in suspended state. + */ +enum qca_wlan_twt_setup_state { + QCA_WLAN_TWT_SETUP_STATE_NOT_ESTABLISHED = 0, + QCA_WLAN_TWT_SETUP_STATE_ACTIVE = 1, + QCA_WLAN_TWT_SETUP_STATE_SUSPEND = 2, +}; + /** * enum qca_wlan_vendor_attr_twt_setup: Represents attributes for * TWT (Target Wake Time) setup request. These attributes are sent as part of * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_SETUP and - * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. + * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. Also used by + * attributes through %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_BCAST: Flag attribute. * Disable (flag attribute not present) - Individual TWT @@ -7190,10 +8086,13 @@ enum qca_wlan_vendor_attr_nan_params { * STA and AP. * Broadcast means the session is across multiple STAs and an AP. The * configuration parameters are announced in Beacon frames by the AP. + * This is used in + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_REQ_TYPE: Required (u8). * Unsigned 8-bit qca_wlan_vendor_twt_setup_req_type to - * specify the TWT request type + * specify the TWT request type. This is used in TWT SET operation. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TRIGGER: Flag attribute * Enable (flag attribute present) - TWT with trigger support. @@ -7201,40 +8100,139 @@ enum qca_wlan_vendor_attr_nan_params { * Trigger means the AP will send the trigger frame to allow STA to send data. * Without trigger, the STA will wait for the MU EDCA timer before * transmitting the data. + * This is used in + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_TYPE: Required (u8) * 0 - Announced TWT - In this mode, STA may skip few service periods to * save more power. If STA wants to wake up, it will send a PS-POLL/QoS * NULL frame to AP. * 1 - Unannounced TWT - The STA will wakeup during every SP. + * This is a required parameter for + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_FLOW_ID: Optional (u8) * Flow ID is the unique identifier for each TWT session. - * Currently this is not required and dialog ID will be set to zero. + * If not provided then dialog ID will be set to zero. + * This is an optional parameter for + * 1. TWT SET Request and Response + * 2. TWT GET Request and Response + * 3. TWT TERMINATE Request and Response + * 4. TWT SUSPEND Request and Response + * Flow ID values from 0 to 254 represent a single TWT session + * Flow ID value of 255 represents all TWT sessions for the following + * 1. TWT TERMINATE Request and Response + * 2. TWT SUSPEND Request and Response + * 4. TWT CLEAR STATISTICS request + * 5. TWT GET STATISTICS request and response + * If an invalid dialog ID is provided, status + * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned. * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_EXP: Required (u8) * This attribute (exp) is used along with the mantissa to derive the * wake interval using the following formula: * pow(2,exp) = wake_intvl_us/wake_intvl_mantis * Wake interval is the interval between 2 successive SP. + * This is a required parameter for + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_PROTECTION: Flag attribute * Enable (flag attribute present) - Protection required. * Disable (flag attribute not present) - Protection not required. * If protection is enabled, then the AP will use protection * mechanism using RTS/CTS to self to reserve the airtime. + * This is used in + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME: Optional (u32) * This attribute is used as the SP offset which is the offset from * TSF after which the wake happens. The units are in microseconds. If * this attribute is not provided, then the value will be set to zero. + * This is an optional parameter for + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION: Required (u32) - * This is the duration of the service period. The units are in TU. + * This is the duration of the service period. This is specified as + * multiples of 256 microseconds. Valid values are 0x1 to 0xFF. + * This is a required parameter for + * 1. TWT SET Request and Response + * 2. TWT GET Response * * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA: Required (u32) * This attribute is used to configure wake interval mantissa. * The units are in TU. + * This is a required parameter for + * 1. TWT SET Request and Response + * 2. TWT GET Response + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS: Required (u8) + * This field is applicable for TWT response only. + * This contains status values in enum qca_wlan_vendor_twt_status + * and is passed to the userspace. This is used in TWT SET operation. + * This is a required parameter for + * 1. TWT SET Response + * 2. TWT TERMINATE Response + * 3. TWT SUSPEND Response + * 4. TWT RESUME Response + * 5. TWT NUDGE Response + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE: Required (u8) + * This field is applicable for TWT response only. + * This field contains response type from the TWT responder and is + * passed to the userspace. The values for this field are defined in + * enum qca_wlan_vendor_twt_setup_resp_type. This is used in TWT SET + * response. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF: Required (u64) + * This field is applicable for TWT response only. + * This field contains absolute TSF value of the wake time received + * from the TWT responder and is passed to the userspace. + * This is a required parameter for + * 1. TWT SET Response + * 2. TWT GET Response + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED: Flag attribute. + * Enable (flag attribute present) - Indicates that the TWT responder + * supports reception of TWT information frame from the TWT requestor. + * Disable (flag attribute not present) - Indicates that the responder + * doesn't support reception of TWT information frame from requestor. + * This is used in + * 1. TWT SET Response + * 2. TWT GET Response + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR: 6-byte MAC address + * Represents the MAC address of the peer for which the TWT session + * is being configured. This is used in AP mode to represent the respective + * client. In AP mode, this is an optional parameter for response and is + * a required parameter for + * 1. TWT SET Request + * 2. TWT GET Request + * 3. TWT TERMINATE Request + * 4. TWT SUSPEND Request + * In STA mode, this is an optional parameter in request and response for + * the above four TWT operations. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL: Optional (u32) + * Minimum tolerance limit of wake interval parameter in microseconds. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL: Optional (u32) + * Maximum tolerance limit of wake interval parameter in microseconds. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION: Optional (u32) + * Minimum tolerance limit of wake duration parameter in microseconds. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION: Optional (u32) + * Maximum tolerance limit of wake duration parameter in microseconds. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE: Optional (u32) + * TWT state for the given dialog id. The values for this are represented + * by enum qca_wlan_twt_setup_state. + * This is obtained through TWT GET operation. */ enum qca_wlan_vendor_attr_twt_setup { QCA_WLAN_VENDOR_ATTR_TWT_SETUP_INVALID = 0, @@ -7249,6 +8247,19 @@ enum qca_wlan_vendor_attr_twt_setup { QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_DURATION = 9, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_INTVL_MANTISSA = 10, + /* TWT Response only attributes */ + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATUS = 11, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_RESP_TYPE = 12, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_WAKE_TIME_TSF = 13, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_TWT_INFO_ENABLED = 14, + + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAC_ADDR = 15, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_INTVL = 16, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_INTVL = 17, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MIN_WAKE_DURATION = 18, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX_WAKE_DURATION = 19, + QCA_WLAN_VENDOR_ATTR_TWT_SETUP_STATE = 20, + /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_SETUP_AFTER_LAST, QCA_WLAN_VENDOR_ATTR_TWT_SETUP_MAX = @@ -7256,24 +8267,101 @@ enum qca_wlan_vendor_attr_twt_setup { }; /** - * enum qca_wlan_vendor_attr_twt_resume: Represents attributes for + * enum qca_wlan_vendor_twt_status - Represents the status of the requested + * TWT operation + * + * @QCA_WLAN_VENDOR_TWT_STATUS_OK: TWT request successfully completed + * @QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_ENABLED: TWT not enabled + * @QCA_WLAN_VENDOR_TWT_STATUS_USED_DIALOG_ID: TWT dialog ID is already used + * @QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY: TWT session is busy + * @QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST: TWT session does not exist + * @QCA_WLAN_VENDOR_TWT_STATUS_NOT_SUSPENDED: TWT session not in suspend state + * @QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM: Invalid parameters + * @QCA_WLAN_VENDOR_TWT_STATUS_NOT_READY: FW not ready + * @QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE: FW resource exhausted + * @QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK: Peer AP/STA did not ACK the + * request/response frame + * @QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE: Peer AP did not send the response + * frame + * @QCA_WLAN_VENDOR_TWT_STATUS_DENIED: AP did not accept the request + * @QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR: Adding TWT dialog failed due to an + * unknown reason + * @QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED: TWT session already in + * suspend state + * @QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID: FW has dropped the frame due to + * invalid IE in the received TWT frame + * @QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE: Parameters received from + * the responder are not in the specified range + * @QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE: FW terminated the TWT + * session due to request from the responder. Used on the TWT_TERMINATE + * notification from the firmware. + * @QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE: FW terminated the TWT + * session due to roaming. Used on the TWT_TERMINATE notification from the + * firmware. + */ +enum qca_wlan_vendor_twt_status { + QCA_WLAN_VENDOR_TWT_STATUS_OK = 0, + QCA_WLAN_VENDOR_TWT_STATUS_TWT_NOT_ENABLED = 1, + QCA_WLAN_VENDOR_TWT_STATUS_USED_DIALOG_ID = 2, + QCA_WLAN_VENDOR_TWT_STATUS_SESSION_BUSY = 3, + QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST = 4, + QCA_WLAN_VENDOR_TWT_STATUS_NOT_SUSPENDED = 5, + QCA_WLAN_VENDOR_TWT_STATUS_INVALID_PARAM = 6, + QCA_WLAN_VENDOR_TWT_STATUS_NOT_READY = 7, + QCA_WLAN_VENDOR_TWT_STATUS_NO_RESOURCE = 8, + QCA_WLAN_VENDOR_TWT_STATUS_NO_ACK = 9, + QCA_WLAN_VENDOR_TWT_STATUS_NO_RESPONSE = 10, + QCA_WLAN_VENDOR_TWT_STATUS_DENIED = 11, + QCA_WLAN_VENDOR_TWT_STATUS_UNKNOWN_ERROR = 12, + QCA_WLAN_VENDOR_TWT_STATUS_ALREADY_SUSPENDED = 13, + QCA_WLAN_VENDOR_TWT_STATUS_IE_INVALID = 14, + QCA_WLAN_VENDOR_TWT_STATUS_PARAMS_NOT_IN_RANGE = 15, + QCA_WLAN_VENDOR_TWT_STATUS_PEER_INITIATED_TERMINATE = 16, + QCA_WLAN_VENDOR_TWT_STATUS_ROAM_INITIATED_TERMINATE = 17, +}; + +/** + * enum qca_wlan_vendor_attr_twt_resume - Represents attributes for * TWT (Target Wake Time) resume request. These attributes are sent as part of * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_TWT_RESUME and - * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. + * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. Also used by + * attributes through %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT: Optional (u8) - * This attribute is used as the SP offset which is the offset from - * TSF after which the wake happens. The units are in microseconds. - * If this attribute is not provided, then the value will be set to - * zero. + * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT2_TWT: Optional (u32) + * These attributes are used as the SP offset which is the offset from TSF after + * which the wake happens. The units are in microseconds. Please note that + * _NEXT_TWT is limited to u8 whereas _NEXT2_TWT takes the u32 data. + * _NEXT2_TWT takes the precedence over _NEXT_TWT and thus the recommendation + * is to use _NEXT2_TWT. If neither of these attributes is provided, the value + * will be set to zero. * * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE: Required (u32) * This attribute represents the next TWT subfield size. + * Value 0 represents 0 bits, 1 represents 32 bits, 2 for 48 bits, + * and 4 for 64 bits. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID: Required (u8). + * Flow ID is the unique identifier for each TWT session. This attribute + * represents the respective TWT session to resume. + * Flow ID values from 0 to 254 represent a single TWT session + * Flow ID value of 255 represents all TWT sessions. + * If an invalid dialog id is provided, status + * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAC_ADDR: 6-byte MAC address + * Represents the MAC address of the peer to which TWT Resume is + * being sent. This is used in AP mode to represent the respective + * client and is a required parameter. In STA mode, this is an optional + * parameter */ enum qca_wlan_vendor_attr_twt_resume { QCA_WLAN_VENDOR_ATTR_TWT_RESUME_INVALID = 0, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT = 1, QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT_TWT_SIZE = 2, + QCA_WLAN_VENDOR_ATTR_TWT_RESUME_FLOW_ID = 3, + QCA_WLAN_VENDOR_ATTR_TWT_RESUME_NEXT2_TWT = 4, + QCA_WLAN_VENDOR_ATTR_TWT_RESUME_MAC_ADDR = 5, /* keep last */ QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST, @@ -7281,6 +8369,232 @@ enum qca_wlan_vendor_attr_twt_resume { QCA_WLAN_VENDOR_ATTR_TWT_RESUME_AFTER_LAST - 1, }; +/** + * enum qca_wlan_vendor_attr_twt_nudge - Represents attributes for + * TWT (Target Wake Time) nudge request. TWT nudge is a combination of suspend + * and resume in a single request. These attributes are sent as part of + * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID: Required (u8) + * Flow ID is the unique identifier for each TWT session. This attribute + * represents the respective TWT session to suspend and resume. + * Flow ID values from 0 to 254 represent a single TWT session + * Flow ID value of 255 represents all TWT sessions in TWT NUDGE request + * and response. + * If an invalid dialog id is provided, status + * QCA_WLAN_VENDOR_TWT_STATUS_SESSION_NOT_EXIST will be returned. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME: Required (u32) + * This attribute is used as the SP offset which is the offset from + * TSF after which the wake happens. The units are in microseconds. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE: Required (u32) + * This attribute represents the next TWT subfield size. + * Value 0 represents 0 bits, 1 represents 32 bits, 2 for 48 bits, + * and 4 for 64 bits. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR: 6-byte MAC address + * Represents the MAC address of the peer to which TWT Suspend and Resume is + * being sent. This is used in AP mode to represent the respective + * client and is a required parameter. In STA mode, this is an optional + * parameter. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF: Optional (u64) + * This field contains absolute TSF value of the time at which the TWT + * session will be resumed. + */ +enum qca_wlan_vendor_attr_twt_nudge { + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_FLOW_ID = 1, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME = 2, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_NEXT_TWT_SIZE = 3, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAC_ADDR = 4, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_WAKE_TIME_TSF = 5, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_MAX = + QCA_WLAN_VENDOR_ATTR_TWT_NUDGE_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_twt_stats: Represents attributes for + * TWT (Target Wake Time) get statistics and clear statistics request. + * These attributes are sent as part of + * %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TWT. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID: Required (u8) + * Flow ID is the unique identifier for each TWT session. This attribute + * represents the respective TWT session for get and clear TWT statistics. + * Flow ID values from 0 to 254 represent a single TWT session + * Flow ID value of 255 represents all TWT sessions in + * 1) TWT GET STATISTICS request and response + * 2) TWT CLEAR STATISTICS request + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR: 6-byte MAC address + * Represents the MAC address of the peer for which TWT Statistics + * is required. + * In AP mode this is used to represent the respective + * client and is a required parameter for + * 1) TWT GET STATISTICS request and response + * 2) TWT CLEAR STATISTICS request and response + * In STA mode, this is an optional parameter. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION: Required (u32) + * This is the duration of the service period in microseconds. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION: Required (u32) + * Average of the actual wake duration observed so far. Unit is microseconds. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS: Required (u32) + * The number of TWT service periods elapsed so far. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION: Required (u32) + * This is the minimum value of the wake duration observed across + * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. Unit is + * microseconds. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION: Required (u32) + * This is the maximum value of wake duration observed across + * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. Unit is + * microseconds. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU: Required (u32) + * Average number of MPDUs transmitted successfully across + * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU: Required (u32) + * Average number of MPDUs received successfully across + * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE: Required (u32) + * Average number of bytes transmitted successfully across + * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE: Required (u32) + * Average number of bytes received successfully across + * QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS. + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS: Required (u32) + * Status of the TWT GET STATISTICS request. + * This contains status values in enum qca_wlan_vendor_twt_status + * Obtained in the QCA_WLAN_TWT_GET_STATS response from the firmware. + */ +enum qca_wlan_vendor_attr_twt_stats { + QCA_WLAN_VENDOR_ATTR_TWT_STATS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_FLOW_ID = 1, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAC_ADDR = 2, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_SESSION_WAKE_DURATION = 3, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVG_WAKE_DURATION = 4, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_NUM_SP_ITERATIONS = 5, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_MIN_WAKE_DURATION = 6, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX_WAKE_DURATION = 7, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_MPDU = 8, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_MPDU = 9, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_TX_PACKET_SIZE = 10, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AVERAGE_RX_PACKET_SIZE = 11, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_STATUS = 12, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TWT_STATS_MAX = + QCA_WLAN_VENDOR_ATTR_TWT_STATS_AFTER_LAST - 1, +}; + +/** + * qca_wlan_twt_get_capa - Represents the bitmap of TWT capabilities + * supported by the device and the peer. + * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TWT_GET_CAPABILITIES + * + * @QCA_WLAN_TWT_CAPA_REQUESTOR: TWT requestor support is advertised by + * TWT non-scheduling STA. This capability is advertised in the HE + * Capability/Extended Capabilities information element in the + * Association Request frame by the device. + * + * @QCA_WLAN_TWT_CAPA_RESPONDER: TWT responder support is advertised by + * the TWT scheduling AP. This capability is advertised in the Extended + * Capabilities/HE Capabilities information element. + * + * @QCA_WLAN_TWT_CAPA_BROADCAST: On the requestor side, this indicates support + * for the broadcast TWT functionality. On the responder side, this indicates + * support for the role of broadcast TWT scheduling functionality. This + * capability is advertised in the HE Capabilities information element. + * + * @QCA_WLAN_TWT_CAPA_TWT_FLEXIBLE: The device supports flexible TWT schedule. + * This capability is advertised in the HE Capabilities information element. + * + * @QCA_WLAN_TWT_CAPA_REQUIRED: The TWT Required is advertised by AP to indicate + * that it mandates the associated HE STAs to support TWT. This capability is + * advertised by AP in the HE Operation Parameters field of the HE Operation + * information element. + */ +enum qca_wlan_twt_capa { + QCA_WLAN_TWT_CAPA_REQUESTOR = BIT(0), + QCA_WLAN_TWT_CAPA_RESPONDER = BIT(1), + QCA_WLAN_TWT_CAPA_BROADCAST = BIT(2), + QCA_WLAN_TWT_CAPA_FLEXIBLE = BIT(3), + QCA_WLAN_TWT_CAPA_REQUIRED = BIT(4), +}; + +/** + * enum qca_wlan_vendor_attr_twt_capability - Represents attributes for TWT + * get capabilities request type. Used by QCA_WLAN_TWT_GET_CAPABILITIES TWT + * operation. + * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAC_ADDR: 6-byte MAC address + * Represents the MAC address of the peer for which the TWT capabilities + * are being queried. This is used in AP mode to represent the respective + * client. In STA mode, this is an optional parameter. + * + * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF: (u16). + * Self TWT capabilities. Carries a bitmap of TWT capabilities specified in + * enum qca_wlan_twt_capa. + * @QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER: (u16). + * Peer TWT capabilities. Carries a bitmap of TWT capabilities specified in + * enum qca_wlan_twt_capa. + */ +enum qca_wlan_vendor_attr_twt_capability { + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAC_ADDR = 1, + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_SELF = 2, + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_PEER = 3, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_MAX = + QCA_WLAN_VENDOR_ATTR_TWT_CAPABILITIES_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_twt_setup_resp_type - Represents the response type by + * the TWT responder + * + * @QCA_WLAN_VENDOR_TWT_RESP_ALTERNATE: TWT responder suggests TWT + * parameters that are different from TWT requesting STA suggested + * or demanded TWT parameters + * @QCA_WLAN_VENDOR_TWT_RESP_DICTATE: TWT responder demands TWT + * parameters that are different from TWT requesting STA TWT suggested + * or demanded parameters + * @QCA_WLAN_VENDOR_TWT_RESP_REJECT: TWT responder rejects TWT + * setup + * @QCA_WLAN_VENDOR_TWT_RESP_ACCEPT: TWT responder accepts the TWT + * setup. + */ +enum qca_wlan_vendor_twt_setup_resp_type { + QCA_WLAN_VENDOR_TWT_RESP_ALTERNATE = 1, + QCA_WLAN_VENDOR_TWT_RESP_DICTATE = 2, + QCA_WLAN_VENDOR_TWT_RESP_REJECT = 3, + QCA_WLAN_VENDOR_TWT_RESP_ACCEPT = 4, +}; + /** * enum qca_wlan_vendor_twt_setup_req_type - Required (u8) * Represents the setup type being requested for TWT. @@ -7353,10 +8667,42 @@ enum qca_wlan_vendor_attr_roam_scan { * enum qca_wlan_vendor_cfr_method - QCA vendor CFR methods used by * attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD as part of vendor * command QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG. + * @QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL: CFR method using QoS Null frame + * @QCA_WLAN_VENDOR_CFR_QOS_NULL_WITH_PHASE: CFR method using QoS Null frame + * with phase + * @QCA_WLAN_VENDOR_CFR_PROBE_RESPONSE: CFR method using Probe Response frame */ enum qca_wlan_vendor_cfr_method { - /* CFR method using QOS Null frame */ QCA_WLAN_VENDOR_CFR_METHOD_QOS_NULL = 0, + QCA_WLAN_VENDOR_CFR_QOS_NULL_WITH_PHASE = 1, + QCA_WLAN_VENDOR_CFR_PROBE_RESPONSE = 2, +}; + +/** + * enum qca_wlan_vendor_cfr_capture_type - QCA vendor CFR capture type used by + * attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE. + * @QCA_WLAN_VENDOR_CFR_DIRECT_FTM: Filter directed FTM ACK frames. + * @QCA_WLAN_VENDOR_CFR_ALL_FTM_ACK: Filter all FTM ACK frames. + * @QCA_WLAN_VENDOR_CFR_DIRECT_NDPA_NDP: Filter NDPA NDP directed frames. + * @QCA_WLAN_VENDOR_CFR_TA_RA: Filter frames based on TA/RA/Subtype which + * is provided by one or more of below attributes: + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER + * @QCA_WLAN_CFR_ALL_PACKET: Filter all packets. + * @QCA_WLAN_VENDOR_CFR_NDPA_NDP_ALL: Filter all NDPA NDP frames. + */ +enum qca_wlan_vendor_cfr_capture_type { + QCA_WLAN_VENDOR_CFR_DIRECT_FTM = 0, + QCA_WLAN_VENDOR_CFR_ALL_FTM_ACK = 1, + QCA_WLAN_VENDOR_CFR_DIRECT_NDPA_NDP = 2, + QCA_WLAN_VENDOR_CFR_TA_RA = 3, + QCA_WLAN_VENDOR_CFR_ALL_PACKET = 4, + QCA_WLAN_VENDOR_CFR_NDPA_NDP_ALL = 5, }; /** @@ -7364,44 +8710,177 @@ enum qca_wlan_vendor_cfr_method { * QCA_NL80211_VENDOR_SUBCMD_PEER_CFR_CAPTURE_CFG to configure peer * Channel Frequency Response capture parameters and enable periodic CFR * capture. + * + * @QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR: Optional (6-byte MAC address) + * MAC address of peer. This is for CFR version 1 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE: Required (flag) + * Enable peer CFR capture. This attribute is mandatory to enable peer CFR + * capture. If this attribute is not present, peer CFR capture is disabled. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH: Optional (u8) + * BW of measurement, attribute uses the values in enum nl80211_chan_width + * Supported values: 20, 40, 80, 80+80, 160. + * Note that all targets may not support all bandwidths. + * This attribute is mandatory for version 1 if attribute + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY: Optional (u32) + * Periodicity of CFR measurement in milliseconds. + * Periodicity should be a multiple of Base timer. + * Current Base timer value supported is 10 milliseconds (default). + * 0 for one shot capture. + * This attribute is mandatory for version 1 if attribute + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD: Optional (u8) + * Method used to capture Channel Frequency Response. + * Attribute uses the values defined in enum qca_wlan_vendor_cfr_method. + * This attribute is mandatory for version 1 if attribute + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. + * + * @QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE: Optional (flag) + * Enable periodic CFR capture. + * This attribute is mandatory for version 1 to enable Periodic CFR capture. + * If this attribute is not present, periodic CFR capture is disabled. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION: Optional (u8) + * Value is 1 or 2 since there are two versions of CFR capture. Two versions + * can't be enabled at same time. This attribute is mandatory if target + * support both versions and use one of them. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP: Optional (u32) + * This attribute is mandatory for version 2 if + * QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY is used. + * Bits 15:0 bitfield indicates which group is to be enabled. + * Bits 31:16 Reserved for future use. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION: Optional (u32) + * CFR capture duration in microsecond. This attribute is mandatory for + * version 2 if attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL is used. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL: Optional (u32) + * CFR capture interval in microsecond. This attribute is mandatory for + * version 2 if attribute QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION is used. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE: Optional (u32) + * CFR capture type is defined in enum qca_wlan_vendor_cfr_capture_type. + * This attribute is mandatory for version 2. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK: Optional (u64) + * Bitfield indicating which user in the current UL MU transmissions are + * enabled for CFR capture. Bits 36 to 0 indicate user indexes for 37 users in + * a UL MU transmission. If bit 0 is set, the CFR capture will happen for user + * index 0 in the current UL MU transmission. If bits 0 and 2 are set, CFR + * capture for UL MU TX corresponds to user indices 0 and 2. Bits 63:37 are + * reserved for future use. This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT: Optional (u32) + * Indicates the number of consecutive RX frames to be skipped before CFR + * capture is enabled again. This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE: Nested attribute containing + * one or more %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY attributes. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY: Nested attribute containing + * the following group attributes: + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER, + * %QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER: Optional (u32) + * Target supports multiple groups for some configurations. The group number + * can be any value between 0 and 15. This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA: Optional (6-byte MAC address) + * Transmitter address which is used to filter frames. This MAC address takes + * effect with QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK. This is for CFR + * version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA: Optional (6-byte MAC address) + * Receiver address which is used to filter frames. This MAC address takes + * effect with QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK. This is for CFR + * version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK: Optional (6-byte MAC address) + * Mask of transmitter address which is used to filter frames. This is for CFR + * version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK: Optional (6-byte MAC address) + * Mask of receiver address which is used to filter frames. This is for CFR + * version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS: Optional (u32) + * Indicates frames with a specific NSS will be filtered for CFR capture. + * This is for CFR version 2 only. This is a bitmask. Bits 7:0 request CFR + * capture to be done for frames matching the NSS specified within this bitmask. + * Bits 31:8 are reserved for future use. Bits 7:0 map to NSS: + * bit 0 : NSS 1 + * bit 1 : NSS 2 + * ... + * bit 7 : NSS 8 + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW: Optional (u32) + * Indicates frames with a specific bandwidth will be filtered for CFR capture. + * This is for CFR version 2 only. This is a bitmask. Bits 4:0 request CFR + * capture to be done for frames matching the bandwidths specified within this + * bitmask. Bits 31:5 are reserved for future use. Bits 4:0 map to bandwidth + * numerated in enum nl80211_band (although not all bands may be supported + * by a given device). + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER: Optional (u32) + * Management frames matching the subtype filter categories will be filtered in + * by MAC for CFR capture. This is a bitmask in which each bit represents the + * corresponding Management frame subtype value per IEEE Std 802.11-2016, + * 9.2.4.1.3 Type and Subtype subfields. For example, Beacon frame control type + * is 8 and its value is 1 << 8 = 0x100. This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER: Optional (u32) + * Control frames matching the subtype filter categories will be filtered in by + * MAC for CFR capture. This is a bitmask in which each bit represents the + * corresponding Control frame subtype value per IEEE Std 802.11-2016, + * 9.2.4.1.3 Type and Subtype subfields. This is for CFR version 2 only. + * + * @QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER: Optional (u32) + * Data frames matching the subtype filter categories will be filtered in by + * MAC for CFR capture. This is a bitmask in which each bit represents the + * corresponding Data frame subtype value per IEEE Std 802.11-2016, + * 9.2.4.1.3 Type and Subtype subfields. This is for CFR version 2 only. */ enum qca_wlan_vendor_peer_cfr_capture_attr { QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_INVALID = 0, - /* 6-byte MAC address of the peer. - * This attribute is mandatory. - */ QCA_WLAN_VENDOR_ATTR_CFR_PEER_MAC_ADDR = 1, - /* Enable peer CFR Capture, flag attribute. - * This attribute is mandatory to enable peer CFR capture. - * If this attribute is not present, peer CFR capture is disabled. - */ QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE = 2, - /* BW of measurement, attribute uses the values in enum nl80211_chan_width - * Supported values: 20, 40, 80, 80+80, 160. - * Note that all targets may not support all bandwidths. - * u8 attribute. This attribute is mandatory if attribute - * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. - */ QCA_WLAN_VENDOR_ATTR_PEER_CFR_BANDWIDTH = 3, - /* Periodicity of CFR measurement in msec. - * Periodicity should be a multiple of Base timer. - * Current Base timer value supported is 10 msecs (default). - * 0 for one shot capture. u32 attribute. - * This attribute is mandatory if attribute - * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. - */ QCA_WLAN_VENDOR_ATTR_PEER_CFR_PERIODICITY = 4, - /* Method used to capture Channel Frequency Response. - * Attribute uses the values defined in enum qca_wlan_vendor_cfr_method. - * u8 attribute. This attribute is mandatory if attribute - * QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE is used. - */ QCA_WLAN_VENDOR_ATTR_PEER_CFR_METHOD = 5, - /* Enable periodic CFR capture, flag attribute. - * This attribute is mandatory to enable Periodic CFR capture. - * If this attribute is not present, periodic CFR capture is disabled. - */ QCA_WLAN_VENDOR_ATTR_PERIODIC_CFR_CAPTURE_ENABLE = 6, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_VERSION = 7, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_ENABLE_GROUP_BITMAP = 8, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_DURATION = 9, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_INTERVAL = 10, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_CAPTURE_TYPE = 11, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_UL_MU_MASK = 12, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_FREEZE_TLV_DELAY_COUNT = 13, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TABLE = 14, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_ENTRY = 15, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NUMBER = 16, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA = 17, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA = 18, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_TA_MASK = 19, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_RA_MASK = 20, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_NSS = 21, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_BW = 22, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_MGMT_FILTER = 23, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_CTRL_FILTER = 24, + QCA_WLAN_VENDOR_ATTR_PEER_CFR_GROUP_DATA_FILTER = 25, /* Keep last */ QCA_WLAN_VENDOR_ATTR_PEER_CFR_AFTER_LAST, @@ -8049,10 +9528,14 @@ enum qca_vendor_oem_device_type { * enum qca_wlan_vendor_attr_oem_data_params - Used by the vendor command/event * QCA_NL80211_VENDOR_SUBCMD_OEM_DATA. * - * @QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA: The binary blob for the vendor - * command/event QCA_NL80211_VENDOR_SUBCMD_OEM_DATA are carried through this - * attribute. - * NLA_BINARY attribute, the max size is 1024 bytes. + * @QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA: This NLA_BINARY attribute is + * used to set/query the data to/from the firmware. On query, the same + * attribute is used to carry the respective data in the reply sent by the + * driver to userspace. The request to set/query the data and the format of the + * respective data from the firmware are embedded in the attribute. The + * maximum size of the attribute payload is 1024 bytes. + * Userspace has to set the QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED + * attribute when the data is queried from the firmware. * * @QCA_WLAN_VENDOR_ATTR_OEM_DEVICE_INFO: The binary blob will be routed * based on this field. This optional attribute is included to specify whether @@ -8061,11 +9544,16 @@ enum qca_vendor_oem_device_type { * command/event. * This u8 attribute is used to carry information for the device type using * values defined by enum qca_vendor_oem_device_type. + * + * @QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED: This NLA_FLAG attribute + * is set when the userspace queries data from the firmware. This attribute + * should not be set when userspace sets the OEM data to the firmware. */ enum qca_wlan_vendor_attr_oem_data_params { QCA_WLAN_VENDOR_ATTR_OEM_DATA_INVALID = 0, QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA = 1, QCA_WLAN_VENDOR_ATTR_OEM_DEVICE_INFO = 2, + QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED = 3, /* keep last */ QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_AFTER_LAST, @@ -8399,6 +9887,36 @@ enum qca_vendor_wlan_sta_guard_interval { * disconnect reason for the last disconnection if the disconnection is * triggered from the host driver. The values are referred from * enum qca_disconnect_reason_codes. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_MIC_ERROR_COUNT: u32, used in STA mode + * only. This represents the number of group addressed robust management frames + * received from this station with an invalid MIC or a missing MME when PMF is + * enabled. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT: u32, used in STA mode + * only. This represents the number of group addressed robust management frames + * received from this station with the packet number less than or equal to the + * last received packet number when PMF is enabled. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT: u32, used in STA + * mode only. This represents the number of Beacon frames received from this + * station with an invalid MIC or a missing MME when beacon protection is + * enabled. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT: u32, used in STA mode + * only. This represents number of Beacon frames received from this station with + * the packet number less than or equal to the last received packet number when + * beacon protection is enabled. + * + * @QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE: u32, used in + * STA mode only. The driver uses this attribute to populate the connection + * failure reason codes and the values are defined in + * enum qca_sta_connect_fail_reason_codes. Userspace applications can send + * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO vendor command after receiving + * a connection failure indication from the driver. The driver shall not + * include this attribute in response to the + * QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO command if there is no connection + * failure observed in the last attempted connection. */ enum qca_wlan_vendor_attr_get_sta_info { QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_INVALID = 0, @@ -8440,6 +9958,11 @@ enum qca_wlan_vendor_attr_get_sta_info { QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_IES = 36, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_PROBE_RESP_IES = 37, QCA_WLAN_VENDOR_ATTR_GET_STA_DRIVER_DISCONNECT_REASON = 38, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_MIC_ERROR_COUNT = 39, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BIP_REPLAY_COUNT = 40, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_MIC_ERROR_COUNT = 41, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_BEACON_REPLAY_COUNT = 42, + QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE = 43, /* keep last */ QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_AFTER_LAST, @@ -8569,4 +10092,352 @@ enum qca_wlan_vendor_attr_driver_disconnect_reason { QCA_WLAN_VENDOR_ATTR_DRIVER_DISCONNECT_REASON_AFTER_LAST - 1, }; +/** + * enum qca_wlan_tspec_operation - Operation of the config TSPEC request + * + * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_OPERATION. + */ +enum qca_wlan_tspec_operation { + QCA_WLAN_TSPEC_ADD = 0, + QCA_WLAN_TSPEC_DEL = 1, + QCA_WLAN_TSPEC_GET = 2, +}; + +/** + * enum qca_wlan_tspec_direction - Direction in TSPEC + * As what is defined in IEEE Std 802.11-2016, Table 9-139. + * + * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_DIRECTION. + */ +enum qca_wlan_tspec_direction { + QCA_WLAN_TSPEC_DIRECTION_UPLINK = 0, + QCA_WLAN_TSPEC_DIRECTION_DOWNLINK = 1, + QCA_WLAN_TSPEC_DIRECTION_DIRECT = 2, + QCA_WLAN_TSPEC_DIRECTION_BOTH = 3, +}; + +/** + * enum qca_wlan_tspec_ack_policy - MAC acknowledgement policy in TSPEC + * As what is defined in IEEE Std 802.11-2016, Table 9-141. + * + * Values for %QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_ACK_POLICY. + */ +enum qca_wlan_tspec_ack_policy { + QCA_WLAN_TSPEC_NORMAL_ACK = 0, + QCA_WLAN_TSPEC_NO_ACK = 1, + /* Reserved */ + QCA_WLAN_TSPEC_BLOCK_ACK = 3, +}; + +/** + * enum qca_wlan_vendor_attr_config_tspec - Defines attributes + * used by %QCA_NL80211_VENDOR_SUBCMD_CONFIG_TSPEC vendor command. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_OPERATION: + * u8 attribute. Specify the TSPEC operation of this request. Possible values + * are defined in enum qca_wlan_tspec_operation. + * Mandatory attribute for all kinds of config TSPEC requests. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_TSID: + * u8 attribute. TS ID. Possible values are 0-7. + * Applicable for operation: QCA_WLAN_TSPEC_ADD, QCA_WLAN_TSPEC_DEL, + * QCA_WLAN_TSPEC_GET. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_DIRECTION: + * u8 attribute. Direction of data carried by the TS. Possible values are + * defined in enum qca_wlan_tspec_direction. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_APSD: + * Flag attribute. Indicate whether APSD is enabled for the traffic associated + * with the TS. set - enabled, not set - disabled. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_USER_PRIORITY: + * u8 attribute. User priority to be used for the transport of MSDUs/A-MSDUs + * belonging to this TS. Possible values are 0-7. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_ACK_POLICY: + * u8 attribute. Indicate whether MAC acknowledgements are required for + * MPDUs/A-MSDUs belonging to this TS and the form of those acknowledgements. + * Possible values are defined in enum qca_wlan_tspec_ack_policy. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_NOMINAL_MSDU_SIZE: + * u16 attribute. Specify the nominal size in bytes of MSDUs/A-MSDUs + * belonging to this TS. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAXIMUM_MSDU_SIZE: + * u16 attribute. Specify the maximum size in bytes of MSDUs/A-MSDUs + * belonging to this TS. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MIN_SERVICE_INTERVAL: + * u32 attribute. Specify the minimum interval in microseconds between the + * start of two successive SPs. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAX_SERVICE_INTERVAL: + * u32 attribute. Specify the maximum interval in microseconds between the + * start of two successive SPs. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_INACTIVITY_INTERVAL: + * u32 attribute. Specify the minimum interval in microseconds that can elapse + * without arrival or transfer of an MPDU belonging to the TS before this TS + * is deleted by the MAC entity at the HC. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_SUSPENSION_INTERVAL: + * u32 attribute. Specify the minimum interval in microseconds that can elapse + * without arrival or transfer of an MSDU belonging to the TS before the + * generation of successive QoS(+)CF-Poll is stopped for this TS. A value of + * 0xFFFFFFFF disables the suspension interval. The value of the suspension + * interval is always less than or equal to the inactivity interval. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MINIMUM_DATA_RATE: + * u32 attribute. Indicate the lowest data rate in bps specified at the MAC + * SAP for transport of MSDUs or A-MSDUs belonging to this TS within the + * bounds of this TSPEC. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MEAN_DATA_RATE: + * u32 attribute. Indicate the average data rate in bps specified at the MAC + * SAP for transport of MSDUs or A-MSDUs belonging to this TS within the + * bounds of this TSPEC. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_PEAK_DATA_RATE: + * u32 attribute. Indicate the maximum allowable data rate in bps specified at + * the MAC SAP for transport of MSDUs or A-MSDUs belonging to this TS within + * the bounds of this TSPEC. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_BURST_SIZE: + * u32 attribute. Specify the maximum burst size in bytes of the MSDUs/A-MSDUs + * belonging to this TS that arrive at the MAC SAP at the peak data rate. A + * value of 0 indicates that there are no bursts. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MINIMUM_PHY_RATE: + * u32 attribute. Indicate the minimum PHY rate in bps for transport of + * MSDUs/A-MSDUs belonging to this TS within the bounds of this TSPEC. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. An optional attribute. + * + * @QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_SURPLUS_BANDWIDTH_ALLOWANCE: + * u16 attribute. Specify the excess allocation of time (and bandwidth) over + * and above the stated application rates required to transport an MSDU/A-MSDU + * belonging to the TS in this TSPEC. + * Applicable for operation: QCA_WLAN_TSPEC_ADD. A mandatory attribute. + */ +enum qca_wlan_vendor_attr_config_tspec { + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_OPERATION = 1, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_TSID = 2, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_DIRECTION = 3, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_APSD = 4, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_USER_PRIORITY = 5, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_ACK_POLICY = 6, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_NOMINAL_MSDU_SIZE = 7, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAXIMUM_MSDU_SIZE = 8, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MIN_SERVICE_INTERVAL = 9, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAX_SERVICE_INTERVAL = 10, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_INACTIVITY_INTERVAL = 11, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_SUSPENSION_INTERVAL = 12, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MINIMUM_DATA_RATE = 13, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MEAN_DATA_RATE = 14, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_PEAK_DATA_RATE = 15, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_BURST_SIZE = 16, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MINIMUM_PHY_RATE = 17, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_SURPLUS_BANDWIDTH_ALLOWANCE = 18, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_MAX = + QCA_WLAN_VENDOR_ATTR_CONFIG_TSPEC_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_oci_override_frame_type - OCI override frame type + * @QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_REQ: SA Query Request frame + * @QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_RESP: SA Query Response frame + * @QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FT_REASSOC_REQ: FT Reassociation Request + * frame + * @QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FILS_REASSOC_REQ: FILS Reassociation + * Request frame. + */ +enum qca_wlan_vendor_oci_override_frame_type { + QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_REQ = 1, + QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_SA_QUERY_RESP = 2, + QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FT_REASSOC_REQ = 3, + QCA_WLAN_VENDOR_OCI_OVERRIDE_FRAME_FILS_REASSOC_REQ = 4, +}; + +/** + * enum qca_wlan_vendor_attr_oci_override: Represents attributes for + * OCI override request. These attributes are used inside nested attribute + * %QCA_WLAN_VENDOR_ATTR_WIFI_TEST_CONFIG_OCI_OVERRIDE in QCA vendor command + * %QCA_NL80211_VENDOR_SUBCMD_WIFI_TEST_CONFIGURATION. + * + * @QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE: Required attribute, u8. + * Values from enum qca_wlan_vendor_oci_override_frame_type used in this + * attribute to specify the frame type in which the OCI is to be overridden. + * + * @QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY: Required (u32) + * OCI frequency (in MHz) to override in the specified frame type. + */ +enum qca_wlan_vendor_attr_oci_override { + QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FRAME_TYPE = 1, + QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_FREQUENCY = 2, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_MAX = + QCA_WLAN_VENDOR_ATTR_OCI_OVERRIDE_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_medium_assess_type - Type of medium assess request + * + * Values for %QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TYPE. + */ +enum qca_wlan_medium_assess_type { + QCA_WLAN_MEDIUM_ASSESS_CCA = 0, + QCA_WLAN_MEDIUM_ASSESS_CONGESTION_REPORT = 1, +}; + +/** + * enum qca_wlan_vendor_attr_medium_assess - Attributes used by + * %QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS vendor command. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TYPE: + * u8 attribute. Mandatory in all kinds of medium assess requests/responses. + * Specify the type of medium assess request and indicate its type in response. + * Possible values are defined in enum qca_wlan_medium_assess_type. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_PERIOD: + * u32 attribute. Mandatory in CCA request. + * Specify the assessment period in terms of seconds. Assessment result will be + * sent as the response to the CCA request after the assessment period. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TOTAL_CYCLE_COUNT: + * u32 attribute. Mandatory in response to CCA request. + * Total timer tick count of the assessment cycle. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IDLE_COUNT: + * u32 attribute. Mandatory in response to CCA request. + * Timer tick count of idle time in the assessment cycle. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IBSS_RX_COUNT: + * u32 attribute. Mandatory in response to CCA request. + * Timer tick count of Intra BSS traffic RX time in the assessment cycle. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_OBSS_RX_COUNT: + * u32 attribute. Mandatory in response to CCA request. + * Timer tick count of Overlapping BSS traffic RX time in the assessment cycle. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MAX_IBSS_RSSI: + * s32 attribute. Mandatory in response to CCA request. + * Maximum RSSI of Intra BSS traffic in the assessment cycle. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MIN_IBSS_RSSI: + * s32 attribute. Mandatory in response to CCA request. + * Minimum RSSI of Intra BSS traffic in the assessment cycle. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_ENABLE: + * u8 attribute. Mandatory in congestion report request. + * 1-enable 0-disable. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_THRESHOLD: + * u8 attribute. Mandatory in congestion report enable request and will be + * ignored if present in congestion report disable request. Possible values are + * 0-100. A vendor event QCA_NL80211_VENDOR_SUBCMD_MEDIUM_ASSESS with the type + * QCA_WLAN_MEDIUM_ASSESS_CONGESTION_REPORT will be sent to userspace if + * congestion percentage reaches the configured threshold. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_INTERVAL: + * u8 attribute. Optional in congestion report enable request and will be + * ignored if present in congestion report disable request. + * Specify the interval of congestion report event in terms of seconds. Possible + * values are 1-255. Default value 1 will be used if this attribute is omitted + * or using invalid values. + * + * @QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_PERCENTAGE: + * u8 attribute. Mandatory in congestion report event. + * Indicate the actual congestion percentage. Possible values are 0-100. + */ +enum qca_wlan_vendor_attr_medium_assess { + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TYPE = 1, + + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_PERIOD = 2, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_TOTAL_CYCLE_COUNT = 3, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IDLE_COUNT = 4, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_IBSS_RX_COUNT = 5, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_OBSS_RX_COUNT = 6, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MAX_IBSS_RSSI = 7, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MIN_IBSS_RSSI = 8, + + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_ENABLE = 9, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_THRESHOLD = 10, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_REPORT_INTERVAL = 11, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_CONGESTION_PERCENTAGE = 12, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_MAX = + QCA_WLAN_VENDOR_ATTR_MEDIUM_ASSESS_AFTER_LAST - 1, +}; + +/** + * enum qca_wlan_vendor_attr_mbssid_tx_vdev_status - Defines attributes + * used by QCA_NL80211_VENDOR_SUBCMD_MBSSID_TX_VDEV_STATUS vendor command. + * + * @QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL: + * u8 attribute. Notify the TX VDEV status. Possible values 0, 1 + * belonging to MBSSID/EMA_AP configuration. 0 means Non-Tx VDEV, + * 1 means Tx VDEV. Mandatory attribute for all MBSSID VDEV status events. + */ +enum qca_wlan_vendor_attr_mbssid_tx_vdev_status { + QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_INVALID = 0, + QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_VAL = 1, + + /* keep last */ + QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST, + QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_MAX = + QCA_WLAN_VENDOR_ATTR_MBSSID_TX_VDEV_STATUS_AFTER_LAST - 1, +}; + +/** + * enum qca_sta_connect_fail_reason_codes - Defines values carried + * by QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE vendor + * attribute. + * @QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: No Probe Response frame received + * for unicast Probe Request frame. + * @QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: STA failed to send auth request. + * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: AP didn't send ACK for + * auth request. + * @QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: Auth response is not + * received from AP. + * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: STA failed to send + * Association Request frame. + * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: AP didn't send ACK for + * Association Request frame. + * @QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: Association Response + * frame is not received from AP. + */ +enum qca_sta_connect_fail_reason_codes { + QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND = 1, + QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL = 2, + QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED = 3, + QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED = 4, + QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL = 5, + QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED = 6, + QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7, +}; + #endif /* QCA_VENDOR_H */ diff --git a/src/common/sae.c b/src/common/sae.c index 7ed53be1c..372905db0 100644 --- a/src/common/sae.c +++ b/src/common/sae.c @@ -169,7 +169,7 @@ static int sae_test_pwd_seed_ecc(struct sae_data *sae, const u8 *pwd_seed, * being smaller than prime. */ in_range = const_time_fill_msb((unsigned int) cmp_prime); /* The algorithm description would skip the next steps if - * cmp_prime >= 0 (reutnr 0 here), but go through them regardless to + * cmp_prime >= 0 (return 0 here), but go through them regardless to * minimize externally observable differences in behavior. */ x_cand = crypto_bignum_init_set(pwd_value, sae->tmp->prime_len); @@ -713,6 +713,8 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group, goto fail; const_time_select_bin(m_is_zero, bin1, bin2, prime_len, bin); x1 = crypto_bignum_init_set(bin, prime_len); + if (!x1) + goto fail; debug_print_bignum("SSWU: x1 = CSEL(l, x1a, x1b)", x1, prime_len); /* gx1 = x1^3 + a * x1 + b */ @@ -753,6 +755,8 @@ static struct crypto_ec_point * sswu(struct crypto_ec *ec, int group, goto fail; const_time_select_bin(is_qr, bin1, bin2, prime_len, bin); v = crypto_bignum_init_set(bin, prime_len); + if (!v) + goto fail; debug_print_bignum("SSWU: v = CSEL(l, gx1, gx2)", v, prime_len); /* x = CSEL(l, x1, x2) */ @@ -1052,10 +1056,17 @@ sae_derive_pt_group(int group, const u8 *ssid, size_t ssid_len, wpa_printf(MSG_DEBUG, "SAE: Derive PT - group %d", group); + if (ssid_len > 32) + return NULL; + pt = os_zalloc(sizeof(*pt)); if (!pt) return NULL; +#ifdef CONFIG_SAE_PK + os_memcpy(pt->ssid, ssid, ssid_len); + pt->ssid_len = ssid_len; +#endif /* CONFIG_SAE_PK */ pt->group = group; pt->ec = crypto_ec_init(group); if (pt->ec) { @@ -1354,14 +1365,15 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2, identifier) < 0)) return -1; - sae->tmp->h2e = 0; + sae->h2e = 0; + sae->pk = 0; return sae_derive_commit(sae); } int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, const u8 *addr1, const u8 *addr2, - int *rejected_groups) + int *rejected_groups, const struct sae_pk *pk) { if (!sae->tmp) return -1; @@ -1377,6 +1389,11 @@ int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, return -1; } +#ifdef CONFIG_SAE_PK + os_memcpy(sae->tmp->ssid, pt->ssid, pt->ssid_len); + sae->tmp->ssid_len = pt->ssid_len; + sae->tmp->ap_pk = pk; +#endif /* CONFIG_SAE_PK */ sae->tmp->own_addr_higher = os_memcmp(addr1, addr2, ETH_ALEN) > 0; wpabuf_free(sae->tmp->own_rejected_groups); sae->tmp->own_rejected_groups = NULL; @@ -1409,7 +1426,7 @@ int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, return -1; } - sae->tmp->h2e = 1; + sae->h2e = 1; return sae_derive_commit(sae); } @@ -1515,7 +1532,7 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k) const u8 *salt; struct wpabuf *rejected_groups = NULL; u8 keyseed[SAE_MAX_HASH_LEN]; - u8 keys[SAE_MAX_HASH_LEN + SAE_PMK_LEN]; + u8 keys[2 * SAE_MAX_HASH_LEN + SAE_PMK_LEN]; struct crypto_bignum *tmp; int ret = -1; size_t hash_len, salt_len, prime_len = sae->tmp->prime_len; @@ -1530,15 +1547,18 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k) * KCK || PMK = KDF-Hash-Length(keyseed, "SAE KCK and PMK", * (commit-scalar + peer-commit-scalar) modulo r) * PMKID = L((commit-scalar + peer-commit-scalar) modulo r, 0, 128) + * + * When SAE-PK is used, + * KCK || PMK || KEK = KDF-Hash-Length(keyseed, "SAE-PK keys", context) */ - if (!sae->tmp->h2e) + if (!sae->h2e) hash_len = SHA256_MAC_LEN; else if (sae->tmp->dh) hash_len = sae_ffc_prime_len_2_hash_len(prime_len); else hash_len = sae_ecc_prime_len_2_hash_len(prime_len); - if (sae->tmp->h2e && (sae->tmp->own_rejected_groups || - sae->tmp->peer_rejected_groups)) { + if (sae->h2e && (sae->tmp->own_rejected_groups || + sae->tmp->peer_rejected_groups)) { struct wpabuf *own, *peer; own = sae->tmp->own_rejected_groups; @@ -1589,15 +1609,40 @@ static int sae_derive_keys(struct sae_data *sae, const u8 *k) * octets). */ crypto_bignum_to_bin(tmp, val, sizeof(val), sae->tmp->order_len); wpa_hexdump(MSG_DEBUG, "SAE: PMKID", val, SAE_PMKID_LEN); + +#ifdef CONFIG_SAE_PK + if (sae->pk) { + if (sae_kdf_hash(hash_len, keyseed, "SAE-PK keys", + val, sae->tmp->order_len, + keys, 2 * hash_len + SAE_PMK_LEN) < 0) + goto fail; + } else { + if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", + val, sae->tmp->order_len, + keys, hash_len + SAE_PMK_LEN) < 0) + goto fail; + } +#else /* CONFIG_SAE_PK */ if (sae_kdf_hash(hash_len, keyseed, "SAE KCK and PMK", val, sae->tmp->order_len, keys, hash_len + SAE_PMK_LEN) < 0) goto fail; +#endif /* !CONFIG_SAE_PK */ + forced_memzero(keyseed, sizeof(keyseed)); os_memcpy(sae->tmp->kck, keys, hash_len); sae->tmp->kck_len = hash_len; os_memcpy(sae->pmk, keys + hash_len, SAE_PMK_LEN); os_memcpy(sae->pmkid, val, SAE_PMKID_LEN); +#ifdef CONFIG_SAE_PK + if (sae->pk) { + os_memcpy(sae->tmp->kek, keys + hash_len + SAE_PMK_LEN, + hash_len); + sae->tmp->kek_len = hash_len; + wpa_hexdump_key(MSG_DEBUG, "SAE: KEK for SAE-PK", + sae->tmp->kek, sae->tmp->kek_len); + } +#endif /* CONFIG_SAE_PK */ forced_memzero(keys, sizeof(keys)); wpa_hexdump_key(MSG_DEBUG, "SAE: KCK", sae->tmp->kck, sae->tmp->kck_len); @@ -1623,38 +1668,42 @@ int sae_process_commit(struct sae_data *sae) } -void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, - const struct wpabuf *token, const char *identifier) +int sae_write_commit(struct sae_data *sae, struct wpabuf *buf, + const struct wpabuf *token, const char *identifier) { u8 *pos; if (sae->tmp == NULL) - return; + return -1; wpabuf_put_le16(buf, sae->group); /* Finite Cyclic Group */ - if (!sae->tmp->h2e && token) { + if (!sae->h2e && token) { wpabuf_put_buf(buf, token); wpa_hexdump(MSG_DEBUG, "SAE: Anti-clogging token", wpabuf_head(token), wpabuf_len(token)); } pos = wpabuf_put(buf, sae->tmp->prime_len); - crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos, - sae->tmp->prime_len, sae->tmp->prime_len); + if (crypto_bignum_to_bin(sae->tmp->own_commit_scalar, pos, + sae->tmp->prime_len, sae->tmp->prime_len) < 0) + return -1; wpa_hexdump(MSG_DEBUG, "SAE: own commit-scalar", pos, sae->tmp->prime_len); if (sae->tmp->ec) { pos = wpabuf_put(buf, 2 * sae->tmp->prime_len); - crypto_ec_point_to_bin(sae->tmp->ec, - sae->tmp->own_commit_element_ecc, - pos, pos + sae->tmp->prime_len); + if (crypto_ec_point_to_bin(sae->tmp->ec, + sae->tmp->own_commit_element_ecc, + pos, pos + sae->tmp->prime_len) < 0) + return -1; wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(x)", pos, sae->tmp->prime_len); wpa_hexdump(MSG_DEBUG, "SAE: own commit-element(y)", pos + sae->tmp->prime_len, sae->tmp->prime_len); } else { pos = wpabuf_put(buf, sae->tmp->prime_len); - crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos, - sae->tmp->prime_len, sae->tmp->prime_len); + if (crypto_bignum_to_bin(sae->tmp->own_commit_element_ffc, pos, + sae->tmp->prime_len, + sae->tmp->prime_len) < 0) + return -1; wpa_hexdump(MSG_DEBUG, "SAE: own commit-element", pos, sae->tmp->prime_len); } @@ -1669,7 +1718,7 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, identifier); } - if (sae->tmp->h2e && sae->tmp->own_rejected_groups) { + if (sae->h2e && sae->tmp->own_rejected_groups) { wpa_hexdump_buf(MSG_DEBUG, "SAE: own Rejected Groups", sae->tmp->own_rejected_groups); wpabuf_put_u8(buf, WLAN_EID_EXTENSION); @@ -1679,7 +1728,7 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, wpabuf_put_buf(buf, sae->tmp->own_rejected_groups); } - if (sae->tmp->h2e && token) { + if (sae->h2e && token) { wpabuf_put_u8(buf, WLAN_EID_EXTENSION); wpabuf_put_u8(buf, 1 + wpabuf_len(token)); wpabuf_put_u8(buf, WLAN_EID_EXT_ANTI_CLOGGING_TOKEN); @@ -1688,6 +1737,8 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, "SAE: Anti-clogging token (in container)", token); } + + return 0; } @@ -2183,13 +2234,14 @@ static int sae_cn_confirm_ffc(struct sae_data *sae, const u8 *sc, } -void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) +int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) { const u8 *sc; size_t hash_len; + int res; if (sae->tmp == NULL) - return; + return -1; hash_len = sae->tmp->kck_len; @@ -2200,17 +2252,26 @@ void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf) sae->send_confirm++; if (sae->tmp->ec) - sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar, - sae->tmp->own_commit_element_ecc, - sae->peer_commit_scalar, - sae->tmp->peer_commit_element_ecc, - wpabuf_put(buf, hash_len)); + res = sae_cn_confirm_ecc(sae, sc, sae->tmp->own_commit_scalar, + sae->tmp->own_commit_element_ecc, + sae->peer_commit_scalar, + sae->tmp->peer_commit_element_ecc, + wpabuf_put(buf, hash_len)); else - sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar, - sae->tmp->own_commit_element_ffc, - sae->peer_commit_scalar, - sae->tmp->peer_commit_element_ffc, - wpabuf_put(buf, hash_len)); + res = sae_cn_confirm_ffc(sae, sc, sae->tmp->own_commit_scalar, + sae->tmp->own_commit_element_ffc, + sae->peer_commit_scalar, + sae->tmp->peer_commit_element_ffc, + wpabuf_put(buf, hash_len)); + if (res) + return res; + +#ifdef CONFIG_SAE_PK + if (sae_write_confirm_pk(sae, buf) < 0) + return -1; +#endif /* CONFIG_SAE_PK */ + + return 0; } @@ -2264,6 +2325,12 @@ int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len) return -1; } +#ifdef CONFIG_SAE_PK + if (sae_check_confirm_pk(sae, data + 2 + hash_len, + len - 2 - hash_len) < 0) + return -1; +#endif /* CONFIG_SAE_PK */ + return 0; } diff --git a/src/common/sae.h b/src/common/sae.h index e3e7d0eec..2243c0f33 100644 --- a/src/common/sae.h +++ b/src/common/sae.h @@ -16,11 +16,27 @@ #define SAE_MAX_ECC_PRIME_LEN 66 #define SAE_MAX_HASH_LEN 64 #define SAE_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN + 255) +#ifdef CONFIG_SAE_PK +#define SAE_CONFIRM_MAX_LEN ((2 + SAE_MAX_HASH_LEN) + 1500) +#else /* CONFIG_SAE_PK */ #define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_HASH_LEN) +#endif /* CONFIG_SAE_PK */ +#define SAE_PK_M_LEN 16 /* Special value returned by sae_parse_commit() */ #define SAE_SILENTLY_DISCARD 65535 +struct sae_pk { + struct wpabuf *m; + struct crypto_ec_key *key; + int group; + struct wpabuf *pubkey; /* DER encoded subjectPublicKey */ +#ifdef CONFIG_TESTING_OPTIONS + struct crypto_ec_key *sign_key_override; +#endif /* CONFIG_TESTING_OPTIONS */ +}; + + struct sae_temporary_data { u8 kck[SAE_MAX_HASH_LEN]; size_t kck_len; @@ -46,8 +62,25 @@ struct sae_temporary_data { u8 bssid[ETH_ALEN]; struct wpabuf *own_rejected_groups; struct wpabuf *peer_rejected_groups; - unsigned int h2e:1; unsigned int own_addr_higher:1; + +#ifdef CONFIG_SAE_PK + u8 kek[SAE_MAX_HASH_LEN]; + size_t kek_len; + const struct sae_pk *ap_pk; + u8 own_addr[ETH_ALEN]; + u8 peer_addr[ETH_ALEN]; + u8 fingerprint[SAE_MAX_HASH_LEN]; + size_t fingerprint_bytes; + size_t fingerprint_bits; + size_t lambda; + unsigned int sec; + u8 ssid[32]; + size_t ssid_len; +#ifdef CONFIG_TESTING_OPTIONS + bool omit_pk_elem; +#endif /* CONFIG_TESTING_OPTIONS */ +#endif /* CONFIG_SAE_PK */ }; struct sae_pt { @@ -58,6 +91,10 @@ struct sae_pt { const struct dh_group *dh; struct crypto_bignum *ffc_pt; +#ifdef CONFIG_SAE_PK + u8 ssid[32]; + size_t ssid_len; +#endif /* CONFIG_SAE_PK */ }; enum sae_state { @@ -74,6 +111,8 @@ struct sae_data { int group; unsigned int sync; /* protocol instance variable: Sync */ u16 rc; /* protocol instance variable: Rc (received send-confirm) */ + unsigned int h2e:1; + unsigned int pk:1; struct sae_temporary_data *tmp; }; @@ -86,17 +125,19 @@ int sae_prepare_commit(const u8 *addr1, const u8 *addr2, const char *identifier, struct sae_data *sae); int sae_prepare_commit_pt(struct sae_data *sae, const struct sae_pt *pt, const u8 *addr1, const u8 *addr2, - int *rejected_groups); + int *rejected_groups, const struct sae_pk *pk); int sae_process_commit(struct sae_data *sae); -void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, - const struct wpabuf *token, const char *identifier); +int sae_write_commit(struct sae_data *sae, struct wpabuf *buf, + const struct wpabuf *token, const char *identifier); u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len, const u8 **token, size_t *token_len, int *allowed_groups, int h2e); -void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf); +int sae_write_confirm(struct sae_data *sae, struct wpabuf *buf); int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len); u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group); const char * sae_state_txt(enum sae_state state); +size_t sae_ecc_prime_len_2_hash_len(size_t prime_len); +size_t sae_ffc_prime_len_2_hash_len(size_t prime_len); struct sae_pt * sae_derive_pt(int *groups, const u8 *ssid, size_t ssid_len, const u8 *password, size_t password_len, const char *identifier); @@ -108,4 +149,24 @@ sae_derive_pwe_from_pt_ffc(const struct sae_pt *pt, const u8 *addr1, const u8 *addr2); void sae_deinit_pt(struct sae_pt *pt); +/* sae_pk.c */ +#ifdef CONFIG_SAE_PK +bool sae_pk_valid_password(const char *pw); +#else /* CONFIG_SAE_PK */ +static inline bool sae_pk_valid_password(const char *pw) +{ + return false; +} +#endif /* CONFIG_SAE_PK */ +char * sae_pk_base32_encode(const u8 *src, size_t len_bits); +u8 * sae_pk_base32_decode(const char *src, size_t len, size_t *out_len); +int sae_pk_set_password(struct sae_data *sae, const char *password); +void sae_deinit_pk(struct sae_pk *pk); +struct sae_pk * sae_parse_pk(const char *val); +int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf); +int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len); +int sae_hash(size_t hash_len, const u8 *data, size_t len, u8 *hash); +u32 sae_pk_get_be19(const u8 *buf); +void sae_pk_buf_shift_left_19(u8 *buf, size_t len); + #endif /* SAE_H */ diff --git a/src/common/sae_pk.c b/src/common/sae_pk.c new file mode 100644 index 000000000..df79e5f2c --- /dev/null +++ b/src/common/sae_pk.c @@ -0,0 +1,884 @@ +/* + * SAE-PK + * Copyright (c) 2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include + +#include "utils/common.h" +#include "utils/base64.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "crypto/crypto.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" +#include "sae.h" + + +/* RFC 4648 base 32 alphabet with lowercase characters */ +static const char *sae_pk_base32_table = "abcdefghijklmnopqrstuvwxyz234567"; + + +static const u8 d_mult_table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, + 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, + 24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, + 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, + 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 10, 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 11, 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 14, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 31, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, + 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, + 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, + 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, + 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, + 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, + 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, + 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, + 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, + 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, + 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, 23, + 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 7, + 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24, + 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, + 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, + 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, + 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, + 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, + 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, + 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, + 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, + 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, + 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, + 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, + 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, + 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 31, + 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 15, + 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, + 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 +}; + +static const u8 d_perm_table[] = { + 7, 2, 1, 30, 16, 20, 27, 11, 31, 6, 8, 13, 29, 5, 10, 21, + 22, 3, 24, 0, 23, 25, 12, 9, 28, 14, 4, 15, 17, 18, 19, 26 +}; + + +static u8 d_permute(u8 val, unsigned int iter) +{ + if (iter == 0) + return val; + return d_permute(d_perm_table[val], iter - 1); +} + + +static u8 d_invert(u8 val) +{ + if (val > 0 && val < 16) + return 16 - val; + return val; +} + + +static char d_check_char(const char *str, size_t len) +{ + size_t i; + u8 val = 0; + u8 dtable[256]; + unsigned int iter = 1; + int j; + + os_memset(dtable, 0x80, 256); + for (i = 0; sae_pk_base32_table[i]; i++) + dtable[(u8) sae_pk_base32_table[i]] = i; + + for (j = len - 1; j >= 0; j--) { + u8 c, p; + + c = dtable[(u8) str[j]]; + if (c == 0x80) + continue; + p = d_permute(c, iter); + iter++; + val = d_mult_table[val * 32 + p]; + } + + return sae_pk_base32_table[d_invert(val)]; +} + + +bool sae_pk_valid_password(const char *pw) +{ + int pos; + size_t i, pw_len = os_strlen(pw); + u8 sec_1b; + u8 dtable[256]; + + os_memset(dtable, 0x80, 256); + for (i = 0; sae_pk_base32_table[i]; i++) + dtable[(u8) sae_pk_base32_table[i]] = i; + + /* SAE-PK password has at least three four character components + * separated by hyphens. */ + if (pw_len < 14 || pw_len % 5 != 4) { + wpa_printf(MSG_DEBUG, "SAE-PK: Not a valid password (length)"); + return false; + } + + for (pos = 0; pw[pos]; pos++) { + if (pos && pos % 5 == 4) { + if (pw[pos] != '-') { + wpa_printf(MSG_DEBUG, + "SAE-PK: Not a valid password (separator)"); + return false; + } + continue; + } + if (dtable[(u8) pw[pos]] == 0x80) { + wpa_printf(MSG_DEBUG, + "SAE-PK: Not a valid password (character)"); + return false; + } + } + + /* Verify that the checksum character is valid */ + if (pw[pw_len - 1] != d_check_char(pw, pw_len - 1)) { + wpa_printf(MSG_DEBUG, + "SAE-PK: Not a valid password (checksum)"); + return false; + } + + /* Verify that Sec_1b bits match */ + sec_1b = dtable[(u8) pw[0]] & BIT(4); + for (i = 5; i < pw_len; i += 5) { + if (sec_1b != (dtable[(u8) pw[i]] & BIT(4))) { + wpa_printf(MSG_DEBUG, + "SAE-PK: Not a valid password (Sec_1b)"); + return false; + } + } + return true; +} + + +static char * add_char(const char *start, char *pos, u8 idx, size_t *bits) +{ + if (*bits == 0) + return pos; + if (*bits > 5) + *bits -= 5; + else + *bits = 0; + + if ((pos - start) % 5 == 4) + *pos++ = '-'; + *pos++ = sae_pk_base32_table[idx]; + return pos; +} + + +/* Base32 encode a password and add hyper separators and checksum */ +char * sae_pk_base32_encode(const u8 *src, size_t len_bits) +{ + char *out, *pos; + size_t olen, extra_pad, i; + u64 block = 0; + u8 val; + size_t len = (len_bits + 7) / 8; + size_t left = len_bits; + int j; + + if (len == 0 || len >= SIZE_MAX / 8) + return NULL; + olen = len * 8 / 5 + 1; + olen += olen / 4; /* hyphen separators */ + pos = out = os_zalloc(olen + 2); /* include room for ChkSum and nul */ + if (!out) + return NULL; + + extra_pad = (5 - len % 5) % 5; + for (i = 0; i < len + extra_pad; i++) { + val = i < len ? src[i] : 0; + block <<= 8; + block |= val; + if (i % 5 == 4) { + for (j = 7; j >= 0; j--) + pos = add_char(out, pos, + (block >> j * 5) & 0x1f, &left); + block = 0; + } + } + + *pos = d_check_char(out, os_strlen(out)); + + return out; +} + + +u8 * sae_pk_base32_decode(const char *src, size_t len, size_t *out_len) +{ + u8 dtable[256], *out, *pos, tmp; + u64 block = 0; + size_t i, count, olen; + int pad = 0; + size_t extra_pad; + + os_memset(dtable, 0x80, 256); + for (i = 0; sae_pk_base32_table[i]; i++) + dtable[(u8) sae_pk_base32_table[i]] = i; + dtable['='] = 0; + + count = 0; + for (i = 0; i < len; i++) { + if (dtable[(u8) src[i]] != 0x80) + count++; + } + + if (count == 0) + return NULL; + extra_pad = (8 - count % 8) % 8; + + olen = (count + extra_pad) / 8 * 5; + pos = out = os_malloc(olen); + if (!out) + return NULL; + + count = 0; + for (i = 0; i < len + extra_pad; i++) { + u8 val; + + if (i >= len) + val = '='; + else + val = src[i]; + tmp = dtable[val]; + if (tmp == 0x80) + continue; + + if (val == '=') + pad++; + block <<= 5; + block |= tmp; + count++; + if (count == 8) { + *pos++ = (block >> 32) & 0xff; + *pos++ = (block >> 24) & 0xff; + *pos++ = (block >> 16) & 0xff; + *pos++ = (block >> 8) & 0xff; + *pos++ = block & 0xff; + count = 0; + block = 0; + if (pad) { + /* Leave in all the available bits with zero + * padding to full octets from right. */ + pos -= pad * 5 / 8; + break; + } + } + } + + *out_len = pos - out; + return out; +} + + +u32 sae_pk_get_be19(const u8 *buf) +{ + return (buf[0] << 11) | (buf[1] << 3) | (buf[2] >> 5); +} + + +/* shift left by two octets and three bits; fill in zeros from right; + * len must be at least three */ +void sae_pk_buf_shift_left_19(u8 *buf, size_t len) +{ + u8 *dst, *src, *end; + + dst = buf; + src = buf + 2; + end = buf + len; + + while (src + 1 < end) { + *dst++ = (src[0] << 3) | (src[1] >> 5); + src++; + } + *dst++ = *src << 3; + *dst++ = 0; + *dst++ = 0; +} + + +static void sae_pk_buf_shift_left_1(u8 *buf, size_t len) +{ + u8 *dst, *src, *end; + + dst = buf; + src = buf; + end = buf + len; + + while (src + 1 < end) { + *dst++ = (src[0] << 1) | (src[1] >> 7); + src++; + } + *dst++ = *src << 1; +} + + +int sae_pk_set_password(struct sae_data *sae, const char *password) +{ + struct sae_temporary_data *tmp = sae->tmp; + size_t len, pw_len; + u8 *pw, *pos; + int bits; + u32 val = 0, val19; + unsigned int val_bits = 0; + + if (!tmp) + return -1; + + os_memset(tmp->fingerprint, 0, sizeof(tmp->fingerprint)); + tmp->fingerprint_bytes = tmp->fingerprint_bits = 0; + + len = os_strlen(password); + if (len < 1 || !sae_pk_valid_password(password)) + return -1; + + pw = sae_pk_base32_decode(password, len, &pw_len); + if (!pw) + return -1; + + tmp->sec = (pw[0] & BIT(7)) ? 3 : 5; + tmp->lambda = len - len / 5; + tmp->fingerprint_bits = 8 * tmp->sec + 19 * tmp->lambda / 4 - 5; + wpa_printf(MSG_DEBUG, "SAE-PK: Sec=%u Lambda=%zu fingerprint_bits=%zu", + tmp->sec, tmp->lambda, tmp->fingerprint_bits); + + /* Construct Fingerprint from PasswordBase by prefixing with Sec zero + * octets and skipping the Sec_1b bits */ + pos = &tmp->fingerprint[tmp->sec]; + bits = tmp->fingerprint_bits - 8 * tmp->sec; + wpa_hexdump_key(MSG_DEBUG, "SAE-PK: PasswordBase", pw, pw_len); + while (bits > 0) { + if (val_bits < 8) { + sae_pk_buf_shift_left_1(pw, pw_len); /* Sec_1b */ + val19 = sae_pk_get_be19(pw); + sae_pk_buf_shift_left_19(pw, pw_len); + val = (val << 19) | val19; + val_bits += 19; + } + if (val_bits >= 8) { + if (bits < 8) + break; + *pos++ = (val >> (val_bits - 8)) & 0xff; + val_bits -= 8; + bits -= 8; + } + } + if (bits > 0) { + val >>= val_bits - bits; + *pos++ = val << (8 - bits); + } + tmp->fingerprint_bytes = pos - tmp->fingerprint; + wpa_hexdump_key(MSG_DEBUG, "SAE-PK: Fingerprint", + tmp->fingerprint, tmp->fingerprint_bytes); + bin_clear_free(pw, pw_len); + return 0; +} + + +static size_t sae_group_2_hash_len(int group) +{ + switch (group) { + case 19: + return 32; + case 20: + return 48; + case 21: + return 64; + } + + return 0; +} + + +void sae_deinit_pk(struct sae_pk *pk) +{ + if (pk) { + wpabuf_free(pk->m); + crypto_ec_key_deinit(pk->key); +#ifdef CONFIG_TESTING_OPTIONS + crypto_ec_key_deinit(pk->sign_key_override); +#endif /* CONFIG_TESTING_OPTIONS */ + wpabuf_free(pk->pubkey); + os_free(pk); + } +} + + +struct sae_pk * sae_parse_pk(const char *val) +{ + struct sae_pk *pk; + const char *pos; +#ifdef CONFIG_TESTING_OPTIONS + const char *pos2; +#endif /* CONFIG_TESTING_OPTIONS */ + size_t len; + unsigned char *der; + size_t der_len, b_len; + + /* : */ + + pos = os_strchr(val, ':'); + if (!pos || (pos - val) & 0x01) + return NULL; + len = (pos - val) / 2; + if (len != SAE_PK_M_LEN) { + wpa_printf(MSG_INFO, "SAE: Unexpected Modifier M length %zu", + len); + return NULL; + } + + pk = os_zalloc(sizeof(*pk)); + if (!pk) + return NULL; + pk->m = wpabuf_alloc(len); + if (!pk->m || hexstr2bin(val, wpabuf_put(pk->m, len), len)) { + wpa_printf(MSG_INFO, "SAE: Failed to parse m"); + goto fail; + } + + pos++; + b_len = os_strlen(pos); +#ifdef CONFIG_TESTING_OPTIONS + pos2 = os_strchr(pos, ':'); + if (pos2) { + b_len = pos2 - pos; + pos2++; + } +#endif /* CONFIG_TESTING_OPTIONS */ + der = base64_decode(pos, b_len, &der_len); + if (!der) { + wpa_printf(MSG_INFO, "SAE: Failed to base64 decode PK key"); + goto fail; + } + + pk->key = crypto_ec_key_parse_priv(der, der_len); + bin_clear_free(der, der_len); + if (!pk->key) + goto fail; + pk->group = crypto_ec_key_group(pk->key); + pk->pubkey = crypto_ec_key_get_subject_public_key(pk->key); + if (!pk->pubkey) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (pos2) { + der = base64_decode(pos2, os_strlen(pos2), &der_len); + if (!der) { + wpa_printf(MSG_INFO, + "SAE: Failed to base64 decode PK key"); + goto fail; + } + + pk->sign_key_override = crypto_ec_key_parse_priv(der, der_len); + bin_clear_free(der, der_len); + if (!pk->sign_key_override) + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + return pk; +fail: + sae_deinit_pk(pk); + return NULL; +} + + +int sae_hash(size_t hash_len, const u8 *data, size_t len, u8 *hash) +{ + if (hash_len == 32) + return sha256_vector(1, &data, &len, hash); +#ifdef CONFIG_SHA384 + if (hash_len == 48) + return sha384_vector(1, &data, &len, hash); +#endif /* CONFIG_SHA384 */ +#ifdef CONFIG_SHA512 + if (hash_len == 64) + return sha512_vector(1, &data, &len, hash); +#endif /* CONFIG_SHA512 */ + return -1; +} + + +static int sae_pk_hash_sig_data(struct sae_data *sae, size_t hash_len, + bool ap, const u8 *m, size_t m_len, + const u8 *pubkey, size_t pubkey_len, u8 *hash) +{ + struct sae_temporary_data *tmp = sae->tmp; + struct wpabuf *sig_data; + u8 *pos; + int ret = -1; + + /* Signed data for KeyAuth: eleAP || eleSTA || scaAP || scaSTA || + * M || K_AP || AP-BSSID || STA-MAC */ + sig_data = wpabuf_alloc(tmp->prime_len * 6 + m_len + pubkey_len + + 2 * ETH_ALEN); + if (!sig_data) + goto fail; + pos = wpabuf_put(sig_data, 2 * tmp->prime_len); + if (crypto_ec_point_to_bin(tmp->ec, ap ? tmp->own_commit_element_ecc : + tmp->peer_commit_element_ecc, + pos, pos + tmp->prime_len) < 0) + goto fail; + pos = wpabuf_put(sig_data, 2 * tmp->prime_len); + if (crypto_ec_point_to_bin(tmp->ec, ap ? tmp->peer_commit_element_ecc : + tmp->own_commit_element_ecc, + pos, pos + tmp->prime_len) < 0) + goto fail; + if (crypto_bignum_to_bin(ap ? tmp->own_commit_scalar : + sae->peer_commit_scalar, + wpabuf_put(sig_data, tmp->prime_len), + tmp->prime_len, tmp->prime_len) < 0 || + crypto_bignum_to_bin(ap ? sae->peer_commit_scalar : + tmp->own_commit_scalar, + wpabuf_put(sig_data, tmp->prime_len), + tmp->prime_len, tmp->prime_len) < 0) + goto fail; + wpabuf_put_data(sig_data, m, m_len); + wpabuf_put_data(sig_data, pubkey, pubkey_len); + wpabuf_put_data(sig_data, ap ? tmp->own_addr : tmp->peer_addr, + ETH_ALEN); + wpabuf_put_data(sig_data, ap ? tmp->peer_addr : tmp->own_addr, + ETH_ALEN); + wpa_hexdump_buf_key(MSG_DEBUG, "SAE-PK: Data to be signed for KeyAuth", + sig_data); + if (sae_hash(hash_len, wpabuf_head(sig_data), wpabuf_len(sig_data), + hash) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "SAE-PK: hash(data to be signed)", + hash, hash_len); + ret = 0; +fail: + wpabuf_free(sig_data); + return ret; +} + + +int sae_write_confirm_pk(struct sae_data *sae, struct wpabuf *buf) +{ + struct sae_temporary_data *tmp = sae->tmp; + struct wpabuf *sig = NULL; + size_t need; + int ret = -1; + u8 *encr_mod; + size_t encr_mod_len; + const struct sae_pk *pk; + u8 hash[SAE_MAX_HASH_LEN]; + size_t hash_len; + struct crypto_ec_key *key; + + if (!tmp) + return -1; + + pk = tmp->ap_pk; + if (!sae->pk || !pk) + return 0; + + key = pk->key; +#ifdef CONFIG_TESTING_OPTIONS + if (tmp->omit_pk_elem) + return 0; + if (pk->sign_key_override) { + wpa_printf(MSG_INFO, "TESTING: Override SAE-PK signing key"); + key = pk->sign_key_override; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (tmp->kek_len != 32 && tmp->kek_len != 48 && tmp->kek_len != 64) { + wpa_printf(MSG_INFO, + "SAE-PK: No KEK available for writing confirm"); + return -1; + } + + if (!tmp->ec) { + /* Only ECC groups are supported for SAE-PK in the current + * implementation. */ + wpa_printf(MSG_INFO, + "SAE-PK: SAE commit did not use an ECC group"); + return -1; + } + + hash_len = sae_group_2_hash_len(pk->group); + if (sae_pk_hash_sig_data(sae, hash_len, true, wpabuf_head(pk->m), + wpabuf_len(pk->m), wpabuf_head(pk->pubkey), + wpabuf_len(pk->pubkey), hash) < 0) + goto fail; + sig = crypto_ec_key_sign(key, hash, hash_len); + if (!sig) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "SAE-PK: KeyAuth = Sig_AP()", sig); + + /* TODO: fragmentation if any of the elements needs it for a group + * using sufficiently large primes (none of the currently supported + * ones do) */ + + encr_mod_len = wpabuf_len(pk->m) + AES_BLOCK_SIZE; + need = 4 + wpabuf_len(pk->pubkey) + 3 + wpabuf_len(sig) + + 6 + encr_mod_len; + if (wpabuf_tailroom(buf) < need) { + wpa_printf(MSG_INFO, + "SAE-PK: No room in message buffer for SAE-PK elements (%zu < %zu)", + wpabuf_tailroom(buf), need); + goto fail; + } + + /* FILS Public Key element */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); + wpabuf_put_u8(buf, 2 + wpabuf_len(pk->pubkey)); + wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_PUBLIC_KEY); + wpabuf_put_u8(buf, 2); /* Key Type: ECDSA public key */ + wpabuf_put_buf(buf, pk->pubkey); + + /* FILS Key Confirmation element (KeyAuth) */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); + wpabuf_put_u8(buf, 1 + wpabuf_len(sig)); + wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM); + /* KeyAuth = Sig_AP(eleAP || eleSTA || scaAP || scaSTA || M || K_AP || + * AP-BSSID || STA-MAC) */ + wpabuf_put_buf(buf, sig); + + /* SAE-PK element */ + wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); + wpabuf_put_u8(buf, 4 + encr_mod_len); + wpabuf_put_be32(buf, SAE_PK_IE_VENDOR_TYPE); + /* EncryptedModifier = AES-SIV-Q(M); no AAD */ + encr_mod = wpabuf_put(buf, encr_mod_len); + if (aes_siv_encrypt(tmp->kek, tmp->kek_len, + wpabuf_head(pk->m), wpabuf_len(pk->m), + 0, NULL, NULL, encr_mod) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "SAE-PK: EncryptedModifier", + encr_mod, encr_mod_len); + + ret = 0; +fail: + wpabuf_free(sig); + return ret; + +} + + +static bool sae_pk_valid_fingerprint(struct sae_data *sae, + const u8 *m, size_t m_len, + const u8 *k_ap, size_t k_ap_len, int group) +{ + struct sae_temporary_data *tmp = sae->tmp; + u8 *hash_data, *pos; + size_t hash_len, hash_data_len; + u8 hash[SAE_MAX_HASH_LEN]; + int res; + + if (!tmp->fingerprint_bytes) { + wpa_printf(MSG_DEBUG, + "SAE-PK: No PW available for K_AP fingerprint check"); + return false; + } + + /* Fingerprint = L(Hash(SSID || M || K_AP), 0, 8*Sec + 19*Lambda/4 - 5) + */ + + hash_len = sae_group_2_hash_len(group); + hash_data_len = tmp->ssid_len + m_len + k_ap_len; + hash_data = os_malloc(hash_data_len); + if (!hash_data) + return false; + pos = hash_data; + os_memcpy(pos, tmp->ssid, tmp->ssid_len); + pos += tmp->ssid_len; + os_memcpy(pos, m, m_len); + pos += m_len; + os_memcpy(pos, k_ap, k_ap_len); + + wpa_hexdump_key(MSG_DEBUG, "SAE-PK: SSID || M || K_AP", + hash_data, hash_data_len); + res = sae_hash(hash_len, hash_data, hash_data_len, hash); + bin_clear_free(hash_data, hash_data_len); + if (res < 0) + return false; + wpa_hexdump(MSG_DEBUG, "SAE-PK: Hash(SSID || M || K_AP)", + hash, hash_len); + + if (tmp->fingerprint_bits > hash_len * 8) { + wpa_printf(MSG_INFO, + "SAE-PK: Not enough hash output bits for the fingerprint"); + return false; + } + if (tmp->fingerprint_bits % 8) { + size_t extra; + + /* Zero out the extra bits in the last octet */ + extra = 8 - tmp->fingerprint_bits % 8; + pos = &hash[tmp->fingerprint_bits / 8]; + *pos = (*pos >> extra) << extra; + } + wpa_hexdump(MSG_DEBUG, "SAE-PK: Fingerprint", hash, + tmp->fingerprint_bytes); + res = os_memcmp_const(hash, tmp->fingerprint, tmp->fingerprint_bytes); + if (res) { + wpa_printf(MSG_DEBUG, "SAE-PK: K_AP fingerprint mismatch"); + wpa_hexdump(MSG_DEBUG, "SAE-PK: Expected fingerprint", + tmp->fingerprint, tmp->fingerprint_bytes); + return false; + } + + wpa_printf(MSG_DEBUG, "SAE-PK: Valid K_AP fingerprint"); + return true; +} + + +int sae_check_confirm_pk(struct sae_data *sae, const u8 *ies, size_t ies_len) +{ + struct sae_temporary_data *tmp = sae->tmp; + const u8 *k_ap; + u8 m[SAE_PK_M_LEN]; + size_t k_ap_len; + struct crypto_ec_key *key; + int res; + u8 hash[SAE_MAX_HASH_LEN]; + size_t hash_len; + int group; + struct ieee802_11_elems elems; + + if (!tmp) + return -1; + if (!sae->pk || tmp->ap_pk) + return 0; + + if (tmp->kek_len != 32 && tmp->kek_len != 48 && tmp->kek_len != 64) { + wpa_printf(MSG_INFO, + "SAE-PK: No KEK available for checking confirm"); + return -1; + } + + if (!tmp->ec) { + /* Only ECC groups are supported for SAE-PK in the current + * implementation. */ + wpa_printf(MSG_INFO, + "SAE-PK: SAE commit did not use an ECC group"); + return -1; + } + + wpa_hexdump(MSG_DEBUG, "SAE-PK: Received confirm IEs", ies, ies_len); + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) { + wpa_printf(MSG_INFO, "SAE-PK: Failed to parse confirm IEs"); + return -1; + } + if (!elems.fils_pk || !elems.fils_key_confirm || !elems.sae_pk) { + wpa_printf(MSG_INFO, + "SAE-PK: Not all mandatory IEs included in confirm"); + return -1; + } + + /* TODO: Fragment reassembly */ + + if (elems.sae_pk_len < SAE_PK_M_LEN + AES_BLOCK_SIZE) { + wpa_printf(MSG_INFO, + "SAE-PK: No room for EncryptedModifier in SAE-PK element"); + return -1; + } + + wpa_hexdump(MSG_DEBUG, "SAE-PK: EncryptedModifier", + elems.sae_pk, SAE_PK_M_LEN + AES_BLOCK_SIZE); + + if (aes_siv_decrypt(tmp->kek, tmp->kek_len, + elems.sae_pk, SAE_PK_M_LEN + AES_BLOCK_SIZE, + 0, NULL, NULL, m) < 0) { + wpa_printf(MSG_INFO, + "SAE-PK: Failed to decrypt EncryptedModifier"); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "SAE-PK: Modifier M", m, SAE_PK_M_LEN); + + if (elems.fils_pk[0] != 2) { + wpa_printf(MSG_INFO, "SAE-PK: Unsupported public key type %u", + elems.fils_pk[0]); + return -1; + } + k_ap_len = elems.fils_pk_len - 1; + k_ap = elems.fils_pk + 1; + wpa_hexdump(MSG_DEBUG, "SAE-PK: Received K_AP", k_ap, k_ap_len); + /* TODO: Check against the public key, if one is stored in the network + * profile */ + + key = crypto_ec_key_parse_pub(k_ap, k_ap_len); + if (!key) { + wpa_printf(MSG_INFO, "SAE-PK: Failed to parse K_AP"); + return -1; + } + + group = crypto_ec_key_group(key); + if (!sae_pk_valid_fingerprint(sae, m, SAE_PK_M_LEN, k_ap, k_ap_len, + group)) { + crypto_ec_key_deinit(key); + return -1; + } + + wpa_hexdump(MSG_DEBUG, "SAE-PK: Received KeyAuth", + elems.fils_key_confirm, elems.fils_key_confirm_len); + + hash_len = sae_group_2_hash_len(group); + if (sae_pk_hash_sig_data(sae, hash_len, false, m, SAE_PK_M_LEN, + k_ap, k_ap_len, hash) < 0) { + crypto_ec_key_deinit(key); + return -1; + } + + res = crypto_ec_key_verify_signature(key, hash, hash_len, + elems.fils_key_confirm, + elems.fils_key_confirm_len); + crypto_ec_key_deinit(key); + + if (res != 1) { + wpa_printf(MSG_INFO, + "SAE-PK: Invalid or incorrect signature in KeyAuth"); + return -1; + } + + wpa_printf(MSG_DEBUG, "SAE-PK: Valid KeyAuth signature received"); + + /* TODO: Store validated public key into network profile */ + + return 0; +} diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 5ecb1eceb..82a5a174f 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -355,6 +355,14 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, size_t data_len = 2 * ETH_ALEN + 2 * WPA_NONCE_LEN; u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; size_t ptk_len; +#ifdef CONFIG_OWE + int owe_ptk_workaround = 0; + + if (akmp == (WPA_KEY_MGMT_OWE | WPA_KEY_MGMT_PSK_SHA256)) { + owe_ptk_workaround = 1; + akmp = WPA_KEY_MGMT_OWE; + } +#endif /* CONFIG_OWE */ if (pmk_len == 0) { wpa_printf(MSG_ERROR, "WPA: No PMK set for PTK derivation"); @@ -413,7 +421,8 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, tmp, ptk_len) < 0) return -1; #ifdef CONFIG_OWE - } else if (akmp == WPA_KEY_MGMT_OWE && pmk_len == 32) { + } else if (akmp == WPA_KEY_MGMT_OWE && (pmk_len == 32 || + owe_ptk_workaround)) { wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA256)"); if (sha256_prf(pmk, pmk_len, label, data, data_len, tmp, ptk_len) < 0) @@ -925,6 +934,10 @@ static int wpa_ft_parse_ftie(const u8 *ie, size_t ie_len, parse->oci_len = len; break; #endif /* CONFIG_OCV */ + case FTIE_SUBELEM_BIGTK: + parse->bigtk = pos; + parse->bigtk_len = len; + break; default: wpa_printf(MSG_DEBUG, "FT: Unknown subelem id %u", id); break; @@ -1620,7 +1633,8 @@ int wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, if (!use_sha384 && sha256_vector(2, addr, len, hash) < 0) return -1; os_memcpy(pmk_r0_name, hash, WPA_PMK_NAME_LEN); - os_memset(r0_key_data, 0, sizeof(r0_key_data)); + wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN); + forced_memzero(r0_key_data, sizeof(r0_key_data)); return 0; } @@ -1657,6 +1671,7 @@ int wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, if (!use_sha384 && sha256_vector(4, addr, len, hash) < 0) return -1; os_memcpy(pmk_r1_name, hash, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); return 0; } @@ -1826,7 +1841,7 @@ int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, size_t pmk_r1_len, wpa_hexdump_key(MSG_DEBUG, "FT: TK", ptk->tk, ptk->tk_len); wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); - os_memset(tmp, 0, sizeof(tmp)); + forced_memzero(tmp, sizeof(tmp)); return 0; } @@ -1961,10 +1976,12 @@ const char * wpa_cipher_txt(int cipher) switch (cipher) { case WPA_CIPHER_NONE: return "NONE"; +#ifdef CONFIG_WEP case WPA_CIPHER_WEP40: return "WEP-40"; case WPA_CIPHER_WEP104: return "WEP-104"; +#endif /* CONFIG_WEP */ case WPA_CIPHER_TKIP: return "TKIP"; case WPA_CIPHER_CCMP: @@ -2100,8 +2117,6 @@ u32 wpa_akm_to_suite(int akm) return RSN_AUTH_KEY_MGMT_OWE; if (akm & WPA_KEY_MGMT_DPP) return RSN_AUTH_KEY_MGMT_DPP; - if (akm & WPA_KEY_MGMT_OSEN) - return RSN_AUTH_KEY_MGMT_OSEN; return 0; } @@ -2292,7 +2307,7 @@ enum wpa_alg wpa_cipher_to_alg(int cipher) case WPA_CIPHER_TKIP: return WPA_ALG_TKIP; case WPA_CIPHER_AES_128_CMAC: - return WPA_ALG_IGTK; + return WPA_ALG_BIP_CMAC_128; case WPA_CIPHER_BIP_GMAC_128: return WPA_ALG_BIP_GMAC_128; case WPA_CIPHER_BIP_GMAC_256: @@ -2306,11 +2321,18 @@ enum wpa_alg wpa_cipher_to_alg(int cipher) int wpa_cipher_valid_pairwise(int cipher) { +#ifdef CONFIG_NO_TKIP + return cipher == WPA_CIPHER_CCMP_256 || + cipher == WPA_CIPHER_GCMP_256 || + cipher == WPA_CIPHER_CCMP || + cipher == WPA_CIPHER_GCMP; +#else /* CONFIG_NO_TKIP */ return cipher == WPA_CIPHER_CCMP_256 || cipher == WPA_CIPHER_GCMP_256 || cipher == WPA_CIPHER_CCMP || cipher == WPA_CIPHER_GCMP || cipher == WPA_CIPHER_TKIP; +#endif /* CONFIG_NO_TKIP */ } @@ -2463,12 +2485,16 @@ int wpa_parse_cipher(const char *value) val |= WPA_CIPHER_CCMP; else if (os_strcmp(start, "GCMP") == 0) val |= WPA_CIPHER_GCMP; +#ifndef CONFIG_NO_TKIP else if (os_strcmp(start, "TKIP") == 0) val |= WPA_CIPHER_TKIP; +#endif /* CONFIG_NO_TKIP */ +#ifdef CONFIG_WEP else if (os_strcmp(start, "WEP104") == 0) val |= WPA_CIPHER_WEP104; else if (os_strcmp(start, "WEP40") == 0) val |= WPA_CIPHER_WEP40; +#endif /* CONFIG_WEP */ else if (os_strcmp(start, "NONE") == 0) val |= WPA_CIPHER_NONE; else if (os_strcmp(start, "GTK_NOT_USED") == 0) @@ -2631,10 +2657,9 @@ int fils_domain_name_hash(const char *domain, u8 *hash) * @pos: Pointer to the IE header * @end: Pointer to the end of the Key Data buffer * @ie: Pointer to parsed IE data - * Returns: 0 on success, 1 if end mark is found, -1 on failure */ -static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end, - struct wpa_eapol_ie_parse *ie) +static void wpa_parse_vendor_specific(const u8 *pos, const u8 *end, + struct wpa_eapol_ie_parse *ie) { unsigned int oui; @@ -2642,7 +2667,7 @@ static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end, wpa_printf(MSG_MSGDUMP, "Too short vendor specific IE ignored (len=%u)", pos[1]); - return 1; + return; } oui = WPA_GET_BE24(&pos[2]); @@ -2659,19 +2684,16 @@ static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end, ie->wmm, ie->wmm_len); } } - return 0; } /** * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs * @pos: Pointer to the IE header - * @end: Pointer to the end of the Key Data buffer * @ie: Pointer to parsed IE data - * Returns: 0 on success, 1 if end mark is found, -1 on failure + * Returns: 0 on success, 1 if end mark is found, 2 if KDE is not recognized */ -static int wpa_parse_generic(const u8 *pos, const u8 *end, - struct wpa_eapol_ie_parse *ie) +static int wpa_parse_generic(const u8 *pos, struct wpa_eapol_ie_parse *ie) { if (pos[1] == 0) return 1; @@ -2693,8 +2715,7 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, return 0; } - if (1 + RSN_SELECTOR_LEN < end - pos && - pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && + if (pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key", @@ -2702,6 +2723,14 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, return 0; } + if (pos[1] >= RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_KEYID) { + ie->key_id = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: KeyID in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { ie->gtk = pos + 2 + RSN_SELECTOR_LEN; @@ -2729,6 +2758,15 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, return 0; } + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_BIGTK) { + ie->bigtk = pos + 2 + RSN_SELECTOR_LEN; + ie->bigtk_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump_key(MSG_DEBUG, "WPA: BIGTK in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + if (pos[1] >= RSN_SELECTOR_LEN + 1 && RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) { ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN; @@ -2755,7 +2793,26 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, return 0; } - return 0; + if (pos[1] >= RSN_SELECTOR_LEN + 1 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_TRANSITION_DISABLE) { + ie->transition_disable = pos + 2 + RSN_SELECTOR_LEN; + ie->transition_disable_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, + "WPA: Transition Disable KDE in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + + if (pos[1] >= RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_DPP) { + ie->dpp_kde = pos + 2 + RSN_SELECTOR_LEN; + ie->dpp_kde_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: DPP KDE in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + + return 2; } @@ -2863,21 +2920,19 @@ int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) ie->supp_oper_classes_len = pos[1]; } } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { - ret = wpa_parse_generic(pos, end, ie); - if (ret < 0) - break; - if (ret > 0) { + ret = wpa_parse_generic(pos, ie); + if (ret == 1) { + /* end mark found */ ret = 0; break; } - ret = wpa_parse_vendor_specific(pos, end, ie); - if (ret < 0) - break; - if (ret > 0) { - ret = 0; - break; + if (ret == 2) { + /* not a known KDE */ + wpa_parse_vendor_specific(pos, end, ie); } + + ret = 0; } else { wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key Key Data IE", diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index beb1ecd5e..065dc7113 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -22,6 +22,15 @@ #define OWE_DH_GROUP 19 +#ifdef CONFIG_NO_TKIP +#define WPA_ALLOWED_PAIRWISE_CIPHERS \ +(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_NONE | \ +WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256) +#define WPA_ALLOWED_GROUP_CIPHERS \ +(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | \ +WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256 | \ +WPA_CIPHER_GTK_NOT_USED) +#else /* CONFIG_NO_TKIP */ #define WPA_ALLOWED_PAIRWISE_CIPHERS \ (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE | \ WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256) @@ -29,6 +38,7 @@ WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256) (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | \ WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256 | \ WPA_CIPHER_GTK_NOT_USED) +#endif /* CONFIG_NO_TKIP */ #define WPA_ALLOWED_GROUP_MGMT_CIPHERS \ (WPA_CIPHER_AES_128_CMAC | WPA_CIPHER_BIP_GMAC_128 | WPA_CIPHER_BIP_GMAC_256 | \ WPA_CIPHER_BIP_CMAC_256) @@ -109,9 +119,12 @@ WPA_CIPHER_BIP_CMAC_256) #define RSN_KEY_DATA_MULTIBAND_GTK RSN_SELECTOR(0x00, 0x0f, 0xac, 11) #define RSN_KEY_DATA_MULTIBAND_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 12) #define RSN_KEY_DATA_OCI RSN_SELECTOR(0x00, 0x0f, 0xac, 13) +#define RSN_KEY_DATA_BIGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 14) #define WFA_KEY_DATA_IP_ADDR_REQ RSN_SELECTOR(0x50, 0x6f, 0x9a, 4) #define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5) +#define WFA_KEY_DATA_TRANSITION_DISABLE RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x20) +#define WFA_KEY_DATA_DPP RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x21) #define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1) @@ -130,6 +143,8 @@ WPA_CIPHER_BIP_CMAC_256) #define WPA_IGTK_LEN 16 #define WPA_IGTK_MAX_LEN 32 +#define WPA_BIGTK_LEN 16 +#define WPA_BIGTK_MAX_LEN 32 /* IEEE 802.11, 7.3.2.25.3 RSN Capabilities */ @@ -227,6 +242,11 @@ struct wpa_igtk { size_t igtk_len; }; +struct wpa_bigtk { + u8 bigtk[WPA_BIGTK_MAX_LEN]; + size_t bigtk_len; +}; + /* WPA IE version 1 * 00-50-f2:1 (OUI:OUI type) * 0x01 0x00 (version; little endian) @@ -292,6 +312,13 @@ struct wpa_igtk_kde { u8 igtk[WPA_IGTK_MAX_LEN]; } STRUCT_PACKED; +#define WPA_BIGTK_KDE_PREFIX_LEN (2 + 6) +struct wpa_bigtk_kde { + u8 keyid[2]; + u8 pn[6]; + u8 bigtk[WPA_BIGTK_MAX_LEN]; +} STRUCT_PACKED; + struct rsn_mdie { u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; u8 ft_capab; @@ -321,6 +348,7 @@ struct rsn_ftie_sha384 { #define FTIE_SUBELEM_R0KH_ID 3 #define FTIE_SUBELEM_IGTK 4 #define FTIE_SUBELEM_OCI 5 +#define FTIE_SUBELEM_BIGTK 6 struct rsn_rdie { u8 id; @@ -328,6 +356,16 @@ struct rsn_rdie { le16 status_code; } STRUCT_PACKED; +/* WFA Transition Disable KDE (using OUI_WFA) */ +/* Transition Disable Bitmap bits */ +#define TRANSITION_DISABLE_WPA3_PERSONAL BIT(0) +#define TRANSITION_DISABLE_SAE_PK BIT(1) +#define TRANSITION_DISABLE_WPA3_ENTERPRISE BIT(2) +#define TRANSITION_DISABLE_ENHANCED_OPEN BIT(3) + +/* DPP KDE Flags */ +#define DPP_KDE_PFS_ALLOWED BIT(0) +#define DPP_KDE_PFS_REQUIRED BIT(1) #ifdef _MSC_VER #pragma pack(pop) @@ -455,6 +493,8 @@ struct wpa_ft_ies { size_t tie_len; const u8 *igtk; size_t igtk_len; + const u8 *bigtk; + size_t bigtk_len; #ifdef CONFIG_OCV const u8 *oci; size_t oci_len; @@ -476,18 +516,25 @@ struct wpa_eapol_ie_parse { const u8 *rsn_ie; size_t rsn_ie_len; const u8 *pmkid; + const u8 *key_id; const u8 *gtk; size_t gtk_len; const u8 *mac_addr; size_t mac_addr_len; const u8 *igtk; size_t igtk_len; + const u8 *bigtk; + size_t bigtk_len; const u8 *mdie; size_t mdie_len; const u8 *ftie; size_t ftie_len; const u8 *ip_addr_req; const u8 *ip_addr_alloc; + const u8 *transition_disable; + size_t transition_disable_len; + const u8 *dpp_kde; + size_t dpp_kde_len; const u8 *oci; size_t oci_len; const u8 *osen; diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h index 48002be6c..acc2d6c4c 100644 --- a/src/common/wpa_ctrl.h +++ b/src/common/wpa_ctrl.h @@ -95,6 +95,12 @@ extern "C" { /** SAE authentication failed due to unknown password identifier */ #define WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER \ "CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER " +/** Unprotected Beacon frame dropped */ +#define WPA_EVENT_UNPROT_BEACON "CTRL-EVENT-UNPROT-BEACON " +/** Decision made to do a within-ESS roam */ +#define WPA_EVENT_DO_ROAM "CTRL-EVENT-DO-ROAM " +/** Decision made to skip a within-ESS roam */ +#define WPA_EVENT_SKIP_ROAM "CTRL-EVENT-SKIP-ROAM " /** IP subnet status change notification * @@ -120,6 +126,8 @@ extern "C" { #define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT " /** Frequency ranges that the driver recommends to avoid */ #define WPA_EVENT_AVOID_FREQ "CTRL-EVENT-AVOID-FREQ " +/** Result of MSCS setup */ +#define WPA_EVENT_MSCS_RESULT "CTRL-EVENT-MSCS-RESULT " /** WPS overlap detected in PBC mode */ #define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED " /** Available WPS AP with active PBC found in scan results */ @@ -176,7 +184,11 @@ extern "C" { #define DPP_EVENT_CONFOBJ_PSK "DPP-CONFOBJ-PSK " #define DPP_EVENT_CONNECTOR "DPP-CONNECTOR " #define DPP_EVENT_C_SIGN_KEY "DPP-C-SIGN-KEY " +#define DPP_EVENT_PP_KEY "DPP-PP-KEY " #define DPP_EVENT_NET_ACCESS_KEY "DPP-NET-ACCESS-KEY " +#define DPP_EVENT_SERVER_NAME "DPP-SERVER-NAME " +#define DPP_EVENT_CERTBAG "DPP-CERTBAG " +#define DPP_EVENT_CACERT "DPP-CACERT " #define DPP_EVENT_MISSING_CONNECTOR "DPP-MISSING-CONNECTOR " #define DPP_EVENT_NETWORK_ID "DPP-NETWORK-ID " #define DPP_EVENT_CONFIGURATOR_ID "DPP-CONFIGURATOR-ID " @@ -187,6 +199,11 @@ extern "C" { #define DPP_EVENT_PKEX_T_LIMIT "DPP-PKEX-T-LIMIT " #define DPP_EVENT_INTRO "DPP-INTRO " #define DPP_EVENT_CONF_REQ_RX "DPP-CONF-REQ-RX " +#define DPP_EVENT_CHIRP_STOPPED "DPP-CHIRP-STOPPED " +#define DPP_EVENT_MUD_URL "DPP-MUD-URL " +#define DPP_EVENT_BAND_SUPPORT "DPP-BAND-SUPPORT " +#define DPP_EVENT_CSR "DPP-CSR " +#define DPP_EVENT_CHIRP_RX "DPP-CHIRP-RX " /* MESH events */ #define MESH_GROUP_STARTED "MESH-GROUP-STARTED " @@ -380,6 +397,17 @@ extern "C" { #define WDS_STA_INTERFACE_ADDED "WDS-STA-INTERFACE-ADDED " #define WDS_STA_INTERFACE_REMOVED "WDS-STA-INTERFACE-REMOVED " +/* Transition mode disabled indication - followed by bitmap */ +#define TRANSITION_DISABLE "TRANSITION-DISABLE " + +/* OCV validation failure; parameters: addr= + * frame= error= */ +#define OCV_FAILURE "OCV-FAILURE " + +#ifndef BIT +#define BIT(x) (1U << (x)) +#endif + /* BSS command information masks */ #define WPA_BSS_MASK_ALL 0xFFFDFFFF diff --git a/src/crypto/.gitignore b/src/crypto/.gitignore deleted file mode 100644 index ee606048c..000000000 --- a/src/crypto/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libcrypto.a diff --git a/src/crypto/Makefile b/src/crypto/Makefile index c40e95566..ce0997091 100644 --- a/src/crypto/Makefile +++ b/src/crypto/Makefile @@ -1,14 +1,3 @@ -all: libcrypto.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libcrypto.a - -install: - @echo Nothing to be made. - - -include ../lib.rules - CFLAGS += -DCONFIG_CRYPTO_INTERNAL CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER @@ -68,8 +57,4 @@ ifndef TEST_FUZZ LIB_OBJS += random.o endif - -libcrypto.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index 440da0302..7d2ebd61c 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -485,7 +485,7 @@ int rc4_skip(const u8 *key, size_t keylen, size_t skip, u8 *data, size_t data_len); /** - * crypto_get_random - Generate cryptographically strong pseudy-random bytes + * crypto_get_random - Generate cryptographically strong pseudo-random bytes * @buf: Buffer for data * @len: Number of bytes to generate * Returns: 0 on success, -1 on failure @@ -916,5 +916,18 @@ struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y); struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, const u8 *key, size_t len); void crypto_ecdh_deinit(struct crypto_ecdh *ecdh); +size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh); + +struct crypto_ec_key; + +struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len); +struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len); +void crypto_ec_key_deinit(struct crypto_ec_key *key); +struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key); +struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, + size_t len); +int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, + size_t len, const u8 *sig, size_t sig_len); +int crypto_ec_key_group(struct crypto_ec_key *key); #endif /* CRYPTO_H */ diff --git a/src/crypto/crypto_module_tests.c b/src/crypto/crypto_module_tests.c index 1cc73d8ec..fafb688b4 100644 --- a/src/crypto/crypto_module_tests.c +++ b/src/crypto/crypto_module_tests.c @@ -744,6 +744,155 @@ static int test_key_wrap(void) } +static int test_aes_ctr(void) +{ + int res = 0; + +#if defined(CONFIG_MESH) || defined(CONFIG_PSK) + /* CTR-AES*.Encrypt test vectors from NIST SP 800-38a */ + const u8 key128[] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c + }; + const u8 counter128[] = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + const u8 plain128[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + const u8 cipher128[] = { + 0x87, 0x4d, 0x61, 0x91, 0xb6, 0x20, 0xe3, 0x26, + 0x1b, 0xef, 0x68, 0x64, 0x99, 0x0d, 0xb6, 0xce, + 0x98, 0x06, 0xf6, 0x6b, 0x79, 0x70, 0xfd, 0xff, + 0x86, 0x17, 0x18, 0x7b, 0xb9, 0xff, 0xfd, 0xff, + 0x5a, 0xe4, 0xdf, 0x3e, 0xdb, 0xd5, 0xd3, 0x5e, + 0x5b, 0x4f, 0x09, 0x02, 0x0d, 0xb0, 0x3e, 0xab, + 0x1e, 0x03, 0x1d, 0xda, 0x2f, 0xbe, 0x03, 0xd1, + 0x79, 0x21, 0x70, 0xa0, 0xf3, 0x00, 0x9c, 0xee + }; + const u8 key192[] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b + }; + const u8 counter192[] = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + const u8 plain192[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + const u8 cipher192[] = { + 0x1a, 0xbc, 0x93, 0x24, 0x17, 0x52, 0x1c, 0xa2, + 0x4f, 0x2b, 0x04, 0x59, 0xfe, 0x7e, 0x6e, 0x0b, + 0x09, 0x03, 0x39, 0xec, 0x0a, 0xa6, 0xfa, 0xef, + 0xd5, 0xcc, 0xc2, 0xc6, 0xf4, 0xce, 0x8e, 0x94, + 0x1e, 0x36, 0xb2, 0x6b, 0xd1, 0xeb, 0xc6, 0x70, + 0xd1, 0xbd, 0x1d, 0x66, 0x56, 0x20, 0xab, 0xf7, + 0x4f, 0x78, 0xa7, 0xf6, 0xd2, 0x98, 0x09, 0x58, + 0x5a, 0x97, 0xda, 0xec, 0x58, 0xc6, 0xb0, 0x50 + }; + const u8 key256[] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 + }; + const u8 counter256[] = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, + 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + const u8 plain256[] = { + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 + }; + const u8 cipher256[] = { + 0x60, 0x1e, 0xc3, 0x13, 0x77, 0x57, 0x89, 0xa5, + 0xb7, 0xa7, 0xf5, 0x04, 0xbb, 0xf3, 0xd2, 0x28, + 0xf4, 0x43, 0xe3, 0xca, 0x4d, 0x62, 0xb5, 0x9a, + 0xca, 0x84, 0xe9, 0x90, 0xca, 0xca, 0xf5, 0xc5, + 0x2b, 0x09, 0x30, 0xda, 0xa2, 0x3d, 0xe9, 0x4c, + 0xe8, 0x70, 0x17, 0xba, 0x2d, 0x84, 0x98, 0x8d, + 0xdf, 0xc9, 0xc5, 0x8d, 0xb6, 0x7a, 0xad, 0xa6, + 0x13, 0xc2, 0xdd, 0x08, 0x45, 0x79, 0x41, 0xa6 + }; + size_t len; + u8 *tmp; + + wpa_printf(MSG_DEBUG, "CTR-AES128.Encrypt"); + len = sizeof(plain128); + tmp = os_malloc(len); + if (!tmp) + return -1; + os_memcpy(tmp, plain128, len); + if (aes_ctr_encrypt(key128, sizeof(key128), counter128, tmp, len) < 0) { + wpa_printf(MSG_ERROR, "aes_ctr_encrypt() failed"); + res = -1; + } else if (os_memcmp(tmp, cipher128, len) != 0) { + wpa_printf(MSG_ERROR, + "CTR-AES128.Encrypt test vector did not match"); + res = -1; + } + os_free(tmp); + + wpa_printf(MSG_DEBUG, "CTR-AES192.Encrypt"); + len = sizeof(plain192); + tmp = os_malloc(len); + if (!tmp) + return -1; + os_memcpy(tmp, plain192, len); + if (aes_ctr_encrypt(key192, sizeof(key192), counter192, tmp, len) < 0) { + wpa_printf(MSG_ERROR, "aes_ctr_encrypt() failed"); + res = -1; + } else if (os_memcmp(tmp, cipher192, len) != 0) { + wpa_printf(MSG_ERROR, + "CTR-AES192.Encrypt test vector did not match"); + res = -1; + } + os_free(tmp); + + wpa_printf(MSG_DEBUG, "CTR-AES256.Encrypt"); + len = sizeof(plain256); + tmp = os_malloc(len); + if (!tmp) + return -1; + os_memcpy(tmp, plain256, len); + if (aes_ctr_encrypt(key256, sizeof(key256), counter256, tmp, len) < 0) { + wpa_printf(MSG_ERROR, "aes_ctr_encrypt() failed"); + res = -1; + } else if (os_memcmp(tmp, cipher256, len) != 0) { + wpa_printf(MSG_ERROR, + "CTR-AES256.Encrypt test vector did not match"); + res = -1; + } + os_free(tmp); +#endif + + return res; +} + + static int test_md5(void) { #ifndef CONFIG_FIPS @@ -2154,6 +2303,7 @@ int crypto_module_tests(void) test_cbc() || test_ecb() || test_key_wrap() || + test_aes_ctr() || test_md5() || test_sha1() || test_sha256() || diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c index 783b293e9..72f93c192 100644 --- a/src/crypto/crypto_openssl.c +++ b/src/crypto/crypto_openssl.c @@ -21,6 +21,7 @@ #endif /* CONFIG_OPENSSL_CMAC */ #ifdef CONFIG_ECC #include +#include #endif /* CONFIG_ECC */ #include "common.h" @@ -79,6 +80,14 @@ static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) bin_clear_free(ctx, sizeof(*ctx)); } + +static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey) +{ + if (pkey->type != EVP_PKEY_EC) + return NULL; + return pkey->pkey.ec; +} + #endif /* OpenSSL version < 1.1.0 */ static BIGNUM * get_group5_prime(void) @@ -2168,4 +2177,170 @@ void crypto_ecdh_deinit(struct crypto_ecdh *ecdh) } } + +size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh) +{ + return crypto_ec_prime_len(ecdh->ec); +} + + +struct crypto_ec_key { + EVP_PKEY *pkey; + EC_KEY *eckey; +}; + + +struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len) +{ + struct crypto_ec_key *key; + + key = os_zalloc(sizeof(*key)); + if (!key) + return NULL; + + key->eckey = d2i_ECPrivateKey(NULL, &der, der_len); + if (!key->eckey) { + wpa_printf(MSG_INFO, "OpenSSL: d2i_ECPrivateKey() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + EC_KEY_set_conv_form(key->eckey, POINT_CONVERSION_COMPRESSED); + + key->pkey = EVP_PKEY_new(); + if (!key->pkey || EVP_PKEY_assign_EC_KEY(key->pkey, key->eckey) != 1) { + EC_KEY_free(key->eckey); + key->eckey = NULL; + goto fail; + } + + return key; +fail: + crypto_ec_key_deinit(key); + return NULL; +} + + +struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len) +{ + struct crypto_ec_key *key; + + key = os_zalloc(sizeof(*key)); + if (!key) + return NULL; + + key->pkey = d2i_PUBKEY(NULL, &der, der_len); + if (!key->pkey) { + wpa_printf(MSG_INFO, "OpenSSL: d2i_PUBKEY() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + key->eckey = EVP_PKEY_get0_EC_KEY(key->pkey); + if (!key->eckey) + goto fail; + return key; +fail: + crypto_ec_key_deinit(key); + return NULL; +} + + +void crypto_ec_key_deinit(struct crypto_ec_key *key) +{ + if (key) { + EVP_PKEY_free(key->pkey); + os_free(key); + } +} + + +struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key) +{ + unsigned char *der = NULL; + int der_len; + struct wpabuf *buf; + + der_len = i2d_PUBKEY(key->pkey, &der); + if (der_len <= 0) { + wpa_printf(MSG_INFO, "OpenSSL: i2d_PUBKEY() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return NULL; + } + + buf = wpabuf_alloc_copy(der, der_len); + OPENSSL_free(der); + return buf; +} + + +struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, + size_t len) +{ + EVP_PKEY_CTX *pkctx; + struct wpabuf *sig_der; + size_t sig_len; + + sig_len = EVP_PKEY_size(key->pkey); + sig_der = wpabuf_alloc(sig_len); + if (!sig_der) + return NULL; + + pkctx = EVP_PKEY_CTX_new(key->pkey, NULL); + if (!pkctx || + EVP_PKEY_sign_init(pkctx) <= 0 || + EVP_PKEY_sign(pkctx, wpabuf_put(sig_der, 0), &sig_len, + data, len) <= 0) { + wpabuf_free(sig_der); + sig_der = NULL; + } else { + wpabuf_put(sig_der, sig_len); + } + + EVP_PKEY_CTX_free(pkctx); + return sig_der; +} + + +int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, + size_t len, const u8 *sig, size_t sig_len) +{ + EVP_PKEY_CTX *pkctx; + int ret; + + pkctx = EVP_PKEY_CTX_new(key->pkey, NULL); + if (!pkctx || EVP_PKEY_verify_init(pkctx) <= 0) { + EVP_PKEY_CTX_free(pkctx); + return -1; + } + + ret = EVP_PKEY_verify(pkctx, sig, sig_len, data, len); + EVP_PKEY_CTX_free(pkctx); + if (ret == 1) + return 1; /* signature ok */ + if (ret == 0) + return 0; /* incorrect signature */ + return -1; +} + + +int crypto_ec_key_group(struct crypto_ec_key *key) +{ + const EC_GROUP *group; + int nid; + + group = EC_KEY_get0_group(key->eckey); + if (!group) + return -1; + nid = EC_GROUP_get_curve_name(group); + switch (nid) { + case NID_X9_62_prime256v1: + return 19; + case NID_secp384r1: + return 20; + case NID_secp521r1: + return 21; + } + return -1; +} + #endif /* CONFIG_ECC */ diff --git a/src/crypto/crypto_wolfssl.c b/src/crypto/crypto_wolfssl.c index 85ce565bd..2e4bf8962 100644 --- a/src/crypto/crypto_wolfssl.c +++ b/src/crypto/crypto_wolfssl.c @@ -1104,19 +1104,21 @@ int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m) { int ret = 0; WC_RNG rng; + size_t len; + u8 *buf; if (TEST_FAIL()) return -1; if (wc_InitRng(&rng) != 0) return -1; - if (mp_rand_prime((mp_int *) r, - (mp_count_bits((mp_int *) m) + 7) / 8 * 2, - &rng, NULL) != 0) - ret = -1; - if (ret == 0 && + len = (mp_count_bits((mp_int *) m) + 7) / 8; + buf = os_malloc(len); + if (!buf || wc_RNG_GenerateBlock(&rng, buf, len) != 0 || + mp_read_unsigned_bin((mp_int *) r, buf, len) != MP_OKAY || mp_mod((mp_int *) r, (mp_int *) m, (mp_int *) r) != 0) ret = -1; wc_FreeRng(&rng); + bin_clear_free(buf, len); return ret; } @@ -1834,4 +1836,10 @@ fail: goto done; } + +size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh) +{ + return crypto_ec_prime_len(ecdh->ec); +} + #endif /* CONFIG_ECC */ diff --git a/src/crypto/tls.h b/src/crypto/tls.h index c8b1a824e..09fb73b1a 100644 --- a/src/crypto/tls.h +++ b/src/crypto/tls.h @@ -670,4 +670,18 @@ int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len); */ u16 tls_connection_get_cipher_suite(struct tls_connection *conn); +/** + * tls_connection_get_peer_subject - Get peer subject + * @conn: Connection context data from tls_connection_init() + * Returns: Peer subject or %NULL if not authenticated or not available + */ +const char * tls_connection_get_peer_subject(struct tls_connection *conn); + +/** + * tls_connection_get_own_cert_used - Was own certificate used + * @conn: Connection context data from tls_connection_init() + * Returns: true if own certificate was used during authentication + */ +bool tls_connection_get_own_cert_used(struct tls_connection *conn); + #endif /* TLS_H */ diff --git a/src/crypto/tls_openssl.c b/src/crypto/tls_openssl.c index a6a4ce4b9..ef872c50e 100644 --- a/src/crypto/tls_openssl.c +++ b/src/crypto/tls_openssl.c @@ -265,6 +265,7 @@ struct tls_connection { X509 *peer_cert; X509 *peer_issuer; X509 *peer_issuer_issuer; + char *peer_subject; /* peer subject info for authenticated peer */ unsigned char client_random[SSL3_RANDOM_SIZE]; unsigned char server_random[SSL3_RANDOM_SIZE]; @@ -1629,6 +1630,7 @@ void tls_connection_deinit(void *ssl_ctx, struct tls_connection *conn) os_free(conn->domain_match); os_free(conn->check_cert_subject); os_free(conn->session_ticket); + os_free(conn->peer_subject); os_free(conn); } @@ -2579,6 +2581,11 @@ static int tls_verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx) context->event_cb(context->cb_ctx, TLS_CERT_CHAIN_SUCCESS, NULL); + if (depth == 0 && preverify_ok) { + os_free(conn->peer_subject); + conn->peer_subject = os_strdup(buf); + } + return preverify_ok; } @@ -2988,16 +2995,12 @@ static int tls_set_conn_flags(struct tls_connection *conn, unsigned int flags, /* Explicit request to enable TLS versions even if needing to * override systemwide policies. */ - if (flags & TLS_CONN_ENABLE_TLSv1_0) { + if (flags & TLS_CONN_ENABLE_TLSv1_0) version = TLS1_VERSION; - } else if (flags & TLS_CONN_ENABLE_TLSv1_1) { - if (!(flags & TLS_CONN_DISABLE_TLSv1_0)) - version = TLS1_1_VERSION; - } else if (flags & TLS_CONN_ENABLE_TLSv1_2) { - if (!(flags & (TLS_CONN_DISABLE_TLSv1_0 | - TLS_CONN_DISABLE_TLSv1_1))) - version = TLS1_2_VERSION; - } + else if (flags & TLS_CONN_ENABLE_TLSv1_1) + version = TLS1_1_VERSION; + else if (flags & TLS_CONN_ENABLE_TLSv1_2) + version = TLS1_2_VERSION; if (!version) { wpa_printf(MSG_DEBUG, "OpenSSL: Invalid TLS version configuration"); @@ -3011,6 +3014,18 @@ static int tls_set_conn_flags(struct tls_connection *conn, unsigned int flags, } } #endif /* >= 1.1.0 */ +#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !defined(LIBRESSL_VERSION_NUMBER) && \ + !defined(OPENSSL_IS_BORINGSSL) + if ((flags & (TLS_CONN_ENABLE_TLSv1_0 | TLS_CONN_ENABLE_TLSv1_1)) && + SSL_get_security_level(ssl) >= 2) { + /* + * Need to drop to security level 1 to allow TLS versions older + * than 1.2 to be used when explicitly enabled in configuration. + */ + SSL_set_security_level(conn->ssl, 1); + } +#endif #ifdef CONFIG_SUITEB #ifdef OPENSSL_IS_BORINGSSL @@ -3180,7 +3195,11 @@ int tls_connection_set_verify(void *ssl_ctx, struct tls_connection *conn, if (conn == NULL) return -1; - if (verify_peer) { + if (verify_peer == 2) { + conn->ca_cert_verify = 1; + SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | + SSL_VERIFY_CLIENT_ONCE, tls_verify_cb); + } else if (verify_peer) { conn->ca_cert_verify = 1; SSL_set_verify(conn->ssl, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT | @@ -3241,8 +3260,36 @@ static int tls_connection_client_cert(struct tls_connection *conn, "OK"); return 0; } else if (client_cert_blob) { +#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20901000L tls_show_errors(MSG_DEBUG, __func__, "SSL_use_certificate_ASN1 failed"); +#else + BIO *bio; + X509 *x509; + + tls_show_errors(MSG_DEBUG, __func__, + "SSL_use_certificate_ASN1 failed"); + bio = BIO_new(BIO_s_mem()); + if (!bio) + return -1; + BIO_write(bio, client_cert_blob, client_cert_blob_len); + x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL); + if (!x509 || SSL_use_certificate(conn->ssl, x509) != 1) { + X509_free(x509); + BIO_free(bio); + return -1; + } + X509_free(x509); + wpa_printf(MSG_DEBUG, + "OpenSSL: Found PEM encoded certificate from blob"); + while ((x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL))) { + wpa_printf(MSG_DEBUG, + "OpenSSL: Added an additional certificate into the chain"); + SSL_add0_chain_cert(conn->ssl, x509); + } + BIO_free(bio); + return 0; +#endif } if (client_cert == NULL) @@ -3749,6 +3796,17 @@ static int tls_connection_private_key(struct tls_data *data, break; } +#ifndef OPENSSL_NO_EC + if (SSL_use_PrivateKey_ASN1(EVP_PKEY_EC, conn->ssl, + (u8 *) private_key_blob, + private_key_blob_len) == 1) { + wpa_printf(MSG_DEBUG, + "OpenSSL: SSL_use_PrivateKey_ASN1(EVP_PKEY_EC) --> OK"); + ok = 1; + break; + } +#endif /* OPENSSL_NO_EC */ + if (SSL_use_RSAPrivateKey_ASN1(conn->ssl, (u8 *) private_key_blob, private_key_blob_len) == 1) { @@ -5265,6 +5323,9 @@ static void openssl_debug_dump_certificate(int i, X509 *cert) ASN1_INTEGER *ser; char serial_num[128]; + if (!cert) + return; + X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); ser = X509_get_serialNumber(cert); @@ -5649,3 +5710,19 @@ u16 tls_connection_get_cipher_suite(struct tls_connection *conn) return SSL_CIPHER_get_id(cipher) & 0xFFFF; #endif } + + +const char * tls_connection_get_peer_subject(struct tls_connection *conn) +{ + if (conn) + return conn->peer_subject; + return NULL; +} + + +bool tls_connection_get_own_cert_used(struct tls_connection *conn) +{ + if (conn) + return SSL_get_certificate(conn->ssl) != NULL; + return false; +} diff --git a/src/crypto/tls_wolfssl.c b/src/crypto/tls_wolfssl.c index d222d1427..ea8f7063b 100644 --- a/src/crypto/tls_wolfssl.c +++ b/src/crypto/tls_wolfssl.c @@ -19,6 +19,7 @@ #include #include #include +#include #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) #define HAVE_AESGCM @@ -468,7 +469,7 @@ static int tls_connection_client_cert(struct tls_connection *conn, if (client_cert_blob) { if (wolfSSL_use_certificate_chain_buffer_format( conn->ssl, client_cert_blob, blob_len, - SSL_FILETYPE_ASN1) < 0) { + SSL_FILETYPE_ASN1) != SSL_SUCCESS) { wpa_printf(MSG_INFO, "SSL: use client cert DER blob failed"); return -1; @@ -478,13 +479,13 @@ static int tls_connection_client_cert(struct tls_connection *conn, } if (client_cert) { - if (wolfSSL_use_certificate_chain_file(conn->ssl, - client_cert) < 0) { + if (wolfSSL_use_certificate_chain_file( + conn->ssl, client_cert) != SSL_SUCCESS) { wpa_printf(MSG_INFO, "SSL: use client cert PEM file failed"); if (wolfSSL_use_certificate_chain_file_format( conn->ssl, client_cert, - SSL_FILETYPE_ASN1) < 0) { + SSL_FILETYPE_ASN1) != SSL_SUCCESS) { wpa_printf(MSG_INFO, "SSL: use client cert DER file failed"); return -1; @@ -576,7 +577,7 @@ static int tls_connection_private_key(void *tls_ctx, static int tls_match_alt_subject_component(WOLFSSL_X509 *cert, int type, const char *value, size_t len) { - WOLFSSL_ASN1_OBJECT *gen; + WOLFSSL_GENERAL_NAME *gen; void *ext; int found = 0; int i; @@ -585,14 +586,15 @@ static int tls_match_alt_subject_component(WOLFSSL_X509 *cert, int type, for (i = 0; ext && i < wolfSSL_sk_num(ext); i++) { gen = wolfSSL_sk_value(ext, i); - if (gen->type != type) + if (!gen || gen->type != type) continue; - if (os_strlen((char *) gen->obj) == len && - os_memcmp(value, gen->obj, len) == 0) + if ((size_t) wolfSSL_ASN1_STRING_length(gen->d.ia5) == len && + os_memcmp(value, wolfSSL_ASN1_STRING_data(gen->d.ia5), + len) == 0) found++; } - wolfSSL_sk_ASN1_OBJECT_free(ext); + wolfSSL_sk_GENERAL_NAME_free(ext); return found; } @@ -676,7 +678,7 @@ static int domain_suffix_match(const char *val, size_t len, const char *match, static int tls_match_suffix_helper(WOLFSSL_X509 *cert, const char *match, size_t match_len, int full) { - WOLFSSL_ASN1_OBJECT *gen; + WOLFSSL_GENERAL_NAME *gen; void *ext; int i; int j; @@ -690,21 +692,23 @@ static int tls_match_suffix_helper(WOLFSSL_X509 *cert, const char *match, for (j = 0; ext && j < wolfSSL_sk_num(ext); j++) { gen = wolfSSL_sk_value(ext, j); - if (gen->type != ASN_DNS_TYPE) + if (!gen || gen->type != ASN_DNS_TYPE) continue; dns_name++; wpa_hexdump_ascii(MSG_DEBUG, "TLS: Certificate dNSName", - gen->obj, os_strlen((char *)gen->obj)); - if (domain_suffix_match((const char *) gen->obj, - os_strlen((char *) gen->obj), match, - match_len, full) == 1) { + wolfSSL_ASN1_STRING_data(gen->d.ia5), + wolfSSL_ASN1_STRING_length(gen->d.ia5)); + if (domain_suffix_match( + (const char *) wolfSSL_ASN1_STRING_data(gen->d.ia5), + wolfSSL_ASN1_STRING_length(gen->d.ia5), match, + match_len, full) == 1) { wpa_printf(MSG_DEBUG, "TLS: %s in dNSName found", full ? "Match" : "Suffix match"); wolfSSL_sk_ASN1_OBJECT_free(ext); return 1; } } - wolfSSL_sk_ASN1_OBJECT_free(ext); + wolfSSL_sk_GENERAL_NAME_free(ext); if (dns_name) { wpa_printf(MSG_DEBUG, "TLS: None of the dNSName(s) matched"); @@ -858,7 +862,7 @@ static void wolfssl_tls_cert_event(struct tls_connection *conn, struct tls_context *context = conn->context; char *alt_subject[TLS_MAX_ALT_SUBJECT]; int alt, num_alt_subject = 0; - WOLFSSL_ASN1_OBJECT *gen; + WOLFSSL_GENERAL_NAME *gen; void *ext; int i; #ifdef CONFIG_SHA256 @@ -899,12 +903,14 @@ static void wolfssl_tls_cert_event(struct tls_connection *conn, if (num_alt_subject == TLS_MAX_ALT_SUBJECT) break; gen = wolfSSL_sk_value((void *) ext, i); - if (gen->type != GEN_EMAIL && - gen->type != GEN_DNS && - gen->type != GEN_URI) + if (!gen || + (gen->type != GEN_EMAIL && + gen->type != GEN_DNS && + gen->type != GEN_URI)) continue; - pos = os_malloc(10 + os_strlen((char *) gen->obj) + 1); + pos = os_malloc(10 + wolfSSL_ASN1_STRING_length(gen->d.ia5) + + 1); if (!pos) break; alt_subject[num_alt_subject++] = pos; @@ -924,11 +930,12 @@ static void wolfssl_tls_cert_event(struct tls_connection *conn, break; } - os_memcpy(pos, gen->obj, os_strlen((char *)gen->obj)); - pos += os_strlen((char *)gen->obj); + os_memcpy(pos, wolfSSL_ASN1_STRING_data(gen->d.ia5), + wolfSSL_ASN1_STRING_length(gen->d.ia5)); + pos += wolfSSL_ASN1_STRING_length(gen->d.ia5); *pos = '\0'; } - wolfSSL_sk_ASN1_OBJECT_free(ext); + wolfSSL_sk_GENERAL_NAME_free(ext); for (alt = 0; alt < num_alt_subject; alt++) ev.peer_cert.altsubject[alt] = alt_subject[alt]; @@ -1741,7 +1748,7 @@ struct wpabuf * tls_connection_encrypt(void *tls_ctx, if (!conn) return NULL; - wpa_printf(MSG_DEBUG, "SSL: encrypt: %ld bytes", wpabuf_len(in_data)); + wpa_printf(MSG_DEBUG, "SSL: encrypt: %zu bytes", wpabuf_len(in_data)); wolfssl_reset_out_data(&conn->output); @@ -1792,7 +1799,7 @@ struct wpabuf * tls_connection_decrypt(void *tls_ctx, } wpabuf_put(buf, res); - wpa_printf(MSG_DEBUG, "SSL: decrypt: %ld bytes", wpabuf_len(buf)); + wpa_printf(MSG_DEBUG, "SSL: decrypt: %zu bytes", wpabuf_len(buf)); return buf; } diff --git a/src/drivers/.gitignore b/src/drivers/.gitignore deleted file mode 100644 index 1d9e0e661..000000000 --- a/src/drivers/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -build.wpa_supplicant -build.hostapd diff --git a/src/drivers/driver.h b/src/drivers/driver.h index d23e436be..b0543e7b4 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -182,6 +182,7 @@ struct hostapd_channel_data { struct hostapd_wmm_rule wmm_rules[WMM_AC_NUM]; }; +#define HE_MAC_CAPAB_0 0 #define HE_MAX_MAC_CAPAB_SIZE 6 #define HE_MAX_PHY_CAPAB_SIZE 11 #define HE_MAX_MCS_CAPAB_SIZE 12 @@ -196,6 +197,7 @@ struct he_capabilities { u8 mac_cap[HE_MAX_MAC_CAPAB_SIZE]; u8 mcs[HE_MAX_MCS_CAPAB_SIZE]; u8 ppet[HE_MAX_PPET_CAPAB_SIZE]; + u16 he_6ghz_capa; }; #define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0) @@ -1095,6 +1097,13 @@ struct wpa_driver_associate_params { const struct ieee80211_vht_capabilities *vhtcaps_mask; #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + /** + * disable_he - Disable HE for this connection + */ + int disable_he; +#endif /* CONFIG_HE_OVERRIDES */ + /** * req_key_mgmt_offload - Request key management offload for connection * @@ -1180,6 +1189,14 @@ struct wpa_driver_associate_params { * fils_erp_rrk_len - Length of fils_erp_rrk in bytes */ size_t fils_erp_rrk_len; + + /** + * sae_pwe - SAE mechanism for PWE derivation + * 0 = hunting-and-pecking loop only + * 1 = hash-to-element only + * 2 = both hunting-and-pecking loop and hash-to-element enabled + */ + int sae_pwe; }; enum hide_ssid { @@ -1401,14 +1418,6 @@ struct wpa_driver_ap_params { */ u8 p2p_go_ctwindow; - /** - * smps_mode - SMPS mode - * - * SMPS mode to be used by the AP, specified as the relevant bits of - * ht_capab (i.e. HT_CAP_INFO_SMPS_*). - */ - unsigned int smps_mode; - /** * disable_dgaf - Whether group-addressed frames are disabled */ @@ -1487,6 +1496,34 @@ struct wpa_driver_ap_params { * he_spr_srg_obss_pd_max_offset - Maximum TX power offset */ int he_spr_srg_obss_pd_max_offset; + + /** + * he_bss_color - Whether the BSS Color is disabled + */ + int he_bss_color_disabled; + + /** + * he_bss_color_partial - The BSS Color AID equation + */ + int he_bss_color_partial; + + /** + * he_bss_color - The BSS Color of the AP + */ + int he_bss_color; + + /** + * twt_responder - Whether Target Wait Time responder is enabled + */ + int twt_responder; + + /** + * sae_pwe - SAE mechanism for PWE derivation + * 0 = hunting-and-pecking loop only + * 1 = hash-to-element only + * 2 = both hunting-and-pecking loop and hash-to-element enabled + */ + int sae_pwe; }; struct wpa_driver_mesh_bss_params { @@ -1522,6 +1559,7 @@ struct wpa_driver_mesh_join_params { #define WPA_DRIVER_MESH_FLAG_SAE_AUTH 0x00000004 #define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008 unsigned int flags; + bool handle_dfs; }; struct wpa_driver_set_key_params { @@ -1533,7 +1571,7 @@ struct wpa_driver_set_key_params { * alg - Encryption algorithm * * (%WPA_ALG_NONE, %WPA_ALG_WEP, %WPA_ALG_TKIP, %WPA_ALG_CCMP, - * %WPA_ALG_IGTK, %WPA_ALG_PMK, %WPA_ALG_GCMP, %WPA_ALG_GCMP_256, + * %WPA_ALG_BIP_AES_CMAC_128, %WPA_ALG_GCMP, %WPA_ALG_GCMP_256, * %WPA_ALG_CCMP_256, %WPA_ALG_BIP_GMAC_128, %WPA_ALG_BIP_GMAC_256, * %WPA_ALG_BIP_CMAC_256); * %WPA_ALG_NONE clears the key. */ @@ -1552,7 +1590,7 @@ struct wpa_driver_set_key_params { /** * key_idx - Key index * - * (0..3), usually 0 for unicast keys; 0..4095 for IGTK */ + * (0..3), usually 0 for unicast keys; 4..5 for IGTK; 6..7 for BIGTK */ int key_idx; /** @@ -1598,8 +1636,8 @@ struct wpa_driver_set_key_params { * * %KEY_FLAG_MODIFY * Set when an already installed key must be updated. - * So far the only use-case is changing RX/TX status of - * installed keys. Must not be set when deleting a key. + * So far the only use-case is changing RX/TX status for + * pairwise keys. Must not be set when deleting a key. * %KEY_FLAG_DEFAULT * Set when the key is also a default key. Must not be set when * deleting a key. @@ -1639,6 +1677,73 @@ struct wpa_driver_set_key_params { enum key_flag key_flag; }; +enum wpa_driver_if_type { + /** + * WPA_IF_STATION - Station mode interface + */ + WPA_IF_STATION, + + /** + * WPA_IF_AP_VLAN - AP mode VLAN interface + * + * This interface shares its address and Beacon frame with the main + * BSS. + */ + WPA_IF_AP_VLAN, + + /** + * WPA_IF_AP_BSS - AP mode BSS interface + * + * This interface has its own address and Beacon frame. + */ + WPA_IF_AP_BSS, + + /** + * WPA_IF_P2P_GO - P2P Group Owner + */ + WPA_IF_P2P_GO, + + /** + * WPA_IF_P2P_CLIENT - P2P Client + */ + WPA_IF_P2P_CLIENT, + + /** + * WPA_IF_P2P_GROUP - P2P Group interface (will become either + * WPA_IF_P2P_GO or WPA_IF_P2P_CLIENT, but the role is not yet known) + */ + WPA_IF_P2P_GROUP, + + /** + * WPA_IF_P2P_DEVICE - P2P Device interface is used to indentify the + * abstracted P2P Device function in the driver + */ + WPA_IF_P2P_DEVICE, + + /* + * WPA_IF_MESH - Mesh interface + */ + WPA_IF_MESH, + + /* + * WPA_IF_TDLS - TDLS offchannel interface (used for pref freq only) + */ + WPA_IF_TDLS, + + /* + * WPA_IF_IBSS - IBSS interface (used for pref freq only) + */ + WPA_IF_IBSS, + + /* + * WPA_IF_NAN - NAN Device + */ + WPA_IF_NAN, + + /* keep last */ + WPA_IF_MAX +}; + /** * struct wpa_driver_capa - Driver capability information */ @@ -1660,8 +1765,16 @@ struct wpa_driver_capa { #define WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 0x00004000 #define WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 0x00008000 #define WPA_DRIVER_CAPA_KEY_MGMT_SAE 0x00010000 +#define WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256 0x00020000 +#define WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256 0x00040000 +#define WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE 0x00080000 +#define WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE 0x00100000 +#define WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384 0x00200000 +#define WPA_DRIVER_CAPA_KEY_MGMT_CCKM 0x00400000 +#define WPA_DRIVER_CAPA_KEY_MGMT_OSEN 0x00800000 /** Bitfield of supported key management suites */ unsigned int key_mgmt; + unsigned int key_mgmt_iftype[WPA_IF_MAX]; #define WPA_DRIVER_CAPA_ENC_WEP40 0x00000001 #define WPA_DRIVER_CAPA_ENC_WEP104 0x00000002 @@ -1692,7 +1805,7 @@ struct wpa_driver_capa { /** Driver takes care of all DFS operations */ #define WPA_DRIVER_FLAGS_DFS_OFFLOAD 0x00000004 /** Driver takes care of RSN 4-way handshake internally; PMK is configured with - * struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */ + * struct wpa_driver_ops::set_key using key_flag = KEY_FLAG_PMK */ #define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X 0x00000008 /** Driver is for a wired Ethernet interface */ #define WPA_DRIVER_FLAGS_WIRED 0x00000010 @@ -1819,21 +1932,29 @@ struct wpa_driver_capa { #define WPA_DRIVER_FLAGS_FTM_RESPONDER 0x0100000000000000ULL /** Driver support 4-way handshake offload for WPA-Personal */ #define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK 0x0200000000000000ULL -/** Driver supports a separate control port for EAPOL frames */ +/** Driver supports a separate control port TX for EAPOL frames */ #define WPA_DRIVER_FLAGS_CONTROL_PORT 0x0400000000000000ULL /** Driver supports VLAN offload */ #define WPA_DRIVER_FLAGS_VLAN_OFFLOAD 0x0800000000000000ULL /** Driver supports UPDATE_FT_IES command */ #define WPA_DRIVER_FLAGS_UPDATE_FT_IES 0x1000000000000000ULL +/** Driver can correctly rekey PTKs without Extended Key ID */ +#define WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS 0x2000000000000000ULL +/** Driver supports Beacon protection */ +#define WPA_DRIVER_FLAGS_BEACON_PROTECTION 0x4000000000000000ULL +/** Driver supports Extended Key ID */ +#define WPA_DRIVER_FLAGS_EXTENDED_KEY_ID 0x8000000000000000ULL u64 flags; +/** Driver supports a separate control port RX for EAPOL frames */ +#define WPA_DRIVER_FLAGS2_CONTROL_PORT_RX 0x0000000000000001ULL +/** Driver supports TX status reports for EAPOL frames through control port */ +#define WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS 0x0000000000000002ULL + u64 flags2; + #define FULL_AP_CLIENT_STATE_SUPP(drv_flags) \ (drv_flags & WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE) -#define WPA_DRIVER_SMPS_MODE_STATIC 0x00000001 -#define WPA_DRIVER_SMPS_MODE_DYNAMIC 0x00000002 - unsigned int smps_modes; - unsigned int wmm_ac_supported:1; unsigned int mac_addr_rand_scan_supported:1; @@ -1993,6 +2114,7 @@ struct hostapd_sta_add_params { u8 vht_opmode; const struct ieee80211_he_capabilities *he_capab; size_t he_capab_len; + const struct ieee80211_he_6ghz_band_cap *he_6ghz_capab; u32 flags; /* bitmask of WPA_STA_* flags */ u32 flags_mask; /* unset bits in flags */ #ifdef CONFIG_MESH @@ -2020,65 +2142,6 @@ struct hostapd_acl_params { struct mac_address mac_acl[0]; }; -enum wpa_driver_if_type { - /** - * WPA_IF_STATION - Station mode interface - */ - WPA_IF_STATION, - - /** - * WPA_IF_AP_VLAN - AP mode VLAN interface - * - * This interface shares its address and Beacon frame with the main - * BSS. - */ - WPA_IF_AP_VLAN, - - /** - * WPA_IF_AP_BSS - AP mode BSS interface - * - * This interface has its own address and Beacon frame. - */ - WPA_IF_AP_BSS, - - /** - * WPA_IF_P2P_GO - P2P Group Owner - */ - WPA_IF_P2P_GO, - - /** - * WPA_IF_P2P_CLIENT - P2P Client - */ - WPA_IF_P2P_CLIENT, - - /** - * WPA_IF_P2P_GROUP - P2P Group interface (will become either - * WPA_IF_P2P_GO or WPA_IF_P2P_CLIENT, but the role is not yet known) - */ - WPA_IF_P2P_GROUP, - - /** - * WPA_IF_P2P_DEVICE - P2P Device interface is used to indentify the - * abstracted P2P Device function in the driver - */ - WPA_IF_P2P_DEVICE, - - /* - * WPA_IF_MESH - Mesh interface - */ - WPA_IF_MESH, - - /* - * WPA_IF_TDLS - TDLS offchannel interface (used for pref freq only) - */ - WPA_IF_TDLS, - - /* - * WPA_IF_IBSS - IBSS interface (used for pref freq only) - */ - WPA_IF_IBSS, -}; - struct wpa_init_params { void *global_priv; const u8 *bssid; @@ -2281,9 +2344,9 @@ struct wmm_params { #ifdef CONFIG_MACSEC struct macsec_init_params { - Boolean always_include_sci; - Boolean use_es; - Boolean use_scb; + bool always_include_sci; + bool use_es; + bool use_scb; }; #endif /* CONFIG_MACSEC */ @@ -2315,6 +2378,9 @@ struct drv_acs_params { /* ACS frequency list info */ const int *freq_list; + + /* Indicates whether EDMG is enabled */ + int edmg_enabled; }; struct wpa_bss_trans_info { @@ -2340,6 +2406,8 @@ struct wpa_pmkid_params { const u8 *pmkid; const u8 *pmk; size_t pmk_len; + u32 pmk_lifetime; + u8 pmk_reauth_threshold; }; /* Mask used to specify which connection parameters have to be updated */ @@ -2381,6 +2449,13 @@ struct external_auth { const u8 *pmkid; }; +/* enum nested_attr - Used to specify if subcommand uses nested attributes */ +enum nested_attr { + NESTED_ATTR_NOT_USED = 0, + NESTED_ATTR_USED = 1, + NESTED_ATTR_UNSPECIFIED = 2, +}; + /** * struct wpa_driver_ops - Driver interface API definition * @@ -2702,11 +2777,13 @@ struct wpa_driver_ops { * @csa_offs_len: Number of elements in csa_offs * @no_encrypt: Do not encrypt frame even if appropriate key exists * (used only for testing purposes) + * @wait: Time to wait off-channel for a response (in ms), or zero * Returns: 0 on success, -1 on failure */ int (*send_mlme)(void *priv, const u8 *data, size_t data_len, int noack, unsigned int freq, const u16 *csa_offs, - size_t csa_offs_len, int no_encrypt); + size_t csa_offs_len, int no_encrypt, + unsigned int wait); /** * update_ft_ies - Update FT (IEEE 802.11r) IEs @@ -3664,6 +3741,8 @@ struct wpa_driver_ops { * @priv: Private driver interface data * @vendor_id: Vendor id * @subcmd: Vendor command id + * @nested_attr_flag: Specifies if vendor subcommand uses nested + * attributes or not * @data: Vendor command parameters (%NULL if no parameters) * @data_len: Data length * @buf: Return buffer (%NULL to ignore reply) @@ -3671,9 +3750,10 @@ struct wpa_driver_ops { * * This function handles vendor specific commands that are passed to * the driver/device. The command is identified by vendor id and - * command id. Parameters can be passed as argument to the command - * in the data buffer. Reply (if any) will be filled in the supplied - * return buffer. + * command id. The nested_attr_flag specifies whether the subcommand + * uses nested attributes or not. Parameters can be passed + * as argument to the command in the data buffer. Reply (if any) will be + * filled in the supplied return buffer. * * The exact driver behavior is driver interface and vendor specific. As * an example, this will be converted to a vendor specific cfg80211 @@ -3681,6 +3761,7 @@ struct wpa_driver_ops { */ int (*vendor_cmd)(void *priv, unsigned int vendor_id, unsigned int subcmd, const u8 *data, size_t data_len, + enum nested_attr nested_attr_flag, struct wpabuf *buf); /** @@ -3971,30 +4052,30 @@ struct wpa_driver_ops { /** * enable_protect_frames - Set protect frames status * @priv: Private driver interface data - * @enabled: TRUE = protect frames enabled - * FALSE = protect frames disabled + * @enabled: true = protect frames enabled + * false = protect frames disabled * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*enable_protect_frames)(void *priv, Boolean enabled); + int (*enable_protect_frames)(void *priv, bool enabled); /** * enable_encrypt - Set encryption status * @priv: Private driver interface data - * @enabled: TRUE = encrypt outgoing traffic - * FALSE = integrity-only protection on outgoing traffic + * @enabled: true = encrypt outgoing traffic + * false = integrity-only protection on outgoing traffic * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*enable_encrypt)(void *priv, Boolean enabled); + int (*enable_encrypt)(void *priv, bool enabled); /** * set_replay_protect - Set replay protect status and window size * @priv: Private driver interface data - * @enabled: TRUE = replay protect enabled - * FALSE = replay protect disabled + * @enabled: true = replay protect enabled + * false = replay protect disabled * @window: replay window size, valid only when replay protect enabled * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*set_replay_protect)(void *priv, Boolean enabled, u32 window); + int (*set_replay_protect)(void *priv, bool enabled, u32 window); /** * set_current_cipher_suite - Set current cipher suite @@ -4007,11 +4088,11 @@ struct wpa_driver_ops { /** * enable_controlled_port - Set controlled port status * @priv: Private driver interface data - * @enabled: TRUE = controlled port enabled - * FALSE = controlled port disabled + * @enabled: true = controlled port enabled + * false = controlled port disabled * Returns: 0 on success, -1 on failure (or if not supported) */ - int (*enable_controlled_port)(void *priv, Boolean enabled); + int (*enable_controlled_port)(void *priv, bool enabled); /** * get_receive_lowest_pn - Get receive lowest pn @@ -4196,12 +4277,12 @@ struct wpa_driver_ops { int (*do_acs)(void *priv, struct drv_acs_params *params); /** - * set_band - Notify driver of band selection + * set_band - Notify driver of band(s) selection * @priv: Private driver interface data - * @band: The selected band(s) + * @band_mask: The selected band(s) bit mask (from enum set_band) * Returns 0 on success, -1 on failure */ - int (*set_band)(void *priv, enum set_band band); + int (*set_band)(void *priv, u32 band_mask); /** * get_pref_freq_list - Get preferred frequency list for an interface @@ -4334,13 +4415,13 @@ struct wpa_driver_ops { int (*ignore_assoc_disallow)(void *priv, int ignore_disallow); /** - * set_bssid_blacklist - Set blacklist of BSSIDs to the driver + * set_bssid_tmp_disallow - Set disallowed BSSIDs to the driver * @priv: Private driver interface data - * @num_bssid: Number of blacklist BSSIDs - * @bssids: List of blacklisted BSSIDs + * @num_bssid: Number of temporarily disallowed BSSIDs + * @bssids: List of temporarily disallowed BSSIDs */ - int (*set_bssid_blacklist)(void *priv, unsigned int num_bssid, - const u8 *bssid); + int (*set_bssid_tmp_disallow)(void *priv, unsigned int num_bssid, + const u8 *bssid); /** * update_connect_params - Update the connection parameters @@ -4392,6 +4473,17 @@ struct wpa_driver_ops { */ int (*update_dh_ie)(void *priv, const u8 *peer_mac, u16 reason_code, const u8 *ie, size_t ie_len); + + /** + * dpp_listen - Notify driver about start/stop of DPP listen + * @priv: Private driver interface data + * @enable: Whether listen state is enabled (or disabled) + * Returns: 0 on success, -1 on failure + * + * This optional callback can be used to update RX frame filtering to + * explicitly allow reception of broadcast Public Action frames. + */ + int (*dpp_listen)(void *priv, bool enable); }; /** @@ -4942,6 +5034,15 @@ enum wpa_event_type { * EVENT_UPDATE_DH - Notification of updated DH information */ EVENT_UPDATE_DH, + + /** + * EVENT_UNPROT_BEACON - Unprotected Beacon frame received + * + * This event should be called when a Beacon frame is dropped due to it + * not being protected correctly. union wpa_event_data::unprot_beacon + * is required to provide more details of the frame. + */ + EVENT_UNPROT_BEACON, }; @@ -4978,6 +5079,34 @@ struct freq_survey { #define SURVEY_HAS_CHAN_TIME_RX BIT(3) #define SURVEY_HAS_CHAN_TIME_TX BIT(4) +/** + * enum sta_connect_fail_reason_codes - STA connect failure reason code values + * @STA_CONNECT_FAIL_REASON_UNSPECIFIED: No reason code specified for + * connection failure. + * @STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: No Probe Response frame received + * for unicast Probe Request frame. + * @STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: STA failed to send auth request. + * @STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: AP didn't send ACK for + * auth request. + * @STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: Auth response is not + * received from AP. + * @STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: STA failed to send + * Association Request frame. + * @STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: AP didn't send ACK for + * Association Request frame. + * @STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: Association Response + * frame is not received from AP. + */ +enum sta_connect_fail_reason_codes { + STA_CONNECT_FAIL_REASON_UNSPECIFIED = 0, + STA_CONNECT_FAIL_REASON_NO_BSS_FOUND = 1, + STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL = 2, + STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED = 3, + STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED = 4, + STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL = 5, + STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED = 6, + STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED = 7, +}; /** * union wpa_event_data - Additional data for wpa_supplicant_event() calls @@ -5379,6 +5508,11 @@ union wpa_event_data { * FILS ERP messages */ u16 fils_erp_next_seq_num; + + /** + * reason_code - Connection failure reason code from the driver + */ + enum sta_connect_fail_reason_codes reason_code; } assoc_reject; struct timeout_event { @@ -5708,6 +5842,7 @@ union wpa_event_data { * struct acs_selected_channels - Data for EVENT_ACS_CHANNEL_SELECTED * @pri_freq: Selected primary frequency * @sec_freq: Selected secondary frequency + * @edmg_channel: Selected EDMG channel * @vht_seg0_center_ch: VHT mode Segment0 center channel * The value is the index of the channel center frequency for * 20 MHz, 40 MHz, and 80 MHz channels. The value is the center @@ -5726,6 +5861,7 @@ union wpa_event_data { struct acs_selected_channels { unsigned int pri_freq; unsigned int sec_freq; + u8 edmg_channel; u8 vht_seg0_center_ch; u8 vht_seg1_center_ch; u16 ch_width; @@ -5792,6 +5928,13 @@ union wpa_event_data { const u8 *ie; size_t ie_len; } update_dh; + + /** + * struct unprot_beacon - Data for EVENT_UNPROT_BEACON + */ + struct unprot_beacon { + const u8 *sa; + } unprot_beacon; }; /** @@ -5875,6 +6018,7 @@ wpa_get_wowlan_triggers(const char *wowlan_triggers, const struct wpa_driver_capa *capa); /* Convert driver flag to string */ const char * driver_flag_to_string(u64 flag); +const char * driver_flag2_to_string(u64 flag2); /* NULL terminated array of linked in driver wrappers */ extern const struct wpa_driver_ops *const wpa_drivers[]; diff --git a/src/drivers/driver_atheros.c b/src/drivers/driver_atheros.c index 2014f9db4..9b4166d22 100644 --- a/src/drivers/driver_atheros.c +++ b/src/drivers/driver_atheros.c @@ -532,7 +532,7 @@ atheros_set_key(void *priv, struct wpa_driver_set_key_params *params) cipher = IEEE80211_CIPHER_AES_GCM_256; break; #endif /* ATH_GCM_SUPPORT */ - case WPA_ALG_IGTK: + case WPA_ALG_BIP_CMAC_128: cipher = IEEE80211_CIPHER_AES_CMAC; break; #ifdef ATH_GCM_SUPPORT @@ -1965,7 +1965,7 @@ static int atheros_set_ap(void *priv, struct wpa_driver_ap_params *params) static int atheros_send_mgmt(void *priv, const u8 *frm, size_t data_len, int noack, unsigned int freq, const u16 *csa_offs, size_t csa_offs_len, - int no_encrypt) + int no_encrypt, unsigned int wait) { struct atheros_driver_data *drv = priv; u8 buf[1510]; diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c index 1fcafedae..a29d2c801 100644 --- a/src/drivers/driver_bsd.c +++ b/src/drivers/driver_bsd.c @@ -137,7 +137,9 @@ bsd_get80211(void *priv, struct ieee80211req *ireq, int op, void *arg, ireq->i_data = arg; if (ioctl(drv->global->sock, SIOCG80211, ireq) < 0) { - wpa_printf(MSG_ERROR, "ioctl[SIOCG80211, op=%u, " + int level = drv->if_removed ? MSG_DEBUG : MSG_ERROR; + + wpa_printf(level, "ioctl[SIOCG80211, op=%u, " "arg_len=%u]: %s", op, arg_len, strerror(errno)); return -1; } @@ -576,17 +578,13 @@ bsd_set_freq(void *priv, struct hostapd_freq_params *freq) if (channel < 14) { mode = -#ifdef CONFIG_IEEE80211N freq->ht_enabled ? IFM_IEEE80211_11NG : -#endif /* CONFIG_IEEE80211N */ - IFM_IEEE80211_11G; + IFM_IEEE80211_11G; } else if (channel == 14) { mode = IFM_IEEE80211_11B; } else { mode = -#ifdef CONFIG_IEEE80211N freq->ht_enabled ? IFM_IEEE80211_11NA : -#endif /* CONFIG_IEEE80211N */ IFM_IEEE80211_11A; } if (bsd_set_mediaopt(drv, IFM_MMASK, mode) < 0) { @@ -1455,6 +1453,7 @@ wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv) #define GETPARAM(drv, param, v) \ (((v) = get80211param(drv, param)) != -1) struct bsd_driver_data *drv; + int i; drv = os_zalloc(sizeof(*drv)); if (drv == NULL) @@ -1471,6 +1470,9 @@ wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv) drv->global = priv; os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); + /* Set the interface as removed until proven to work. */ + drv->if_removed = 1; + if (!GETPARAM(drv, IEEE80211_IOC_ROAMING, drv->prev_roaming)) { wpa_printf(MSG_DEBUG, "%s: failed to get roaming state: %s", __func__, strerror(errno)); @@ -1490,10 +1492,17 @@ wpa_driver_bsd_init(void *ctx, const char *ifname, void *priv) if (wpa_driver_bsd_capa(drv)) goto fail; + /* Update per interface supported AKMs */ + for (i = 0; i < WPA_IF_MAX; i++) + drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt; + /* Down interface during setup. */ if (bsd_get_iface_flags(drv) < 0) goto fail; + /* Proven to work, lets go! */ + drv->if_removed = 0; + drv->opmode = get80211opmode(drv); dl_list_add(&drv->global->ifaces, &drv->list); diff --git a/src/drivers/driver_common.c b/src/drivers/driver_common.c index 731c6a3b1..a7ebe9566 100644 --- a/src/drivers/driver_common.c +++ b/src/drivers/driver_common.c @@ -89,6 +89,7 @@ const char * event_to_string(enum wpa_event_type event) E2S(INTERFACE_MAC_CHANGED); E2S(WDS_STA_INTERFACE_STATUS); E2S(UPDATE_DH); + E2S(UNPROT_BEACON); } return "UNKNOWN"; @@ -308,6 +309,26 @@ const char * driver_flag_to_string(u64 flag) DF2S(OCE_AP); DF2S(OCE_STA_CFON); DF2S(MFP_OPTIONAL); + DF2S(SELF_MANAGED_REGULATORY); + DF2S(FTM_RESPONDER); + DF2S(CONTROL_PORT); + DF2S(VLAN_OFFLOAD); + DF2S(UPDATE_FT_IES); + DF2S(SAFE_PTK0_REKEYS); + DF2S(BEACON_PROTECTION); + DF2S(EXTENDED_KEY_ID); + } + return "UNKNOWN"; +#undef DF2S +} + + +const char * driver_flag2_to_string(u64 flag2) +{ +#define DF2S(x) case WPA_DRIVER_FLAGS2_ ## x: return #x + switch (flag2) { + DF2S(CONTROL_PORT_RX); + DF2S(CONTROL_PORT_TX_STATUS); } return "UNKNOWN"; #undef DF2S diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c index cfc52c7f3..b9c42e4db 100644 --- a/src/drivers/driver_hostap.c +++ b/src/drivers/driver_hostap.c @@ -264,7 +264,7 @@ static int hostap_init_sockets(struct hostap_driver_data *drv, u8 *own_addr) static int hostap_send_mlme(void *priv, const u8 *msg, size_t len, int noack, unsigned int freq, const u16 *csa_offs, size_t csa_offs_len, - int no_encrypt) + int no_encrypt, unsigned int wait) { struct hostap_driver_data *drv = priv; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg; @@ -313,7 +313,7 @@ static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data, pos += 2; memcpy(pos, data, data_len); - res = hostap_send_mlme(drv, (u8 *) hdr, len, 0, 0, NULL, 0, 0); + res = hostap_send_mlme(drv, (u8 *) hdr, len, 0, 0, NULL, 0, 0, 0); if (res < 0) { wpa_printf(MSG_ERROR, "hostap_send_eapol - packet len: %lu - " "failed: %d (%s)", @@ -1055,7 +1055,7 @@ static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, memcpy(mgmt.bssid, own_addr, ETH_ALEN); mgmt.u.deauth.reason_code = host_to_le16(reason); return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.deauth), 0, 0, NULL, 0, 0); + sizeof(mgmt.u.deauth), 0, 0, NULL, 0, 0, 0); } @@ -1093,7 +1093,7 @@ static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, memcpy(mgmt.bssid, own_addr, ETH_ALEN); mgmt.u.disassoc.reason_code = host_to_le16(reason); return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN + - sizeof(mgmt.u.disassoc), 0, 0, NULL, 0, 0); + sizeof(mgmt.u.disassoc), 0, 0, NULL, 0, 0, 0); } @@ -1173,7 +1173,7 @@ static void wpa_driver_hostap_poll_client(void *priv, const u8 *own_addr, os_memcpy(hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); os_memcpy(hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); - hostap_send_mlme(priv, (u8 *) &hdr, sizeof(hdr), 0, 0, NULL, 0, 0); + hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0, 0, NULL, 0, 0, 0); } diff --git a/src/drivers/driver_macsec_linux.c b/src/drivers/driver_macsec_linux.c index 5319ba2d0..3dba13ce7 100644 --- a/src/drivers/driver_macsec_linux.c +++ b/src/drivers/driver_macsec_linux.c @@ -59,24 +59,24 @@ struct macsec_drv_data { int parent_ifi; int use_pae_group_addr; - Boolean created_link; + bool created_link; - Boolean controlled_port_enabled; - Boolean controlled_port_enabled_set; + bool controlled_port_enabled; + bool controlled_port_enabled_set; - Boolean protect_frames; - Boolean protect_frames_set; + bool protect_frames; + bool protect_frames_set; - Boolean encrypt; - Boolean encrypt_set; + bool encrypt; + bool encrypt_set; - Boolean replay_protect; - Boolean replay_protect_set; + bool replay_protect; + bool replay_protect_set; u32 replay_window; u8 encoding_sa; - Boolean encoding_sa_set; + bool encoding_sa_set; }; @@ -197,7 +197,7 @@ static int try_commit(struct macsec_drv_data *drv) rtnl_link_put(change); - drv->controlled_port_enabled_set = FALSE; + drv->controlled_port_enabled_set = false; } if (drv->protect_frames_set) { @@ -236,9 +236,9 @@ static int try_commit(struct macsec_drv_data *drv) if (err < 0) return err; - drv->protect_frames_set = FALSE; - drv->encrypt_set = FALSE; - drv->replay_protect_set = FALSE; + drv->protect_frames_set = false; + drv->encrypt_set = false; + drv->replay_protect_set = false; return 0; } @@ -390,17 +390,17 @@ static int macsec_drv_get_capability(void *priv, enum macsec_cap *cap) /** * macsec_drv_enable_protect_frames - Set protect frames status * @priv: Private driver interface data - * @enabled: TRUE = protect frames enabled - * FALSE = protect frames disabled + * @enabled: true = protect frames enabled + * false = protect frames disabled * Returns: 0 on success, -1 on failure (or if not supported) */ -static int macsec_drv_enable_protect_frames(void *priv, Boolean enabled) +static int macsec_drv_enable_protect_frames(void *priv, bool enabled) { struct macsec_drv_data *drv = priv; wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE"); - drv->protect_frames_set = TRUE; + drv->protect_frames_set = true; drv->protect_frames = enabled; return try_commit(drv); @@ -410,17 +410,17 @@ static int macsec_drv_enable_protect_frames(void *priv, Boolean enabled) /** * macsec_drv_enable_encrypt - Set protect frames status * @priv: Private driver interface data - * @enabled: TRUE = protect frames enabled - * FALSE = protect frames disabled + * @enabled: true = protect frames enabled + * false = protect frames disabled * Returns: 0 on success, -1 on failure (or if not supported) */ -static int macsec_drv_enable_encrypt(void *priv, Boolean enabled) +static int macsec_drv_enable_encrypt(void *priv, bool enabled) { struct macsec_drv_data *drv = priv; wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE"); - drv->encrypt_set = TRUE; + drv->encrypt_set = true; drv->encrypt = enabled; return try_commit(drv); @@ -430,12 +430,12 @@ static int macsec_drv_enable_encrypt(void *priv, Boolean enabled) /** * macsec_drv_set_replay_protect - Set replay protect status and window size * @priv: Private driver interface data - * @enabled: TRUE = replay protect enabled - * FALSE = replay protect disabled + * @enabled: true = replay protect enabled + * false = replay protect disabled * @window: replay window size, valid only when replay protect enabled * Returns: 0 on success, -1 on failure (or if not supported) */ -static int macsec_drv_set_replay_protect(void *priv, Boolean enabled, +static int macsec_drv_set_replay_protect(void *priv, bool enabled, u32 window) { struct macsec_drv_data *drv = priv; @@ -443,7 +443,7 @@ static int macsec_drv_set_replay_protect(void *priv, Boolean enabled, wpa_printf(MSG_DEBUG, "%s -> %s, %u", __func__, enabled ? "TRUE" : "FALSE", window); - drv->replay_protect_set = TRUE; + drv->replay_protect_set = true; drv->replay_protect = enabled; if (enabled) drv->replay_window = window; @@ -468,18 +468,18 @@ static int macsec_drv_set_current_cipher_suite(void *priv, u64 cs) /** * macsec_drv_enable_controlled_port - Set controlled port status * @priv: Private driver interface data - * @enabled: TRUE = controlled port enabled - * FALSE = controlled port disabled + * @enabled: true = controlled port enabled + * false = controlled port disabled * Returns: 0 on success, -1 on failure (or if not supported) */ -static int macsec_drv_enable_controlled_port(void *priv, Boolean enabled) +static int macsec_drv_enable_controlled_port(void *priv, bool enabled) { struct macsec_drv_data *drv = priv; wpa_printf(MSG_DEBUG, "%s -> %s", __func__, enabled ? "TRUE" : "FALSE"); drv->controlled_port_enabled = enabled; - drv->controlled_port_enabled_set = TRUE; + drv->controlled_port_enabled_set = true; return try_commit(drv); } @@ -712,6 +712,9 @@ static int macsec_drv_set_receive_lowest_pn(void *priv, struct receive_sa *sa) if (!msg) return ret; + if (nla_put_rxsc_config(msg, mka_sci_u64(&sa->sc->sci))) + goto nla_put_failure; + nest = nla_nest_start(msg, MACSEC_ATTR_SA_CONFIG); if (!nest) goto nla_put_failure; @@ -986,7 +989,7 @@ nla_put_failure: static int set_active_rx_sa(const struct macsec_genl_ctx *ctx, int ifindex, - u64 sci, unsigned char an, Boolean state) + u64 sci, unsigned char an, bool state) { struct nl_msg *msg; struct nlattr *nest; @@ -1036,7 +1039,7 @@ static int macsec_drv_enable_receive_sa(void *priv, struct receive_sa *sa) SCI2STR(sa->sc->sci.addr, sa->sc->sci.port)); return set_active_rx_sa(ctx, drv->ifi, mka_sci_u64(&sa->sc->sci), - sa->an, TRUE); + sa->an, true); } @@ -1056,7 +1059,7 @@ static int macsec_drv_disable_receive_sa(void *priv, struct receive_sa *sa) SCI2STR(sa->sc->sci.addr, sa->sc->sci.port)); return set_active_rx_sa(ctx, drv->ifi, mka_sci_u64(&sa->sc->sci), - sa->an, FALSE); + sa->an, false); } @@ -1117,13 +1120,13 @@ static int macsec_drv_create_transmit_sc( sci = mka_sci_u64(&sc->sci); rtnl_link_macsec_set_sci(link, sci); - drv->created_link = TRUE; + drv->created_link = true; err = rtnl_link_add(drv->sk, link, NLM_F_CREATE); if (err == -NLE_BUSY) { wpa_printf(MSG_INFO, DRV_PREFIX "link already exists, using it"); - drv->created_link = FALSE; + drv->created_link = false; } else if (err < 0) { rtnl_link_put(link); wpa_printf(MSG_ERROR, DRV_PREFIX "couldn't create link: err %d", @@ -1296,7 +1299,7 @@ nla_put_failure: static int set_active_tx_sa(const struct macsec_genl_ctx *ctx, int ifindex, - unsigned char an, Boolean state) + unsigned char an, bool state) { struct nl_msg *msg; struct nlattr *nest; @@ -1344,13 +1347,13 @@ static int macsec_drv_enable_transmit_sa(void *priv, struct transmit_sa *sa) SCISTR, drv->ifname, sa->an, SCI2STR(sa->sc->sci.addr, sa->sc->sci.port)); - ret = set_active_tx_sa(ctx, drv->ifi, sa->an, TRUE); + ret = set_active_tx_sa(ctx, drv->ifi, sa->an, true); if (ret < 0) { wpa_printf(MSG_ERROR, DRV_PREFIX "failed to enable txsa"); return ret; } - drv->encoding_sa_set = TRUE; + drv->encoding_sa_set = true; drv->encoding_sa = sa->an; return try_commit(drv); @@ -1372,7 +1375,7 @@ static int macsec_drv_disable_transmit_sa(void *priv, struct transmit_sa *sa) SCISTR, drv->ifname, sa->an, SCI2STR(sa->sc->sci.addr, sa->sc->sci.port)); - return set_active_tx_sa(ctx, drv->ifi, sa->an, FALSE); + return set_active_tx_sa(ctx, drv->ifi, sa->an, false); } diff --git a/src/drivers/driver_macsec_qca.c b/src/drivers/driver_macsec_qca.c index f4e55d5d9..928f02499 100644 --- a/src/drivers/driver_macsec_qca.c +++ b/src/drivers/driver_macsec_qca.c @@ -70,11 +70,11 @@ struct macsec_qca_data { u32 secy_id; /* shadow */ - Boolean always_include_sci; - Boolean use_es; - Boolean use_scb; - Boolean protect_frames; - Boolean replay_protect; + bool always_include_sci; + bool use_es; + bool use_scb; + bool protect_frames; + bool replay_protect; u32 replay_window; struct channel_map receive_channel_map[MAXSC]; @@ -91,7 +91,7 @@ static void __macsec_drv_init(struct macsec_qca_data *drv) wpa_printf(MSG_INFO, "%s: secy_id=%d", __func__, drv->secy_id); /* Enable Secy and Let EAPoL bypass */ - ret = nss_macsec_secy_en_set(drv->secy_id, TRUE); + ret = nss_macsec_secy_en_set(drv->secy_id, true); if (ret) wpa_printf(MSG_ERROR, "nss_macsec_secy_en_set: FAIL"); @@ -123,7 +123,7 @@ static void __macsec_drv_init(struct macsec_qca_data *drv) static void __macsec_drv_deinit(struct macsec_qca_data *drv) { - nss_macsec_secy_en_set(drv->secy_id, FALSE); + nss_macsec_secy_en_set(drv->secy_id, false); nss_macsec_secy_rx_sc_del_all(drv->secy_id); nss_macsec_secy_tx_sc_del_all(drv->secy_id); } @@ -422,7 +422,7 @@ static int macsec_qca_get_capability(void *priv, enum macsec_cap *cap) } -static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled) +static int macsec_qca_enable_protect_frames(void *priv, bool enabled) { struct macsec_qca_data *drv = priv; int ret = 0; @@ -435,7 +435,7 @@ static int macsec_qca_enable_protect_frames(void *priv, Boolean enabled) } -static int macsec_qca_set_replay_protect(void *priv, Boolean enabled, +static int macsec_qca_set_replay_protect(void *priv, bool enabled, unsigned int window) { struct macsec_qca_data *drv = priv; @@ -480,7 +480,7 @@ static int macsec_qca_set_current_cipher_suite(void *priv, u64 cs) } -static int macsec_qca_enable_controlled_port(void *priv, Boolean enabled) +static int macsec_qca_enable_controlled_port(void *priv, bool enabled) { struct macsec_qca_data *drv = priv; int ret = 0; @@ -560,7 +560,7 @@ static int macsec_qca_get_receive_lowest_pn(void *priv, struct receive_sa *sa) struct macsec_qca_data *drv = priv; int ret = 0; u32 next_pn = 0; - bool enabled = FALSE; + bool enabled = false; u32 win; u32 channel; @@ -629,7 +629,7 @@ static int macsec_qca_get_available_receive_sc(void *priv, u32 *channel) struct macsec_qca_data *drv = priv; int ret = 0; u32 sc_ch = 0; - bool in_use = FALSE; + bool in_use = false; for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { ret = nss_macsec_secy_rx_sc_in_used_get(drv->secy_id, sc_ch, @@ -794,7 +794,7 @@ static int macsec_qca_enable_receive_sa(void *priv, struct receive_sa *sa) sa->an); ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, - TRUE); + true); return ret; } @@ -814,7 +814,7 @@ static int macsec_qca_disable_receive_sa(void *priv, struct receive_sa *sa) sa->an); ret += nss_macsec_secy_rx_sa_en_set(drv->secy_id, channel, sa->an, - FALSE); + false); return ret; } @@ -824,7 +824,7 @@ static int macsec_qca_get_available_transmit_sc(void *priv, u32 *channel) { struct macsec_qca_data *drv = priv; u32 sc_ch = 0; - bool in_use = FALSE; + bool in_use = false; for (sc_ch = 0; sc_ch < MAXSC; sc_ch++) { if (nss_macsec_secy_tx_sc_in_used_get(drv->secy_id, sc_ch, @@ -988,7 +988,7 @@ static int macsec_qca_enable_transmit_sa(void *priv, struct transmit_sa *sa) sa->an); ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, - TRUE); + true); return ret; } @@ -1008,7 +1008,7 @@ static int macsec_qca_disable_transmit_sa(void *priv, struct transmit_sa *sa) sa->an); ret += nss_macsec_secy_tx_sa_en_set(drv->secy_id, channel, sa->an, - FALSE); + false); return ret; } diff --git a/src/drivers/driver_ndis.c b/src/drivers/driver_ndis.c index 529fc3bc6..b5fff483e 100644 --- a/src/drivers/driver_ndis.c +++ b/src/drivers/driver_ndis.c @@ -2809,6 +2809,7 @@ static void * wpa_driver_ndis_init(void *ctx, const char *ifname) { struct wpa_driver_ndis_data *drv; u32 mode; + int i; drv = os_zalloc(sizeof(*drv)); if (drv == NULL) @@ -2855,6 +2856,11 @@ static void * wpa_driver_ndis_init(void *ctx, const char *ifname) } wpa_driver_ndis_get_capability(drv); + /* Update per interface supported AKMs */ + for (i = 0; i < WPA_IF_MAX; i++) + drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt; + + /* Make sure that the driver does not have any obsolete PMKID entries. */ wpa_driver_ndis_flush_pmkid(drv); diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 7305ed60b..448c404f3 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -30,7 +30,6 @@ #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/wpa_common.h" -#include "l2_packet/l2_packet.h" #include "netlink.h" #include "linux_defines.h" #include "linux_ioctl.h" @@ -279,6 +278,43 @@ static int ack_handler(struct nl_msg *msg, void *arg) return NL_STOP; } + +struct nl80211_ack_ext_arg { + int *err; + void *ext_data; +}; + + +static int ack_handler_cookie(struct nl_msg *msg, void *arg) +{ + struct nl80211_ack_ext_arg *ext_arg = arg; + struct nlattr *tb[NLMSGERR_ATTR_MAX + 1]; + u64 *cookie = ext_arg->ext_data; + struct nlattr *attrs; + size_t ack_len, attr_len; + + *ext_arg->err = 0; + ack_len = sizeof(struct nlmsghdr) + sizeof(int) + + sizeof(struct nlmsghdr); + attrs = (struct nlattr *) + ((u8 *) nlmsg_data(nlmsg_hdr(msg)) + sizeof(struct nlmsghdr) + + sizeof(int)); + if (nlmsg_hdr(msg)->nlmsg_len <= ack_len) + return NL_STOP; + + attr_len = nlmsg_hdr(msg)->nlmsg_len - ack_len; + + if(!(nlmsg_hdr(msg)->nlmsg_flags & NLM_F_ACK_TLVS)) + return NL_STOP; + + nla_parse(tb, NLMSGERR_ATTR_MAX, attrs, attr_len, NULL); + if (tb[NLMSGERR_ATTR_COOKIE]) + *cookie = nla_get_u64(tb[NLMSGERR_ATTR_COOKIE]); + + return NL_STOP; +} + + static int finish_handler(struct nl_msg *msg, void *arg) { int *ret = arg; @@ -353,7 +389,9 @@ static void nl80211_nlmsg_clear(struct nl_msg *msg) static int send_and_recv(struct nl80211_global *global, struct nl_sock *nl_handle, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) + void *valid_data, + int (*ack_handler_custom)(struct nl_msg *, void *), + void *ack_data) { struct nl_cb *cb; int err = -ENOMEM, opt; @@ -391,7 +429,15 @@ static int send_and_recv(struct nl80211_global *global, nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &err); - nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); + if (ack_handler_custom) { + struct nl80211_ack_ext_arg *ext_arg = ack_data; + + ext_arg->err = &err; + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, + ack_handler_custom, ack_data); + } else { + nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err); + } if (valid_handler) nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, @@ -431,10 +477,66 @@ static int send_and_recv(struct nl80211_global *global, int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), - void *valid_data) + void *valid_data, + int (*ack_handler_custom)(struct nl_msg *, void *), + void *ack_data) { return send_and_recv(drv->global, drv->global->nl, msg, - valid_handler, valid_data); + valid_handler, valid_data, + ack_handler_custom, ack_data); +} + + +/* Use this method to mark that it is necessary to own the connection/interface + * for this operation. + * handle may be set to NULL, to get the same behavior as send_and_recv_msgs(). + * set_owner can be used to mark this socket for receiving control port frames. + */ +static int send_and_recv_msgs_owner(struct wpa_driver_nl80211_data *drv, + struct nl_msg *msg, + struct nl_sock *handle, int set_owner, + int (*valid_handler)(struct nl_msg *, + void *), + void *valid_data, + int (*ack_handler_custom)(struct nl_msg *, + void *), + void *ack_data) +{ + if (!msg) + return -ENOMEM; + + /* Control port over nl80211 needs the flags and attributes below. + * + * The Linux kernel has initial checks for them (in nl80211.c) like: + * validate_pae_over_nl80211(...) + * or final checks like: + * dev->ieee80211_ptr->conn_owner_nlportid != info->snd_portid + * + * Final operations (e.g., disassociate) don't need to set these + * attributes, but they have to be performed on the socket, which has + * the connection owner property set in the kernel. + */ + if ((drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) && + handle && set_owner && + (nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_OVER_NL80211) || + nla_put_flag(msg, NL80211_ATTR_SOCKET_OWNER) || + nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, ETH_P_PAE) || + nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_PREAUTH))) + return -1; + + return send_and_recv(drv->global, handle ? handle : drv->global->nl, + msg, valid_handler, valid_data, + ack_handler_custom, ack_data); +} + + +struct nl_sock * get_connect_handle(struct i802_bss *bss) +{ + if ((bss->drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) || + bss->use_nl_connect) + return bss->nl_connect; + + return NULL; } @@ -492,7 +594,8 @@ static int nl_get_multicast_id(struct nl80211_global *global, return -1; } - ret = send_and_recv(global, global->nl, msg, family_handler, &res); + ret = send_and_recv(global, global->nl, msg, family_handler, &res, + NULL, NULL); if (ret == 0) ret = res.id; return ret; @@ -609,7 +712,8 @@ int nl80211_get_wiphy_index(struct i802_bss *bss) if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE))) return -1; - if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0) + if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data, + NULL, NULL) == 0) return data.wiphy_idx; return -1; } @@ -626,7 +730,8 @@ static enum nl80211_iftype nl80211_get_ifmode(struct i802_bss *bss) if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE))) return NL80211_IFTYPE_UNSPECIFIED; - if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data) == 0) + if (send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data, + NULL, NULL) == 0) return data.nlmode; return NL80211_IFTYPE_UNSPECIFIED; } @@ -642,7 +747,8 @@ static int nl80211_get_macaddr(struct i802_bss *bss) if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_GET_INTERFACE))) return -1; - return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data); + return send_and_recv_msgs(bss->drv, msg, netdev_info_handler, &data, + NULL, NULL); } @@ -662,7 +768,8 @@ static int nl80211_register_beacons(struct wpa_driver_nl80211_data *drv, return -1; } - ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL); + ret = send_and_recv(drv->global, w->nl_beacons, msg, NULL, NULL, + NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Register beacons command " "failed: ret=%d (%s)", @@ -1047,7 +1154,7 @@ static void wpa_driver_nl80211_event_rtm_newlink(void *ctx, while (RTA_OK(attr, attrlen)) { switch (attr->rta_type) { case IFLA_IFNAME: - if (RTA_PAYLOAD(attr) >= IFNAMSIZ) + if (RTA_PAYLOAD(attr) > IFNAMSIZ) break; os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr)); ifname[RTA_PAYLOAD(attr)] = '\0'; @@ -1222,7 +1329,7 @@ static void wpa_driver_nl80211_event_rtm_dellink(void *ctx, while (RTA_OK(attr, attrlen)) { switch (attr->rta_type) { case IFLA_IFNAME: - if (RTA_PAYLOAD(attr) >= IFNAMSIZ) + if (RTA_PAYLOAD(attr) > IFNAMSIZ) break; os_memcpy(ifname, RTA_DATA(attr), RTA_PAYLOAD(attr)); ifname[RTA_PAYLOAD(attr)] = '\0'; @@ -1358,7 +1465,7 @@ try_again: os_memset(&arg, 0, sizeof(arg)); arg.drv = drv; ret = send_and_recv_msgs(drv, msg, nl80211_get_assoc_freq_handler, - &arg); + &arg, NULL, NULL); if (ret == -EAGAIN) { count++; if (count >= 10) { @@ -1392,7 +1499,7 @@ try_again: os_memset(&arg, 0, sizeof(arg)); arg.drv = drv; ret = send_and_recv_msgs(drv, msg, nl80211_get_assoc_freq_handler, - &arg); + &arg, NULL, NULL); if (ret == -EAGAIN) { count++; if (count >= 10) { @@ -1495,7 +1602,7 @@ int nl80211_get_link_signal(struct wpa_driver_nl80211_data *drv, return -ENOBUFS; } - return send_and_recv_msgs(drv, msg, get_link_signal, sig); + return send_and_recv_msgs(drv, msg, get_link_signal, sig, NULL, NULL); } @@ -1552,7 +1659,8 @@ int nl80211_get_link_noise(struct wpa_driver_nl80211_data *drv, sig_change->frequency = drv->assoc_freq; msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY); - return send_and_recv_msgs(drv, msg, get_link_noise, sig_change); + return send_and_recv_msgs(drv, msg, get_link_noise, sig_change, + NULL, NULL); } @@ -1616,7 +1724,7 @@ static int nl80211_channel_info(void *priv, struct wpa_channel_info *ci) struct nl_msg *msg; msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE); - return send_and_recv_msgs(drv, msg, get_channel_info, ci); + return send_and_recv_msgs(drv, msg, get_channel_info, ci, NULL, NULL); } @@ -1665,7 +1773,7 @@ static int wpa_driver_nl80211_set_country(void *priv, const char *alpha2_arg) nlmsg_free(msg); return -EINVAL; } - if (send_and_recv_msgs(drv, msg, NULL, NULL)) + if (send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL)) return -EINVAL; return 0; } @@ -1701,7 +1809,8 @@ static int wpa_driver_nl80211_get_country(void *priv, char *alpha2) nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG); alpha2[0] = '\0'; - ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2); + ret = send_and_recv_msgs(drv, msg, nl80211_get_country, alpha2, + NULL, NULL); if (!alpha2[0]) ret = -1; @@ -1918,6 +2027,25 @@ static void wpa_driver_nl80211_handle_eapol_tx_status(int sock, } +static int nl80211_init_connect_handle(struct i802_bss *bss) +{ + if (bss->nl_connect) { + wpa_printf(MSG_DEBUG, + "nl80211: Connect handle already created (nl_connect=%p)", + bss->nl_connect); + return -1; + } + + bss->nl_connect = nl_create_handle(bss->nl_cb, "connect"); + if (!bss->nl_connect) + return -1; + nl80211_register_eloop_read(&bss->nl_connect, + wpa_driver_nl80211_event_receive, + bss->nl_cb, 1); + return 0; +} + + static int nl80211_init_bss(struct i802_bss *bss) { bss->nl_cb = nl_cb_alloc(NL_CB_DEFAULT); @@ -1929,6 +2057,8 @@ static int nl80211_init_bss(struct i802_bss *bss) nl_cb_set(bss->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, process_bss_event, bss); + nl80211_init_connect_handle(bss); + return 0; } @@ -1937,6 +2067,9 @@ static void nl80211_destroy_bss(struct i802_bss *bss) { nl_cb_put(bss->nl_cb); bss->nl_cb = NULL; + + if (bss->nl_connect) + nl80211_destroy_eloop_handle(&bss->nl_connect, 1); } @@ -2042,6 +2175,11 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname, if (wpa_driver_nl80211_finish_drv_init(drv, set_addr, 1, driver_params)) goto failed; + if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS) { + drv->control_port_ap = 1; + goto skip_wifi_status; + } + drv->eapol_tx_sock = socket(PF_PACKET, SOCK_DGRAM, 0); if (drv->eapol_tx_sock < 0) goto failed; @@ -2052,17 +2190,20 @@ static void * wpa_driver_nl80211_drv_init(void *ctx, const char *ifname, if (setsockopt(drv->eapol_tx_sock, SOL_SOCKET, SO_WIFI_STATUS, &enabled, sizeof(enabled)) < 0) { wpa_printf(MSG_DEBUG, - "nl80211: wifi status sockopt failed\n"); + "nl80211: wifi status sockopt failed: %s", + strerror(errno)); drv->data_tx_status = 0; if (!drv->use_monitor) drv->capa.flags &= ~WPA_DRIVER_FLAGS_EAPOL_TX_STATUS; } else { - eloop_register_read_sock(drv->eapol_tx_sock, + eloop_register_read_sock( + drv->eapol_tx_sock, wpa_driver_nl80211_handle_eapol_tx_status, drv, NULL); } } +skip_wifi_status: if (drv->global) { nl80211_check_global(drv->global); @@ -2096,7 +2237,8 @@ static void * wpa_driver_nl80211_init(void *ctx, const char *ifname, static int nl80211_register_frame(struct i802_bss *bss, struct nl_sock *nl_handle, - u16 type, const u8 *match, size_t match_len) + u16 type, const u8 *match, size_t match_len, + bool multicast) { struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; @@ -2105,17 +2247,20 @@ static int nl80211_register_frame(struct i802_bss *bss, buf[0] = '\0'; wpa_snprintf_hex(buf, sizeof(buf), match, match_len); - wpa_printf(MSG_DEBUG, "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s", - type, fc2str(type), nl_handle, buf); + wpa_printf(MSG_DEBUG, + "nl80211: Register frame type=0x%x (%s) nl_handle=%p match=%s multicast=%d", + type, fc2str(type), nl_handle, buf, multicast); if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_REGISTER_FRAME)) || + (multicast && nla_put_flag(msg, NL80211_ATTR_RECEIVE_MULTICAST)) || nla_put_u16(msg, NL80211_ATTR_FRAME_TYPE, type) || nla_put(msg, NL80211_ATTR_FRAME_MATCH, match_len, match)) { nlmsg_free(msg); return -1; } - ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL); + ret = send_and_recv(drv->global, nl_handle, msg, NULL, NULL, + NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Register frame command " "failed (type=%u): ret=%d (%s)", @@ -2156,32 +2301,14 @@ static int nl80211_register_action_frame(struct i802_bss *bss, { u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4); return nl80211_register_frame(bss, bss->nl_mgmt, - type, match, match_len); -} - - -static int nl80211_init_connect_handle(struct i802_bss *bss) -{ - if (bss->nl_connect) { - wpa_printf(MSG_DEBUG, - "nl80211: Connect handle already created (nl_connect=%p)", - bss->nl_connect); - return -1; - } - - bss->nl_connect = nl_create_handle(bss->nl_cb, "connect"); - if (!bss->nl_connect) - return -1; - nl80211_register_eloop_read(&bss->nl_connect, - wpa_driver_nl80211_event_receive, - bss->nl_cb, 1); - return 0; + type, match, match_len, false); } static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) { struct wpa_driver_nl80211_data *drv = bss->drv; + u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4); int ret = 0; if (nl80211_alloc_mgmt_handle(bss)) @@ -2189,13 +2316,14 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) wpa_printf(MSG_DEBUG, "nl80211: Subscribe to mgmt frames with non-AP " "handle %p", bss->nl_mgmt); - if (drv->nlmode == NL80211_IFTYPE_ADHOC || - ((drv->capa.flags & WPA_DRIVER_FLAGS_SAE) && - !(drv->capa.flags & WPA_DRIVER_FLAGS_SME))) { - u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4); - + if (drv->nlmode == NL80211_IFTYPE_ADHOC) { /* register for any AUTH message */ - nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0); + nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0, false); + } else if ((drv->capa.flags & WPA_DRIVER_FLAGS_SAE) && + !(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { + /* register for SAE Authentication frames */ + nl80211_register_frame(bss, bss->nl_mgmt, type, + (u8 *) "\x03\x00", 2, false); } #ifdef CONFIG_INTERWORKING @@ -2273,10 +2401,19 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) /* FT Action frames */ if (nl80211_register_action_frame(bss, (u8 *) "\x06", 1) < 0) ret = -1; - else + else if (!drv->has_driver_key_mgmt) { + int i; + + /* Update supported AKMs only if the driver doesn't advertize + * any AKM capabilities. */ drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT | WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; + /* Update per interface supported AKMs */ + for (i = 0; i < WPA_IF_MAX; i++) + drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt; + } + /* WNM - BSS Transition Management Request */ if (nl80211_register_action_frame(bss, (u8 *) "\x0a\x07", 2) < 0) ret = -1; @@ -2308,7 +2445,8 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) ret = -1; /* Radio Measurement - Radio Measurement Request */ - if (nl80211_register_action_frame(bss, (u8 *) "\x05\x00", 2) < 0) + if (!drv->no_rrm && + nl80211_register_action_frame(bss, (u8 *) "\x05\x00", 2) < 0) ret = -1; /* Radio Measurement - Link Measurement Request */ @@ -2316,6 +2454,10 @@ static int nl80211_mgmt_subscribe_non_ap(struct i802_bss *bss) (nl80211_register_action_frame(bss, (u8 *) "\x05\x02", 2) < 0)) ret = -1; + /* Robust AV MSCS Response */ + if (nl80211_register_action_frame(bss, (u8 *) "\x13\x05", 2) < 0) + ret = -1; + nl80211_mgmt_handle_register_eloop(bss); return ret; @@ -2337,7 +2479,7 @@ static int nl80211_mgmt_subscribe_mesh(struct i802_bss *bss) if (nl80211_register_frame(bss, bss->nl_mgmt, (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4), - NULL, 0) < 0) + NULL, 0, false) < 0) ret = -1; /* Mesh peering open */ @@ -2362,7 +2504,8 @@ static int nl80211_register_spurious_class3(struct i802_bss *bss) int ret; msg = nl80211_bss_msg(bss, 0, NL80211_CMD_UNEXPECTED_FRAME); - ret = send_and_recv(bss->drv->global, bss->nl_mgmt, msg, NULL, NULL); + ret = send_and_recv(bss->drv->global, bss->nl_mgmt, msg, NULL, NULL, + NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Register spurious class3 " "failed: ret=%d (%s)", @@ -2443,7 +2586,7 @@ static int nl80211_mgmt_subscribe_ap(struct i802_bss *bss) if (nl80211_register_frame(bss, bss->nl_mgmt, (WLAN_FC_TYPE_MGMT << 2) | (stypes[i] << 4), - NULL, 0) < 0) { + NULL, 0, false) < 0) { goto out_err; } } @@ -2477,8 +2620,8 @@ static int nl80211_mgmt_subscribe_ap_dev_sme(struct i802_bss *bss) u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_AUTH << 4); /* Register for all Authentication frames */ - if (nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0) - < 0) + if (nl80211_register_frame(bss, bss->nl_mgmt, type, NULL, 0, + false) < 0) wpa_printf(MSG_DEBUG, "nl80211: Failed to subscribe to handle Authentication frames - SAE offload may not work"); } @@ -2516,7 +2659,7 @@ static void nl80211_del_p2pdev(struct i802_bss *bss) int ret; msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_DEL_INTERFACE); - ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL); + ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: Delete P2P Device %s (0x%llx): %s", bss->ifname, (long long unsigned int) bss->wdev_id, @@ -2531,7 +2674,7 @@ static int nl80211_set_p2pdev(struct i802_bss *bss, int start) msg = nl80211_cmd_msg(bss, 0, start ? NL80211_CMD_START_P2P_DEVICE : NL80211_CMD_STOP_P2P_DEVICE); - ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL); + ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: %s P2P Device %s (0x%llx): %s", start ? "Start" : "Stop", @@ -2602,7 +2745,8 @@ static void qca_vendor_test(struct wpa_driver_nl80211_data *drv) } nla_nest_end(msg, params); - ret = send_and_recv_msgs(drv, msg, qca_vendor_test_cmd_handler, drv); + ret = send_and_recv_msgs(drv, msg, qca_vendor_test_cmd_handler, drv, + NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: QCA vendor test command returned %d (%s)", ret, strerror(-ret)); @@ -2714,8 +2858,6 @@ wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv, if (drv->vendor_cmd_test_avail) qca_vendor_test(drv); - nl80211_init_connect_handle(bss); - return 0; } @@ -2729,7 +2871,7 @@ static int wpa_driver_nl80211_del_beacon(struct i802_bss *bss) drv->ifindex); nl80211_put_wiphy_data_ap(bss); msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON); - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -2828,9 +2970,6 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss) nl80211_del_p2pdev(bss); } - if (bss->nl_connect) - nl80211_destroy_eloop_handle(&bss->nl_connect, 1); - nl80211_destroy_bss(drv->first_bss); os_free(drv->filter_ssids); @@ -2868,7 +3007,7 @@ static u32 wpa_alg_to_cipher_suite(enum wpa_alg alg, size_t key_len) return RSN_CIPHER_SUITE_CCMP_256; case WPA_ALG_GCMP_256: return RSN_CIPHER_SUITE_GCMP_256; - case WPA_ALG_IGTK: + case WPA_ALG_BIP_CMAC_128: return RSN_CIPHER_SUITE_AES_128_CMAC; case WPA_ALG_BIP_GMAC_128: return RSN_CIPHER_SUITE_BIP_GMAC_128; @@ -2881,7 +3020,6 @@ static u32 wpa_alg_to_cipher_suite(enum wpa_alg alg, size_t key_len) case WPA_ALG_KRK: return RSN_CIPHER_SUITE_KRK; case WPA_ALG_NONE: - case WPA_ALG_PMK: wpa_printf(MSG_ERROR, "nl80211: Unexpected encryption algorithm %d", alg); return 0; @@ -2942,6 +3080,40 @@ static int wpa_cipher_to_cipher_suites(unsigned int ciphers, u32 suites[], } +static int wpa_key_mgmt_to_suites(unsigned int key_mgmt_suites, u32 suites[], + int max_suites) +{ + int num_suites = 0; + +#define __AKM(a, b) \ + if (num_suites < max_suites && \ + (key_mgmt_suites & (WPA_KEY_MGMT_ ## a))) \ + suites[num_suites++] = (RSN_AUTH_KEY_MGMT_ ## b) + __AKM(IEEE8021X, UNSPEC_802_1X); + __AKM(PSK, PSK_OVER_802_1X); + __AKM(FT_IEEE8021X, FT_802_1X); + __AKM(FT_PSK, FT_PSK); + __AKM(IEEE8021X_SHA256, 802_1X_SHA256); + __AKM(PSK_SHA256, PSK_SHA256); + __AKM(SAE, SAE); + __AKM(FT_SAE, FT_SAE); + __AKM(CCKM, CCKM); + __AKM(OSEN, OSEN); + __AKM(IEEE8021X_SUITE_B, 802_1X_SUITE_B); + __AKM(IEEE8021X_SUITE_B_192, 802_1X_SUITE_B_192); + __AKM(FILS_SHA256, FILS_SHA256); + __AKM(FILS_SHA384, FILS_SHA384); + __AKM(FT_FILS_SHA256, FT_FILS_SHA256); + __AKM(FT_FILS_SHA384, FT_FILS_SHA384); + __AKM(OWE, OWE); + __AKM(DPP, DPP); + __AKM(FT_IEEE8021X_SHA384, FT_802_1X_SHA384); +#undef __AKM + + return num_suites; +} + + #ifdef CONFIG_DRIVER_NL80211_QCA static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv, const u8 *key, size_t key_len) @@ -2961,7 +3133,7 @@ static int issue_key_mgmt_set_key(struct wpa_driver_nl80211_data *drv, nlmsg_free(msg); return -1; } - ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1); + ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Key management set key failed: ret=%d (%s)", @@ -3001,7 +3173,7 @@ static int nl80211_set_pmk(struct wpa_driver_nl80211_data *drv, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1); + ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Set PMK failed: ret=%d (%s)", ret, strerror(-ret)); @@ -3019,7 +3191,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, struct nl_msg *msg; struct nl_msg *key_msg; int ret; - int tdls = 0; + int skip_set_key = 1; const char *ifname = params->ifname; enum wpa_alg alg = params->alg; const u8 *addr = params->addr; @@ -3030,6 +3202,7 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, const u8 *key = params->key; size_t key_len = params->key_len; int vlan_id = params->vlan_id; + enum key_flag key_flag = params->key_flag; /* Ignore for P2P Device */ if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE) @@ -3037,18 +3210,17 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, ifindex = if_nametoindex(ifname); wpa_printf(MSG_DEBUG, "%s: ifindex=%d (%s) alg=%d addr=%p key_idx=%d " - "set_tx=%d seq_len=%lu key_len=%lu", + "set_tx=%d seq_len=%lu key_len=%lu key_flag=0x%x", __func__, ifindex, ifname, alg, addr, key_idx, set_tx, - (unsigned long) seq_len, (unsigned long) key_len); -#ifdef CONFIG_TDLS - if (key_idx == -1) { - key_idx = 0; - tdls = 1; + (unsigned long) seq_len, (unsigned long) key_len, key_flag); + + if (check_key_flag(key_flag)) { + wpa_printf(MSG_DEBUG, "%s: invalid key_flag", __func__); + return -EINVAL; } -#endif /* CONFIG_TDLS */ #ifdef CONFIG_DRIVER_NL80211_QCA - if (alg == WPA_ALG_PMK && + if ((key_flag & KEY_FLAG_PMK) && (drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) { wpa_printf(MSG_DEBUG, "%s: calling issue_key_mgmt_set_key", __func__); @@ -3057,15 +3229,33 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, } #endif /* CONFIG_DRIVER_NL80211_QCA */ - if (alg == WPA_ALG_PMK && - (drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X)) - return nl80211_set_pmk(drv, key, key_len, addr); + if (key_flag & KEY_FLAG_PMK) { + if (drv->capa.flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) + return nl80211_set_pmk(drv, key, key_len, addr); + /* The driver does not have any offload mechanism for PMK, so + * there is no need to configure this key. */ + return 0; + } + ret = -ENOBUFS; key_msg = nlmsg_alloc(); if (!key_msg) - return -ENOBUFS; + return ret; - if (alg == WPA_ALG_NONE) { + if ((key_flag & KEY_FLAG_PAIRWISE_MASK) == + KEY_FLAG_PAIRWISE_RX_TX_MODIFY) { + wpa_printf(MSG_DEBUG, + "nl80211: SET_KEY (pairwise RX/TX modify)"); + msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY); + if (!msg) + goto fail2; + } else if (alg == WPA_ALG_NONE && (key_flag & KEY_FLAG_RX_TX)) { + wpa_printf(MSG_DEBUG, "%s: invalid key_flag to delete key", + __func__); + ret = -EINVAL; + goto fail2; + } else if (alg == WPA_ALG_NONE) { + wpa_printf(MSG_DEBUG, "nl80211: DEL_KEY"); msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY); if (!msg) goto fail2; @@ -3073,8 +3263,11 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, u32 suite; suite = wpa_alg_to_cipher_suite(alg, key_len); - if (!suite) + if (!suite) { + ret = -EINVAL; goto fail2; + } + wpa_printf(MSG_DEBUG, "nl80211: NEW_KEY"); msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_NEW_KEY); if (!msg) goto fail2; @@ -3082,12 +3275,13 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, nla_put_u32(key_msg, NL80211_KEY_CIPHER, suite)) goto fail; wpa_hexdump_key(MSG_DEBUG, "nl80211: KEY_DATA", key, key_len); - } - if (seq && seq_len) { - if (nla_put(key_msg, NL80211_KEY_SEQ, seq_len, seq)) - goto fail; - wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len); + if (seq && seq_len) { + if (nla_put(key_msg, NL80211_KEY_SEQ, seq_len, seq)) + goto fail; + wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", + seq, seq_len); + } } if (addr && !is_broadcast_ether_addr(addr)) { @@ -3095,22 +3289,42 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr)) goto fail; - if (alg != WPA_ALG_WEP && key_idx && !set_tx) { + if ((key_flag & KEY_FLAG_PAIRWISE_MASK) == + KEY_FLAG_PAIRWISE_RX || + (key_flag & KEY_FLAG_PAIRWISE_MASK) == + KEY_FLAG_PAIRWISE_RX_TX_MODIFY) { + if (nla_put_u8(key_msg, NL80211_KEY_MODE, + key_flag == KEY_FLAG_PAIRWISE_RX ? + NL80211_KEY_NO_TX : NL80211_KEY_SET_TX)) + goto fail; + } else if ((key_flag & KEY_FLAG_GROUP_MASK) == + KEY_FLAG_GROUP_RX) { wpa_printf(MSG_DEBUG, " RSN IBSS RX GTK"); if (nla_put_u32(key_msg, NL80211_KEY_TYPE, NL80211_KEYTYPE_GROUP)) goto fail; - } - } else if (addr && is_broadcast_ether_addr(addr)) { - struct nlattr *types; - - wpa_printf(MSG_DEBUG, " broadcast key"); - - types = nla_nest_start(key_msg, NL80211_KEY_DEFAULT_TYPES); - if (!types || - nla_put_flag(key_msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST)) + } else if (!(key_flag & KEY_FLAG_PAIRWISE)) { + wpa_printf(MSG_DEBUG, + " key_flag missing PAIRWISE when setting a pairwise key"); + ret = -EINVAL; goto fail; - nla_nest_end(key_msg, types); + } else if (alg == WPA_ALG_WEP && + (key_flag & KEY_FLAG_RX_TX) == KEY_FLAG_RX_TX) { + wpa_printf(MSG_DEBUG, " unicast WEP key"); + skip_set_key = 0; + } else { + wpa_printf(MSG_DEBUG, " pairwise key"); + } + } else if ((key_flag & KEY_FLAG_PAIRWISE) || + !(key_flag & KEY_FLAG_GROUP)) { + wpa_printf(MSG_DEBUG, + " invalid key_flag for a broadcast key"); + ret = -EINVAL; + goto fail; + } else { + wpa_printf(MSG_DEBUG, " broadcast key"); + if (key_flag & KEY_FLAG_DEFAULT) + skip_set_key = 0; } if (nla_put_u8(key_msg, NL80211_KEY_IDX, key_idx) || nla_put_nested(msg, NL80211_ATTR_KEY, key_msg)) @@ -3125,38 +3339,37 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, goto fail; } - ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL); + ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL, + NULL, NULL); if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE) ret = 0; if (ret) - wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)", + wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s", ret, strerror(-ret)); /* - * If we failed or don't need to set the default TX key (below), + * If we failed or don't need to set the key as default (below), * we're done here. */ - if (ret || !set_tx || alg == WPA_ALG_NONE || tdls) - return ret; - if (is_ap_interface(drv->nlmode) && addr && - !is_broadcast_ether_addr(addr)) + if (ret || skip_set_key) return ret; + wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_SET_KEY - default key"); + ret = -ENOBUFS; key_msg = nlmsg_alloc(); if (!key_msg) - return -ENOBUFS; + return ret; msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY); if (!msg) goto fail2; if (!key_msg || nla_put_u8(key_msg, NL80211_KEY_IDX, key_idx) || - nla_put_flag(key_msg, (alg == WPA_ALG_IGTK || - alg == WPA_ALG_BIP_GMAC_128 || - alg == WPA_ALG_BIP_GMAC_256 || - alg == WPA_ALG_BIP_CMAC_256) ? - NL80211_KEY_DEFAULT_MGMT : - NL80211_KEY_DEFAULT)) + nla_put_flag(key_msg, wpa_alg_bip(alg) ? + (key_idx == 6 || key_idx == 7 ? + NL80211_KEY_DEFAULT_BEACON : + NL80211_KEY_DEFAULT_MGMT) : + NL80211_KEY_DEFAULT)) goto fail; if (addr && is_broadcast_ether_addr(addr)) { struct nlattr *types; @@ -3189,12 +3402,11 @@ static int wpa_driver_nl80211_set_key(struct i802_bss *bss, goto fail; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); - if (ret == -ENOENT) - ret = 0; + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) - wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; " - "err=%d %s)", ret, strerror(-ret)); + wpa_printf(MSG_DEBUG, + "nl80211: set_key default failed; err=%d %s", + ret, strerror(-ret)); return ret; fail: @@ -3203,7 +3415,7 @@ fail: fail2: nl80211_nlmsg_clear(key_msg); nlmsg_free(key_msg); - return -ENOBUFS; + return ret; } @@ -3222,7 +3434,7 @@ static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg, if (!suite) return -1; - if (defkey && alg == WPA_ALG_IGTK) { + if (defkey && wpa_alg_bip(alg)) { if (nla_put_flag(msg, NL80211_KEY_DEFAULT_MGMT)) return -1; } else if (defkey) { @@ -3314,9 +3526,10 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv, } if (nl_connect) - ret = send_and_recv(drv->global, nl_connect, msg, NULL, NULL); + ret = send_and_recv(drv->global, nl_connect, msg, NULL, NULL, + NULL, NULL); else - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: MLME command failed: reason=%u ret=%d (%s)", @@ -3360,18 +3573,14 @@ static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss, return nl80211_leave_ibss(drv, 1); } if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { - struct nl_sock *nl_connect = NULL; - - if (bss->use_nl_connect) - nl_connect = bss->nl_connect; return wpa_driver_nl80211_disconnect(drv, reason_code, - nl_connect); + get_connect_handle(bss)); } wpa_printf(MSG_DEBUG, "%s(addr=" MACSTR " reason_code=%d)", __func__, MAC2STR(addr), reason_code); nl80211_mark_disconnected(drv); ret = wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE, - reason_code, 0, NULL); + reason_code, 0, get_connect_handle(bss)); /* * For locally generated deauthenticate, supplicant already generates a * DEAUTH event, so ignore the event from NL80211. @@ -3517,6 +3726,9 @@ retry: p.set_tx = i == params->wep_tx_keyidx; p.key = params->wep_key[i]; p.key_len = params->wep_key_len[i]; + p.key_flag = i == params->wep_tx_keyidx ? + KEY_FLAG_GROUP_RX_TX_DEFAULT : + KEY_FLAG_GROUP_RX_TX; wpa_driver_nl80211_set_key(bss, &p); if (params->wep_tx_keyidx != i) continue; @@ -3565,7 +3777,7 @@ retry: goto fail; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_dbg(drv->ctx, MSG_DEBUG, @@ -3696,7 +3908,7 @@ static int wpa_driver_nl80211_send_mlme(struct i802_bss *bss, const u8 *data, mgmt = (struct ieee80211_mgmt *) data; fc = le_to_host16(mgmt->frame_control); - wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da= " MACSTR + wpa_printf(MSG_DEBUG, "nl80211: send_mlme - da=" MACSTR " noack=%d freq=%u no_cck=%d offchanok=%d wait_time=%u no_encrypt=%d fc=0x%x (%s) nlmode=%d", MAC2STR(mgmt->da), noack, freq, no_cck, offchanok, wait_time, no_encrypt, fc, fc2str(fc), drv->nlmode); @@ -3843,7 +4055,7 @@ static int nl80211_set_bss(struct i802_bss *bss, int cts, int preamble, return -ENOBUFS; } - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -3887,7 +4099,7 @@ static int wpa_driver_nl80211_set_acl(void *priv, } nlmsg_free(acl); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Failed to set MAC ACL: %d (%s)", ret, strerror(-ret)); @@ -3939,7 +4151,7 @@ static int nl80211_set_mesh_config(void *priv, return ret; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_ERROR, "nl80211: Mesh config set failed: %d (%s)", @@ -4064,7 +4276,7 @@ static int nl80211_set_multicast_to_unicast(struct i802_bss *bss, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); switch (ret) { case 0: @@ -4092,6 +4304,30 @@ static int nl80211_set_multicast_to_unicast(struct i802_bss *bss, } +#ifdef CONFIG_SAE +static int nl80211_put_sae_pwe(struct nl_msg *msg, int pwe) +{ + u8 sae_pwe; + + wpa_printf(MSG_DEBUG, "nl802111: sae_pwe=%d", pwe); + if (pwe == 0) + sae_pwe = NL80211_SAE_PWE_HUNT_AND_PECK; + else if (pwe == 1) + sae_pwe = NL80211_SAE_PWE_HASH_TO_ELEMENT; + else if (pwe == 2) + sae_pwe = NL80211_SAE_PWE_BOTH; + else if (pwe == 3) + return 0; /* special test mode */ + else + return -1; + if (nla_put_u8(msg, NL80211_ATTR_SAE_PWE, sae_pwe)) + return -1; + + return 0; +} +#endif /* CONFIG_SAE */ + + static int wpa_driver_nl80211_set_ap(void *priv, struct wpa_driver_ap_params *params) { @@ -4102,8 +4338,7 @@ static int wpa_driver_nl80211_set_ap(void *priv, int ret = -ENOBUFS; int beacon_set; int num_suites; - int smps_mode; - u32 suites[10], suite; + u32 suites[20], suite; u32 ver; #ifdef CONFIG_MESH struct wpa_driver_mesh_bss_params mesh_params; @@ -4197,14 +4432,15 @@ static int wpa_driver_nl80211_set_ap(void *priv, wpa_printf(MSG_DEBUG, "nl80211: key_mgmt_suites=0x%x", params->key_mgmt_suites); - num_suites = 0; - if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X) - suites[num_suites++] = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; - if (params->key_mgmt_suites & WPA_KEY_MGMT_PSK) - suites[num_suites++] = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; - if (num_suites && - nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32), - suites)) + num_suites = wpa_key_mgmt_to_suites(params->key_mgmt_suites, + suites, ARRAY_SIZE(suites)); + if (num_suites > NL80211_MAX_NR_AKM_SUITES) + wpa_printf(MSG_DEBUG, + "nl80211: Not enough room for all AKM suites (num_suites=%d > NL80211_MAX_NR_AKM_SUITES)", + num_suites); + else if (num_suites && + nla_put(msg, NL80211_ATTR_AKM_SUITES, num_suites * sizeof(u32), + suites)) goto fail; if (params->key_mgmt_suites & WPA_KEY_MGMT_IEEE8021X_NO_WPA && @@ -4235,27 +4471,6 @@ static int wpa_driver_nl80211_set_ap(void *priv, nla_put_u32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, suite)) goto fail; - if (params->ht_opmode != -1) { - switch (params->smps_mode) { - case HT_CAP_INFO_SMPS_DYNAMIC: - wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - dynamic"); - smps_mode = NL80211_SMPS_DYNAMIC; - break; - case HT_CAP_INFO_SMPS_STATIC: - wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - static"); - smps_mode = NL80211_SMPS_STATIC; - break; - default: - /* invalid - fallback to smps off */ - case HT_CAP_INFO_SMPS_DISABLED: - wpa_printf(MSG_DEBUG, "nl80211: SMPS mode - off"); - smps_mode = NL80211_SMPS_OFF; - break; - } - if (nla_put_u8(msg, NL80211_ATTR_SMPS_MODE, smps_mode)) - goto fail; - } - if (params->beacon_ies) { wpa_hexdump_buf(MSG_DEBUG, "nl80211: beacon_ies", params->beacon_ies); @@ -4340,7 +4555,8 @@ static int wpa_driver_nl80211_set_ap(void *priv, spr = nla_nest_start(msg, NL80211_ATTR_HE_OBSS_PD); wpa_printf(MSG_DEBUG, "nl80211: he_spr=%d", params->he_spr); - if (nla_put_u8(msg, NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET, + if (!spr || + nla_put_u8(msg, NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET, params->he_spr_srg_obss_pd_min_offset) || nla_put_u8(msg, NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET, params->he_spr_srg_obss_pd_max_offset)) @@ -4348,9 +4564,39 @@ static int wpa_driver_nl80211_set_ap(void *priv, nla_nest_end(msg, spr); } + + if (params->freq && params->freq->he_enabled) { + struct nlattr *bss_color; + + bss_color = nla_nest_start(msg, NL80211_ATTR_HE_BSS_COLOR); + if (!bss_color || + (params->he_bss_color_disabled && + nla_put_flag(msg, NL80211_HE_BSS_COLOR_ATTR_DISABLED)) || + (params->he_bss_color_partial && + nla_put_flag(msg, NL80211_HE_BSS_COLOR_ATTR_PARTIAL)) || + nla_put_u8(msg, NL80211_HE_BSS_COLOR_ATTR_COLOR, + params->he_bss_color)) + goto fail; + nla_nest_end(msg, bss_color); + } + + if (params->twt_responder) { + wpa_printf(MSG_DEBUG, "nl80211: twt_responder=%d", + params->twt_responder); + if (nla_put_flag(msg, NL80211_ATTR_TWT_RESPONDER)) + goto fail; + } #endif /* CONFIG_IEEE80211AX */ - ret = send_and_recv_msgs(drv, msg, NULL, NULL); +#ifdef CONFIG_SAE + if (((params->key_mgmt_suites & WPA_KEY_MGMT_SAE) || + (params->key_mgmt_suites & WPA_KEY_MGMT_FT_SAE)) && + nl80211_put_sae_pwe(msg, params->sae_pwe) < 0) + goto fail; +#endif /* CONFIG_SAE */ + + ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1, + NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", ret, strerror(-ret)); @@ -4519,7 +4765,7 @@ static int nl80211_set_channel(struct i802_bss *bss, return -1; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret == 0) { bss->freq = freq->freq; return 0; @@ -4797,7 +5043,7 @@ static int wpa_driver_nl80211_sta_add(void *priv, nla_nest_end(msg, wme); } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION " @@ -4869,7 +5115,7 @@ static int wpa_driver_nl80211_sta_remove(struct i802_bss *bss, const u8 *addr, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: sta_remove -> DEL_STATION %s " MACSTR " --> %d (%s)", bss->ifname, MAC2STR(addr), ret, strerror(-ret)); @@ -4900,7 +5146,7 @@ void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx) } msg = nl80211_ifindex_msg(drv, ifidx, 0, NL80211_CMD_DEL_INTERFACE); - if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0) + if (send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL) == 0) return; wpa_printf(MSG_ERROR, "Failed to remove interface (ifidx=%d)", ifidx); } @@ -4929,6 +5175,10 @@ const char * nl80211_iftype_str(enum nl80211_iftype mode) return "P2P_GO"; case NL80211_IFTYPE_P2P_DEVICE: return "P2P_DEVICE"; + case NL80211_IFTYPE_OCB: + return "OCB"; + case NL80211_IFTYPE_NAN: + return "NAN"; default: return "unknown"; } @@ -4976,7 +5226,7 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv, if (nla_put_flag(msg, NL80211_ATTR_IFACE_SOCKET_OWNER)) goto fail; - ret = send_and_recv_msgs(drv, msg, handler, arg); + ret = send_and_recv_msgs(drv, msg, handler, arg, NULL, NULL); msg = NULL; if (ret) { fail: @@ -5131,8 +5381,10 @@ static int nl80211_tx_control_port(void *priv, const u8 *dest, u16 proto, const u8 *buf, size_t len, int no_encrypt) { + struct nl80211_ack_ext_arg ext_arg; struct i802_bss *bss = priv; struct nl_msg *msg; + u64 cookie = 0; int ret; wpa_printf(MSG_DEBUG, @@ -5151,11 +5403,22 @@ static int nl80211_tx_control_port(void *priv, const u8 *dest, return -ENOBUFS; } - ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL); - if (ret) + os_memset(&ext_arg, 0, sizeof(struct nl80211_ack_ext_arg)); + ext_arg.ext_data = &cookie; + ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, + ack_handler_cookie, &ext_arg); + if (ret) { wpa_printf(MSG_DEBUG, "nl80211: tx_control_port failed: ret=%d (%s)", - ret, strerror(ret)); + ret, strerror(-ret)); + } else { + struct wpa_driver_nl80211_data *drv = bss->drv; + + wpa_printf(MSG_DEBUG, + "nl80211: tx_control_port cookie=0x%llx", + (long long unsigned int) cookie); + drv->eapol_tx_cookie = cookie; + } return ret; } @@ -5203,7 +5466,10 @@ static int wpa_driver_nl80211_hapd_send_eapol( int res; int qos = flags & WPA_STA_WMM; - if (drv->capa.flags & WPA_DRIVER_FLAGS_CONTROL_PORT) + /* For now, disable EAPOL TX over control port in AP mode by default + * since it does not provide TX status notifications. */ + if (drv->control_port_ap && + (drv->capa.flags & WPA_DRIVER_FLAGS_CONTROL_PORT)) return nl80211_tx_control_port(bss, addr, ETH_P_EAPOL, data, data_len, !encrypt); @@ -5249,9 +5515,9 @@ static int wpa_driver_nl80211_hapd_send_eapol( res = nl80211_send_monitor(drv, hdr, len, encrypt, 0); if (res < 0) { - wpa_printf(MSG_ERROR, "i802_send_eapol - packet len: %lu - " - "failed: %d (%s)", - (unsigned long) len, res, strerror(res)); + wpa_printf(MSG_ERROR, + "hapd_send_eapol - packet len: %lu - failed", + (unsigned long) len); } os_free(hdr); @@ -5304,7 +5570,7 @@ static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr, if (nla_put(msg, NL80211_ATTR_STA_FLAGS2, sizeof(upd), &upd)) goto fail; - return send_and_recv_msgs(bss->drv, msg, NULL, NULL); + return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); fail: nlmsg_free(msg); return -ENOBUFS; @@ -5326,7 +5592,7 @@ static int driver_nl80211_sta_set_airtime_weight(void *priv, const u8 *addr, nla_put_u16(msg, NL80211_ATTR_AIRTIME_WEIGHT, weight)) goto fail; - return send_and_recv_msgs(bss->drv, msg, NULL, NULL); + return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); fail: nlmsg_free(msg); return -ENOBUFS; @@ -5370,7 +5636,9 @@ static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv, int ret; msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_IBSS); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs_owner(drv, msg, + get_connect_handle(drv->first_bss), 1, + NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Leave IBSS failed: ret=%d " "(%s)", ret, strerror(-ret)); @@ -5502,7 +5770,9 @@ retry: if (ret < 0) goto fail; - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs_owner(drv, msg, + get_connect_handle(drv->first_bss), 1, + NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Join IBSS failed: ret=%d (%s)", @@ -5549,13 +5819,13 @@ static int nl80211_put_fils_connect_params(struct wpa_driver_nl80211_data *drv, return -1; } - wpa_printf(MSG_DEBUG, " * FILS ERP next seq %u", - params->fils_erp_next_seq_num); - if (nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM, - params->fils_erp_next_seq_num)) - return -1; - if (params->fils_erp_rrk_len) { + wpa_printf(MSG_DEBUG, " * FILS ERP next seq %u", + params->fils_erp_next_seq_num); + if (nla_put_u16(msg, NL80211_ATTR_FILS_ERP_NEXT_SEQ_NUM, + params->fils_erp_next_seq_num)) + return -1; + wpa_printf(MSG_DEBUG, " * FILS ERP rRK (len=%lu)", (unsigned long) params->fils_erp_rrk_len); if (nla_put(msg, NL80211_ATTR_FILS_ERP_RRK, @@ -5875,6 +6145,13 @@ static int wpa_driver_nl80211_try_connect( nla_put_u32(msg, NL80211_ATTR_USE_MFP, NL80211_MFP_OPTIONAL)) goto fail; +#ifdef CONFIG_SAE + if ((params->key_mgmt_suite == WPA_KEY_MGMT_SAE || + params->key_mgmt_suite == WPA_KEY_MGMT_FT_SAE) && + nl80211_put_sae_pwe(msg, params->sae_pwe) < 0) + goto fail; +#endif /* CONFIG_SAE */ + algs = 0; if (params->auth_alg & WPA_AUTH_ALG_OPEN) algs++; @@ -5903,12 +6180,8 @@ skip_auth_type: if (ret) goto fail; - if (nl_connect) - ret = send_and_recv(drv->global, nl_connect, msg, - NULL, (void *) -1); - else - ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1); - + ret = send_and_recv_msgs_owner(drv, msg, nl_connect, 1, NULL, + (void *) -1, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: MLME connect failed: ret=%d " @@ -5977,19 +6250,17 @@ static int wpa_driver_nl80211_associate( if (!(drv->capa.flags & WPA_DRIVER_FLAGS_SME)) { enum nl80211_iftype nlmode = params->p2p ? NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION; - struct nl_sock *nl_connect = NULL; if (wpa_driver_nl80211_set_mode(priv, nlmode) < 0) return -1; if (params->key_mgmt_suite == WPA_KEY_MGMT_SAE || - params->key_mgmt_suite == WPA_KEY_MGMT_FT_SAE) { - nl_connect = bss->nl_connect; + params->key_mgmt_suite == WPA_KEY_MGMT_FT_SAE) bss->use_nl_connect = 1; - } else { + else bss->use_nl_connect = 0; - } - return wpa_driver_nl80211_connect(drv, params, nl_connect); + return wpa_driver_nl80211_connect(drv, params, + get_connect_handle(bss)); } nl80211_mark_disconnected(drv); @@ -6024,7 +6295,9 @@ static int wpa_driver_nl80211_associate( goto fail; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs_owner(drv, msg, + get_connect_handle(drv->first_bss), 1, + NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_dbg(drv->ctx, MSG_DEBUG, @@ -6055,7 +6328,7 @@ static int nl80211_set_mode(struct wpa_driver_nl80211_data *drv, if (!msg || nla_put_u32(msg, NL80211_ATTR_IFTYPE, mode)) goto fail; - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (!ret) return 0; @@ -6131,6 +6404,20 @@ static int wpa_driver_nl80211_set_mode_impl( } } + if (i == 0 && was_ap && !is_ap_interface(nlmode) && + bss->brname[0] && + (bss->added_if_into_bridge || bss->already_in_bridge)) { + wpa_printf(MSG_DEBUG, + "nl80211: Remove AP interface %s temporarily from the bridge %s to allow its mode to be set to STATION", + bss->ifname, bss->brname); + if (linux_br_del_if(drv->global->ioctl_sock, + bss->brname, bss->ifname) < 0) + wpa_printf(MSG_INFO, + "nl80211: Failed to remove interface %s from bridge %s: %s", + bss->ifname, bss->brname, + strerror(errno)); + } + /* Try to set the mode again while the interface is down */ mode_switch_res = nl80211_set_mode(drv, drv->ifindex, nlmode); if (mode_switch_res == -EBUSY) { @@ -6203,6 +6490,29 @@ done: } +void nl80211_restore_ap_mode(struct i802_bss *bss) +{ + struct wpa_driver_nl80211_data *drv = bss->drv; + int was_ap = is_ap_interface(drv->nlmode); + + wpa_driver_nl80211_set_mode(bss, drv->ap_scan_as_station); + if (!was_ap && is_ap_interface(drv->ap_scan_as_station) && + bss->brname[0] && + (bss->added_if_into_bridge || bss->already_in_bridge)) { + wpa_printf(MSG_DEBUG, + "nl80211: Add AP interface %s back into the bridge %s", + bss->ifname, bss->brname); + if (linux_br_add_if(drv->global->ioctl_sock, bss->brname, + bss->ifname) < 0) { + wpa_printf(MSG_WARNING, + "nl80211: Failed to add interface %s into bridge %s: %s", + bss->ifname, bss->brname, strerror(errno)); + } + } + drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; +} + + int wpa_driver_nl80211_set_mode(struct i802_bss *bss, enum nl80211_iftype nlmode) { @@ -6279,7 +6589,7 @@ static int wpa_driver_nl80211_set_supp_port(void *priv, int authorized) return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (!ret) return 0; wpa_printf(MSG_DEBUG, "nl80211: Failed to set STA flag: %d (%s)", @@ -6344,7 +6654,7 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr, memset(seq, 0, 6); - return send_and_recv_msgs(drv, msg, get_key_handler, seq); + return send_and_recv_msgs(drv, msg, get_key_handler, seq, NULL, NULL); } @@ -6367,7 +6677,7 @@ static int i802_set_rts(void *priv, int rts) return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (!ret) return 0; wpa_printf(MSG_DEBUG, "nl80211: Failed to set RTS threshold %d: " @@ -6395,7 +6705,7 @@ static int i802_set_frag(void *priv, int frag) return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (!ret) return 0; wpa_printf(MSG_DEBUG, "nl80211: Failed to set fragmentation threshold " @@ -6417,7 +6727,7 @@ static int i802_flush(void *priv) * XXX: FIX! this needs to flush all VLANs too */ msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_STATION); - res = send_and_recv_msgs(bss->drv, msg, NULL, NULL); + res = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); if (res) { wpa_printf(MSG_DEBUG, "nl80211: Station flush failed: ret=%d " "(%s)", res, strerror(-res)); @@ -6626,7 +6936,8 @@ static int i802_read_sta_data(struct i802_bss *bss, return -ENOBUFS; } - return send_and_recv_msgs(bss->drv, msg, get_sta_handler, data); + return send_and_recv_msgs(bss->drv, msg, get_sta_handler, data, + NULL, NULL); } @@ -6683,7 +6994,7 @@ static int i802_set_tx_queue_params(void *priv, int queue, int aifs, nla_nest_end(msg, txq); - res = send_and_recv_msgs(drv, msg, NULL, NULL); + res = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: TX queue param set: queue=%d aifs=%d cw_min=%d cw_max=%d burst_time=%d --> res=%d", queue, aifs, cw_min, cw_max, burst_time, res); @@ -6709,14 +7020,14 @@ static int i802_set_sta_vlan(struct i802_bss *bss, const u8 *addr, MAC2STR(addr), ifname, if_nametoindex(ifname), vlan_id); if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_SET_STATION)) || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || - ((drv->capa.flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD) && + (vlan_id && (drv->capa.flags & WPA_DRIVER_FLAGS_VLAN_OFFLOAD) && nla_put_u16(msg, NL80211_ATTR_VLAN_ID, vlan_id)) || nla_put_u32(msg, NL80211_ATTR_STA_VLAN, if_nametoindex(ifname))) { nlmsg_free(msg); return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret < 0) { wpa_printf(MSG_ERROR, "nl80211: NL80211_ATTR_STA_VLAN (addr=" MACSTR " ifname=%s vlan_id=%d) failed: %d (%s)", @@ -7160,6 +7471,12 @@ static void *i802_init(struct hostapd_data *hapd, } #endif /* CONFIG_LIBNL3_ROUTE */ + if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) { + wpa_printf(MSG_DEBUG, + "nl80211: Do not open EAPOL RX socket - using control port for RX"); + goto skip_eapol_sock; + } + drv->eapol_sock = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_PAE)); if (drv->eapol_sock < 0) { wpa_printf(MSG_ERROR, "nl80211: socket(PF_PACKET, SOCK_DGRAM, ETH_P_PAE) failed: %s", @@ -7172,6 +7489,7 @@ static void *i802_init(struct hostapd_data *hapd, wpa_printf(MSG_INFO, "nl80211: Could not register read socket for eapol"); goto failed; } +skip_eapol_sock: if (linux_get_ifhwaddr(drv->global->ioctl_sock, bss->ifname, params->own_addr)) @@ -7556,7 +7874,7 @@ static int nl80211_send_frame_cmd(struct i802_bss *bss, goto fail; cookie = 0; - ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie); + ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Frame command failed: ret=%d " @@ -7605,7 +7923,8 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss, struct ieee80211_hdr *hdr; int offchanok = 1; - if (is_ap_interface(drv->nlmode) && (int) freq == bss->freq) + if (is_ap_interface(drv->nlmode) && (int) freq == bss->freq && + bss->beacon_set) offchanok = 0; wpa_printf(MSG_DEBUG, "nl80211: Send Action frame (ifindex=%d, " @@ -7631,6 +7950,28 @@ static int wpa_driver_nl80211_send_action(struct i802_bss *bss, os_memset(bss->rand_addr, 0, ETH_ALEN); } +#ifdef CONFIG_MESH + if (is_mesh_interface(drv->nlmode)) { + struct hostapd_hw_modes *modes; + u16 num_modes, flags; + u8 dfs_domain; + int i; + + modes = nl80211_get_hw_feature_data(bss, &num_modes, + &flags, &dfs_domain); + if (dfs_domain != HOSTAPD_DFS_REGION_ETSI && + ieee80211_is_dfs(bss->freq, modes, num_modes)) + offchanok = 0; + if (modes) { + for (i = 0; i < num_modes; i++) { + os_free(modes[i].channels); + os_free(modes[i].rates); + } + os_free(modes); + } + } +#endif /* CONFIG_MESH */ + if (is_ap_interface(drv->nlmode) && (!(drv->capa.flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) || (int) freq == bss->freq || drv->device_ap_sme || @@ -7662,7 +8003,7 @@ static void nl80211_frame_wait_cancel(struct i802_bss *bss, u64 cookie) return; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: wait cancel failed: ret=%d " "(%s)", ret, strerror(-ret)); @@ -7710,7 +8051,7 @@ static int wpa_driver_nl80211_remain_on_channel(void *priv, unsigned int freq, } cookie = 0; - ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie); + ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL); if (ret == 0) { wpa_printf(MSG_DEBUG, "nl80211: Remain-on-channel cookie " "0x%llx for freq=%u MHz duration=%u", @@ -7750,7 +8091,7 @@ static int wpa_driver_nl80211_cancel_remain_on_channel(void *priv) return -1; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret == 0) return 0; wpa_printf(MSG_DEBUG, "nl80211: Failed to cancel remain-on-channel: " @@ -7797,7 +8138,7 @@ static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report) if (nl80211_register_frame(bss, bss->nl_preq, (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_PROBE_REQ << 4), - NULL, 0) < 0) + NULL, 0, false) < 0) goto out_err; nl80211_register_eloop_read(&bss->nl_preq, @@ -7847,7 +8188,7 @@ static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv, nla_nest_end(msg, bands); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d " "(%s)", ret, strerror(-ret)); @@ -7944,7 +8285,7 @@ static int nl80211_signal_monitor(void *priv, int threshold, int hysteresis) } nla_nest_end(msg, cqm); - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -7982,7 +8323,7 @@ static int nl80211_get_channel_width(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg; msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_INTERFACE); - return send_and_recv_msgs(drv, msg, get_channel_width, sig); + return send_and_recv_msgs(drv, msg, get_channel_width, sig, NULL, NULL); } @@ -8043,8 +8384,35 @@ static int nl80211_set_param(void *priv, const char *param) drv->test_use_roc_tx = 1; } - if (os_strstr(param, "control_port=0")) + if (os_strstr(param, "control_port=0")) { drv->capa.flags &= ~WPA_DRIVER_FLAGS_CONTROL_PORT; + drv->capa.flags2 &= ~(WPA_DRIVER_FLAGS2_CONTROL_PORT_RX | + WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS); + drv->control_port_ap = 0; + } + + if (os_strstr(param, "control_port_ap=1")) + drv->control_port_ap = 1; + + if (os_strstr(param, "control_port_ap=0")) { + drv->capa.flags2 &= ~WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS; + drv->control_port_ap = 0; + } + + if (os_strstr(param, "full_ap_client_state=0")) + drv->capa.flags &= ~WPA_DRIVER_FLAGS_FULL_AP_CLIENT_STATE; + + if (os_strstr(param, "no_rrm=1")) { + drv->no_rrm = 1; + + if (!bss->in_deinit && !is_ap_interface(drv->nlmode) && + !is_mesh_interface(drv->nlmode)) { + nl80211_mgmt_unsubscribe(bss, "no_rrm=1"); + if (nl80211_mgmt_subscribe_non_ap(bss) < 0) + wpa_printf(MSG_DEBUG, + "nl80211: Failed to re-register Action frame processing - ignore for now"); + } + } return 0; } @@ -8146,6 +8514,12 @@ static int nl80211_pmkid(struct i802_bss *bss, int cmd, (params->fils_cache_id && nla_put(msg, NL80211_ATTR_FILS_CACHE_ID, 2, params->fils_cache_id)) || + (params->pmk_lifetime && + nla_put_u32(msg, NL80211_ATTR_PMK_LIFETIME, + params->pmk_lifetime)) || + (params->pmk_reauth_threshold && + nla_put_u8(msg, NL80211_ATTR_PMK_REAUTH_THRESHOLD, + params->pmk_reauth_threshold)) || (cmd != NL80211_CMD_DEL_PMKSA && params->pmk_len && params->pmk_len <= PMK_MAX_LEN && nla_put(msg, NL80211_ATTR_PMK, params->pmk_len, params->pmk))) { @@ -8154,7 +8528,7 @@ static int nl80211_pmkid(struct i802_bss *bss, int cmd, return -ENOBUFS; } - return send_and_recv_msgs(bss->drv, msg, NULL, (void *) -1); + return send_and_recv_msgs(bss->drv, msg, NULL, (void *) -1, NULL, NULL); } @@ -8219,7 +8593,7 @@ static int nl80211_flush_pmkid(void *priv) msg = nl80211_bss_msg(bss, 0, NL80211_CMD_FLUSH_PMKSA); if (!msg) return -ENOBUFS; - return send_and_recv_msgs(bss->drv, msg, NULL, NULL); + return send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); } @@ -8384,7 +8758,7 @@ static int wpa_driver_nl80211_get_survey(void *priv, unsigned int freq) do { wpa_printf(MSG_DEBUG, "nl80211: Fetch survey data"); err = send_and_recv_msgs(drv, msg, survey_handler, - survey_results); + survey_results, NULL, NULL); } while (err > 0); if (err) @@ -8424,7 +8798,7 @@ static void nl80211_set_rekey_info(void *priv, const u8 *kek, size_t kek_len, nla_nest_end(msg, replay_nested); - ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1); + ret = send_and_recv_msgs(drv, msg, NULL, (void *) -1, NULL, NULL); if (ret == -EOPNOTSUPP) { wpa_printf(MSG_DEBUG, "nl80211: Driver does not support rekey offload"); @@ -8491,7 +8865,7 @@ static void nl80211_poll_client(void *priv, const u8 *own_addr, const u8 *addr, return; } - ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie); + ret = send_and_recv_msgs(drv, msg, cookie_handler, &cookie, NULL, NULL); if (ret < 0) { wpa_printf(MSG_DEBUG, "nl80211: Client probe request for " MACSTR " failed: ret=%d (%s)", @@ -8517,7 +8891,7 @@ static int nl80211_set_power_save(struct i802_bss *bss, int enabled) return -ENOBUFS; } - ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL); + ret = send_and_recv_msgs(bss->drv, msg, NULL, NULL, NULL, NULL); if (ret < 0) { wpa_printf(MSG_DEBUG, "nl80211: Setting PS state %s failed: %d (%s)", @@ -8577,7 +8951,7 @@ static int nl80211_start_radar_detection(void *priv, return -1; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret == 0) return 0; wpa_printf(MSG_DEBUG, "nl80211: Failed to start radar detection: " @@ -8624,7 +8998,7 @@ static int nl80211_send_tdls_mgmt(void *priv, const u8 *dst, u8 action_code, nla_put(msg, NL80211_ATTR_IE, len, buf)) goto fail; - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); fail: nlmsg_free(msg); @@ -8674,7 +9048,7 @@ static int nl80211_tdls_oper(void *priv, enum tdls_oper oper, const u8 *peer) return -ENOBUFS; } - res = send_and_recv_msgs(drv, msg, NULL, NULL); + res = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); wpa_printf(MSG_DEBUG, "nl80211: TDLS_OPER: oper=%d mac=" MACSTR " --> res=%d (%s)", nl80211_oper, MAC2STR(peer), res, strerror(-res)); @@ -8708,7 +9082,7 @@ nl80211_tdls_enable_channel_switch(void *priv, const u8 *addr, u8 oper_class, return ret; } - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -8734,7 +9108,7 @@ nl80211_tdls_disable_channel_switch(void *priv, const u8 *addr) return -ENOBUFS; } - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } #endif /* CONFIG TDLS */ @@ -8805,11 +9179,11 @@ static int driver_nl80211_send_mlme(void *priv, const u8 *data, size_t data_len, int noack, unsigned int freq, const u16 *csa_offs, size_t csa_offs_len, - int no_encrypt) + int no_encrypt, unsigned int wait) { struct i802_bss *bss = priv; return wpa_driver_nl80211_send_mlme(bss, data, data_len, noack, - freq, 0, 0, 0, csa_offs, + freq, 0, 0, wait, csa_offs, csa_offs_len, no_encrypt); } @@ -8877,7 +9251,7 @@ static int wpa_driver_nl80211_update_ft_ies(void *priv, const u8 *md, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: update_ft_ies failed " "err=%d (%s)", ret, strerror(-ret)); @@ -8905,7 +9279,7 @@ static int nl80211_update_dh_ie(void *priv, const u8 *peer_mac, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: update_dh_ie failed err=%d (%s)", @@ -9110,7 +9484,7 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen) nl80211_cmd(drv, msg, 0, NL80211_CMD_GET_REG) && nla_put_u32(msg, NL80211_ATTR_WIPHY, drv->wiphy_idx) == 0) { if (send_and_recv_msgs(drv, msg, nl80211_get_country, - alpha2) == 0 && + alpha2, NULL, NULL) == 0 && alpha2[0]) { res = os_snprintf(pos, end - pos, "country=%s\n", alpha2); @@ -9261,7 +9635,7 @@ static int nl80211_switch_channel(void *priv, struct csa_settings *settings) goto fail; nla_nest_end(msg, beacon_csa); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: switch_channel failed err=%d (%s)", ret, strerror(-ret)); @@ -9302,7 +9676,7 @@ static int nl80211_add_ts(void *priv, u8 tsid, const u8 *addr, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: add_ts failed err=%d (%s)", ret, strerror(-ret)); @@ -9329,7 +9703,7 @@ static int nl80211_del_ts(void *priv, u8 tsid, const u8 *addr) return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: del_ts failed err=%d (%s)", ret, strerror(-ret)); @@ -9390,14 +9764,35 @@ static int vendor_reply_handler(struct nl_msg *msg, void *arg) } +static bool is_cmd_with_nested_attrs(unsigned int vendor_id, + unsigned int subcmd) +{ + if (vendor_id != OUI_QCA) + return true; + + switch (subcmd) { + case QCA_NL80211_VENDOR_SUBCMD_AVOID_FREQUENCY: + case QCA_NL80211_VENDOR_SUBCMD_STATS_EXT: + case QCA_NL80211_VENDOR_SUBCMD_SCANNING_MAC_OUI: + case QCA_NL80211_VENDOR_SUBCMD_KEY_MGMT_SET_KEY: + case QCA_NL80211_VENDOR_SUBCMD_SPECTRAL_SCAN_GET_STATUS: + case QCA_NL80211_VENDOR_SUBCMD_NAN: + return false; + default: + return true; + } +} + + static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id, unsigned int subcmd, const u8 *data, - size_t data_len, struct wpabuf *buf) + size_t data_len, enum nested_attr nested_attr, + struct wpabuf *buf) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; - int ret; + int ret, nla_flag; #ifdef CONFIG_TESTING_OPTIONS if (vendor_id == 0xffffffff) { @@ -9409,7 +9804,13 @@ static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id, if (nlmsg_append(msg, (void *) data, data_len, NLMSG_ALIGNTO) < 0) goto fail; - ret = send_and_recv_msgs(drv, msg, cmd_reply_handler, buf); + /* This test vendor_cmd can be used with nl80211 commands that + * need the connect nl_sock, so use the owner-setting variant + * of send_and_recv_msgs(). */ + ret = send_and_recv_msgs_owner(drv, msg, + get_connect_handle(bss), 0, + cmd_reply_handler, buf, + NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: command failed err=%d", ret); @@ -9417,14 +9818,24 @@ static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id, } #endif /* CONFIG_TESTING_OPTIONS */ + if (nested_attr == NESTED_ATTR_USED) + nla_flag = NLA_F_NESTED; + else if (nested_attr == NESTED_ATTR_UNSPECIFIED && + is_cmd_with_nested_attrs(vendor_id, subcmd)) + nla_flag = NLA_F_NESTED; + else + nla_flag = 0; + if (!(msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_VENDOR)) || nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, vendor_id) || nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, subcmd) || (data && - nla_put(msg, NL80211_ATTR_VENDOR_DATA, data_len, data))) + nla_put(msg, nla_flag | NL80211_ATTR_VENDOR_DATA, + data_len, data))) goto fail; - ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf); + ret = send_and_recv_msgs(drv, msg, vendor_reply_handler, buf, + NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: vendor command failed err=%d", ret); @@ -9453,7 +9864,7 @@ static int nl80211_set_qos_map(void *priv, const u8 *qos_map_set, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: Setting QoS Map failed"); @@ -9488,7 +9899,8 @@ static int nl80211_get_wowlan(void *priv) msg = nl80211_drv_msg(drv, 0, NL80211_CMD_GET_WOWLAN); - ret = send_and_recv_msgs(drv, msg, get_wowlan_handler, &wowlan_enabled); + ret = send_and_recv_msgs(drv, msg, get_wowlan_handler, &wowlan_enabled, + NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Getting wowlan status failed"); return 0; @@ -9535,7 +9947,7 @@ static int nl80211_set_wowlan(void *priv, nla_nest_end(msg, wowlan_triggers); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) wpa_printf(MSG_DEBUG, "nl80211: Setting wowlan failed"); @@ -9574,7 +9986,7 @@ static int nl80211_roaming(void *priv, int allowed, const u8 *bssid) } nla_nest_end(msg, params); - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -9602,15 +10014,15 @@ static int nl80211_disable_fils(void *priv, int disable) } nla_nest_end(msg, params); - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } /* Reserved QCA_WLAN_VENDOR_ATTR_ROAMING_REQ_ID value for wpa_supplicant */ #define WPA_SUPPLICANT_CLIENT_ID 1 -static int nl80211_set_bssid_blacklist(void *priv, unsigned int num_bssid, - const u8 *bssid) +static int nl80211_set_bssid_tmp_disallow(void *priv, unsigned int num_bssid, + const u8 *bssid) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; @@ -9618,7 +10030,8 @@ static int nl80211_set_bssid_blacklist(void *priv, unsigned int num_bssid, struct nlattr *params, *nlbssids, *attr; unsigned int i; - wpa_printf(MSG_DEBUG, "nl80211: Set blacklist BSSID (num=%u)", + wpa_printf(MSG_DEBUG, + "nl80211: Set temporarily disallowed BSSIDs (num=%u)", num_bssid); if (!drv->roam_vendor_cmd_avail) @@ -9658,7 +10071,7 @@ static int nl80211_set_bssid_blacklist(void *priv, unsigned int num_bssid, nla_nest_end(msg, nlbssids); nla_nest_end(msg, params); - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); fail: nlmsg_free(msg); @@ -9696,7 +10109,7 @@ static int nl80211_add_sta_node(void *priv, const u8 *addr, u16 auth_alg) } nla_nest_end(msg, params); - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } #endif /* CONFIG_DRIVER_NL80211_QCA */ @@ -9834,6 +10247,9 @@ static int nl80211_join_mesh(struct i802_bss *bss, wpa_printf(MSG_DEBUG, " * flags=%08X", params->flags); + if (params->handle_dfs && nla_put_flag(msg, NL80211_ATTR_HANDLE_DFS)) + goto fail; + container = nla_nest_start(msg, NL80211_ATTR_MESH_SETUP); if (!container) goto fail; @@ -9864,7 +10280,8 @@ static int nl80211_join_mesh(struct i802_bss *bss, if (nl80211_put_mesh_config(msg, ¶ms->conf) < 0) goto fail; - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 1, + NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: mesh join failed: ret=%d (%s)", @@ -9921,7 +10338,8 @@ static int wpa_driver_nl80211_leave_mesh(void *priv) wpa_printf(MSG_DEBUG, "nl80211: mesh leave (ifindex=%d)", drv->ifindex); msg = nl80211_drv_msg(drv, 0, NL80211_CMD_LEAVE_MESH); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs_owner(drv, msg, get_connect_handle(bss), 0, + NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: mesh leave failed: ret=%d (%s)", ret, strerror(-ret)); @@ -9955,7 +10373,7 @@ static int nl80211_probe_mesh_link(void *priv, const u8 *addr, const u8 *eth, return -ENOBUFS; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: mesh link probe to " MACSTR " failed: ret=%d (%s)", @@ -10354,18 +10772,20 @@ static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params) nla_put_u16(msg, QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH, params->ch_width) || add_acs_ch_list(msg, params->freq_list) || - add_acs_freq_list(msg, params->freq_list)) { + add_acs_freq_list(msg, params->freq_list) || + (params->edmg_enabled && + nla_put_flag(msg, QCA_WLAN_VENDOR_ATTR_ACS_EDMG_ENABLED))) { nlmsg_free(msg); return -ENOBUFS; } nla_nest_end(msg, data); wpa_printf(MSG_DEBUG, - "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d", + "nl80211: ACS Params: HW_MODE: %d HT: %d HT40: %d VHT: %d BW: %d EDMG: %d", params->hw_mode, params->ht_enabled, params->ht40_enabled, - params->vht_enabled, params->ch_width); + params->vht_enabled, params->ch_width, params->edmg_enabled); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Failed to invoke driver ACS function: %s", @@ -10375,44 +10795,55 @@ static int wpa_driver_do_acs(void *priv, struct drv_acs_params *params) } -static int nl80211_set_band(void *priv, enum set_band band) +static int nl80211_set_band(void *priv, u32 band_mask) { struct i802_bss *bss = priv; struct wpa_driver_nl80211_data *drv = bss->drv; struct nl_msg *msg; struct nlattr *data; int ret; - enum qca_set_band qca_band; + enum qca_set_band qca_band_value; + u32 qca_band_mask = QCA_SETBAND_AUTO; - if (!drv->setband_vendor_cmd_avail) + if (!drv->setband_vendor_cmd_avail || + (band_mask > (WPA_SETBAND_2G | WPA_SETBAND_5G | WPA_SETBAND_6G))) return -1; - switch (band) { - case WPA_SETBAND_AUTO: - qca_band = QCA_SETBAND_AUTO; - break; - case WPA_SETBAND_5G: - qca_band = QCA_SETBAND_5G; - break; - case WPA_SETBAND_2G: - qca_band = QCA_SETBAND_2G; - break; - default: - return -1; - } + if (band_mask & WPA_SETBAND_5G) + qca_band_mask |= QCA_SETBAND_5G; + if (band_mask & WPA_SETBAND_2G) + qca_band_mask |= QCA_SETBAND_2G; + if (band_mask & WPA_SETBAND_6G) + qca_band_mask |= QCA_SETBAND_6G; + + /* + * QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE is a legacy interface hence make + * it suite to its values (AUTO/5G/2G) for backwards compatibility. + */ + qca_band_value = ((qca_band_mask & QCA_SETBAND_5G) && + (qca_band_mask & QCA_SETBAND_2G)) ? + QCA_SETBAND_AUTO : + qca_band_mask & ~QCA_SETBAND_6G; + + wpa_printf(MSG_DEBUG, + "nl80211: QCA_BAND_MASK = 0x%x, QCA_BAND_VALUE = %d", + qca_band_mask, qca_band_value); if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, QCA_NL80211_VENDOR_SUBCMD_SETBAND) || !(data = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) || - nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE, qca_band)) { + nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_VALUE, + qca_band_value) || + nla_put_u32(msg, QCA_WLAN_VENDOR_ATTR_SETBAND_MASK, + qca_band_mask)) { nlmsg_free(msg); return -ENOBUFS; } nla_nest_end(msg, data); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Driver setband function failed: %s", @@ -10545,7 +10976,8 @@ static int nl80211_get_pref_freq_list(void *priv, nla_nest_end(msg, params); os_memset(freq_list, 0, *num * sizeof(freq_list[0])); - ret = send_and_recv_msgs(drv, msg, preferred_freq_info_handler, ¶m); + ret = send_and_recv_msgs(drv, msg, preferred_freq_info_handler, ¶m, + NULL, NULL); if (ret) { wpa_printf(MSG_ERROR, "%s: err in send_and_recv_msgs", __func__); @@ -10597,7 +11029,7 @@ static int nl80211_set_prob_oper_freq(void *priv, unsigned int freq) } nla_nest_end(msg, params); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_ERROR, "%s: err in send_and_recv_msgs", @@ -10653,7 +11085,7 @@ static int nl80211_p2p_lo_start(void *priv, unsigned int freq, goto fail; nla_nest_end(msg, container); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, @@ -10688,7 +11120,7 @@ static int nl80211_p2p_lo_stop(void *priv) return -1; } - return send_and_recv_msgs(drv, msg, NULL, NULL); + return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); } @@ -10727,7 +11159,7 @@ static int nl80211_set_tdls_mode(void *priv, int tdls_external_control) nla_nest_end(msg, params); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_ERROR, @@ -10920,7 +11352,7 @@ nl80211_get_bss_transition_status(void *priv, struct wpa_bss_trans_info *params) ret = send_and_recv_msgs(drv, msg, nl80211_get_bss_transition_status_handler, - info); + info, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_ERROR, @@ -10973,7 +11405,7 @@ static int nl80211_ignore_assoc_disallow(void *priv, int ignore_disallow) nla_nest_end(msg, attr); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_ERROR, @@ -11176,7 +11608,7 @@ static int nl80211_update_connection_params( nl80211_put_fils_connect_params(drv, params, msg)) goto fail; - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) wpa_dbg(drv->ctx, MSG_DEBUG, @@ -11219,7 +11651,7 @@ static int nl80211_send_external_auth_status(void *priv, (params->bssid && nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid))) goto fail; - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, @@ -11259,7 +11691,7 @@ static int nl80211_set_4addr_mode(void *priv, const char *bridge_ifname, bss->added_if_into_bridge = 0; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (!ret) { if (bridge_ifname[0] && val && @@ -11276,6 +11708,28 @@ fail: } +#ifdef CONFIG_DPP +static int nl80211_dpp_listen(void *priv, bool enable) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + u16 type = (WLAN_FC_TYPE_MGMT << 2) | (WLAN_FC_STYPE_ACTION << 4); + struct nl_sock *handle; + + if (!drv->multicast_registrations || !bss->nl_mgmt) + return 0; /* cannot do more than hope broadcast RX works */ + + wpa_printf(MSG_DEBUG, + "nl80211: Update DPP Public Action frame registration (%s multicast RX)", + enable ? "enable" : "disable"); + handle = (void *) (((intptr_t) bss->nl_mgmt) ^ ELOOP_SOCKET_INVALID); + return nl80211_register_frame(bss, handle, type, + (u8 *) "\x04\x09\x50\x6f\x9a\x1a", 6, + enable); +} +#endif /* CONFIG_DPP */ + + const struct wpa_driver_ops wpa_driver_nl80211_ops = { .name = "nl80211", .desc = "Linux nl80211/cfg80211", @@ -11403,7 +11857,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .get_bss_transition_status = nl80211_get_bss_transition_status, .ignore_assoc_disallow = nl80211_ignore_assoc_disallow, #endif /* CONFIG_MBO */ - .set_bssid_blacklist = nl80211_set_bssid_blacklist, + .set_bssid_tmp_disallow = nl80211_set_bssid_tmp_disallow, .add_sta_node = nl80211_add_sta_node, #endif /* CONFIG_DRIVER_NL80211_QCA */ .configure_data_frame_filters = nl80211_configure_data_frame_filters, @@ -11411,4 +11865,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .update_connect_params = nl80211_update_connection_params, .send_external_auth_status = nl80211_send_external_auth_status, .set_4addr_mode = nl80211_set_4addr_mode, +#ifdef CONFIG_DPP + .dpp_listen = nl80211_dpp_listen, +#endif /* CONFIG_DPP */ }; diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index e4d81b125..4009545fa 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -17,6 +17,11 @@ #include "utils/list.h" #include "driver.h" +#ifndef NL_CAPABILITY_VERSION_3_5_0 +#define nla_nest_start(msg, attrtype) \ + nla_nest_start(msg, NLA_F_NESTED | (attrtype)) +#endif + struct nl80211_global { void *ctx; struct dl_list interfaces; @@ -106,6 +111,7 @@ struct wpa_driver_nl80211_data { unsigned int num_iface_ext_capa; int has_capability; + int has_driver_key_mgmt; int operstate; @@ -164,8 +170,11 @@ struct wpa_driver_nl80211_data { unsigned int set_wifi_conf_vendor_cmd_avail:1; unsigned int fetch_bss_trans_status:1; unsigned int roam_vendor_cmd_avail:1; - unsigned int get_supported_akm_suites_avail:1; unsigned int add_sta_node_vendor_cmd_avail:1; + unsigned int control_port_ap:1; + unsigned int multicast_registrations:1; + unsigned int no_rrm:1; + unsigned int get_sta_info_vendor_cmd_avail:1; u64 vendor_scan_cookie; u64 remain_on_chan_cookie; @@ -173,6 +182,7 @@ struct wpa_driver_nl80211_data { #define MAX_SEND_FRAME_COOKIES 20 u64 send_frame_cookies[MAX_SEND_FRAME_COOKIES]; unsigned int num_send_frame_cookies; + u64 eapol_tx_cookie; unsigned int last_mgmt_freq; @@ -223,7 +233,10 @@ struct nl_msg * nl80211_drv_msg(struct wpa_driver_nl80211_data *drv, int flags, struct nl_msg * nl80211_bss_msg(struct i802_bss *bss, int flags, uint8_t cmd); int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg, int (*valid_handler)(struct nl_msg *, void *), - void *valid_data); + void *valid_data, + int (*ack_handler_custom)(struct nl_msg *, void *), + void *ack_data); +struct nl_sock * get_connect_handle(struct i802_bss *bss); int nl80211_create_iface(struct wpa_driver_nl80211_data *drv, const char *ifname, enum nl80211_iftype iftype, const u8 *addr, int wds, @@ -267,6 +280,8 @@ int process_bss_event(struct nl_msg *msg, void *arg); const char * nl80211_iftype_str(enum nl80211_iftype mode); +void nl80211_restore_ap_mode(struct i802_bss *bss); + #ifdef ANDROID int android_nl_socket_set_nonblocking(struct nl_sock *handle); int android_pno_start(struct i802_bss *bss, diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 6968e8e2a..6c2ab515e 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -49,7 +49,8 @@ static u32 get_nl80211_protocol_features(struct wpa_driver_nl80211_data *drv) return 0; } - if (send_and_recv_msgs(drv, msg, protocol_feature_handler, &feat) == 0) + if (send_and_recv_msgs(drv, msg, protocol_feature_handler, &feat, + NULL, NULL) == 0) return feat; return 0; @@ -79,6 +80,8 @@ struct wiphy_info_data { unsigned int mac_addr_rand_scan_supported:1; unsigned int mac_addr_rand_sched_scan_supported:1; unsigned int update_ft_ies_supported:1; + unsigned int has_key_mgmt:1; + unsigned int has_key_mgmt_iftype:1; }; @@ -252,6 +255,179 @@ static void wiphy_info_supp_cmds(struct wiphy_info_data *info, } +static unsigned int get_akm_suites_info(struct nlattr *tb) +{ + int i, num; + unsigned int key_mgmt = 0; + u32 *akms; + + if (!tb) + return 0; + + num = nla_len(tb) / sizeof(u32); + akms = nla_data(tb); + for (i = 0; i < num; i++) { + switch (akms[i]) { + case RSN_AUTH_KEY_MGMT_UNSPEC_802_1X: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2; + break; + case RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; + break; + case RSN_AUTH_KEY_MGMT_FT_802_1X: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT; + break; + case RSN_AUTH_KEY_MGMT_FT_PSK: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; + break; + case RSN_AUTH_KEY_MGMT_802_1X_SHA256: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256; + break; + case RSN_AUTH_KEY_MGMT_PSK_SHA256: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256; + break; + case RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE; + break; + case RSN_AUTH_KEY_MGMT_FT_SAE: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE; + break; + case RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384; + break; + case RSN_AUTH_KEY_MGMT_CCKM: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_CCKM; + break; + case RSN_AUTH_KEY_MGMT_OSEN: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_OSEN; + break; + case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B; + break; + case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192; + break; + case RSN_AUTH_KEY_MGMT_OWE: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_OWE; + break; + case RSN_AUTH_KEY_MGMT_DPP: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_DPP; + break; + case RSN_AUTH_KEY_MGMT_FILS_SHA256: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256; + break; + case RSN_AUTH_KEY_MGMT_FILS_SHA384: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384; + break; + case RSN_AUTH_KEY_MGMT_FT_FILS_SHA256: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256; + break; + case RSN_AUTH_KEY_MGMT_FT_FILS_SHA384: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384; + break; + case RSN_AUTH_KEY_MGMT_SAE: + key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SAE; + break; + } + } + + return key_mgmt; +} + + +static void get_iface_akm_suites_info(struct wiphy_info_data *info, + struct nlattr *nl_akms) +{ + struct nlattr *tb[NL80211_IFTYPE_AKM_ATTR_MAX + 1]; + struct nlattr *nl_iftype; + unsigned int key_mgmt; + int i; + + if (!nl_akms) + return; + + nla_parse(tb, NL80211_IFTYPE_AKM_ATTR_MAX, + nla_data(nl_akms), nla_len(nl_akms), NULL); + + if (!tb[NL80211_IFTYPE_AKM_ATTR_IFTYPES] || + !tb[NL80211_IFTYPE_AKM_ATTR_SUITES]) + return; + + info->has_key_mgmt_iftype = 1; + key_mgmt = get_akm_suites_info(tb[NL80211_IFTYPE_AKM_ATTR_SUITES]); + + nla_for_each_nested(nl_iftype, tb[NL80211_IFTYPE_AKM_ATTR_IFTYPES], i) { + switch (nla_type(nl_iftype)) { + case NL80211_IFTYPE_ADHOC: + info->drv->capa.key_mgmt_iftype[WPA_IF_IBSS] = key_mgmt; + break; + case NL80211_IFTYPE_STATION: + info->drv->capa.key_mgmt_iftype[WPA_IF_STATION] = + key_mgmt; + break; + case NL80211_IFTYPE_AP: + info->drv->capa.key_mgmt_iftype[WPA_IF_AP_BSS] = + key_mgmt; + break; + case NL80211_IFTYPE_AP_VLAN: + info->drv->capa.key_mgmt_iftype[WPA_IF_AP_VLAN] = + key_mgmt; + break; + case NL80211_IFTYPE_MESH_POINT: + info->drv->capa.key_mgmt_iftype[WPA_IF_MESH] = key_mgmt; + break; + case NL80211_IFTYPE_P2P_CLIENT: + info->drv->capa.key_mgmt_iftype[WPA_IF_P2P_CLIENT] = + key_mgmt; + break; + case NL80211_IFTYPE_P2P_GO: + info->drv->capa.key_mgmt_iftype[WPA_IF_P2P_GO] = + key_mgmt; + break; + case NL80211_IFTYPE_P2P_DEVICE: + info->drv->capa.key_mgmt_iftype[WPA_IF_P2P_DEVICE] = + key_mgmt; + break; + case NL80211_IFTYPE_NAN: + info->drv->capa.key_mgmt_iftype[WPA_IF_NAN] = key_mgmt; + break; + } + wpa_printf(MSG_DEBUG, "nl80211: %s supported key_mgmt 0x%x", + nl80211_iftype_str(nla_type(nl_iftype)), + key_mgmt); + } +} + + +static void wiphy_info_iftype_akm_suites(struct wiphy_info_data *info, + struct nlattr *tb) +{ + struct nlattr *nl_if; + int rem_if; + + if (!tb) + return; + + nla_for_each_nested(nl_if, tb, rem_if) + get_iface_akm_suites_info(info, nl_if); +} + + +static void wiphy_info_akm_suites(struct wiphy_info_data *info, + struct nlattr *tb) +{ + if (!tb) + return; + + info->has_key_mgmt = 1; + info->capa->key_mgmt = get_akm_suites_info(tb); + wpa_printf(MSG_DEBUG, "nl80211: wiphy supported key_mgmt 0x%x", + info->capa->key_mgmt); +} + + static void wiphy_info_cipher_suites(struct wiphy_info_data *info, struct nlattr *tb) { @@ -441,10 +617,33 @@ static void wiphy_info_ext_feature_flags(struct wiphy_info_data *info, if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211)) capa->flags |= WPA_DRIVER_FLAGS_CONTROL_PORT; + if (ext_feature_isset(ext_features, len, + NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH)) + capa->flags2 |= WPA_DRIVER_FLAGS2_CONTROL_PORT_RX; + if (ext_feature_isset( + ext_features, len, + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS)) + capa->flags2 |= WPA_DRIVER_FLAGS2_CONTROL_PORT_TX_STATUS; if (ext_feature_isset(ext_features, len, NL80211_EXT_FEATURE_VLAN_OFFLOAD)) capa->flags |= WPA_DRIVER_FLAGS_VLAN_OFFLOAD; + + if (ext_feature_isset(ext_features, len, + NL80211_EXT_FEATURE_CAN_REPLACE_PTK0)) + capa->flags |= WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS; + + if (ext_feature_isset(ext_features, len, + NL80211_EXT_FEATURE_BEACON_PROTECTION)) + capa->flags |= WPA_DRIVER_FLAGS_BEACON_PROTECTION; + + if (ext_feature_isset(ext_features, len, + NL80211_EXT_FEATURE_EXT_KEY_ID)) + capa->flags |= WPA_DRIVER_FLAGS_EXTENDED_KEY_ID; + + if (ext_feature_isset(ext_features, len, + NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS)) + info->drv->multicast_registrations = 1; } @@ -491,12 +690,6 @@ static void wiphy_info_feature_flags(struct wiphy_info_data *info, if (flags & NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR) info->mac_addr_rand_sched_scan_supported = 1; - if (flags & NL80211_FEATURE_STATIC_SMPS) - capa->smps_modes |= WPA_DRIVER_SMPS_MODE_STATIC; - - if (flags & NL80211_FEATURE_DYNAMIC_SMPS) - capa->smps_modes |= WPA_DRIVER_SMPS_MODE_DYNAMIC; - if (flags & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION) info->wmm_ac_supported = 1; @@ -683,6 +876,8 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) wiphy_info_iface_comb(info, tb[NL80211_ATTR_INTERFACE_COMBINATIONS]); wiphy_info_supp_cmds(info, tb[NL80211_ATTR_SUPPORTED_COMMANDS]); wiphy_info_cipher_suites(info, tb[NL80211_ATTR_CIPHER_SUITES]); + wiphy_info_akm_suites(info, tb[NL80211_ATTR_AKM_SUITES]); + wiphy_info_iftype_akm_suites(info, tb[NL80211_ATTR_IFTYPE_AKM_SUITES]); if (tb[NL80211_ATTR_OFFCHANNEL_TX_OK]) { wpa_printf(MSG_DEBUG, "nl80211: Using driver-based " @@ -796,12 +991,12 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) case QCA_NL80211_VENDOR_SUBCMD_ROAM: drv->roam_vendor_cmd_avail = 1; break; - case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS: - drv->get_supported_akm_suites_avail = 1; - break; case QCA_NL80211_VENDOR_SUBCMD_ADD_STA_NODE: drv->add_sta_node_vendor_cmd_avail = 1; break; + case QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO: + drv->get_sta_info_vendor_cmd_avail = 1; + break; #endif /* CONFIG_DRIVER_NL80211_QCA */ } } @@ -865,7 +1060,7 @@ static int wpa_driver_nl80211_get_info(struct wpa_driver_nl80211_data *drv, return -1; } - if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info)) + if (send_and_recv_msgs(drv, msg, wiphy_info_handler, info, NULL, NULL)) return -1; if (info->auth_supported) @@ -971,132 +1166,13 @@ static void qca_nl80211_check_dfs_capa(struct wpa_driver_nl80211_data *drv) return; } - ret = send_and_recv_msgs(drv, msg, dfs_info_handler, &dfs_capability); + ret = send_and_recv_msgs(drv, msg, dfs_info_handler, &dfs_capability, + NULL, NULL); if (!ret && dfs_capability) drv->capa.flags |= WPA_DRIVER_FLAGS_DFS_OFFLOAD; } -static unsigned int get_akm_suites_info(struct nlattr *tb) -{ - int i, num; - unsigned int key_mgmt = 0; - u32 *akms; - - if (!tb) - return 0; - - num = nla_len(tb) / sizeof(u32); - akms = nla_data(tb); - for (i = 0; i < num; i++) { - u32 a = akms[i]; - - wpa_printf(MSG_DEBUG, - "nl80211: Supported AKM %02x-%02x-%02x:%u", - a >> 24, (a >> 16) & 0xff, - (a >> 8) & 0xff, a & 0xff); - switch (a) { - case RSN_AUTH_KEY_MGMT_UNSPEC_802_1X: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2; - break; - case RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK; - break; - case RSN_AUTH_KEY_MGMT_FT_802_1X: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT; - break; - case RSN_AUTH_KEY_MGMT_FT_PSK: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK; - break; - case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B; - break; - case RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192; - break; - case RSN_AUTH_KEY_MGMT_OWE: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_OWE; - break; - case RSN_AUTH_KEY_MGMT_DPP: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_DPP; - break; - case RSN_AUTH_KEY_MGMT_FILS_SHA256: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256; - break; - case RSN_AUTH_KEY_MGMT_FILS_SHA384: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384; - break; - case RSN_AUTH_KEY_MGMT_FT_FILS_SHA256: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256; - break; - case RSN_AUTH_KEY_MGMT_FT_FILS_SHA384: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384; - break; - case RSN_AUTH_KEY_MGMT_SAE: - key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SAE; - break; - } - } - - return key_mgmt; -} - - -static int get_akm_suites_handler(struct nl_msg *msg, void *arg) -{ - struct nlattr *tb[NL80211_ATTR_MAX + 1]; - struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); - unsigned int *key_mgmt = arg; - - nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), - genlmsg_attrlen(gnlh, 0), NULL); - - if (tb[NL80211_ATTR_VENDOR_DATA]) { - struct nlattr *nl_vend = tb[NL80211_ATTR_VENDOR_DATA]; - struct nlattr *tb_data[NL80211_ATTR_MAX + 1]; - - nla_parse(tb_data, NL80211_ATTR_MAX, - nla_data(nl_vend), nla_len(nl_vend), NULL); - - *key_mgmt = - get_akm_suites_info(tb_data[NL80211_ATTR_AKM_SUITES]); - } - - return NL_SKIP; -} - - -static int qca_nl80211_get_akm_suites(struct wpa_driver_nl80211_data *drv) -{ - struct nl_msg *msg; - unsigned int key_mgmt = 0; - int ret; - - if (!drv->get_supported_akm_suites_avail) - return -1; - - if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || - nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || - nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, - QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_AKMS)) { - nlmsg_free(msg); - return -1; - } - - ret = send_and_recv_msgs(drv, msg, get_akm_suites_handler, &key_mgmt); - if (!ret) { - wpa_printf(MSG_DEBUG, - "nl80211: Replace capa.key_mgmt based on driver advertised capabilities: 0x%x", - key_mgmt); - drv->capa.key_mgmt = key_mgmt; - } - - return ret; -} - - struct features_info { u8 *flags; size_t flags_len; @@ -1178,7 +1254,8 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv) os_memset(&info, 0, sizeof(info)); info.capa = &drv->capa; - ret = send_and_recv_msgs(drv, msg, features_info_handler, &info); + ret = send_and_recv_msgs(drv, msg, features_info_handler, &info, + NULL, NULL); if (ret || !info.flags) return; @@ -1208,6 +1285,8 @@ static void qca_nl80211_get_features(struct wpa_driver_nl80211_data *drv) int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) { struct wiphy_info_data info; + int i; + if (wpa_driver_nl80211_get_info(drv, &info)) return -1; @@ -1215,33 +1294,62 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) return -1; drv->has_capability = 1; - drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B | - WPA_DRIVER_CAPA_KEY_MGMT_OWE | - WPA_DRIVER_CAPA_KEY_MGMT_DPP; + drv->has_driver_key_mgmt = info.has_key_mgmt | info.has_key_mgmt_iftype; - if (drv->capa.enc & (WPA_DRIVER_CAPA_ENC_CCMP_256 | - WPA_DRIVER_CAPA_ENC_GCMP_256)) - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192; + /* Fallback to hardcoded defaults if the driver does nott advertize any + * AKM capabilities. */ + if (!drv->has_driver_key_mgmt) { + drv->capa.key_mgmt = WPA_DRIVER_CAPA_KEY_MGMT_WPA | + WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2 | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK | + WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B | + WPA_DRIVER_CAPA_KEY_MGMT_OWE | + WPA_DRIVER_CAPA_KEY_MGMT_DPP; - if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 | - WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 | - WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 | - WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 | - WPA_DRIVER_CAPA_KEY_MGMT_SAE; - else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) - drv->capa.key_mgmt |= WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 | - WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384; + if (drv->capa.enc & (WPA_DRIVER_CAPA_ENC_CCMP_256 | + WPA_DRIVER_CAPA_ENC_GCMP_256)) + drv->capa.key_mgmt |= + WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192; -#ifdef CONFIG_DRIVER_NL80211_QCA - /* Override drv->capa.key_mgmt based on driver advertised capability - * constraints, if available. */ - qca_nl80211_get_akm_suites(drv); -#endif /* CONFIG_DRIVER_NL80211_QCA */ + if (drv->capa.flags & WPA_DRIVER_FLAGS_SME) + drv->capa.key_mgmt |= + WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 | + WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384 | + WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256 | + WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384 | + WPA_DRIVER_CAPA_KEY_MGMT_SAE; + else if (drv->capa.flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) + drv->capa.key_mgmt |= + WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256 | + WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384; + } + + if (!info.has_key_mgmt_iftype) { + /* If the driver does not advertize per interface AKM + * capabilities, consider all interfaces to support default AKMs + * in key_mgmt. */ + for (i = 0; i < WPA_IF_MAX; i++) + drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt; + } else if (info.has_key_mgmt_iftype && !info.has_key_mgmt) { + /* If the driver advertizes only per interface supported AKMs + * but does not advertize per wiphy AKM capabilities, consider + * the default key_mgmt as a mask of per interface supported + * AKMs. */ + drv->capa.key_mgmt = 0; + for (i = 0; i < WPA_IF_MAX; i++) + drv->capa.key_mgmt |= drv->capa.key_mgmt_iftype[i]; + } else if (info.has_key_mgmt_iftype && info.has_key_mgmt) { + /* If the driver advertizes AKM capabilities both per wiphy and + * per interface, consider the interfaces for which per + * interface AKM capabilities were not received to support the + * default key_mgmt capabilities. + */ + for (i = 0; i < WPA_IF_MAX; i++) + if (!drv->capa.key_mgmt_iftype[i]) + drv->capa.key_mgmt_iftype[i] = + drv->capa.key_mgmt; + } drv->capa.auth = WPA_DRIVER_AUTH_OPEN | WPA_DRIVER_AUTH_SHARED | @@ -1309,6 +1417,12 @@ int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv) drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_SIMULTANEOUS; #endif /* CONFIG_DRIVER_NL80211_QCA */ + wpa_printf(MSG_DEBUG, + "nl80211: key_mgmt=0x%x enc=0x%x auth=0x%x flags=0x%llx rrm_flags=0x%x probe_resp_offloads=0x%x max_stations=%u max_remain_on_chan=%u max_scan_ssids=%d", + drv->capa.key_mgmt, drv->capa.enc, drv->capa.auth, + (unsigned long long) drv->capa.flags, drv->capa.rrm_flags, + drv->capa.probe_resp_offloads, drv->capa.max_stations, + drv->capa.max_remain_on_chan, drv->capa.max_scan_ssids); return 0; } @@ -1686,6 +1800,13 @@ static void phy_info_iftype_copy(struct he_capabilities *he_capab, nla_data(tb[NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE]), len); } + + if (tb[NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA]) { + u16 capa; + + capa = nla_get_u16(tb[NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA]); + he_capab->he_6ghz_capa = le_to_host16(capa); + } } @@ -1828,7 +1949,10 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes, for (m = 0; m < *num_modes; m++) { if (!modes[m].num_channels) continue; - if (modes[m].channels[0].freq < 4000) { + if (modes[m].channels[0].freq < 2000) { + modes[m].num_channels = 0; + continue; + } else if (modes[m].channels[0].freq < 4000) { modes[m].mode = HOSTAPD_MODE_IEEE80211B; for (i = 0; i < modes[m].num_rates; i++) { if (modes[m].rates[i] > 200) { @@ -1842,6 +1966,24 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes, modes[m].mode = HOSTAPD_MODE_IEEE80211A; } + /* Remove unsupported bands */ + m = 0; + while (m < *num_modes) { + if (modes[m].mode == NUM_HOSTAPD_MODES) { + wpa_printf(MSG_DEBUG, + "nl80211: Remove unsupported mode"); + os_free(modes[m].channels); + os_free(modes[m].rates); + if (m + 1 < *num_modes) + os_memmove(&modes[m], &modes[m + 1], + sizeof(struct hostapd_hw_modes) * + (*num_modes - (m + 1))); + (*num_modes)--; + continue; + } + m++; + } + /* If only 802.11g mode is included, use it to construct matching * 802.11b mode data. */ @@ -2216,7 +2358,8 @@ static int nl80211_set_regulatory_flags(struct wpa_driver_nl80211_data *drv, } } - return send_and_recv_msgs(drv, msg, nl80211_get_reg, results); + return send_and_recv_msgs(drv, msg, nl80211_get_reg, results, + NULL, NULL); } @@ -2305,7 +2448,8 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags, return NULL; } - if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0) { + if (send_and_recv_msgs(drv, msg, phy_info_handler, &result, + NULL, NULL) == 0) { struct hostapd_hw_modes *modes; nl80211_set_regulatory_flags(drv, &result); diff --git a/src/drivers/driver_nl80211_event.c b/src/drivers/driver_nl80211_event.c index 8327644fb..a3e2eee93 100644 --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c @@ -20,6 +20,12 @@ #include "driver_nl80211.h" +static void +nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv, + const u8 *frame, size_t len, + struct nlattr *ack, struct nlattr *cookie); + + static const char * nl80211_command_to_string(enum nl80211_commands cmd) { #define C2S(x) case x: return #x; @@ -137,6 +143,9 @@ static const char * nl80211_command_to_string(enum nl80211_commands cmd) C2S(NL80211_CMD_STA_OPMODE_CHANGED) C2S(NL80211_CMD_CONTROL_PORT_FRAME) C2S(NL80211_CMD_UPDATE_OWE_INFO) + C2S(NL80211_CMD_UNPROT_BEACON) + C2S(NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS) + default: return "NL80211_CMD_UNKNOWN"; } @@ -287,6 +296,94 @@ static void mlme_event_assoc(struct wpa_driver_nl80211_data *drv, } +#ifdef CONFIG_DRIVER_NL80211_QCA + +static int qca_drv_connect_fail_reason_code_handler(struct nl_msg *msg, + void *arg) +{ + struct nlattr *tb[NL80211_ATTR_MAX + 1]; + struct nlattr *tb_sta_info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX + 1]; + struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg)); + u32 *reason_code = arg; + + *reason_code = 0; + nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0), + genlmsg_attrlen(gnlh, 0), NULL); + + if (!tb[NL80211_ATTR_VENDOR_DATA]) { + wpa_printf(MSG_ERROR, "%s: Vendor data not found", __func__); + return NL_SKIP; + } + + nla_parse(tb_sta_info, QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_MAX, + nla_data(tb[NL80211_ATTR_VENDOR_DATA]), + nla_len(tb[NL80211_ATTR_VENDOR_DATA]), NULL); + + if (!tb_sta_info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE]) { + wpa_printf(MSG_INFO, "%s: Vendor attr not found", __func__); + return NL_SKIP; + } + + *reason_code = nla_get_u32(tb_sta_info[QCA_WLAN_VENDOR_ATTR_GET_STA_INFO_CONNECT_FAIL_REASON_CODE]); + + return NL_SKIP; +} + + +static enum qca_sta_connect_fail_reason_codes +drv_get_connect_fail_reason_code(struct wpa_driver_nl80211_data *drv) +{ + enum qca_sta_connect_fail_reason_codes reason_code; + struct nl_msg *msg; + int ret; + + msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR); + if (!msg || nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || + nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, + QCA_NL80211_VENDOR_SUBCMD_GET_STA_INFO)) { + nlmsg_free(msg); + return 0; + } + + ret = send_and_recv_msgs(drv, msg, + qca_drv_connect_fail_reason_code_handler, + &reason_code, NULL, NULL); + if (ret) + wpa_printf(MSG_DEBUG, + "nl80211: Get connect fail reason_code failed: ret=%d (%s)", + ret, strerror(-ret)); + + return reason_code; +} + + +static enum sta_connect_fail_reason_codes +convert_connect_fail_reason_codes(enum qca_sta_connect_fail_reason_codes + reason_code) +{ + switch (reason_code) { + case QCA_STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: + return STA_CONNECT_FAIL_REASON_NO_BSS_FOUND; + case QCA_STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: + return STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL; + case QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: + return STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED; + case QCA_STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: + return STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED; + case QCA_STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: + return STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL; + case QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: + return STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED; + case QCA_STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: + return STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED; + default: + return STA_CONNECT_FAIL_REASON_UNSPECIFIED; + } +} + +#endif /* CONFIG_DRIVER_NL80211_QCA */ + + static void mlme_event_connect(struct wpa_driver_nl80211_data *drv, enum nl80211_commands cmd, struct nlattr *status, struct nlattr *addr, struct nlattr *req_ie, @@ -376,6 +473,17 @@ static void mlme_event_connect(struct wpa_driver_nl80211_data *drv, if (fils_erp_next_seq_num) event.assoc_reject.fils_erp_next_seq_num = nla_get_u16(fils_erp_next_seq_num); + +#ifdef CONFIG_DRIVER_NL80211_QCA + if (drv->get_sta_info_vendor_cmd_avail) { + enum qca_sta_connect_fail_reason_codes reason_code; + + reason_code = drv_get_connect_fail_reason_code(drv); + event.assoc_reject.reason_code = + convert_connect_fail_reason_codes(reason_code); + } +#endif /* CONFIG_DRIVER_NL80211_QCA */ + wpa_supplicant_event(drv->ctx, EVENT_ASSOC_REJECT, &event); return; } @@ -683,17 +791,38 @@ static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv, size_t len, struct nlattr *ack) { union wpa_event_data event; - const struct ieee80211_hdr *hdr; - u16 fc; + const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *) frame; + u16 fc = le_to_host16(hdr->frame_control); + u64 cookie_val = 0; - wpa_printf(MSG_DEBUG, "nl80211: Frame TX status event"); - if (!is_ap_interface(drv->nlmode)) { - u64 cookie_val; + if (cookie) + cookie_val = nla_get_u64(cookie); + wpa_printf(MSG_DEBUG, + "nl80211: Frame TX status event A1=" MACSTR + " %sstype=%d cookie=0x%llx%s ack=%d", + MAC2STR(hdr->addr1), + WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT ? "not-mgmt " : "", + WLAN_FC_GET_STYPE(fc), (long long unsigned int) cookie_val, + cookie ? "" : "(N/A)", ack != NULL); + if (cookie_val && cookie_val == drv->eapol_tx_cookie && + len >= ETH_HLEN && + WPA_GET_BE16(frame + 2 * ETH_ALEN) == ETH_P_PAE) { + wpa_printf(MSG_DEBUG, + "nl80211: Work around misdelivered control port TX status for EAPOL"); + nl80211_control_port_frame_tx_status(drv, frame, len, ack, + cookie); + return; + } + + if (WLAN_FC_GET_TYPE(fc) != WLAN_FC_TYPE_MGMT) + return; + + if (!is_ap_interface(drv->nlmode) && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION) { if (!cookie) return; - cookie_val = nla_get_u64(cookie); wpa_printf(MSG_DEBUG, "nl80211: Frame TX status: cookie=0x%llx%s (ack=%d)", (long long unsigned int) cookie_val, @@ -701,11 +830,13 @@ static void mlme_event_mgmt_tx_status(struct wpa_driver_nl80211_data *drv, " (match)" : " (unknown)", ack != NULL); if (cookie_val != drv->send_frame_cookie) return; + } else if (!is_ap_interface(drv->nlmode) && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_AUTH) { + wpa_printf(MSG_DEBUG, + "nl80211: Authentication frame TX status: ack=%d", + !!ack); } - hdr = (const struct ieee80211_hdr *) frame; - fc = le_to_host16(hdr->frame_control); - os_memset(&event, 0, sizeof(event)); event.tx_status.type = WLAN_FC_GET_TYPE(fc); event.tx_status.stype = WLAN_FC_GET_STYPE(fc); @@ -880,6 +1011,23 @@ static void mlme_event_unprot_disconnect(struct wpa_driver_nl80211_data *drv, } +static void mlme_event_unprot_beacon(struct wpa_driver_nl80211_data *drv, + const u8 *frame, size_t len) +{ + const struct ieee80211_mgmt *mgmt; + union wpa_event_data event; + + if (len < 24) + return; + + mgmt = (const struct ieee80211_mgmt *) frame; + + os_memset(&event, 0, sizeof(event)); + event.unprot_beacon.sa = mgmt->sa; + wpa_supplicant_event(drv->ctx, EVENT_UNPROT_BEACON, &event); +} + + static void mlme_event(struct i802_bss *bss, enum nl80211_commands cmd, struct nlattr *frame, struct nlattr *addr, struct nlattr *timed_out, @@ -961,6 +1109,9 @@ static void mlme_event(struct i802_bss *bss, mlme_event_unprot_disconnect(drv, EVENT_UNPROT_DISASSOC, nla_data(frame), nla_len(frame)); break; + case NL80211_CMD_UNPROT_BEACON: + mlme_event_unprot_beacon(drv, nla_data(frame), nla_len(frame)); + break; default: break; } @@ -1225,7 +1376,6 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv, struct nlattr *cqm[NL80211_ATTR_CQM_MAX + 1]; enum nl80211_cqm_rssi_threshold_event event; union wpa_event_data ed; - struct wpa_signal_info sig; int res; if (tb[NL80211_ATTR_CQM] == NULL || @@ -1292,19 +1442,27 @@ static void nl80211_cqm_event(struct wpa_driver_nl80211_data *drv, return; } - res = nl80211_get_link_signal(drv, &sig); + /* + * nl80211_get_link_signal() and nl80211_get_link_noise() set default + * values in case querying the driver fails. + */ + res = nl80211_get_link_signal(drv, &ed.signal_change); if (res == 0) { - ed.signal_change.current_signal = sig.current_signal; - ed.signal_change.current_txrate = sig.current_txrate; wpa_printf(MSG_DEBUG, "nl80211: Signal: %d dBm txrate: %d", - sig.current_signal, sig.current_txrate); + ed.signal_change.current_signal, + ed.signal_change.current_txrate); + } else { + wpa_printf(MSG_DEBUG, + "nl80211: Querying the driver for signal info failed"); } - res = nl80211_get_link_noise(drv, &sig); + res = nl80211_get_link_noise(drv, &ed.signal_change); if (res == 0) { - ed.signal_change.current_noise = sig.current_noise; wpa_printf(MSG_DEBUG, "nl80211: Noise: %d dBm", - sig.current_noise); + ed.signal_change.current_noise); + } else { + wpa_printf(MSG_DEBUG, + "nl80211: Querying the driver for noise info failed"); } wpa_supplicant_event(drv->ctx, EVENT_SIGNAL_CHANGE, &ed); @@ -1740,8 +1898,41 @@ static enum hostapd_hw_mode get_qca_hw_mode(u8 hw_mode) } -static unsigned int chan_2ghz_or_5ghz_to_freq(u8 chan) +static unsigned int chan_to_freq(struct wpa_driver_nl80211_data *drv, + u8 chan, enum hostapd_hw_mode hw_mode) { + if (hw_mode == NUM_HOSTAPD_MODES) { + /* For drivers that do not report ACS_HW_MODE */ + u16 num_modes, flags; + struct hostapd_hw_modes *modes; + u8 dfs_domain; + int i; + + modes = nl80211_get_hw_feature_data(drv->first_bss, &num_modes, + &flags, &dfs_domain); + if (!modes) { + wpa_printf(MSG_DEBUG, + "nl80211: Fetching hardware mode failed"); + goto try_2_4_or_5; + } + if (num_modes == 1) + hw_mode = modes[0].mode; + + for (i = 0; i < num_modes; i++) { + os_free(modes[i].channels); + os_free(modes[i].rates); + } + + os_free(modes); + } + + if (hw_mode == HOSTAPD_MODE_IEEE80211AD) { + if (chan >= 1 && chan <= 6) + return 56160 + (2160 * chan); + return 0; + } + +try_2_4_or_5: if (chan >= 1 && chan <= 13) return 2407 + 5 * chan; if (chan == 14) @@ -1772,34 +1963,8 @@ static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv, return; os_memset(&event, 0, sizeof(event)); - if (tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]) { - event.acs_selected_channels.pri_freq = nla_get_u32( - tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]); - } else { - chan = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]); - event.acs_selected_channels.pri_freq = - chan_2ghz_or_5ghz_to_freq(chan); - } + event.acs_selected_channels.hw_mode = NUM_HOSTAPD_MODES; - if (tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]) { - event.acs_selected_channels.sec_freq = nla_get_u32( - tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]); - } else { - chan = nla_get_u8( - tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]); - event.acs_selected_channels.sec_freq = - chan_2ghz_or_5ghz_to_freq(chan); - } - - if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]) - event.acs_selected_channels.vht_seg0_center_ch = - nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]); - if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]) - event.acs_selected_channels.vht_seg1_center_ch = - nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]); - if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) - event.acs_selected_channels.ch_width = - nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]); if (tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]) { u8 hw_mode = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_HW_MODE]); @@ -1814,14 +1979,48 @@ static void qca_nl80211_acs_select_ch(struct wpa_driver_nl80211_data *drv, } } + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]) { + event.acs_selected_channels.pri_freq = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_FREQUENCY]); + } else { + chan = nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_PRIMARY_CHANNEL]); + event.acs_selected_channels.pri_freq = + chan_to_freq(drv, chan, + event.acs_selected_channels.hw_mode); + } + + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]) { + event.acs_selected_channels.sec_freq = nla_get_u32( + tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_FREQUENCY]); + } else { + chan = nla_get_u8( + tb[QCA_WLAN_VENDOR_ATTR_ACS_SECONDARY_CHANNEL]); + event.acs_selected_channels.sec_freq = + chan_to_freq(drv, chan, + event.acs_selected_channels.hw_mode); + } + + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL]) + event.acs_selected_channels.edmg_channel = + nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_EDMG_CHANNEL]); + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]) + event.acs_selected_channels.vht_seg0_center_ch = + nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG0_CENTER_CHANNEL]); + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]) + event.acs_selected_channels.vht_seg1_center_ch = + nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_ACS_VHT_SEG1_CENTER_CHANNEL]); + if (tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]) + event.acs_selected_channels.ch_width = + nla_get_u16(tb[QCA_WLAN_VENDOR_ATTR_ACS_CHWIDTH]); wpa_printf(MSG_INFO, - "nl80211: ACS Results: PFreq: %d SFreq: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d", + "nl80211: ACS Results: PFreq: %d SFreq: %d BW: %d VHT0: %d VHT1: %d HW_MODE: %d EDMGCH: %d", event.acs_selected_channels.pri_freq, event.acs_selected_channels.sec_freq, event.acs_selected_channels.ch_width, event.acs_selected_channels.vht_seg0_center_ch, event.acs_selected_channels.vht_seg1_center_ch, - event.acs_selected_channels.hw_mode); + event.acs_selected_channels.hw_mode, + event.acs_selected_channels.edmg_channel); /* Ignore ACS channel list check for backwards compatibility */ @@ -2451,12 +2650,57 @@ static void nl80211_sta_opmode_change_event(struct wpa_driver_nl80211_data *drv, static void nl80211_control_port_frame(struct wpa_driver_nl80211_data *drv, struct nlattr **tb) { - if (!tb[NL80211_ATTR_MAC] || !tb[NL80211_ATTR_FRAME]) + u8 *src_addr; + u16 ethertype; + + if (!tb[NL80211_ATTR_MAC] || + !tb[NL80211_ATTR_FRAME] || + !tb[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]) return; - drv_event_eapol_rx(drv->ctx, nla_data(tb[NL80211_ATTR_MAC]), - nla_data(tb[NL80211_ATTR_FRAME]), - nla_len(tb[NL80211_ATTR_FRAME])); + src_addr = nla_data(tb[NL80211_ATTR_MAC]); + ethertype = nla_get_u16(tb[NL80211_ATTR_CONTROL_PORT_ETHERTYPE]); + + switch (ethertype) { + case ETH_P_RSN_PREAUTH: + wpa_printf(MSG_INFO, "nl80211: Got pre-auth frame from " + MACSTR " over control port unexpectedly", + MAC2STR(src_addr)); + break; + case ETH_P_PAE: + drv_event_eapol_rx(drv->ctx, src_addr, + nla_data(tb[NL80211_ATTR_FRAME]), + nla_len(tb[NL80211_ATTR_FRAME])); + break; + default: + wpa_printf(MSG_INFO, "nl80211: Unxpected ethertype 0x%04x from " + MACSTR " over control port", + ethertype, MAC2STR(src_addr)); + break; + } +} + + +static void +nl80211_control_port_frame_tx_status(struct wpa_driver_nl80211_data *drv, + const u8 *frame, size_t len, + struct nlattr *ack, struct nlattr *cookie) +{ + union wpa_event_data event; + + if (!cookie || len < ETH_HLEN) + return; + + wpa_printf(MSG_DEBUG, + "nl80211: Control port TX status (ack=%d), cookie=%llu", + ack != NULL, (long long unsigned int) nla_get_u64(cookie)); + + os_memset(&event, 0, sizeof(event)); + event.eapol_tx_status.dst = frame; + event.eapol_tx_status.data = frame + ETH_HLEN; + event.eapol_tx_status.data_len = len - ETH_HLEN; + event.eapol_tx_status.ack = ack != NULL; + wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event); } @@ -2465,6 +2709,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, { struct wpa_driver_nl80211_data *drv = bss->drv; int external_scan_event = 0; + struct nlattr *frame = tb[NL80211_ATTR_FRAME]; wpa_printf(MSG_DEBUG, "nl80211: Drv Event %d (%s) received for %s", cmd, nl80211_command_to_string(cmd), bss->ifname); @@ -2483,11 +2728,8 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED && (cmd == NL80211_CMD_NEW_SCAN_RESULTS || - cmd == NL80211_CMD_SCAN_ABORTED)) { - wpa_driver_nl80211_set_mode(drv->first_bss, - drv->ap_scan_as_station); - drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; - } + cmd == NL80211_CMD_SCAN_ABORTED)) + nl80211_restore_ap_mode(bss); switch (cmd) { case NL80211_CMD_TRIGGER_SCAN: @@ -2675,8 +2917,19 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd, case NL80211_CMD_UPDATE_OWE_INFO: mlme_event_dh_event(drv, bss, tb); break; - case NL80211_CMD_CONTROL_PORT_FRAME: - nl80211_control_port_frame(drv, tb); + case NL80211_CMD_UNPROT_BEACON: + if (frame) + mlme_event_unprot_beacon(drv, nla_data(frame), + nla_len(frame)); + break; + case NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS: + if (!frame) + break; + nl80211_control_port_frame_tx_status(drv, + nla_data(frame), + nla_len(frame), + tb[NL80211_ATTR_ACK], + tb[NL80211_ATTR_COOKIE]); break; default: wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " @@ -2767,6 +3020,9 @@ int process_bss_event(struct nl_msg *msg, void *arg) case NL80211_CMD_EXTERNAL_AUTH: nl80211_external_auth(bss->drv, tb); break; + case NL80211_CMD_CONTROL_PORT_FRAME: + nl80211_control_port_frame(bss->drv, tb); + break; default: wpa_printf(MSG_DEBUG, "nl80211: Ignored unknown event " "(cmd=%d)", gnlh->cmd); diff --git a/src/drivers/driver_nl80211_scan.c b/src/drivers/driver_nl80211_scan.c index 413d6f757..233175d19 100644 --- a/src/drivers/driver_nl80211_scan.c +++ b/src/drivers/driver_nl80211_scan.c @@ -82,7 +82,8 @@ static int nl80211_get_noise_for_scan_results( os_memset(info, 0, sizeof(*info)); msg = nl80211_drv_msg(drv, NLM_F_DUMP, NL80211_CMD_GET_SURVEY); - return send_and_recv_msgs(drv, msg, get_noise_for_scan_results, info); + return send_and_recv_msgs(drv, msg, get_noise_for_scan_results, info, + NULL, NULL); } @@ -94,7 +95,7 @@ static int nl80211_abort_scan(struct i802_bss *bss) wpa_printf(MSG_DEBUG, "nl80211: Abort scan"); msg = nl80211_cmd_msg(bss, 0, NL80211_CMD_ABORT_SCAN); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Abort scan failed: ret=%d (%s)", ret, strerror(-ret)); @@ -125,7 +126,7 @@ static int nl80211_abort_vendor_scan(struct wpa_driver_nl80211_data *drv, nla_nest_end(msg, params); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_INFO, @@ -166,11 +167,8 @@ void wpa_driver_nl80211_scan_timeout(void *eloop_ctx, void *timeout_ctx) wpa_printf(MSG_DEBUG, "nl80211: Failed to abort scan"); - if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) { - wpa_driver_nl80211_set_mode(drv->first_bss, - drv->ap_scan_as_station); - drv->ap_scan_as_station = NL80211_IFTYPE_UNSPECIFIED; - } + if (drv->ap_scan_as_station != NL80211_IFTYPE_UNSPECIFIED) + nl80211_restore_ap_mode(drv->first_bss); wpa_printf(MSG_DEBUG, "nl80211: Try to get scan results"); wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL); @@ -236,6 +234,11 @@ nl80211_scan_common(struct i802_bss *bss, u8 cmd, params->filter_ssids = NULL; drv->num_filter_ssids = params->num_filter_ssids; + if (!drv->hostapd && is_ap_interface(drv->nlmode)) { + wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_AP"); + scan_flags |= NL80211_SCAN_FLAG_AP; + } + if (params->only_new_results) { wpa_printf(MSG_DEBUG, "nl80211: Add NL80211_SCAN_FLAG_FLUSH"); scan_flags |= NL80211_SCAN_FLAG_FLUSH; @@ -363,7 +366,7 @@ int wpa_driver_nl80211_scan(struct i802_bss *bss, goto fail; } - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Scan trigger failed: ret=%d " @@ -616,7 +619,7 @@ int wpa_driver_nl80211_sched_scan(void *priv, params->sched_scan_start_delay)) goto fail; - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); /* TODO: if we get an error here, we should fall back to normal scan */ @@ -653,7 +656,7 @@ int wpa_driver_nl80211_stop_sched_scan(void *priv) #endif /* ANDROID */ msg = nl80211_drv_msg(drv, 0, NL80211_CMD_STOP_SCHED_SCAN); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Sched scan stop failed: ret=%d (%s)", @@ -867,7 +870,7 @@ static void clear_state_mismatch(struct wpa_driver_nl80211_data *drv, wpa_driver_nl80211_mlme(drv, addr, NL80211_CMD_DEAUTHENTICATE, WLAN_REASON_PREV_AUTH_NOT_VALID, 1, - NULL); + get_connect_handle(drv->first_bss)); } } @@ -942,7 +945,7 @@ try_again: arg.drv = drv; arg.res = res; - ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg); + ret = send_and_recv_msgs(drv, msg, bss_info_handler, &arg, NULL, NULL); if (ret == -EAGAIN) { count++; if (count >= 10) { @@ -1026,7 +1029,8 @@ void nl80211_dump_scan(struct wpa_driver_nl80211_data *drv) ctx.idx = 0; msg = nl80211_cmd_msg(drv->first_bss, NLM_F_DUMP, NL80211_CMD_GET_SCAN); if (msg) - send_and_recv_msgs(drv, msg, nl80211_dump_scan_handler, &ctx); + send_and_recv_msgs(drv, msg, nl80211_dump_scan_handler, &ctx, + NULL, NULL); } @@ -1219,7 +1223,8 @@ int wpa_driver_nl80211_vendor_scan(struct i802_bss *bss, nla_nest_end(msg, attr); - ret = send_and_recv_msgs(drv, msg, scan_cookie_handler, &cookie); + ret = send_and_recv_msgs(drv, msg, scan_cookie_handler, &cookie, + NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_DEBUG, @@ -1282,7 +1287,7 @@ int nl80211_set_default_scan_ies(void *priv, const u8 *ies, size_t ies_len) nla_nest_end(msg, attr); - ret = send_and_recv_msgs(drv, msg, NULL, NULL); + ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); msg = NULL; if (ret) { wpa_printf(MSG_ERROR, diff --git a/src/drivers/driver_openbsd.c b/src/drivers/driver_openbsd.c index e0eede96b..bfc231178 100644 --- a/src/drivers/driver_openbsd.c +++ b/src/drivers/driver_openbsd.c @@ -73,11 +73,12 @@ wpa_driver_openbsd_set_key(void *priv, struct wpa_driver_set_key_params *params) { struct openbsd_driver_data *drv = priv; struct ieee80211_keyavail keyavail; - enum wpa_alg alg = params->alg; + enum key_flag key_flag = params->key_flag; const u8 *key = params->key; size_t key_len = params->key_len; - if (alg != WPA_ALG_PMK || key_len > IEEE80211_PMK_LEN) + if (key_len > IEEE80211_PMK_LEN || + (key_flag & KEY_FLAG_PMK_MASK) != KEY_FLAG_PMK) { return -1; memset(&keyavail, 0, sizeof(keyavail)); diff --git a/src/drivers/driver_privsep.c b/src/drivers/driver_privsep.c index 807657ebc..d6735b49c 100644 --- a/src/drivers/driver_privsep.c +++ b/src/drivers/driver_privsep.c @@ -230,6 +230,7 @@ static int wpa_driver_privsep_set_key(void *priv, os_memset(cmd.addr, 0xff, ETH_ALEN); cmd.key_idx = key_idx; cmd.set_tx = set_tx; + cmd.key_flag = params->key_flag; if (seq && seq_len > 0 && seq_len < sizeof(cmd.seq)) { os_memcpy(cmd.seq, seq, seq_len); cmd.seq_len = seq_len; @@ -796,6 +797,8 @@ static int wpa_driver_privsep_get_capa(void *priv, capa->extended_capa = NULL; capa->extended_capa_mask = NULL; capa->extended_capa_len = 0; + /* Control port is not yet supported */ + capa->flags &= ~WPA_DRIVER_FLAGS_CONTROL_PORT; return 0; } diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c index 776eff72d..0f0ad1f53 100644 --- a/src/drivers/driver_wext.c +++ b/src/drivers/driver_wext.c @@ -968,6 +968,7 @@ static void wext_check_hostap(struct wpa_driver_wext_data *drv) static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv) { int send_rfkill_event = 0; + int i; if (linux_set_iface_flags(drv->ioctl_sock, drv->ifname, 1) < 0) { if (rfkill_is_blocked(drv->rfkill)) { @@ -996,6 +997,10 @@ static int wpa_driver_wext_finish_drv_init(struct wpa_driver_wext_data *drv) wpa_driver_wext_get_range(drv); + /* Update per interface supported AKMs */ + for (i = 0; i < WPA_IF_MAX; i++) + drv->capa.key_mgmt_iftype[i] = drv->capa.key_mgmt; + /* * Unlock the driver's BSSID and force to a random SSID to clear any * previous association the driver might have when the supplicant @@ -1712,7 +1717,8 @@ static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) + const u8 *key, size_t key_len, + enum key_flag key_flag) { struct wpa_driver_wext_data *drv = priv; struct iwreq iwr; @@ -1751,30 +1757,31 @@ static int wpa_driver_wext_set_key_ext(void *priv, enum wpa_alg alg, os_memcpy(ext + 1, key, key_len); ext->key_len = key_len; } - switch (alg) { - case WPA_ALG_NONE: - ext->alg = IW_ENCODE_ALG_NONE; - break; - case WPA_ALG_WEP: - ext->alg = IW_ENCODE_ALG_WEP; - break; - case WPA_ALG_TKIP: - ext->alg = IW_ENCODE_ALG_TKIP; - break; - case WPA_ALG_CCMP: - ext->alg = IW_ENCODE_ALG_CCMP; - break; - case WPA_ALG_PMK: + if (key_flag & KEY_FLAG_PMK) { ext->alg = IW_ENCODE_ALG_PMK; - break; - case WPA_ALG_IGTK: - ext->alg = IW_ENCODE_ALG_AES_CMAC; - break; - default: - wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d", - __FUNCTION__, alg); - os_free(ext); - return -1; + } else { + switch (alg) { + case WPA_ALG_NONE: + ext->alg = IW_ENCODE_ALG_NONE; + break; + case WPA_ALG_WEP: + ext->alg = IW_ENCODE_ALG_WEP; + break; + case WPA_ALG_TKIP: + ext->alg = IW_ENCODE_ALG_TKIP; + break; + case WPA_ALG_CCMP: + ext->alg = IW_ENCODE_ALG_CCMP; + break; + case WPA_ALG_BIP_CMAC_128: + ext->alg = IW_ENCODE_ALG_AES_CMAC; + break; + default: + wpa_printf(MSG_DEBUG, "%s: Unknown algorithm %d", + __FUNCTION__, alg); + os_free(ext); + return -1; + } } if (seq && seq_len) { @@ -1816,6 +1823,7 @@ static int wpa_driver_wext_set_key(void *priv, struct iwreq iwr; int ret = 0; enum wpa_alg alg = params->alg; + enum key_flag key_flag = params->key_flag; const u8 *addr = params->addr; int key_idx = params->key_idx; int set_tx = params->set_tx; @@ -1830,7 +1838,7 @@ static int wpa_driver_wext_set_key(void *priv, (unsigned long) seq_len, (unsigned long) key_len); ret = wpa_driver_wext_set_key_ext(drv, alg, addr, key_idx, set_tx, - seq, seq_len, key, key_len); + seq, seq_len, key, key_len, key_flag); if (ret == 0) return 0; diff --git a/src/drivers/nl80211_copy.h b/src/drivers/nl80211_copy.h index 341e0e8ca..3e0d4a038 100644 --- a/src/drivers/nl80211_copy.h +++ b/src/drivers/nl80211_copy.h @@ -11,7 +11,7 @@ * Copyright 2008 Jouni Malinen * Copyright 2008 Colin McCabe * Copyright 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -183,18 +183,27 @@ * * By setting @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK flag drivers * can indicate they support offloading EAPOL handshakes for WPA/WPA2 - * preshared key authentication. In %NL80211_CMD_CONNECT the preshared - * key should be specified using %NL80211_ATTR_PMK. Drivers supporting - * this offload may reject the %NL80211_CMD_CONNECT when no preshared - * key material is provided, for example when that driver does not - * support setting the temporal keys through %CMD_NEW_KEY. + * preshared key authentication in station mode. In %NL80211_CMD_CONNECT + * the preshared key should be specified using %NL80211_ATTR_PMK. Drivers + * supporting this offload may reject the %NL80211_CMD_CONNECT when no + * preshared key material is provided, for example when that driver does + * not support setting the temporal keys through %NL80211_CMD_NEW_KEY. * * Similarly @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X flag can be * set by drivers indicating offload support of the PTK/GTK EAPOL - * handshakes during 802.1X authentication. In order to use the offload - * the %NL80211_CMD_CONNECT should have %NL80211_ATTR_WANT_1X_4WAY_HS - * attribute flag. Drivers supporting this offload may reject the - * %NL80211_CMD_CONNECT when the attribute flag is not present. + * handshakes during 802.1X authentication in station mode. In order to + * use the offload the %NL80211_CMD_CONNECT should have + * %NL80211_ATTR_WANT_1X_4WAY_HS attribute flag. Drivers supporting this + * offload may reject the %NL80211_CMD_CONNECT when the attribute flag is + * not present. + * + * By setting @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK flag drivers + * can indicate they support offloading EAPOL handshakes for WPA/WPA2 + * preshared key authentication in AP mode. In %NL80211_CMD_START_AP + * the preshared key should be specified using %NL80211_ATTR_PMK. Drivers + * supporting this offload may reject the %NL80211_CMD_START_AP when no + * preshared key material is provided, for example when that driver does + * not support setting the temporal keys through %NL80211_CMD_NEW_KEY. * * For 802.1X the PMK or PMK-R0 are set by providing %NL80211_ATTR_PMK * using %NL80211_CMD_SET_PMK. For offloaded FT support also @@ -243,9 +252,13 @@ * DOC: SAE authentication offload * * By setting @NL80211_EXT_FEATURE_SAE_OFFLOAD flag drivers can indicate they - * support offloading SAE authentication for WPA3-Personal networks. In - * %NL80211_CMD_CONNECT the password for SAE should be specified using - * %NL80211_ATTR_SAE_PASSWORD. + * support offloading SAE authentication for WPA3-Personal networks in station + * mode. Similarly @NL80211_EXT_FEATURE_SAE_OFFLOAD_AP flag can be set by + * drivers indicating the offload support in AP mode. + * + * The password for SAE should be specified using %NL80211_ATTR_SAE_PASSWORD in + * %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP for station and AP mode + * respectively. */ /** @@ -264,6 +277,29 @@ * %NL80211_ATTR_VLAN_ID. */ +/** + * DOC: TID configuration + * + * TID config support can be checked in the %NL80211_ATTR_TID_CONFIG + * attribute given in wiphy capabilities. + * + * The necessary configuration parameters are mentioned in + * &enum nl80211_tid_config_attr and it will be passed to the + * %NL80211_CMD_SET_TID_CONFIG command in %NL80211_ATTR_TID_CONFIG. + * + * If the configuration needs to be applied for specific peer then the MAC + * address of the peer needs to be passed in %NL80211_ATTR_MAC, otherwise the + * configuration will be applied for all the connected peers in the vif except + * any peers that have peer specific configuration for the TID by default; if + * the %NL80211_TID_CONFIG_ATTR_OVERRIDE flag is set, peer specific values + * will be overwritten. + * + * All this configuration is valid only for STA's current connection + * i.e. the configuration will be reset to default when the STA connects back + * after disconnection/roaming, and this configuration will be cleared when + * the interface goes down. + */ + /** * enum nl80211_commands - supported nl80211 commands * @@ -273,13 +309,14 @@ * to get a list of all present wiphys. * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, - * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ (and the - * attributes determining the channel width; this is used for setting - * monitor mode channel), %NL80211_ATTR_WIPHY_RETRY_SHORT, - * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, - * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. - * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL - * instead, the support here is for backward compatibility only. + * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ, + * %NL80211_ATTR_WIPHY_FREQ_OFFSET (and the attributes determining the + * channel width; this is used for setting monitor mode channel), + * %NL80211_ATTR_WIPHY_RETRY_SHORT, %NL80211_ATTR_WIPHY_RETRY_LONG, + * %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, and/or + * %NL80211_ATTR_WIPHY_RTS_THRESHOLD. However, for setting the channel, + * see %NL80211_CMD_SET_CHANNEL instead, the support here is for backward + * compatibility only. * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request * or rename notification. Has attributes %NL80211_ATTR_WIPHY and * %NL80211_ATTR_WIPHY_NAME. @@ -328,7 +365,8 @@ * %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_INACTIVITY_TIMEOUT, * %NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS. * The channel to use can be set on the interface or be given using the - * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width. + * %NL80211_ATTR_WIPHY_FREQ and %NL80211_ATTR_WIPHY_FREQ_OFFSET, and the + * attributes determining channel width. * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP @@ -338,7 +376,7 @@ * @NL80211_CMD_SET_STATION: Set station attributes for station identified by * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the - * the interface identified by %NL80211_ATTR_IFINDEX. + * interface identified by %NL80211_ATTR_IFINDEX. * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC * or, if no MAC address given, all stations, on the interface identified * by %NL80211_ATTR_IFINDEX. %NL80211_ATTR_MGMT_SUBTYPE and @@ -358,7 +396,7 @@ * @NL80211_CMD_DEL_MPATH: Delete a mesh path to the destination given by * %NL80211_ATTR_MAC. * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the - * the interface identified by %NL80211_ATTR_IFINDEX. + * interface identified by %NL80211_ATTR_IFINDEX. * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC * or, if no MAC address given, all mesh paths, on the interface identified * by %NL80211_ATTR_IFINDEX. @@ -513,11 +551,12 @@ * interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify * the SSID (mainly for association, but is included in authentication - * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used - * to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE - * is used to specify the authentication type. %NL80211_ATTR_IE is used to - * define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs) - * to be added to the frame. + * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ + + * %NL80211_ATTR_WIPHY_FREQ_OFFSET is used to specify the frequence of the + * channel in MHz. %NL80211_ATTR_AUTH_TYPE is used to specify the + * authentication type. %NL80211_ATTR_IE is used to define IEs + * (VendorSpecificInfo, but also including RSN IE and FT IEs) to be added + * to the frame. * When used as an event, this reports reception of an Authentication * frame in station and IBSS modes when the local MLME processed the * frame, i.e., it was for the local STA and was received in correct @@ -572,8 +611,9 @@ * requests to connect to a specified network but without separating * auth and assoc steps. For this, you need to specify the SSID in a * %NL80211_ATTR_SSID attribute, and can optionally specify the association - * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, - * %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, + * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, + * %NL80211_ATTR_USE_MFP, %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, + * %NL80211_ATTR_WIPHY_FREQ_OFFSET, %NL80211_ATTR_CONTROL_PORT, * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, * %NL80211_ATTR_CONTROL_PORT_OVER_NL80211, %NL80211_ATTR_MAC_HINT, and @@ -611,13 +651,9 @@ * authentication/association or not receiving a response from the AP. * Non-zero %NL80211_ATTR_STATUS_CODE value is indicated in that case as * well to remain backwards compatible. - * When establishing a security association, drivers that support 4 way - * handshake offload should send %NL80211_CMD_PORT_AUTHORIZED event when - * the 4 way handshake is completed successfully. * @NL80211_CMD_ROAM: Notification indicating the card/driver roamed by itself. - * When a security association was established with the new AP (e.g. if - * the FT protocol was used for roaming or the driver completed the 4 way - * handshake), this event should be followed by an + * When a security association was established on an 802.1X network using + * fast transition, this event should be followed by an * %NL80211_CMD_PORT_AUTHORIZED event. * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify * userspace that a connection was dropped by the AP or due to other @@ -664,6 +700,10 @@ * four bytes for vendor frames including the OUI. The registration * cannot be dropped, but is removed automatically when the netlink * socket is closed. Multiple registrations can be made. + * The %NL80211_ATTR_RECEIVE_MULTICAST flag attribute can be given if + * %NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS is available, in which + * case the registration can also be modified to include/exclude the + * flag, rather than requiring unregistration to change it. * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for * backward compatibility * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This @@ -717,7 +757,8 @@ * of any other interfaces, and other interfaces will again take * precedence when they are used. * - * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface. + * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface + * (no longer supported). * * @NL80211_CMD_SET_MULTICAST_TO_UNICAST: Configure if this AP should perform * multicast to unicast conversion. When enabled, all multicast packets @@ -763,7 +804,7 @@ * various triggers. These triggers can be configured through this * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For * more background information, see - * http://wireless.kernel.org/en/users/Documentation/WoWLAN. + * https://wireless.wiki.kernel.org/en/users/Documentation/WoWLAN. * The @NL80211_CMD_SET_WOWLAN command can also be used as a notification * from the driver reporting the wakeup reason. In this case, the * @NL80211_ATTR_WOWLAN_TRIGGERS attribute will contain the reason @@ -903,7 +944,7 @@ * @NL80211_CMD_SET_COALESCE: Configure coalesce rules or clear existing rules. * * @NL80211_CMD_CHANNEL_SWITCH: Perform a channel switch by announcing the - * the new channel information (Channel Switch Announcement - CSA) + * new channel information (Channel Switch Announcement - CSA) * in the beacon for some time (as defined in the * %NL80211_ATTR_CH_SWITCH_COUNT parameter) and then change to the * new channel. Userspace provides the new channel information (using @@ -1027,13 +1068,11 @@ * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously * configured PMK for the authenticator address identified by * %NL80211_ATTR_MAC. - * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates that the 4 way - * handshake was completed successfully by the driver. The BSSID is - * specified with %NL80211_ATTR_MAC. Drivers that support 4 way handshake - * offload should send this event after indicating 802.11 association with - * %NL80211_CMD_CONNECT or %NL80211_CMD_ROAM. If the 4 way handshake failed - * %NL80211_CMD_DISCONNECT should be indicated instead. - * + * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates an 802.1X FT roam was + * completed successfully. Drivers that support 4 way handshake offload + * should send this event after indicating 802.1X FT assocation with + * %NL80211_CMD_ROAM. If the 4 way handshake failed %NL80211_CMD_DISCONNECT + * should be indicated instead. * @NL80211_CMD_CONTROL_PORT_FRAME: Control Port (e.g. PAE) frame TX request * and RX notification. This command is used both as a request to transmit * a control port frame and as a notification that a control port frame @@ -1082,7 +1121,7 @@ * randomization may be enabled and configured by specifying the * %NL80211_ATTR_MAC and %NL80211_ATTR_MAC_MASK attributes. * If a timeout is requested, use the %NL80211_ATTR_TIMEOUT attribute. - * A u64 cookie for further %NL80211_ATTR_COOKIE use is is returned in + * A u64 cookie for further %NL80211_ATTR_COOKIE use is returned in * the netlink extended ack message. * * To cancel a measurement, close the socket that requested it. @@ -1125,6 +1164,20 @@ * peer MAC address and %NL80211_ATTR_FRAME is used to specify the frame * content. The frame is ethernet data. * + * @NL80211_CMD_SET_TID_CONFIG: Data frame TID specific configuration + * is passed using %NL80211_ATTR_TID_CONFIG attribute. + * + * @NL80211_CMD_UNPROT_BEACON: Unprotected or incorrectly protected Beacon + * frame. This event is used to indicate that a received Beacon frame was + * dropped because it did not include a valid MME MIC while beacon + * protection was enabled (BIGTK configured in station mode). + * + * @NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS: Report TX status of a control + * port frame transmitted with %NL80211_CMD_CONTROL_PORT_FRAME. + * %NL80211_ATTR_COOKIE identifies the TX command and %NL80211_ATTR_FRAME + * includes the contents of the frame. %NL80211_ATTR_ACK flag is included + * if the recipient acknowledged the frame. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -1349,6 +1402,12 @@ enum nl80211_commands { NL80211_CMD_PROBE_MESH_LINK, + NL80211_CMD_SET_TID_CONFIG, + + NL80211_CMD_UNPROT_BEACON, + + NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1394,7 +1453,8 @@ enum nl80211_commands { * of &enum nl80211_chan_width, describing the channel width. See the * documentation of the enum for more information. * @NL80211_ATTR_CENTER_FREQ1: Center frequency of the first part of the - * channel, used for anything but 20 MHz bandwidth + * channel, used for anything but 20 MHz bandwidth. In S1G this is the + * operating channel center frequency. * @NL80211_ATTR_CENTER_FREQ2: Center frequency of the second part of the * channel, used only for 80+80 MHz bandwidth * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ @@ -1459,7 +1519,7 @@ enum nl80211_commands { * rates as defined by IEEE 802.11 7.3.2.2 but without the length * restriction (at most %NL80211_MAX_SUPP_RATES). * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station - * to, or the AP interface the station was originally added to to. + * to, or the AP interface the station was originally added to. * @NL80211_ATTR_STA_INFO: information about a station, part of station info * given for %NL80211_CMD_GET_STATION, nested attribute containing * info as possible, see &enum nl80211_sta_info. @@ -1604,7 +1664,8 @@ enum nl80211_commands { * flag is included, then control port frames are sent over NL80211 instead * using %CMD_CONTROL_PORT_FRAME. If control port routing over NL80211 is * to be used then userspace must also use the %NL80211_ATTR_SOCKET_OWNER - * flag. + * flag. When used with %NL80211_ATTR_CONTROL_PORT_NO_PREAUTH, pre-auth + * frames are not forwared over the control port. * * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. * We recommend using nested, driver-specific attributes within this. @@ -1690,8 +1751,9 @@ enum nl80211_commands { * specify just a single bitrate, which is to be used for the beacon. * The driver must also specify support for this with the extended * features NL80211_EXT_FEATURE_BEACON_RATE_LEGACY, - * NL80211_EXT_FEATURE_BEACON_RATE_HT and - * NL80211_EXT_FEATURE_BEACON_RATE_VHT. + * NL80211_EXT_FEATURE_BEACON_RATE_HT, + * NL80211_EXT_FEATURE_BEACON_RATE_VHT and + * NL80211_EXT_FEATURE_BEACON_RATE_HE. * * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. @@ -2020,10 +2082,10 @@ enum nl80211_commands { * operation). * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information * for the time while performing a channel switch. - * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel - * switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL). - * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel - * switch counters in the probe response (%NL80211_ATTR_PROBE_RESP). + * @NL80211_ATTR_CNTDWN_OFFS_BEACON: An array of offsets (u16) to the channel + * switch or color change counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL). + * @NL80211_ATTR_CNTDWN_OFFS_PRESP: An array of offsets (u16) to the channel + * switch or color change counters in the probe response (%NL80211_ATTR_PROBE_RESP). * * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. * As specified in the &enum nl80211_rxmgmt_flags. @@ -2031,7 +2093,7 @@ enum nl80211_commands { * @NL80211_ATTR_STA_SUPPORTED_CHANNELS: array of supported channels. * * @NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES: array of supported - * supported operating classes. + * operating classes. * * @NL80211_ATTR_HANDLE_DFS: A flag indicating whether user space * controls DFS operation in IBSS mode. If the flag is included in @@ -2309,10 +2371,11 @@ enum nl80211_commands { * * @NL80211_ATTR_PMK: attribute for passing PMK key material. Used with * %NL80211_CMD_SET_PMKSA for the PMKSA identified by %NL80211_ATTR_PMKID. - * For %NL80211_CMD_CONNECT it is used to provide PSK for offloading 4-way - * handshake for WPA/WPA2-PSK networks. For 802.1X authentication it is - * used with %NL80211_CMD_SET_PMK. For offloaded FT support this attribute - * specifies the PMK-R0 if NL80211_ATTR_PMKR0_NAME is included as well. + * For %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP it is used to provide + * PSK for offloading 4-way handshake for WPA/WPA2-PSK networks. For 802.1X + * authentication it is used with %NL80211_CMD_SET_PMK. For offloaded FT + * support this attribute specifies the PMK-R0 if NL80211_ATTR_PMKR0_NAME + * is included as well. * * @NL80211_ATTR_SCHED_SCAN_MULTI: flag attribute which user-space shall use to * indicate that it supports multiple active scheduled scan requests. @@ -2342,7 +2405,7 @@ enum nl80211_commands { * nl80211_txq_stats) * @NL80211_ATTR_TXQ_LIMIT: Total packet limit for the TXQ queues for this phy. * The smaller of this and the memory limit is enforced. - * @NL80211_ATTR_TXQ_MEMORY_LIMIT: Total memory memory limit (in bytes) for the + * @NL80211_ATTR_TXQ_MEMORY_LIMIT: Total memory limit (in bytes) for the * TXQ queues for this phy. The smaller of this and the packet limit is * enforced. * @NL80211_ATTR_TXQ_QUANTUM: TXQ scheduler quantum (bytes). Number of bytes @@ -2400,6 +2463,77 @@ enum nl80211_commands { * @NL80211_ATTR_VLAN_ID: VLAN ID (1..4094) for the station and VLAN group key * (u16). * + * @NL80211_ATTR_HE_BSS_COLOR: nested attribute for BSS Color Settings. + * + * @NL80211_ATTR_IFTYPE_AKM_SUITES: nested array attribute, with each entry + * using attributes from &enum nl80211_iftype_akm_attributes. This + * attribute is sent in a response to %NL80211_CMD_GET_WIPHY indicating + * supported AKM suites capability per interface. AKMs advertised in + * %NL80211_ATTR_AKM_SUITES are default capabilities if AKM suites not + * advertised for a specific interface type. + * + * @NL80211_ATTR_TID_CONFIG: TID specific configuration in a + * nested attribute with &enum nl80211_tid_config_attr sub-attributes; + * on output (in wiphy attributes) it contains only the feature sub- + * attributes. + * + * @NL80211_ATTR_CONTROL_PORT_NO_PREAUTH: disable preauth frame rx on control + * port in order to forward/receive them as ordinary data frames. + * + * @NL80211_ATTR_PMK_LIFETIME: Maximum lifetime for PMKSA in seconds (u32, + * dot11RSNAConfigPMKReauthThreshold; 0 is not a valid value). + * An optional parameter configured through %NL80211_CMD_SET_PMKSA. + * Drivers that trigger roaming need to know the lifetime of the + * configured PMKSA for triggering the full vs. PMKSA caching based + * authentication. This timeout helps authentication methods like SAE, + * where PMK gets updated only by going through a full (new SAE) + * authentication instead of getting updated during an association for EAP + * authentication. No new full authentication within the PMK expiry shall + * result in a disassociation at the end of the lifetime. + * + * @NL80211_ATTR_PMK_REAUTH_THRESHOLD: Reauthentication threshold time, in + * terms of percentage of %NL80211_ATTR_PMK_LIFETIME + * (u8, dot11RSNAConfigPMKReauthThreshold, 1..100). This is an optional + * parameter configured through %NL80211_CMD_SET_PMKSA. Requests the + * driver to trigger a full authentication roam (without PMKSA caching) + * after the reauthentication threshold time, but before the PMK lifetime + * has expired. + * + * Authentication methods like SAE need to be able to generate a new PMKSA + * entry without having to force a disconnection after the PMK timeout. If + * no roaming occurs between the reauth threshold and PMK expiration, + * disassociation is still forced. + * @NL80211_ATTR_RECEIVE_MULTICAST: multicast flag for the + * %NL80211_CMD_REGISTER_FRAME command, see the description there. + * @NL80211_ATTR_WIPHY_FREQ_OFFSET: offset of the associated + * %NL80211_ATTR_WIPHY_FREQ in positive KHz. Only valid when supplied with + * an %NL80211_ATTR_WIPHY_FREQ_OFFSET. + * @NL80211_ATTR_CENTER_FREQ1_OFFSET: Center frequency offset in KHz for the + * first channel segment specified in %NL80211_ATTR_CENTER_FREQ1. + * @NL80211_ATTR_SCAN_FREQ_KHZ: nested attribute with KHz frequencies + * + * @NL80211_ATTR_HE_6GHZ_CAPABILITY: HE 6 GHz Band Capability element (from + * association request when used with NL80211_CMD_NEW_STATION). + * + * @NL80211_ATTR_FILS_DISCOVERY: Optional parameter to configure FILS + * discovery. It is a nested attribute, see + * &enum nl80211_fils_discovery_attributes. + * + * @NL80211_ATTR_UNSOL_BCAST_PROBE_RESP: Optional parameter to configure + * unsolicited broadcast probe response. It is a nested attribute, see + * &enum nl80211_unsol_bcast_probe_resp_attributes. + * + * @NL80211_ATTR_S1G_CAPABILITY: S1G Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * @NL80211_ATTR_S1G_CAPABILITY_MASK: S1G Capability Information element + * override mask. Used with NL80211_ATTR_S1G_CAPABILITY in + * NL80211_CMD_ASSOCIATE or NL80211_CMD_CONNECT. + * + * @NL80211_ATTR_SAE_PWE: Indicates the mechanism(s) allowed for SAE PWE + * derivation in WPA3-Personal networks which are using SAE authentication. + * This is a u8 attribute that encapsulates one of the values from + * &enum nl80211_sae_pwe_mechanism. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use @@ -2706,8 +2840,8 @@ enum nl80211_attrs { NL80211_ATTR_CH_SWITCH_COUNT, NL80211_ATTR_CH_SWITCH_BLOCK_TX, NL80211_ATTR_CSA_IES, - NL80211_ATTR_CSA_C_OFF_BEACON, - NL80211_ATTR_CSA_C_OFF_PRESP, + NL80211_ATTR_CNTDWN_OFFS_BEACON, + NL80211_ATTR_CNTDWN_OFFS_PRESP, NL80211_ATTR_RXMGMT_FLAGS, @@ -2864,6 +2998,33 @@ enum nl80211_attrs { NL80211_ATTR_VLAN_ID, + NL80211_ATTR_HE_BSS_COLOR, + + NL80211_ATTR_IFTYPE_AKM_SUITES, + + NL80211_ATTR_TID_CONFIG, + + NL80211_ATTR_CONTROL_PORT_NO_PREAUTH, + + NL80211_ATTR_PMK_LIFETIME, + NL80211_ATTR_PMK_REAUTH_THRESHOLD, + + NL80211_ATTR_RECEIVE_MULTICAST, + NL80211_ATTR_WIPHY_FREQ_OFFSET, + NL80211_ATTR_CENTER_FREQ1_OFFSET, + NL80211_ATTR_SCAN_FREQ_KHZ, + + NL80211_ATTR_HE_6GHZ_CAPABILITY, + + NL80211_ATTR_FILS_DISCOVERY, + + NL80211_ATTR_UNSOL_BCAST_PROBE_RESP, + + NL80211_ATTR_S1G_CAPABILITY, + NL80211_ATTR_S1G_CAPABILITY_MASK, + + NL80211_ATTR_SAE_PWE, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -2876,6 +3037,8 @@ enum nl80211_attrs { #define NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG #define NL80211_ATTR_IFACE_SOCKET_OWNER NL80211_ATTR_SOCKET_OWNER #define NL80211_ATTR_SAE_DATA NL80211_ATTR_AUTH_DATA +#define NL80211_ATTR_CSA_C_OFF_BEACON NL80211_ATTR_CNTDWN_OFFS_BEACON +#define NL80211_ATTR_CSA_C_OFF_PRESP NL80211_ATTR_CNTDWN_OFFS_PRESP /* * Allow user space programs to use #ifdef on new attributes by defining them @@ -3053,6 +3216,18 @@ enum nl80211_he_gi { NL80211_RATE_INFO_HE_GI_3_2, }; +/** + * enum nl80211_he_ltf - HE long training field + * @NL80211_RATE_INFO_HE_1xLTF: 3.2 usec + * @NL80211_RATE_INFO_HE_2xLTF: 6.4 usec + * @NL80211_RATE_INFO_HE_4xLTF: 12.8 usec + */ +enum nl80211_he_ltf { + NL80211_RATE_INFO_HE_1XLTF, + NL80211_RATE_INFO_HE_2XLTF, + NL80211_RATE_INFO_HE_4XLTF, +}; + /** * enum nl80211_he_ru_alloc - HE RU allocation values * @NL80211_RATE_INFO_HE_RU_ALLOC_26: 26-tone RU allocation @@ -3247,6 +3422,8 @@ enum nl80211_sta_bss_param { * @NL80211_STA_INFO_AIRTIME_LINK_METRIC: airtime link metric for mesh station * @NL80211_STA_INFO_ASSOC_AT_BOOTTIME: Timestamp (CLOCK_BOOTTIME, nanoseconds) * of STA's association + * @NL80211_STA_INFO_CONNECTED_TO_AS: set to true if STA has a path to a + * authentication server (u8, 0 or 1) * @__NL80211_STA_INFO_AFTER_LAST: internal * @NL80211_STA_INFO_MAX: highest possible station info attribute */ @@ -3294,6 +3471,7 @@ enum nl80211_sta_info { NL80211_STA_INFO_AIRTIME_WEIGHT, NL80211_STA_INFO_AIRTIME_LINK_METRIC, NL80211_STA_INFO_ASSOC_AT_BOOTTIME, + NL80211_STA_INFO_CONNECTED_TO_AS, /* keep last */ __NL80211_STA_INFO_AFTER_LAST, @@ -3442,6 +3620,8 @@ enum nl80211_mpath_info { * defined in HE capabilities IE * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band HE capability attribute currently * defined + * @NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA: HE 6GHz band capabilities (__le16), + * given for all 6 GHz band channels * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use */ enum nl80211_band_iftype_attr { @@ -3452,6 +3632,7 @@ enum nl80211_band_iftype_attr { NL80211_BAND_IFTYPE_ATTR_HE_CAP_PHY, NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, + NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, /* keep last */ __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, @@ -3583,6 +3764,19 @@ enum nl80211_wmm_rule { * @NL80211_FREQUENCY_ATTR_WMM: this channel has wmm limitations. * This is a nested attribute that contains the wmm limitation per AC. * (see &enum nl80211_wmm_rule) + * @NL80211_FREQUENCY_ATTR_NO_HE: HE operation is not allowed on this channel + * in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_OFFSET: frequency offset in KHz + * @NL80211_FREQUENCY_ATTR_1MHZ: 1 MHz operation is allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_2MHZ: 2 MHz operation is allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_4MHZ: 4 MHz operation is allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_8MHZ: 8 MHz operation is allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_16MHZ: 16 MHz operation is allowed + * on this channel in current regulatory domain. * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number * currently defined * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use @@ -3612,6 +3806,13 @@ enum nl80211_frequency_attr { NL80211_FREQUENCY_ATTR_NO_20MHZ, NL80211_FREQUENCY_ATTR_NO_10MHZ, NL80211_FREQUENCY_ATTR_WMM, + NL80211_FREQUENCY_ATTR_NO_HE, + NL80211_FREQUENCY_ATTR_OFFSET, + NL80211_FREQUENCY_ATTR_1MHZ, + NL80211_FREQUENCY_ATTR_2MHZ, + NL80211_FREQUENCY_ATTR_4MHZ, + NL80211_FREQUENCY_ATTR_8MHZ, + NL80211_FREQUENCY_ATTR_16MHZ, /* keep last */ __NL80211_FREQUENCY_ATTR_AFTER_LAST, @@ -3809,6 +4010,7 @@ enum nl80211_sched_scan_match_attr { * @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed + * @NL80211_RRF_NO_HE: HE operation not allowed */ enum nl80211_reg_rule_flags { NL80211_RRF_NO_OFDM = 1<<0, @@ -3826,6 +4028,7 @@ enum nl80211_reg_rule_flags { NL80211_RRF_NO_HT40PLUS = 1<<14, NL80211_RRF_NO_80MHZ = 1<<15, NL80211_RRF_NO_160MHZ = 1<<16, + NL80211_RRF_NO_HE = 1<<17, }; #define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR @@ -3903,6 +4106,7 @@ enum nl80211_user_reg_hint_type { * receiving frames destined to the local BSS * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number * currently defined + * @NL80211_SURVEY_INFO_FREQUENCY_OFFSET: center frequency offset in KHz * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use */ enum nl80211_survey_info { @@ -3918,6 +4122,7 @@ enum nl80211_survey_info { NL80211_SURVEY_INFO_TIME_SCAN, NL80211_SURVEY_INFO_PAD, NL80211_SURVEY_INFO_TIME_BSS_RX, + NL80211_SURVEY_INFO_FREQUENCY_OFFSET, /* keep last */ __NL80211_SURVEY_INFO_AFTER_LAST, @@ -4103,6 +4308,16 @@ enum nl80211_mesh_power_mode { * field. If left unset then the mesh formation field will only * advertise such if there is an active root mesh path. * + * @NL80211_MESHCONF_NOLEARN: Try to avoid multi-hop path discovery (e.g. + * PREQ/PREP for HWMP) if the destination is a direct neighbor. Note that + * this might not be the optimal decision as a multi-hop route might be + * better. So if using this setting you will likely also want to disable + * dot11MeshForwarding and use another mesh routing protocol on top. + * + * @NL80211_MESHCONF_CONNECTED_TO_AS: If set to true then this mesh STA + * will advertise that it is connected to a authentication server + * in the mesh formation field. + * * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use */ enum nl80211_meshconf_params { @@ -4136,6 +4351,8 @@ enum nl80211_meshconf_params { NL80211_MESHCONF_AWAKE_WINDOW, NL80211_MESHCONF_PLINK_TIMEOUT, NL80211_MESHCONF_CONNECTED_TO_GATE, + NL80211_MESHCONF_NOLEARN, + NL80211_MESHCONF_CONNECTED_TO_AS, /* keep last */ __NL80211_MESHCONF_ATTR_AFTER_LAST, @@ -4304,6 +4521,11 @@ enum nl80211_key_mode { * attribute must be provided as well * @NL80211_CHAN_WIDTH_5: 5 MHz OFDM channel * @NL80211_CHAN_WIDTH_10: 10 MHz OFDM channel + * @NL80211_CHAN_WIDTH_1: 1 MHz OFDM channel + * @NL80211_CHAN_WIDTH_2: 2 MHz OFDM channel + * @NL80211_CHAN_WIDTH_4: 4 MHz OFDM channel + * @NL80211_CHAN_WIDTH_8: 8 MHz OFDM channel + * @NL80211_CHAN_WIDTH_16: 16 MHz OFDM channel */ enum nl80211_chan_width { NL80211_CHAN_WIDTH_20_NOHT, @@ -4314,6 +4536,11 @@ enum nl80211_chan_width { NL80211_CHAN_WIDTH_160, NL80211_CHAN_WIDTH_5, NL80211_CHAN_WIDTH_10, + NL80211_CHAN_WIDTH_1, + NL80211_CHAN_WIDTH_2, + NL80211_CHAN_WIDTH_4, + NL80211_CHAN_WIDTH_8, + NL80211_CHAN_WIDTH_16, }; /** @@ -4324,11 +4551,15 @@ enum nl80211_chan_width { * @NL80211_BSS_CHAN_WIDTH_20: control channel is 20 MHz wide or compatible * @NL80211_BSS_CHAN_WIDTH_10: control channel is 10 MHz wide * @NL80211_BSS_CHAN_WIDTH_5: control channel is 5 MHz wide + * @NL80211_BSS_CHAN_WIDTH_1: control channel is 1 MHz wide + * @NL80211_BSS_CHAN_WIDTH_2: control channel is 2 MHz wide */ enum nl80211_bss_scan_width { NL80211_BSS_CHAN_WIDTH_20, NL80211_BSS_CHAN_WIDTH_10, NL80211_BSS_CHAN_WIDTH_5, + NL80211_BSS_CHAN_WIDTH_1, + NL80211_BSS_CHAN_WIDTH_2, }; /** @@ -4380,6 +4611,7 @@ enum nl80211_bss_scan_width { * @NL80211_BSS_CHAIN_SIGNAL: per-chain signal strength of last BSS update. * Contains a nested array of signal strength attributes (u8, dBm), * using the nesting index as the antenna number. + * @NL80211_BSS_FREQUENCY_OFFSET: frequency offset in KHz * @__NL80211_BSS_AFTER_LAST: internal * @NL80211_BSS_MAX: highest BSS attribute */ @@ -4404,6 +4636,7 @@ enum nl80211_bss { NL80211_BSS_PARENT_TSF, NL80211_BSS_PARENT_BSSID, NL80211_BSS_CHAIN_SIGNAL, + NL80211_BSS_FREQUENCY_OFFSET, /* keep last */ __NL80211_BSS_AFTER_LAST, @@ -4532,6 +4765,7 @@ enum nl80211_key_default_types { * See &enum nl80211_key_default_types. * @NL80211_KEY_MODE: the mode from enum nl80211_key_mode. * Defaults to @NL80211_KEY_RX_TX. + * @NL80211_KEY_DEFAULT_BEACON: flag indicating default Beacon frame key * * @__NL80211_KEY_AFTER_LAST: internal * @NL80211_KEY_MAX: highest key attribute @@ -4547,6 +4781,7 @@ enum nl80211_key_attributes { NL80211_KEY_TYPE, NL80211_KEY_DEFAULT_TYPES, NL80211_KEY_MODE, + NL80211_KEY_DEFAULT_BEACON, /* keep last */ __NL80211_KEY_AFTER_LAST, @@ -4565,6 +4800,10 @@ enum nl80211_key_attributes { * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection, * see &struct nl80211_txrate_vht * @NL80211_TXRATE_GI: configure GI, see &enum nl80211_txrate_gi + * @NL80211_TXRATE_HE: HE rates allowed for TX rate selection, + * see &struct nl80211_txrate_he + * @NL80211_TXRATE_HE_GI: configure HE GI, 0.8us, 1.6us and 3.2us. + * @NL80211_TXRATE_HE_LTF: configure HE LTF, 1XLTF, 2XLTF and 4XLTF. * @__NL80211_TXRATE_AFTER_LAST: internal * @NL80211_TXRATE_MAX: highest TX rate attribute */ @@ -4574,6 +4813,9 @@ enum nl80211_tx_rate_attributes { NL80211_TXRATE_HT, NL80211_TXRATE_VHT, NL80211_TXRATE_GI, + NL80211_TXRATE_HE, + NL80211_TXRATE_HE_GI, + NL80211_TXRATE_HE_LTF, /* keep last */ __NL80211_TXRATE_AFTER_LAST, @@ -4591,6 +4833,15 @@ struct nl80211_txrate_vht { __u16 mcs[NL80211_VHT_NSS_MAX]; }; +#define NL80211_HE_NSS_MAX 8 +/** + * struct nl80211_txrate_he - HE MCS/NSS txrate bitmap + * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.) + */ +struct nl80211_txrate_he { + __u16 mcs[NL80211_HE_NSS_MAX]; +}; + enum nl80211_txrate_gi { NL80211_TXRATE_DEFAULT_GI, NL80211_TXRATE_FORCE_SGI, @@ -4603,6 +4854,7 @@ enum nl80211_txrate_gi { * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz) * @NL80211_BAND_6GHZ: around 6 GHz band (5.9 - 7.2 GHz) + * @NL80211_BAND_S1GHZ: around 900MHz, supported by S1G PHYs * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace * since newer kernel versions may support more bands */ @@ -4611,6 +4863,7 @@ enum nl80211_band { NL80211_BAND_5GHZ, NL80211_BAND_60GHZ, NL80211_BAND_6GHZ, + NL80211_BAND_S1GHZ, NUM_NL80211_BANDS, }; @@ -4702,6 +4955,92 @@ enum nl80211_tx_power_setting { NL80211_TX_POWER_FIXED, }; +/** + * enum nl80211_tid_config - TID config state + * @NL80211_TID_CONFIG_ENABLE: Enable config for the TID + * @NL80211_TID_CONFIG_DISABLE: Disable config for the TID + */ +enum nl80211_tid_config { + NL80211_TID_CONFIG_ENABLE, + NL80211_TID_CONFIG_DISABLE, +}; + +/* enum nl80211_tx_rate_setting - TX rate configuration type + * @NL80211_TX_RATE_AUTOMATIC: automatically determine TX rate + * @NL80211_TX_RATE_LIMITED: limit the TX rate by the TX rate parameter + * @NL80211_TX_RATE_FIXED: fix TX rate to the TX rate parameter + */ +enum nl80211_tx_rate_setting { + NL80211_TX_RATE_AUTOMATIC, + NL80211_TX_RATE_LIMITED, + NL80211_TX_RATE_FIXED, +}; + +/* enum nl80211_tid_config_attr - TID specific configuration. + * @NL80211_TID_CONFIG_ATTR_PAD: pad attribute for 64-bit values + * @NL80211_TID_CONFIG_ATTR_VIF_SUPP: a bitmap (u64) of attributes supported + * for per-vif configuration; doesn't list the ones that are generic + * (%NL80211_TID_CONFIG_ATTR_TIDS, %NL80211_TID_CONFIG_ATTR_OVERRIDE). + * @NL80211_TID_CONFIG_ATTR_PEER_SUPP: same as the previous per-vif one, but + * per peer instead. + * @NL80211_TID_CONFIG_ATTR_OVERRIDE: flag attribue, if set indicates + * that the new configuration overrides all previous peer + * configurations, otherwise previous peer specific configurations + * should be left untouched. + * @NL80211_TID_CONFIG_ATTR_TIDS: a bitmask value of TIDs (bit 0 to 7) + * Its type is u16. + * @NL80211_TID_CONFIG_ATTR_NOACK: Configure ack policy for the TID. + * specified in %NL80211_TID_CONFIG_ATTR_TID. see %enum nl80211_tid_config. + * Its type is u8. + * @NL80211_TID_CONFIG_ATTR_RETRY_SHORT: Number of retries used with data frame + * transmission, user-space sets this configuration in + * &NL80211_CMD_SET_TID_CONFIG. It is u8 type, min value is 1 and + * the max value is advertised by the driver in this attribute on + * output in wiphy capabilities. + * @NL80211_TID_CONFIG_ATTR_RETRY_LONG: Number of retries used with data frame + * transmission, user-space sets this configuration in + * &NL80211_CMD_SET_TID_CONFIG. Its type is u8, min value is 1 and + * the max value is advertised by the driver in this attribute on + * output in wiphy capabilities. + * @NL80211_TID_CONFIG_ATTR_AMPDU_CTRL: Enable/Disable MPDU aggregation + * for the TIDs specified in %NL80211_TID_CONFIG_ATTR_TIDS. + * Its type is u8, using the values from &nl80211_tid_config. + * @NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL: Enable/Disable RTS_CTS for the TIDs + * specified in %NL80211_TID_CONFIG_ATTR_TIDS. It is u8 type, using + * the values from &nl80211_tid_config. + * @NL80211_TID_CONFIG_ATTR_AMSDU_CTRL: Enable/Disable MSDU aggregation + * for the TIDs specified in %NL80211_TID_CONFIG_ATTR_TIDS. + * Its type is u8, using the values from &nl80211_tid_config. + * @NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE: This attribute will be useful + * to notfiy the driver that what type of txrate should be used + * for the TIDs specified in %NL80211_TID_CONFIG_ATTR_TIDS. using + * the values form &nl80211_tx_rate_setting. + * @NL80211_TID_CONFIG_ATTR_TX_RATE: Data frame TX rate mask should be applied + * with the parameters passed through %NL80211_ATTR_TX_RATES. + * configuration is applied to the data frame for the tid to that connected + * station. + */ +enum nl80211_tid_config_attr { + __NL80211_TID_CONFIG_ATTR_INVALID, + NL80211_TID_CONFIG_ATTR_PAD, + NL80211_TID_CONFIG_ATTR_VIF_SUPP, + NL80211_TID_CONFIG_ATTR_PEER_SUPP, + NL80211_TID_CONFIG_ATTR_OVERRIDE, + NL80211_TID_CONFIG_ATTR_TIDS, + NL80211_TID_CONFIG_ATTR_NOACK, + NL80211_TID_CONFIG_ATTR_RETRY_SHORT, + NL80211_TID_CONFIG_ATTR_RETRY_LONG, + NL80211_TID_CONFIG_ATTR_AMPDU_CTRL, + NL80211_TID_CONFIG_ATTR_RTSCTS_CTRL, + NL80211_TID_CONFIG_ATTR_AMSDU_CTRL, + NL80211_TID_CONFIG_ATTR_TX_RATE_TYPE, + NL80211_TID_CONFIG_ATTR_TX_RATE, + + /* keep last */ + __NL80211_TID_CONFIG_ATTR_AFTER_LAST, + NL80211_TID_CONFIG_ATTR_MAX = __NL80211_TID_CONFIG_ATTR_AFTER_LAST - 1 +}; + /** * enum nl80211_packet_pattern_attr - packet pattern attribute * @__NL80211_PKTPAT_INVALID: invalid number for nested attribute @@ -5173,6 +5512,8 @@ enum plink_actions { #define NL80211_KCK_LEN 16 #define NL80211_KEK_LEN 16 +#define NL80211_KCK_EXT_LEN 24 +#define NL80211_KEK_EXT_LEN 32 #define NL80211_REPLAY_CTR_LEN 8 /** @@ -5181,6 +5522,7 @@ enum plink_actions { * @NL80211_REKEY_DATA_KEK: key encryption key (binary) * @NL80211_REKEY_DATA_KCK: key confirmation key (binary) * @NL80211_REKEY_DATA_REPLAY_CTR: replay counter (binary) + * @NL80211_REKEY_DATA_AKM: AKM data (OUI, suite type) * @NUM_NL80211_REKEY_DATA: number of rekey attributes (internal) * @MAX_NL80211_REKEY_DATA: highest rekey attribute (internal) */ @@ -5189,6 +5531,7 @@ enum nl80211_rekey_data { NL80211_REKEY_DATA_KEK, NL80211_REKEY_DATA_KCK, NL80211_REKEY_DATA_REPLAY_CTR, + NL80211_REKEY_DATA_AKM, /* keep last */ NUM_NL80211_REKEY_DATA, @@ -5409,7 +5752,7 @@ enum nl80211_feature_flags { * enum nl80211_ext_feature_index - bit index of extended features. * @NL80211_EXT_FEATURE_VHT_IBSS: This driver supports IBSS with VHT datarates. * @NL80211_EXT_FEATURE_RRM: This driver supports RRM. When featured, user can - * can request to use RRM (see %NL80211_ATTR_USE_RRM) with + * request to use RRM (see %NL80211_ATTR_USE_RRM) with * %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests, which will set * the ASSOC_REQ_USE_RRM flag in the association request even if * NL80211_FEATURE_QUIET is not advertized. @@ -5517,6 +5860,54 @@ enum nl80211_feature_flags { * with VLAN tagged frames and separate VLAN-specific netdevs added using * vconfig similarly to the Ethernet case. * + * @NL80211_EXT_FEATURE_AQL: The driver supports the Airtime Queue Limit (AQL) + * feature, which prevents bufferbloat by using the expected transmission + * time to limit the amount of data buffered in the hardware. + * + * @NL80211_EXT_FEATURE_BEACON_PROTECTION: The driver supports Beacon protection + * and can receive key configuration for BIGTK using key indexes 6 and 7. + * @NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT: The driver supports Beacon + * protection as a client only and cannot transmit protected beacons. + * + * @NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH: The driver can disable the + * forwarding of preauth frames over the control port. They are then + * handled as ordinary data frames. + * + * @NL80211_EXT_FEATURE_PROTECTED_TWT: Driver supports protected TWT frames + * + * @NL80211_EXT_FEATURE_DEL_IBSS_STA: The driver supports removing stations + * in IBSS mode, essentially by dropping their state. + * + * @NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS: management frame registrations + * are possible for multicast frames and those will be reported properly. + * + * @NL80211_EXT_FEATURE_SCAN_FREQ_KHZ: This driver supports receiving and + * reporting scan request with %NL80211_ATTR_SCAN_FREQ_KHZ. In order to + * report %NL80211_ATTR_SCAN_FREQ_KHZ, %NL80211_SCAN_FLAG_FREQ_KHZ must be + * included in the scan request. + * + * @NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS: The driver + * can report tx status for control port over nl80211 tx operations. + * + * @NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION: Driver supports Operating + * Channel Validation (OCV) when using driver's SME for RSNA handshakes. + * + * @NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK: Device wants to do 4-way + * handshake with PSK in AP mode (PSK is passed as part of the start AP + * command). + * + * @NL80211_EXT_FEATURE_SAE_OFFLOAD_AP: Device wants to do SAE authentication + * in AP mode (SAE password is passed as part of the start AP command). + * + * @NL80211_EXT_FEATURE_FILS_DISCOVERY: Driver/device supports FILS discovery + * frames transmission + * + * @NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP: Driver/device supports + * unsolicited broadcast probe response transmission + * + * @NL80211_EXT_FEATURE_BEACON_RATE_HE: Driver supports beacon rate + * configuration (AP/mesh) with HE rates. + * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. */ @@ -5563,6 +5954,21 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_STA_TX_PWR, NL80211_EXT_FEATURE_SAE_OFFLOAD, NL80211_EXT_FEATURE_VLAN_OFFLOAD, + NL80211_EXT_FEATURE_AQL, + NL80211_EXT_FEATURE_BEACON_PROTECTION, + NL80211_EXT_FEATURE_CONTROL_PORT_NO_PREAUTH, + NL80211_EXT_FEATURE_PROTECTED_TWT, + NL80211_EXT_FEATURE_DEL_IBSS_STA, + NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS, + NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT, + NL80211_EXT_FEATURE_SCAN_FREQ_KHZ, + NL80211_EXT_FEATURE_CONTROL_PORT_OVER_NL80211_TX_STATUS, + NL80211_EXT_FEATURE_OPERATING_CHANNEL_VALIDATION, + NL80211_EXT_FEATURE_4WAY_HANDSHAKE_AP_PSK, + NL80211_EXT_FEATURE_SAE_OFFLOAD_AP, + NL80211_EXT_FEATURE_FILS_DISCOVERY, + NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP, + NL80211_EXT_FEATURE_BEACON_RATE_HE, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, @@ -5674,6 +6080,11 @@ enum nl80211_timeout_reason { * @NL80211_SCAN_FLAG_MIN_PREQ_CONTENT: minimize probe request content to * only have supported rates and no additional capabilities (unless * added by userspace explicitly.) + * @NL80211_SCAN_FLAG_FREQ_KHZ: report scan results with + * %NL80211_ATTR_SCAN_FREQ_KHZ. This also means + * %NL80211_ATTR_SCAN_FREQUENCIES will not be included. + * @NL80211_SCAN_FLAG_COLOCATED_6GHZ: scan for colocated APs reported by + * 2.4/5 GHz APs */ enum nl80211_scan_flags { NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, @@ -5689,6 +6100,8 @@ enum nl80211_scan_flags { NL80211_SCAN_FLAG_HIGH_ACCURACY = 1<<10, NL80211_SCAN_FLAG_RANDOM_SN = 1<<11, NL80211_SCAN_FLAG_MIN_PREQ_CONTENT = 1<<12, + NL80211_SCAN_FLAG_FREQ_KHZ = 1<<13, + NL80211_SCAN_FLAG_COLOCATED_6GHZ = 1<<14, }; /** @@ -5776,7 +6189,7 @@ enum nl80211_dfs_state { }; /** - * enum enum nl80211_protocol_features - nl80211 protocol features + * enum nl80211_protocol_features - nl80211 protocol features * @NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: nl80211 supports splitting * wiphy dumps (if requested by the application with the attribute * %NL80211_ATTR_SPLIT_WIPHY_DUMP. Also supported is filtering the @@ -6185,12 +6598,14 @@ enum nl80211_ftm_responder_stats { * @NL80211_PREAMBLE_HT: HT preamble * @NL80211_PREAMBLE_VHT: VHT preamble * @NL80211_PREAMBLE_DMG: DMG preamble + * @NL80211_PREAMBLE_HE: HE preamble */ enum nl80211_preamble { NL80211_PREAMBLE_LEGACY, NL80211_PREAMBLE_HT, NL80211_PREAMBLE_VHT, NL80211_PREAMBLE_DMG, + NL80211_PREAMBLE_HE, }; /** @@ -6383,6 +6798,10 @@ enum nl80211_peer_measurement_attrs { * is valid) * @NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST: u32 attribute indicating * the maximum FTMs per burst (if not present anything is valid) + * @NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED: flag attribute indicating if + * trigger based ranging measurement is supported + * @NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED: flag attribute indicating + * if non trigger based ranging measurement is supported * * @NUM_NL80211_PMSR_FTM_CAPA_ATTR: internal * @NL80211_PMSR_FTM_CAPA_ATTR_MAX: highest attribute number @@ -6398,6 +6817,8 @@ enum nl80211_peer_measurement_ftm_capa { NL80211_PMSR_FTM_CAPA_ATTR_BANDWIDTHS, NL80211_PMSR_FTM_CAPA_ATTR_MAX_BURSTS_EXPONENT, NL80211_PMSR_FTM_CAPA_ATTR_MAX_FTMS_PER_BURST, + NL80211_PMSR_FTM_CAPA_ATTR_TRIGGER_BASED, + NL80211_PMSR_FTM_CAPA_ATTR_NON_TRIGGER_BASED, /* keep last */ NUM_NL80211_PMSR_FTM_CAPA_ATTR, @@ -6427,6 +6848,20 @@ enum nl80211_peer_measurement_ftm_capa { * @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI: request LCI data (flag) * @NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC: request civic location data * (flag) + * @NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED: request trigger based ranging + * measurement (flag). + * This attribute and %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED are + * mutually exclusive. + * if neither %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED nor + * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set, EDCA based + * ranging will be used. + * @NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED: request non trigger based + * ranging measurement (flag) + * This attribute and %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED are + * mutually exclusive. + * if neither %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED nor + * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set, EDCA based + * ranging will be used. * * @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal * @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number @@ -6443,6 +6878,8 @@ enum nl80211_peer_measurement_ftm_req { NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES, NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI, NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC, + NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED, + NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED, /* keep last */ NUM_NL80211_PMSR_FTM_REQ_ATTR, @@ -6567,6 +7004,13 @@ enum nl80211_peer_measurement_ftm_resp { * * @NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET: the OBSS PD minimum tx power offset. * @NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET: the OBSS PD maximum tx power offset. + * @NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET: the non-SRG OBSS PD maximum + * tx power offset. + * @NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP: bitmap that indicates the BSS color + * values used by members of the SRG. + * @NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP: bitmap that indicates the partial + * BSSID values used by members of the SRG. + * @NL80211_HE_OBSS_PD_ATTR_SR_CTRL: The SR Control field of SRP element. * * @__NL80211_HE_OBSS_PD_ATTR_LAST: Internal * @NL80211_HE_OBSS_PD_ATTR_MAX: highest OBSS PD attribute. @@ -6576,11 +7020,140 @@ enum nl80211_obss_pd_attributes { NL80211_HE_OBSS_PD_ATTR_MIN_OFFSET, NL80211_HE_OBSS_PD_ATTR_MAX_OFFSET, + NL80211_HE_OBSS_PD_ATTR_NON_SRG_MAX_OFFSET, + NL80211_HE_OBSS_PD_ATTR_BSS_COLOR_BITMAP, + NL80211_HE_OBSS_PD_ATTR_PARTIAL_BSSID_BITMAP, + NL80211_HE_OBSS_PD_ATTR_SR_CTRL, /* keep last */ __NL80211_HE_OBSS_PD_ATTR_LAST, NL80211_HE_OBSS_PD_ATTR_MAX = __NL80211_HE_OBSS_PD_ATTR_LAST - 1, }; +/** + * enum nl80211_bss_color_attributes - BSS Color attributes + * @__NL80211_HE_BSS_COLOR_ATTR_INVALID: Invalid + * + * @NL80211_HE_BSS_COLOR_ATTR_COLOR: the current BSS Color. + * @NL80211_HE_BSS_COLOR_ATTR_DISABLED: is BSS coloring disabled. + * @NL80211_HE_BSS_COLOR_ATTR_PARTIAL: the AID equation to be used.. + * + * @__NL80211_HE_BSS_COLOR_ATTR_LAST: Internal + * @NL80211_HE_BSS_COLOR_ATTR_MAX: highest BSS Color attribute. + */ +enum nl80211_bss_color_attributes { + __NL80211_HE_BSS_COLOR_ATTR_INVALID, + NL80211_HE_BSS_COLOR_ATTR_COLOR, + NL80211_HE_BSS_COLOR_ATTR_DISABLED, + NL80211_HE_BSS_COLOR_ATTR_PARTIAL, + + /* keep last */ + __NL80211_HE_BSS_COLOR_ATTR_LAST, + NL80211_HE_BSS_COLOR_ATTR_MAX = __NL80211_HE_BSS_COLOR_ATTR_LAST - 1, +}; + +/** + * enum nl80211_iftype_akm_attributes - interface type AKM attributes + * @__NL80211_IFTYPE_AKM_ATTR_INVALID: Invalid + * + * @NL80211_IFTYPE_AKM_ATTR_IFTYPES: nested attribute containing a flag + * attribute for each interface type that supports AKM suites specified in + * %NL80211_IFTYPE_AKM_ATTR_SUITES + * @NL80211_IFTYPE_AKM_ATTR_SUITES: an array of u32. Used to indicate supported + * AKM suites for the specified interface types. + * + * @__NL80211_IFTYPE_AKM_ATTR_LAST: Internal + * @NL80211_IFTYPE_AKM_ATTR_MAX: highest interface type AKM attribute. + */ +enum nl80211_iftype_akm_attributes { + __NL80211_IFTYPE_AKM_ATTR_INVALID, + + NL80211_IFTYPE_AKM_ATTR_IFTYPES, + NL80211_IFTYPE_AKM_ATTR_SUITES, + + /* keep last */ + __NL80211_IFTYPE_AKM_ATTR_LAST, + NL80211_IFTYPE_AKM_ATTR_MAX = __NL80211_IFTYPE_AKM_ATTR_LAST - 1, +}; + +/** + * enum nl80211_fils_discovery_attributes - FILS discovery configuration + * from IEEE Std 802.11ai-2016, Annex C.3 MIB detail. + * + * @__NL80211_FILS_DISCOVERY_ATTR_INVALID: Invalid + * + * @NL80211_FILS_DISCOVERY_ATTR_INT_MIN: Minimum packet interval (u32, TU). + * Allowed range: 0..10000 (TU = Time Unit) + * @NL80211_FILS_DISCOVERY_ATTR_INT_MAX: Maximum packet interval (u32, TU). + * Allowed range: 0..10000 (TU = Time Unit) + * @NL80211_FILS_DISCOVERY_ATTR_TMPL: Template data for FILS discovery action + * frame including the headers. + * + * @__NL80211_FILS_DISCOVERY_ATTR_LAST: Internal + * @NL80211_FILS_DISCOVERY_ATTR_MAX: highest attribute + */ +enum nl80211_fils_discovery_attributes { + __NL80211_FILS_DISCOVERY_ATTR_INVALID, + + NL80211_FILS_DISCOVERY_ATTR_INT_MIN, + NL80211_FILS_DISCOVERY_ATTR_INT_MAX, + NL80211_FILS_DISCOVERY_ATTR_TMPL, + + /* keep last */ + __NL80211_FILS_DISCOVERY_ATTR_LAST, + NL80211_FILS_DISCOVERY_ATTR_MAX = __NL80211_FILS_DISCOVERY_ATTR_LAST - 1 +}; + +/* + * FILS discovery template minimum length with action frame headers and + * mandatory fields. + */ +#define NL80211_FILS_DISCOVERY_TMPL_MIN_LEN 42 + +/** + * enum nl80211_unsol_bcast_probe_resp_attributes - Unsolicited broadcast probe + * response configuration. Applicable only in 6GHz. + * + * @__NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INVALID: Invalid + * + * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT: Maximum packet interval (u32, TU). + * Allowed range: 0..20 (TU = Time Unit). IEEE P802.11ax/D6.0 + * 26.17.2.3.2 (AP behavior for fast passive scanning). + * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL: Unsolicited broadcast probe response + * frame template (binary). + * + * @__NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST: Internal + * @NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX: highest attribute + */ +enum nl80211_unsol_bcast_probe_resp_attributes { + __NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INVALID, + + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_INT, + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_TMPL, + + /* keep last */ + __NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST, + NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_MAX = + __NL80211_UNSOL_BCAST_PROBE_RESP_ATTR_LAST - 1 +}; + +/** + * enum nl80211_sae_pwe_mechanism - The mechanism(s) allowed for SAE PWE + * derivation. Applicable only when WPA3-Personal SAE authentication is + * used. + * + * @NL80211_SAE_PWE_UNSPECIFIED: not specified, used internally to indicate that + * attribute is not present from userspace. + * @NL80211_SAE_PWE_HUNT_AND_PECK: hunting-and-pecking loop only + * @NL80211_SAE_PWE_HASH_TO_ELEMENT: hash-to-element only + * @NL80211_SAE_PWE_BOTH: both hunting-and-pecking loop and hash-to-element + * can be used. + */ +enum nl80211_sae_pwe_mechanism { + NL80211_SAE_PWE_UNSPECIFIED, + NL80211_SAE_PWE_HUNT_AND_PECK, + NL80211_SAE_PWE_HASH_TO_ELEMENT, + NL80211_SAE_PWE_BOTH, +}; #endif /* __LINUX_NL80211_H */ diff --git a/src/eap_common/Makefile b/src/eap_common/Makefile index f00b438c6..fd058a09a 100644 --- a/src/eap_common/Makefile +++ b/src/eap_common/Makefile @@ -1,13 +1,3 @@ -all: libeap_common.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libeap_common.a - -install: - @echo Nothing to be made. - -include ../lib.rules - LIB_OBJS= \ chap.o \ eap_common.o \ @@ -25,7 +15,4 @@ LIB_OBJS= \ eap_wsc_common.o \ ikev2_common.o -libeap_common.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/eap_peer/.gitignore b/src/eap_peer/.gitignore new file mode 100644 index 000000000..140f8cf80 --- /dev/null +++ b/src/eap_peer/.gitignore @@ -0,0 +1 @@ +*.so diff --git a/src/eap_peer/Makefile b/src/eap_peer/Makefile index 6531ccd5d..bdbead6a6 100644 --- a/src/eap_peer/Makefile +++ b/src/eap_peer/Makefile @@ -1,23 +1,13 @@ -all: libeap_peer.a - -clean: - rm -f *~ *.o *.so *.d *.gcno *.gcda *.gcov libeap_peer.a - -install: - if ls *.so >/dev/null 2>&1; then \ - install -d $(DESTDIR)$(LIBDIR)/wpa_supplicant && \ - cp *.so $(DESTDIR)$(LIBDIR)/wpa_supplicant \ - ; fi - -include ../lib.rules - CFLAGS += -DIEEE8021X_EAPOL LIB_OBJS= \ eap.o \ eap_methods.o -libeap_peer.a: $(LIB_OBJS) - $(AR) crT $@ $? +include ../lib.rules --include $(OBJS:%.o=%.d) +install: + if ls *.so >/dev/null 2>&1; then \ + install -d $(DESTDIR)$(LIBDIR)/wpa_supplicant && \ + cp *.so $(DESTDIR)$(LIBDIR)/wpa_supplicant \ + ; fi diff --git a/src/eap_peer/eap.c b/src/eap_peer/eap.c index c78b21482..74c2ad361 100644 --- a/src/eap_peer/eap.c +++ b/src/eap_peer/eap.c @@ -37,8 +37,8 @@ #define EAP_CLIENT_TIMEOUT_DEFAULT 60 -static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor, - enum eap_type method); +static bool eap_sm_allowMethod(struct eap_sm *sm, int vendor, + enum eap_type method); static struct wpabuf * eap_sm_buildNak(struct eap_sm *sm, int id); static void eap_sm_processIdentity(struct eap_sm *sm, const struct wpabuf *req); @@ -54,14 +54,14 @@ static void eap_sm_request(struct eap_sm *sm, enum wpa_ctrl_req_type field, -static Boolean eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var) +static bool eapol_get_bool(struct eap_sm *sm, enum eapol_bool_var var) { return sm->eapol_cb->get_bool(sm->eapol_ctx, var); } static void eapol_set_bool(struct eap_sm *sm, enum eapol_bool_var var, - Boolean value) + bool value) { sm->eapol_cb->set_bool(sm->eapol_ctx, var, value); } @@ -210,8 +210,8 @@ static int eap_sm_append_3gpp_realm(struct eap_sm *sm, char *imsi, /* * This state initializes state machine variables when the machine is - * activated (portEnabled = TRUE). This is also used when re-starting - * authentication (eapRestart == TRUE). + * activated (portEnabled = true). This is also used when re-starting + * authentication (eapRestart == true). */ SM_STATE(EAP, INITIALIZE) { @@ -229,17 +229,17 @@ SM_STATE(EAP, INITIALIZE) } sm->selectedMethod = EAP_TYPE_NONE; sm->methodState = METHOD_NONE; - sm->allowNotifications = TRUE; + sm->allowNotifications = true; sm->decision = DECISION_FAIL; sm->ClientTimeout = EAP_CLIENT_TIMEOUT_DEFAULT; eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); - eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); - eapol_set_bool(sm, EAPOL_eapFail, FALSE); + eapol_set_bool(sm, EAPOL_eapSuccess, false); + eapol_set_bool(sm, EAPOL_eapFail, false); eap_sm_free_key(sm); os_free(sm->eapSessionId); sm->eapSessionId = NULL; - sm->eapKeyAvailable = FALSE; - eapol_set_bool(sm, EAPOL_eapRestart, FALSE); + sm->eapKeyAvailable = false; + eapol_set_bool(sm, EAPOL_eapRestart, false); sm->lastId = -1; /* new session - make sure this does not match with * the first EAP-Packet */ /* @@ -247,16 +247,16 @@ SM_STATE(EAP, INITIALIZE) * seemed to be able to trigger cases where both were set and if EAPOL * state machine uses eapNoResp first, it may end up not sending a real * reply correctly. This occurred when the workaround in FAIL state set - * eapNoResp = TRUE.. Maybe that workaround needs to be fixed to do + * eapNoResp = true.. Maybe that workaround needs to be fixed to do * something else(?) */ - eapol_set_bool(sm, EAPOL_eapResp, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, FALSE); + eapol_set_bool(sm, EAPOL_eapResp, false); + eapol_set_bool(sm, EAPOL_eapNoResp, false); /* * RFC 4137 does not reset ignore here, but since it is possible for - * some method code paths to end up not setting ignore=FALSE, clear the + * some method code paths to end up not setting ignore=false, clear the * value here to avoid issues if a previous authentication attempt - * failed with ignore=TRUE being left behind in the last + * failed with ignore=true being left behind in the last * m.check(eapReqData) operation. */ sm->ignore = 0; @@ -264,7 +264,7 @@ SM_STATE(EAP, INITIALIZE) sm->num_rounds_short = 0; sm->prev_failure = 0; sm->expected_failure = 0; - sm->reauthInit = FALSE; + sm->reauthInit = false; sm->erp_seq = (u32) -1; sm->use_machine_cred = 0; } @@ -272,7 +272,7 @@ SM_STATE(EAP, INITIALIZE) /* * This state is reached whenever service from the lower layer is interrupted - * or unavailable (portEnabled == FALSE). Immediate transition to INITIALIZE + * or unavailable (portEnabled == false). Immediate transition to INITIALIZE * occurs when the port becomes enabled. */ SM_STATE(EAP, DISABLED) @@ -301,7 +301,7 @@ SM_STATE(EAP, IDLE) /* - * This state is entered when an EAP packet is received (eapReq == TRUE) to + * This state is entered when an EAP packet is received (eapReq == true) to * parse the packet header. */ SM_STATE(EAP, RECEIVED) @@ -866,7 +866,7 @@ static int eap_peer_erp_reauth_start(struct eap_sm *sm, u8 eap_id) wpa_printf(MSG_DEBUG, "EAP: Sending EAP-Initiate/Re-auth"); wpabuf_free(sm->eapRespData); sm->eapRespData = msg; - sm->reauthInit = TRUE; + sm->reauthInit = true; return 0; } #endif /* CONFIG_ERP */ @@ -964,14 +964,14 @@ SM_STATE(EAP, SEND_RESPONSE) os_memcpy(sm->last_sha1, sm->req_sha1, 20); sm->lastId = sm->reqId; sm->lastRespData = wpabuf_dup(sm->eapRespData); - eapol_set_bool(sm, EAPOL_eapResp, TRUE); + eapol_set_bool(sm, EAPOL_eapResp, true); } else { wpa_printf(MSG_DEBUG, "EAP: No eapRespData available"); sm->lastRespData = NULL; } - eapol_set_bool(sm, EAPOL_eapReq, FALSE); + eapol_set_bool(sm, EAPOL_eapReq, false); eapol_set_int(sm, EAPOL_idleWhile, sm->ClientTimeout); - sm->reauthInit = FALSE; + sm->reauthInit = false; } @@ -982,8 +982,8 @@ SM_STATE(EAP, SEND_RESPONSE) SM_STATE(EAP, DISCARD) { SM_ENTRY(EAP, DISCARD); - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); + eapol_set_bool(sm, EAPOL_eapReq, false); + eapol_set_bool(sm, EAPOL_eapNoResp, true); } @@ -1048,15 +1048,15 @@ SM_STATE(EAP, SUCCESS) SM_ENTRY(EAP, SUCCESS); if (sm->eapKeyData != NULL) - sm->eapKeyAvailable = TRUE; - eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); + sm->eapKeyAvailable = true; + eapol_set_bool(sm, EAPOL_eapSuccess, true); /* * RFC 4137 does not clear eapReq here, but this seems to be required * to avoid processing the same request twice when state machine is * initialized. */ - eapol_set_bool(sm, EAPOL_eapReq, FALSE); + eapol_set_bool(sm, EAPOL_eapReq, false); /* * RFC 4137 does not set eapNoResp here, but this seems to be required @@ -1064,7 +1064,7 @@ SM_STATE(EAP, SUCCESS) * addition, either eapResp or eapNoResp is required to be set after * processing the received EAP frame. */ - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); + eapol_set_bool(sm, EAPOL_eapNoResp, true); wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS "EAP authentication completed successfully"); @@ -1083,21 +1083,21 @@ SM_STATE(EAP, SUCCESS) SM_STATE(EAP, FAILURE) { SM_ENTRY(EAP, FAILURE); - eapol_set_bool(sm, EAPOL_eapFail, TRUE); + eapol_set_bool(sm, EAPOL_eapFail, true); /* * RFC 4137 does not clear eapReq here, but this seems to be required * to avoid processing the same request twice when state machine is * initialized. */ - eapol_set_bool(sm, EAPOL_eapReq, FALSE); + eapol_set_bool(sm, EAPOL_eapReq, false); /* * RFC 4137 does not set eapNoResp here. However, either eapResp or * eapNoResp is required to be set after processing the received EAP * frame. */ - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); + eapol_set_bool(sm, EAPOL_eapNoResp, true); wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE "EAP authentication failed"); @@ -1367,19 +1367,19 @@ SM_STEP(EAP) } -static Boolean eap_sm_allowMethod(struct eap_sm *sm, int vendor, - enum eap_type method) +static bool eap_sm_allowMethod(struct eap_sm *sm, int vendor, + enum eap_type method) { if (!eap_allowed_method(sm, vendor, method)) { wpa_printf(MSG_DEBUG, "EAP: configuration does not allow: " "vendor %u method %u", vendor, method); - return FALSE; + return false; } if (eap_peer_get_eap_method(vendor, method)) - return TRUE; + return true; wpa_printf(MSG_DEBUG, "EAP: not included in build: " "vendor %u method %u", vendor, method); - return FALSE; + return false; } @@ -1802,7 +1802,7 @@ invalid: #endif /* CONFIG_ERP */ wpa_printf(MSG_DEBUG, "EAP: EAP-Initiate/Re-auth-Start - No suitable ERP keys available - try to start full EAP authentication"); - eapol_set_bool(sm, EAPOL_eapTriggerStart, TRUE); + eapol_set_bool(sm, EAPOL_eapTriggerStart, true); } @@ -1926,9 +1926,9 @@ no_auth_tag: if (flags & 0x80 || !auth_tag_ok) { wpa_printf(MSG_DEBUG, "EAP: EAP-Finish/Re-auth indicated failure"); - eapol_set_bool(sm, EAPOL_eapFail, TRUE); - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); + eapol_set_bool(sm, EAPOL_eapFail, true); + eapol_set_bool(sm, EAPOL_eapReq, false); + eapol_set_bool(sm, EAPOL_eapNoResp, true); wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE "EAP authentication failed"); sm->prev_failure = 1; @@ -1957,10 +1957,10 @@ no_auth_tag: } wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rMSK", sm->eapKeyData, sm->eapKeyDataLen); - sm->eapKeyAvailable = TRUE; - eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); - eapol_set_bool(sm, EAPOL_eapReq, FALSE); - eapol_set_bool(sm, EAPOL_eapNoResp, TRUE); + sm->eapKeyAvailable = true; + eapol_set_bool(sm, EAPOL_eapSuccess, true); + eapol_set_bool(sm, EAPOL_eapReq, false); + eapol_set_bool(sm, EAPOL_eapNoResp, true); wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS "EAP re-authentication completed successfully"); #endif /* CONFIG_ERP */ @@ -1973,7 +1973,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) size_t plen; const u8 *pos; - sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = FALSE; + sm->rxReq = sm->rxResp = sm->rxSuccess = sm->rxFailure = false; sm->reqId = 0; sm->reqMethod = EAP_TYPE_NONE; sm->reqVendor = EAP_VENDOR_IETF; @@ -2007,7 +2007,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) "no Type field"); return; } - sm->rxReq = TRUE; + sm->rxReq = true; pos = (const u8 *) (hdr + 1); sm->reqMethod = *pos++; if (sm->reqMethod == EAP_TYPE_EXPANDED) { @@ -2038,7 +2038,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) "EAP-Response - no Type field"); return; } - sm->rxResp = TRUE; + sm->rxResp = true; pos = (const u8 *) (hdr + 1); sm->reqMethod = *pos; wpa_printf(MSG_DEBUG, "EAP: Received EAP-Response for " @@ -2051,7 +2051,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) case EAP_CODE_SUCCESS: wpa_printf(MSG_DEBUG, "EAP: Received EAP-Success"); eap_notify_status(sm, "completion", "success"); - sm->rxSuccess = TRUE; + sm->rxSuccess = true; break; case EAP_CODE_FAILURE: wpa_printf(MSG_DEBUG, "EAP: Received EAP-Failure"); @@ -2065,7 +2065,7 @@ static void eap_sm_parseEapReq(struct eap_sm *sm, const struct wpabuf *req) if (error_code != NO_EAP_METHOD_ERROR) eap_report_error(sm, error_code); } - sm->rxFailure = TRUE; + sm->rxFailure = true; break; case EAP_CODE_INITIATE: eap_peer_initiate(sm, hdr, plen); @@ -2233,7 +2233,7 @@ int eap_peer_sm_step(struct eap_sm *sm) { int res = 0; do { - sm->changed = FALSE; + sm->changed = false; SM_STEP_RUN(EAP); if (sm->changed) res = 1; @@ -2262,7 +2262,7 @@ void eap_sm_abort(struct eap_sm *sm) /* This is not clearly specified in the EAP statemachines draft, but * it seems necessary to make sure that some of the EAPOL variables get * cleared for the next authentication. */ - eapol_set_bool(sm, EAPOL_eapSuccess, FALSE); + eapol_set_bool(sm, EAPOL_eapSuccess, false); } @@ -3005,8 +3005,8 @@ void eap_notify_lower_layer_success(struct eap_sm *sm) return; if (sm->eapKeyData != NULL) - sm->eapKeyAvailable = TRUE; - eapol_set_bool(sm, EAPOL_eapSuccess, TRUE); + sm->eapKeyAvailable = true; + eapol_set_bool(sm, EAPOL_eapSuccess, true); wpa_msg(sm->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS "EAP authentication completed successfully (based on lower " "layer success)"); diff --git a/src/eap_peer/eap.h b/src/eap_peer/eap.h index acd70d05d..a40d007d9 100644 --- a/src/eap_peer/eap.h +++ b/src/eap_peer/eap.h @@ -44,7 +44,7 @@ enum eapol_bool_var { /** * EAPOL_eapRestart - Lower layer request to restart authentication * - * Set to TRUE in lower layer, FALSE in EAP state machine. + * Set to true in lower layer, false in EAP state machine. */ EAPOL_eapRestart, @@ -58,21 +58,21 @@ enum eapol_bool_var { /** * EAPOL_eapResp - Response to send * - * Set to TRUE in EAP state machine, FALSE in lower layer. + * Set to true in EAP state machine, false in lower layer. */ EAPOL_eapResp, /** * EAPOL_eapNoResp - Request has been process; no response to send * - * Set to TRUE in EAP state machine, FALSE in lower layer. + * Set to true in EAP state machine, false in lower layer. */ EAPOL_eapNoResp, /** * EAPOL_eapReq - EAP request available from lower layer * - * Set to TRUE in lower layer, FALSE in EAP state machine. + * Set to true in lower layer, false in EAP state machine. */ EAPOL_eapReq, @@ -147,7 +147,7 @@ struct eapol_callbacks { * @variable: EAPOL boolean variable to get * Returns: Value of the EAPOL variable */ - Boolean (*get_bool)(void *ctx, enum eapol_bool_var variable); + bool (*get_bool)(void *ctx, enum eapol_bool_var variable); /** * set_bool - Set a boolean EAPOL state variable @@ -155,8 +155,7 @@ struct eapol_callbacks { * @variable: EAPOL boolean variable to set * @value: Value for the EAPOL variable */ - void (*set_bool)(void *ctx, enum eapol_bool_var variable, - Boolean value); + void (*set_bool)(void *ctx, enum eapol_bool_var variable, bool value); /** * get_int - Get an integer EAPOL state variable diff --git a/src/eap_peer/eap_aka.c b/src/eap_peer/eap_aka.c index d50bc6186..e57461a33 100644 --- a/src/eap_peer/eap_aka.c +++ b/src/eap_peer/eap_aka.c @@ -1365,24 +1365,24 @@ static struct wpabuf * eap_aka_process(struct eap_sm *sm, void *priv, if (eap_get_config_identity(sm, &len) == NULL) { wpa_printf(MSG_INFO, "EAP-AKA: Identity not configured"); eap_sm_request_identity(sm); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_method, reqData, &len); if (pos == NULL || len < 3) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } req = wpabuf_head(reqData); id = req->identifier; len = be_to_host16(req->length); - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; subtype = *pos++; wpa_printf(MSG_DEBUG, "EAP-AKA: Subtype=%d", subtype); @@ -1441,14 +1441,14 @@ done: ret->methodState = METHOD_CONT; if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; + ret->allowNotifications = false; } return res; } -static Boolean eap_aka_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_aka_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_aka_data *data = priv; return data->pseudonym || data->reauth_id; @@ -1497,7 +1497,7 @@ static const u8 * eap_aka_get_identity(struct eap_sm *sm, void *priv, } -static Boolean eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_aka_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_aka_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_eke.c b/src/eap_peer/eap_eke.c index 534af262e..902944270 100644 --- a/src/eap_peer/eap_eke.c +++ b/src/eap_peer/eap_eke.c @@ -211,7 +211,7 @@ static struct wpabuf * eap_eke_build_fail(struct eap_eke_data *data, eap_eke_state(data, FAILURE); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return resp; } @@ -617,7 +617,7 @@ static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data, eap_eke_state(data, SUCCESS); ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return resp; } @@ -656,7 +656,7 @@ static struct wpabuf * eap_eke_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, reqData, &len); if (pos == NULL || len < 1) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -666,10 +666,10 @@ static struct wpabuf * eap_eke_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: exch %d", eke_exch); wpa_hexdump(MSG_DEBUG, "EAP-EKE: Received Data", pos, end - pos); - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; switch (eke_exch) { case EAP_EKE_ID: @@ -689,18 +689,18 @@ static struct wpabuf * eap_eke_process(struct eap_sm *sm, void *priv, break; default: wpa_printf(MSG_DEBUG, "EAP-EKE: Ignoring message with unknown EKE-Exch %d", eke_exch); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (ret->methodState == METHOD_DONE) - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return resp; } -static Boolean eap_eke_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_eke_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_eke_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_fast.c b/src/eap_peer/eap_fast.c index 0ed4a2b70..b12cfee31 100644 --- a/src/eap_peer/eap_fast.c +++ b/src/eap_peer/eap_fast.c @@ -1688,7 +1688,7 @@ static struct wpabuf * eap_fast_process(struct eap_sm *sm, void *priv, #if 0 /* FIX */ -static Boolean eap_fast_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_fast_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_fast_data *data = priv; return tls_connection_established(sm->ssl_ctx, data->ssl.conn); @@ -1754,7 +1754,7 @@ static int eap_fast_get_status(struct eap_sm *sm, void *priv, char *buf, } -static Boolean eap_fast_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_fast_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_fast_data *data = priv; return data->success; diff --git a/src/eap_peer/eap_gpsk.c b/src/eap_peer/eap_gpsk.c index f9c4d3773..20d96c139 100644 --- a/src/eap_peer/eap_gpsk.c +++ b/src/eap_peer/eap_gpsk.c @@ -280,7 +280,7 @@ static struct wpabuf * eap_gpsk_process_gpsk_1(struct eap_sm *sm, struct wpabuf *resp; if (data->state != GPSK_1) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -588,7 +588,7 @@ static struct wpabuf * eap_gpsk_process_gpsk_3(struct eap_sm *sm, const u8 *pos, *end; if (data->state != GPSK_3) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -671,7 +671,7 @@ static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, reqData, &len); if (pos == NULL || len < 1) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -680,10 +680,10 @@ static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, len--; wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", opcode); - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; switch (opcode) { case EAP_GPSK_OPCODE_GPSK_1: @@ -696,7 +696,7 @@ static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with unknown opcode %d", opcode); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -704,7 +704,7 @@ static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, } -static Boolean eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_gpsk_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_gtc.c b/src/eap_peer/eap_gtc.c index a519a780a..72c02cc19 100644 --- a/src/eap_peer/eap_gtc.c +++ b/src/eap_peer/eap_gtc.c @@ -54,7 +54,7 @@ static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, reqData, &len); if (pos == NULL) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } id = eap_get_id(reqData); @@ -85,15 +85,15 @@ static struct wpabuf * eap_gtc_process(struct eap_sm *sm, void *priv, if (password == NULL) { wpa_printf(MSG_INFO, "EAP-GTC: Password not configured"); eap_sm_request_otp(sm, (const char *) pos, len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = data->prefix ? METHOD_MAY_CONT : METHOD_DONE; ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; plen = password_len; identity = eap_get_config_identity(sm, &identity_len); diff --git a/src/eap_peer/eap_i.h b/src/eap_peer/eap_i.h index 8f29d4a26..f43891e39 100644 --- a/src/eap_peer/eap_i.h +++ b/src/eap_peer/eap_i.h @@ -38,7 +38,7 @@ struct eap_method_ret { /** * ignore - Whether method decided to drop the current packed (OUT) */ - Boolean ignore; + bool ignore; /** * methodState - Method-specific state (IN/OUT) @@ -53,7 +53,7 @@ struct eap_method_ret { /** * allowNotifications - Whether method allows notifications (OUT) */ - Boolean allowNotifications; + bool allowNotifications; }; @@ -123,9 +123,9 @@ struct eap_method { * isKeyAvailable - Find out whether EAP method has keying material * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() * @priv: Pointer to private EAP method data from eap_method::init() - * Returns: %TRUE if key material (eapKeyData) is available + * Returns: %true if key material (eapKeyData) is available */ - Boolean (*isKeyAvailable)(struct eap_sm *sm, void *priv); + bool (*isKeyAvailable)(struct eap_sm *sm, void *priv); /** * getKey - Get EAP method specific keying material (eapKeyData) @@ -161,13 +161,13 @@ struct eap_method { * has_reauth_data - Whether method is ready for fast reauthentication * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init() * @priv: Pointer to private EAP method data from eap_method::init() - * Returns: %TRUE or %FALSE based on whether fast reauthentication is + * Returns: %true or %false based on whether fast reauthentication is * possible * * This function is an optional handler that only EAP methods * supporting fast re-authentication need to implement. */ - Boolean (*has_reauth_data)(struct eap_sm *sm, void *priv); + bool (*has_reauth_data)(struct eap_sm *sm, void *priv); /** * deinit_for_reauth - Release data that is not needed for fast re-auth @@ -318,39 +318,39 @@ struct eap_sm { struct wpabuf *lastRespData; EapDecision decision; /* Short-term local variables */ - Boolean rxReq; - Boolean rxSuccess; - Boolean rxFailure; + bool rxReq; + bool rxSuccess; + bool rxFailure; int reqId; enum eap_type reqMethod; int reqVendor; u32 reqVendorMethod; - Boolean ignore; + bool ignore; /* Constants */ int ClientTimeout; /* Miscellaneous variables */ - Boolean allowNotifications; /* peer state machine <-> methods */ + bool allowNotifications; /* peer state machine <-> methods */ struct wpabuf *eapRespData; /* peer to lower layer */ - Boolean eapKeyAvailable; /* peer to lower layer */ + bool eapKeyAvailable; /* peer to lower layer */ u8 *eapKeyData; /* peer to lower layer */ size_t eapKeyDataLen; /* peer to lower layer */ u8 *eapSessionId; /* peer to lower layer */ size_t eapSessionIdLen; /* peer to lower layer */ const struct eap_method *m; /* selected EAP method */ /* not defined in RFC 4137 */ - Boolean changed; + bool changed; void *eapol_ctx; const struct eapol_callbacks *eapol_cb; void *eap_method_priv; int init_phase2; int fast_reauth; - Boolean reauthInit; /* send EAP-Identity/Re-auth */ + bool reauthInit; /* send EAP-Identity/Re-auth */ u32 erp_seq; - Boolean rxResp /* LEAP only */; - Boolean leap_done; - Boolean peap_done; + bool rxResp /* LEAP only */; + bool leap_done; + bool peap_done; u8 req_sha1[20]; /* SHA1() of the current EAP packet */ u8 last_sha1[20]; /* SHA1() of the previously received EAP packet; used * in duplicate request detection. */ diff --git a/src/eap_peer/eap_ikev2.c b/src/eap_peer/eap_ikev2.c index 6ddf50835..b49fe1672 100644 --- a/src/eap_peer/eap_ikev2.c +++ b/src/eap_peer/eap_ikev2.c @@ -138,9 +138,9 @@ static struct wpabuf * eap_ikev2_build_msg(struct eap_ikev2_data *data, u8 flags; size_t send_len, plen, icv_len = 0; - ret->ignore = FALSE; + ret->ignore = false; wpa_printf(MSG_DEBUG, "EAP-IKEV2: Generating Response"); - ret->allowNotifications = TRUE; + ret->allowNotifications = true; flags = 0; send_len = wpabuf_len(data->out_buf) - data->out_used; @@ -293,7 +293,7 @@ static struct wpabuf * eap_ikev2_process_fragment(struct eap_ikev2_data *data, if (data->in_buf == NULL && !(flags & IKEV2_FLAGS_LENGTH_INCLUDED)) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: No Message Length field in " "a fragmented packet"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -303,14 +303,14 @@ static struct wpabuf * eap_ikev2_process_fragment(struct eap_ikev2_data *data, /* Limit maximum memory allocation */ wpa_printf(MSG_DEBUG, "EAP-IKEV2: Ignore too long message"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } data->in_buf = wpabuf_alloc(message_length); if (data->in_buf == NULL) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: No memory for " "message"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpabuf_put_data(data->in_buf, buf, len); @@ -320,7 +320,7 @@ static struct wpabuf * eap_ikev2_process_fragment(struct eap_ikev2_data *data, (unsigned long) wpabuf_tailroom(data->in_buf)); } - ret->ignore = FALSE; + ret->ignore = false; return eap_ikev2_build_frag_ack(id, EAP_CODE_RESPONSE); } @@ -338,7 +338,7 @@ static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_IKEV2, reqData, &len); if (pos == NULL) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -355,14 +355,14 @@ static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, if (eap_ikev2_process_icv(data, reqData, flags, pos, &end, data->state == WAIT_FRAG_ACK && len == 0) < 0) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (flags & IKEV2_FLAGS_LENGTH_INCLUDED) { if (end - pos < 4) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: Message underflow"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } message_length = WPA_GET_BE32(pos); @@ -372,7 +372,7 @@ static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_DEBUG, "EAP-IKEV2: Invalid Message " "Length (%d; %ld remaining in this msg)", message_length, (long) (end - pos)); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } @@ -384,7 +384,7 @@ static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, if (len != 0) { wpa_printf(MSG_DEBUG, "EAP-IKEV2: Unexpected payload " "in WAIT_FRAG_ACK state"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_printf(MSG_DEBUG, "EAP-IKEV2: Fragment acknowledged"); @@ -393,10 +393,10 @@ static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, } if (data->in_buf && eap_ikev2_process_cont(data, pos, end - pos) < 0) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - + if (flags & IKEV2_FLAGS_MORE_FRAGMENTS) { return eap_ikev2_process_fragment(data, ret, id, flags, message_length, pos, @@ -435,7 +435,7 @@ static struct wpabuf * eap_ikev2_process(struct eap_sm *sm, void *priv, } -static Boolean eap_ikev2_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_ikev2_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_ikev2_data *data = priv; return data->state == DONE && data->keymat_ok; diff --git a/src/eap_peer/eap_leap.c b/src/eap_peer/eap_leap.c index 34758e021..02daddfb4 100644 --- a/src/eap_peer/eap_leap.c +++ b/src/eap_peer/eap_leap.c @@ -45,7 +45,7 @@ static void * eap_leap_init(struct eap_sm *sm) return NULL; data->state = LEAP_WAIT_CHALLENGE; - sm->leap_done = FALSE; + sm->leap_done = false; return data; } @@ -77,14 +77,14 @@ static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len); if (pos == NULL || len < 3) { wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Request frame"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (*pos != LEAP_VERSION) { wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " "%d", *pos); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } pos++; @@ -96,7 +96,7 @@ static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv, wpa_printf(MSG_INFO, "EAP-LEAP: Invalid challenge " "(challenge_len=%d reqDataLen=%lu)", challenge_len, (unsigned long) wpabuf_len(reqData)); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } challenge = pos; @@ -119,7 +119,7 @@ static struct wpabuf * eap_leap_process_request(struct eap_sm *sm, void *priv, (!pwhash && nt_challenge_response(challenge, password, password_len, rpos))) { wpa_printf(MSG_DEBUG, "EAP-LEAP: Failed to derive response"); - ret->ignore = TRUE; + ret->ignore = true; wpabuf_free(resp); return NULL; } @@ -153,7 +153,7 @@ static struct wpabuf * eap_leap_process_success(struct eap_sm *sm, void *priv, if (data->state != LEAP_WAIT_SUCCESS) { wpa_printf(MSG_INFO, "EAP-LEAP: EAP-Success received in " "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -170,7 +170,7 @@ static struct wpabuf * eap_leap_process_success(struct eap_sm *sm, void *priv, wpa_printf(MSG_WARNING, "EAP-LEAP: Failed to read random data " "for challenge"); wpabuf_free(resp); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } os_memcpy(data->ap_challenge, pos, LEAP_CHALLENGE_LEN); @@ -204,14 +204,14 @@ static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_LEAP, reqData, &len); if (pos == NULL || len < 3) { wpa_printf(MSG_INFO, "EAP-LEAP: Invalid EAP-Response frame"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (*pos != LEAP_VERSION) { wpa_printf(MSG_WARNING, "EAP-LEAP: Unsupported LEAP version " "%d", *pos); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } pos++; @@ -223,7 +223,7 @@ static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv, wpa_printf(MSG_INFO, "EAP-LEAP: Invalid response " "(response_len=%d reqDataLen=%lu)", response_len, (unsigned long) wpabuf_len(reqData)); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -233,23 +233,23 @@ static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv, if (pwhash) { if (hash_nt_password_hash(password, pw_hash_hash)) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } else { if (nt_password_hash(password, password_len, pw_hash) || hash_nt_password_hash(pw_hash, pw_hash_hash)) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } if (challenge_response(data->ap_challenge, pw_hash_hash, expected)) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } ret->methodState = METHOD_DONE; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; if (os_memcmp_const(pos, expected, LEAP_RESPONSE_LEN) != 0) { wpa_printf(MSG_WARNING, "EAP-LEAP: AP sent an invalid " @@ -265,7 +265,7 @@ static struct wpabuf * eap_leap_process_response(struct eap_sm *sm, void *priv, /* LEAP is somewhat odd method since it sends EAP-Success in the middle * of the authentication. Use special variable to transit EAP state * machine to SUCCESS state. */ - sm->leap_done = TRUE; + sm->leap_done = true; data->state = LEAP_DONE; /* No more authentication messages expected; AP will send EAPOL-Key @@ -286,7 +286,7 @@ static struct wpabuf * eap_leap_process(struct eap_sm *sm, void *priv, if (password == NULL) { wpa_printf(MSG_INFO, "EAP-LEAP: Password not configured"); eap_sm_request_password(sm); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -300,16 +300,16 @@ static struct wpabuf * eap_leap_process(struct eap_sm *sm, void *priv, if (wpabuf_len(reqData) < sizeof(*eap) || be_to_host16(eap->length) > wpabuf_len(reqData)) { wpa_printf(MSG_INFO, "EAP-LEAP: Invalid frame"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; - ret->allowNotifications = TRUE; + ret->ignore = false; + ret->allowNotifications = true; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - sm->leap_done = FALSE; + sm->leap_done = false; switch (eap->code) { case EAP_CODE_REQUEST: @@ -321,13 +321,13 @@ static struct wpabuf * eap_leap_process(struct eap_sm *sm, void *priv, default: wpa_printf(MSG_INFO, "EAP-LEAP: Unexpected EAP code (%d) - " "ignored", eap->code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } -static Boolean eap_leap_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_leap_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_leap_data *data = priv; return data->state == LEAP_DONE; diff --git a/src/eap_peer/eap_md5.c b/src/eap_peer/eap_md5.c index efae8deba..14ac5696e 100644 --- a/src/eap_peer/eap_md5.c +++ b/src/eap_peer/eap_md5.c @@ -39,7 +39,7 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, if (password == NULL) { wpa_printf(MSG_INFO, "EAP-MD5: Password not configured"); eap_sm_request_password(sm); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -47,7 +47,7 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, if (pos == NULL || len == 0) { wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame (pos=%p len=%lu)", pos, (unsigned long) len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -60,10 +60,10 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_INFO, "EAP-MD5: Invalid challenge " "(challenge_len=%lu len=%lu)", (unsigned long) challenge_len, (unsigned long) len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; + ret->ignore = false; challenge = pos; wpa_hexdump(MSG_MSGDUMP, "EAP-MD5: Challenge", challenge, challenge_len); @@ -71,7 +71,7 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_DEBUG, "EAP-MD5: Generating Challenge Response"); ret->methodState = METHOD_DONE; ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MD5, 1 + CHAP_MD5_LEN, EAP_CODE_RESPONSE, eap_get_id(reqData)); @@ -89,7 +89,7 @@ static struct wpabuf * eap_md5_process(struct eap_sm *sm, void *priv, if (chap_md5(id, password, password_len, challenge, challenge_len, rpos)) { wpa_printf(MSG_INFO, "EAP-MD5: CHAP MD5 operation failed"); - ret->ignore = TRUE; + ret->ignore = true; wpabuf_free(resp); return NULL; } diff --git a/src/eap_peer/eap_mschapv2.c b/src/eap_peer/eap_mschapv2.c index 249baec88..8ad4d18b3 100644 --- a/src/eap_peer/eap_mschapv2.c +++ b/src/eap_peer/eap_mschapv2.c @@ -250,7 +250,7 @@ static struct wpabuf * eap_mschapv2_challenge( if (req_len < sizeof(*req) + 1) { wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge data " "(len %lu)", (unsigned long) req_len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } pos = (const u8 *) (req + 1); @@ -259,7 +259,7 @@ static struct wpabuf * eap_mschapv2_challenge( if (challenge_len != MSCHAPV2_CHAL_LEN) { wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid challenge length " "%lu", (unsigned long) challenge_len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -267,7 +267,7 @@ static struct wpabuf * eap_mschapv2_challenge( wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Too short challenge" " packet: len=%lu challenge_len=%lu", (unsigned long) len, (unsigned long) challenge_len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -282,10 +282,10 @@ static struct wpabuf * eap_mschapv2_challenge( wpa_hexdump_ascii(MSG_DEBUG, "EAP-MSCHAPV2: Authentication Servername", pos, len); - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; return eap_mschapv2_challenge_reply(sm, data, id, req->mschapv2_id, challenge); @@ -377,7 +377,7 @@ static struct wpabuf * eap_mschapv2_success(struct eap_sm *sm, if (resp == NULL) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Failed to allocate " "buffer for success response"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -385,7 +385,7 @@ static struct wpabuf * eap_mschapv2_success(struct eap_sm *sm, ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; data->success = 1; if (data->prev_error == ERROR_PASSWD_EXPIRED) @@ -531,10 +531,10 @@ static struct wpabuf * eap_mschapv2_change_password( username = mschapv2_remove_domain(username, &username_len); - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; ms_len = sizeof(*ms) + sizeof(*cp); resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, ms_len, @@ -672,10 +672,10 @@ static struct wpabuf * eap_mschapv2_failure(struct eap_sm *sm, os_free(buf); } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; if (data->prev_error == ERROR_PASSWD_EXPIRED && data->passwd_change_version == 3) { @@ -783,7 +783,7 @@ static struct wpabuf * eap_mschapv2_process(struct eap_sm *sm, void *priv, u8 id; if (eap_mschapv2_check_config(sm)) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -800,13 +800,13 @@ static struct wpabuf * eap_mschapv2_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, reqData, &len); if (pos == NULL || len < sizeof(*ms) + 1) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } ms = (const struct eap_mschapv2_hdr *) pos; if (eap_mschapv2_check_mslen(sm, len, ms)) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -826,13 +826,13 @@ static struct wpabuf * eap_mschapv2_process(struct eap_sm *sm, void *priv, default: wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Unknown op %d - ignored", ms->op_code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } -static Boolean eap_mschapv2_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_mschapv2_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_mschapv2_data *data = priv; return data->success && data->master_key_valid; diff --git a/src/eap_peer/eap_otp.c b/src/eap_peer/eap_otp.c index 0ab4c7907..87615c6a6 100644 --- a/src/eap_peer/eap_otp.c +++ b/src/eap_peer/eap_otp.c @@ -36,7 +36,7 @@ static struct wpabuf * eap_otp_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_OTP, reqData, &len); if (pos == NULL) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-OTP: Request message", @@ -53,15 +53,15 @@ static struct wpabuf * eap_otp_process(struct eap_sm *sm, void *priv, if (password == NULL) { wpa_printf(MSG_INFO, "EAP-OTP: Password not configured"); eap_sm_request_otp(sm, (const char *) pos, len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_DONE; ret->decision = DECISION_COND_SUCC; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_OTP, password_len, EAP_CODE_RESPONSE, eap_get_id(reqData)); diff --git a/src/eap_peer/eap_pax.c b/src/eap_peer/eap_pax.c index 3cef1c880..a641d44c1 100644 --- a/src/eap_peer/eap_pax.c +++ b/src/eap_peer/eap_pax.c @@ -127,14 +127,14 @@ static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, if (data->state != PAX_INIT) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 received in " "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (req->flags & EAP_PAX_FLAGS_CE) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with CE flag set - " "ignored"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -143,7 +143,7 @@ static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, if (left < 2 + EAP_PAX_RAND_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with too short " "payload"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -152,7 +152,7 @@ static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with incorrect A " "length %d (expected %d)", WPA_GET_BE16(pos), EAP_PAX_RAND_LEN); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -171,7 +171,7 @@ static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, if (random_get_bytes(data->rand.r.y, EAP_PAX_RAND_LEN)) { wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)", @@ -180,7 +180,7 @@ static struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, if (eap_pax_initial_key_derivation(req->mac_id, data->ak, data->rand.e, data->mk, data->ck, data->ick, data->mid) < 0) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -243,14 +243,14 @@ static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, if (data->state != PAX_STD_2_SENT) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 received in " "unexpected state (%d) - ignored", data->state); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (req->flags & EAP_PAX_FLAGS_CE) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with CE flag set - " "ignored"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -259,7 +259,7 @@ static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, if (left < 2 + EAP_PAX_MAC_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with too short " "payload"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -268,7 +268,7 @@ static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with incorrect " "MAC_CK length %d (expected %d)", WPA_GET_BE16(pos), EAP_PAX_MAC_LEN); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } pos += 2; @@ -323,7 +323,7 @@ static struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, data->state = PAX_DONE; ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return resp; } @@ -343,7 +343,7 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, reqData, &len); if (pos == NULL || len < sizeof(*req) + EAP_PAX_ICV_LEN) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } id = eap_get_id(reqData); @@ -363,7 +363,7 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_INFO, "EAP-PAX: MAC ID changed during " "authentication (was 0x%d, is 0x%d)", data->mac_id, req->mac_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -371,7 +371,7 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_INFO, "EAP-PAX: DH Group ID changed during " "authentication (was 0x%d, is 0x%d)", data->dh_group_id, req->dh_group_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -380,7 +380,7 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_INFO, "EAP-PAX: Public Key ID changed during " "authentication (was 0x%d, is 0x%d)", data->public_key_id, req->public_key_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -388,21 +388,21 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, if (req->mac_id != EAP_PAX_MAC_HMAC_SHA1_128) { wpa_printf(MSG_INFO, "EAP-PAX: Unsupported MAC ID 0x%x", req->mac_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (req->dh_group_id != EAP_PAX_DH_GROUP_NONE) { wpa_printf(MSG_INFO, "EAP-PAX: Unsupported DH Group ID 0x%x", req->dh_group_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (req->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) { wpa_printf(MSG_INFO, "EAP-PAX: Unsupported Public Key ID 0x%x", req->public_key_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -410,7 +410,7 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, /* TODO: add support for reassembling fragments */ wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported - " "ignored packet"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -430,14 +430,14 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, "message"); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected ICV", icvbuf, EAP_PAX_ICV_LEN); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; switch (req->op_code) { case EAP_PAX_OP_STD_1: @@ -449,19 +449,19 @@ static struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, default: wpa_printf(MSG_DEBUG, "EAP-PAX: ignoring message with unknown " "op_code %d", req->op_code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; + ret->allowNotifications = false; } return resp; } -static Boolean eap_pax_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_pax_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_pax_data *data = priv; return data->state == PAX_DONE; diff --git a/src/eap_peer/eap_peap.c b/src/eap_peer/eap_peap.c index 92b15ec34..7c3704369 100644 --- a/src/eap_peer/eap_peap.c +++ b/src/eap_peer/eap_peap.c @@ -137,7 +137,7 @@ static void * eap_peap_init(struct eap_sm *sm) data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; - sm->peap_done = FALSE; + sm->peap_done = false; data->peap_version = EAP_PEAP_VERSION; data->force_peap_version = -1; data->peap_outer_success = 2; @@ -920,7 +920,7 @@ continue_req: /* No EAP-Success expected for Phase 1 (outer, * unencrypted auth), so force EAP state * machine to SUCCESS state. */ - sm->peap_done = TRUE; + sm->peap_done = true; } } else { /* FIX: ? */ @@ -930,7 +930,7 @@ continue_req: wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure"); ret->decision = DECISION_FAIL; ret->methodState = METHOD_MAY_CONT; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; /* Reply with EAP-Failure within the TLS channel to complete * failure reporting. */ resp = wpabuf_alloc(sizeof(struct eap_hdr)); @@ -1014,7 +1014,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, data->force_peap_version); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return NULL; } wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d", @@ -1166,7 +1166,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, } if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; + ret->allowNotifications = false; } if (res == 1) { @@ -1179,7 +1179,7 @@ static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv, } -static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_peap_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_peap_data *data = priv; return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && @@ -1220,7 +1220,7 @@ static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv) data->phase2_eap_started = 0; data->resuming = 1; data->reauth = 1; - sm->peap_done = FALSE; + sm->peap_done = false; return priv; } @@ -1245,7 +1245,7 @@ static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf, } -static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_peap_data *data = priv; return data->key_data != NULL && data->phase2_success; diff --git a/src/eap_peer/eap_psk.c b/src/eap_peer/eap_psk.c index eea9430d2..4997e6a56 100644 --- a/src/eap_peer/eap_psk.c +++ b/src/eap_peer/eap_psk.c @@ -100,7 +100,7 @@ static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data, "length (%lu; expected %lu or more)", (unsigned long) len, (unsigned long) sizeof(*hdr1)); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags); @@ -120,7 +120,7 @@ static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data, if (data->id_s == NULL) { wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for " "ID_S (len=%lu)", (unsigned long) data->id_s_len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S", @@ -128,7 +128,7 @@ static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data, if (random_get_bytes(data->rand_p, EAP_PSK_RAND_LEN)) { wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -198,7 +198,7 @@ static struct wpabuf * eap_psk_process_3(struct eap_psk_data *data, "length (%lu; expected %lu or more)", (unsigned long) len, (unsigned long) sizeof(*hdr3)); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } left = len - sizeof(*hdr3); @@ -220,7 +220,7 @@ static struct wpabuf * eap_psk_process_3(struct eap_psk_data *data, wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " "third message (len=%lu, expected 21)", (unsigned long) left); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -377,14 +377,14 @@ static struct wpabuf * eap_psk_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len); if (pos == NULL) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; switch (data->state) { case PSK_INIT: @@ -396,19 +396,19 @@ static struct wpabuf * eap_psk_process(struct eap_sm *sm, void *priv, case PSK_DONE: wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore " "unexpected message"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; + ret->allowNotifications = false; } return resp; } -static Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_psk_data *data = priv; return data->state == PSK_DONE; diff --git a/src/eap_peer/eap_pwd.c b/src/eap_peer/eap_pwd.c index 54f102a3b..605feb24f 100644 --- a/src/eap_peer/eap_pwd.c +++ b/src/eap_peer/eap_pwd.c @@ -257,13 +257,13 @@ eap_pwd_perform_id_exchange(struct eap_sm *sm, struct eap_pwd_data *data, struct eap_pwd_id *id; if (data->state != PWD_ID_Req) { - ret->ignore = TRUE; + ret->ignore = true; eap_pwd_state(data, FAILURE); return; } if (payload_len < sizeof(struct eap_pwd_id)) { - ret->ignore = TRUE; + ret->ignore = true; eap_pwd_state(data, FAILURE); return; } @@ -369,14 +369,14 @@ eap_pwd_perform_commit_exchange(struct eap_sm *sm, struct eap_pwd_data *data, int res; if (data->state != PWD_Commit_Req) { - ret->ignore = TRUE; + ret->ignore = true; goto fin; } if (!data->grp) { wpa_printf(MSG_DEBUG, "EAP-PWD (client): uninitialized EAP-pwd group"); - ret->ignore = TRUE; + ret->ignore = true; goto fin; } @@ -696,7 +696,7 @@ eap_pwd_perform_confirm_exchange(struct eap_sm *sm, struct eap_pwd_data *data, size_t prime_len = 0, order_len = 0; if (data->state != PWD_Confirm_Req) { - ret->ignore = TRUE; + ret->ignore = true; goto fin; } @@ -878,14 +878,14 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, wpa_printf(MSG_DEBUG, "EAP-pwd: Got a frame but pos is %s and " "len is %d", pos == NULL ? "NULL" : "not NULL", (int) len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; lm_exch = *pos; pos++; /* skip over the bits and the exch */ @@ -951,7 +951,7 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, if (len < 2) { wpa_printf(MSG_DEBUG, "EAP-pwd: Frame too short to contain Total-Length field"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } tot_len = WPA_GET_BE16(pos); @@ -962,7 +962,7 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, if (data->inbuf) { wpa_printf(MSG_DEBUG, "EAP-pwd: Unexpected new fragment start when previous fragment is still in use"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } data->inbuf = wpabuf_alloc(tot_len); @@ -1107,7 +1107,7 @@ eap_pwd_process(struct eap_sm *sm, void *priv, struct eap_method_ret *ret, } -static Boolean eap_pwd_key_available(struct eap_sm *sm, void *priv) +static bool eap_pwd_key_available(struct eap_sm *sm, void *priv) { struct eap_pwd_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_sake.c b/src/eap_peer/eap_sake.c index 255241f6d..39c195dfd 100644 --- a/src/eap_peer/eap_sake.c +++ b/src/eap_peer/eap_sake.c @@ -148,7 +148,7 @@ static struct wpabuf * eap_sake_process_identity(struct eap_sm *sm, struct wpabuf *resp; if (data->state != IDENTITY) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -195,7 +195,7 @@ static struct wpabuf * eap_sake_process_challenge(struct eap_sm *sm, if (data->state != IDENTITY && data->state != CHALLENGE) { wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Challenge received " "in unexpected state (%d)", data->state); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (data->state == IDENTITY) @@ -296,7 +296,7 @@ static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, u8 *rpos; if (data->state != CONFIRM) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -320,7 +320,7 @@ static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, eap_sake_state(data, FAILURE); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Auth-Reject"); return eap_sake_build_msg(data, id, 0, EAP_SAKE_SUBTYPE_AUTH_REJECT); @@ -330,7 +330,7 @@ static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, eap_sake_state(data, FAILURE); ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending " "Response/Auth-Reject"); return eap_sake_build_msg(data, id, 0, @@ -361,7 +361,7 @@ static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm, eap_sake_state(data, SUCCESS); ret->methodState = METHOD_DONE; ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return resp; } @@ -380,7 +380,7 @@ static struct wpabuf * eap_sake_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, reqData, &len); if (pos == NULL || len < sizeof(struct eap_sake_hdr)) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -399,16 +399,16 @@ static struct wpabuf * eap_sake_process(struct eap_sm *sm, void *priv, if (data->session_id_set && data->session_id != session_id) { wpa_printf(MSG_INFO, "EAP-SAKE: Session ID mismatch (%d,%d)", session_id, data->session_id); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } data->session_id = session_id; data->session_id_set = 1; - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; switch (subtype) { case EAP_SAKE_SUBTYPE_IDENTITY: @@ -426,18 +426,18 @@ static struct wpabuf * eap_sake_process(struct eap_sm *sm, void *priv, default: wpa_printf(MSG_DEBUG, "EAP-SAKE: Ignoring message with " "unknown subtype %d", subtype); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (ret->methodState == METHOD_DONE) - ret->allowNotifications = FALSE; + ret->allowNotifications = false; return resp; } -static Boolean eap_sake_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_sake_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_sake_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_sim.c b/src/eap_peer/eap_sim.c index dd9848ec6..09866277d 100644 --- a/src/eap_peer/eap_sim.c +++ b/src/eap_peer/eap_sim.c @@ -520,6 +520,12 @@ static struct wpabuf * eap_sim_response_start(struct eap_sm *sm, wpa_printf(MSG_DEBUG, "Generating EAP-SIM Start (id=%d)", id); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, id, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START); + if (identity) { + wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", + identity, identity_len); + eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, + identity, identity_len); + } if (!data->reauth) { wpa_hexdump(MSG_DEBUG, " AT_NONCE_MT", data->nonce_mt, EAP_SIM_NONCE_MT_LEN); @@ -531,13 +537,6 @@ static struct wpabuf * eap_sim_response_start(struct eap_sm *sm, data->selected_version, NULL, 0); } - if (identity) { - wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", - identity, identity_len); - eap_sim_msg_add(msg, EAP_SIM_AT_IDENTITY, identity_len, - identity, identity_len); - } - resp = eap_sim_msg_finish(msg, EAP_TYPE_SIM, NULL, NULL, 0); if (resp) eap_sim_state(data, START_DONE); @@ -1104,23 +1103,23 @@ static struct wpabuf * eap_sim_process(struct eap_sm *sm, void *priv, if (eap_get_config_identity(sm, &len) == NULL) { wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured"); eap_sm_request_identity(sm); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, reqData, &len); if (pos == NULL || len < 3) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } req = wpabuf_head(reqData); id = req->identifier; len = be_to_host16(req->length); - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; subtype = *pos++; wpa_printf(MSG_DEBUG, "EAP-SIM: Subtype=%d", subtype); @@ -1173,14 +1172,14 @@ done: ret->methodState = METHOD_CONT; if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; + ret->allowNotifications = false; } return res; } -static Boolean eap_sim_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_sim_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_sim_data *data = priv; return data->pseudonym || data->reauth_id; @@ -1231,7 +1230,7 @@ static const u8 * eap_sim_get_identity(struct eap_sm *sm, void *priv, } -static Boolean eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_sim_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_sim_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_teap.c b/src/eap_peer/eap_teap.c index f751fbec3..e8cc7844c 100644 --- a/src/eap_peer/eap_teap.c +++ b/src/eap_peer/eap_teap.c @@ -1388,6 +1388,15 @@ static int eap_teap_process_decrypted(struct eap_sm *sm, "EAP-TEAP: PAC used - server may decide to skip inner authentication"); ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_COND_SUCC; + } else if (data->result_success_done && + tls_connection_get_own_cert_used(data->ssl.conn) && + eap_teap_derive_msk(data) == 0) { + /* Assume the server might accept authentication without going + * through inner authentication. */ + wpa_printf(MSG_DEBUG, + "EAP-TEAP: Client certificate used - server may decide to skip inner authentication"); + ret->methodState = METHOD_MAY_CONT; + ret->decision = DECISION_COND_SUCC; } if (tlv.pac) { @@ -1985,7 +1994,7 @@ static struct wpabuf * eap_teap_process(struct eap_sm *sm, void *priv, #if 0 /* TODO */ -static Boolean eap_teap_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_teap_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_teap_data *data = priv; @@ -2048,7 +2057,7 @@ static int eap_teap_get_status(struct eap_sm *sm, void *priv, char *buf, } -static Boolean eap_teap_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_teap_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_teap_data *data = priv; diff --git a/src/eap_peer/eap_tls.c b/src/eap_peer/eap_tls.c index d9771f601..ad079a7b7 100644 --- a/src/eap_peer/eap_tls.c +++ b/src/eap_peer/eap_tls.c @@ -62,12 +62,12 @@ static void * eap_tls_init(struct eap_sm *sm) wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard " "PIN"); eap_sm_request_pin(sm); - sm->ignore = TRUE; + sm->ignore = true; } else if (cert->private_key && !cert->private_key_passwd) { wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private " "key passphrase"); eap_sm_request_passphrase(sm); - sm->ignore = TRUE; + sm->ignore = true; } return NULL; } @@ -326,7 +326,7 @@ static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, } -static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_tls_data *data = priv; return tls_connection_established(data->ssl_ctx, data->ssl.conn); @@ -364,7 +364,7 @@ static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, } -static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_tls_data *data = priv; return data->key_data != NULL; diff --git a/src/eap_peer/eap_tls_common.c b/src/eap_peer/eap_tls_common.c index 80e2d71e9..ab1067878 100644 --- a/src/eap_peer/eap_tls_common.c +++ b/src/eap_peer/eap_tls_common.c @@ -269,12 +269,12 @@ static int eap_tls_init_connection(struct eap_sm *sm, os_free(config->cert.pin); config->cert.pin = NULL; eap_sm_request_pin(sm); - sm->ignore = TRUE; + sm->ignore = true; } else if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) { wpa_printf(MSG_INFO, "TLS: Failed to initialize engine"); } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) { wpa_printf(MSG_INFO, "TLS: Failed to load private key"); - sm->ignore = TRUE; + sm->ignore = true; } if (res) { wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection " @@ -913,7 +913,7 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm, if (tls_get_errors(data->ssl_ctx)) { wpa_printf(MSG_INFO, "SSL: TLS errors detected"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -929,14 +929,14 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm, pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, &left); if (pos == NULL) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (left == 0) { wpa_printf(MSG_DEBUG, "SSL: Invalid TLS message: no Flags " "octet included"); if (!sm->workaround) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -954,7 +954,7 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm, if (left < 4) { wpa_printf(MSG_INFO, "SSL: Short frame with TLS " "length"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } tls_msg_len = WPA_GET_BE32(pos); @@ -973,15 +973,15 @@ const u8 * eap_peer_tls_process_init(struct eap_sm *sm, wpa_printf(MSG_INFO, "SSL: TLS Message Length (%d " "bytes) smaller than this fragment (%d " "bytes)", (int) tls_msg_len, (int) left); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; *len = left; return pos; diff --git a/src/eap_peer/eap_tnc.c b/src/eap_peer/eap_tnc.c index 726221e6b..af1777364 100644 --- a/src/eap_peer/eap_tnc.c +++ b/src/eap_peer/eap_tnc.c @@ -92,9 +92,9 @@ static struct wpabuf * eap_tnc_build_msg(struct eap_tnc_data *data, u8 flags; size_t send_len, plen; - ret->ignore = FALSE; + ret->ignore = false; wpa_printf(MSG_DEBUG, "EAP-TNC: Generating Response"); - ret->allowNotifications = TRUE; + ret->allowNotifications = true; flags = EAP_TNC_VERSION; send_len = wpabuf_len(data->out_buf) - data->out_used; @@ -174,7 +174,7 @@ static struct wpabuf * eap_tnc_process_fragment(struct eap_tnc_data *data, if (data->in_buf == NULL && !(flags & EAP_TNC_FLAGS_LENGTH_INCLUDED)) { wpa_printf(MSG_DEBUG, "EAP-TNC: No Message Length field in a " "fragmented packet"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -184,7 +184,7 @@ static struct wpabuf * eap_tnc_process_fragment(struct eap_tnc_data *data, if (data->in_buf == NULL) { wpa_printf(MSG_DEBUG, "EAP-TNC: No memory for " "message"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpabuf_put_data(data->in_buf, buf, len); @@ -219,7 +219,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, if (pos == NULL) { wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame (pos=%p len=%lu)", pos, (unsigned long) len); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -235,14 +235,14 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, if (len > 0 && (flags & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) { wpa_printf(MSG_DEBUG, "EAP-TNC: Unsupported version %d", flags & EAP_TNC_VERSION_MASK); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (flags & EAP_TNC_FLAGS_LENGTH_INCLUDED) { if (end - pos < 4) { wpa_printf(MSG_DEBUG, "EAP-TNC: Message underflow"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } message_length = WPA_GET_BE32(pos); @@ -253,7 +253,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, wpa_printf(MSG_DEBUG, "EAP-TNC: Invalid Message " "Length (%d; %ld remaining in this msg)", message_length, (long) (end - pos)); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } @@ -265,7 +265,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, if (len > 1) { wpa_printf(MSG_DEBUG, "EAP-TNC: Unexpected payload in " "WAIT_FRAG_ACK state"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_printf(MSG_DEBUG, "EAP-TNC: Fragment acknowledged"); @@ -274,10 +274,10 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, } if (data->in_buf && eap_tnc_process_cont(data, pos, end - pos) < 0) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } - + if (flags & EAP_TNC_FLAGS_MORE_FRAGMENTS) { return eap_tnc_process_fragment(data, ret, id, flags, message_length, pos, @@ -294,7 +294,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, if (!(flags & EAP_TNC_FLAGS_START)) { wpa_printf(MSG_DEBUG, "EAP-TNC: Server did not use " "start flag in the first message"); - ret->ignore = TRUE; + ret->ignore = true; goto fail; } @@ -307,7 +307,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, if (flags & EAP_TNC_FLAGS_START) { wpa_printf(MSG_DEBUG, "EAP-TNC: Server used start " "flag again"); - ret->ignore = TRUE; + ret->ignore = true; goto fail; } @@ -316,7 +316,7 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, wpabuf_len(data->in_buf)); switch (res) { case TNCCS_PROCESS_ERROR: - ret->ignore = TRUE; + ret->ignore = true; goto fail; case TNCCS_PROCESS_OK_NO_RECOMMENDATION: case TNCCS_RECOMMENDATION_ERROR: @@ -345,10 +345,10 @@ static struct wpabuf * eap_tnc_process(struct eap_sm *sm, void *priv, wpabuf_free(data->in_buf); data->in_buf = NULL; - ret->ignore = FALSE; + ret->ignore = false; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_UNCOND_SUCC; - ret->allowNotifications = TRUE; + ret->allowNotifications = true; if (tncs_done) { resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TNC, 1, diff --git a/src/eap_peer/eap_ttls.c b/src/eap_peer/eap_ttls.c index 662676f8f..642d179c6 100644 --- a/src/eap_peer/eap_ttls.c +++ b/src/eap_peer/eap_ttls.c @@ -1578,7 +1578,7 @@ static void eap_ttls_check_auth_status(struct eap_sm *sm, struct eap_method_ret *ret) { if (ret->methodState == METHOD_DONE) { - ret->allowNotifications = FALSE; + ret->allowNotifications = false; if (ret->decision == DECISION_UNCOND_SUCC || ret->decision == DECISION_COND_SUCC) { wpa_printf(MSG_DEBUG, "EAP-TTLS: Authentication " @@ -1673,7 +1673,7 @@ static struct wpabuf * eap_ttls_process(struct eap_sm *sm, void *priv, } -static Boolean eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv) +static bool eap_ttls_has_reauth_data(struct eap_sm *sm, void *priv) { struct eap_ttls_data *data = priv; return tls_connection_established(sm->ssl_ctx, data->ssl.conn) && @@ -1764,7 +1764,7 @@ static int eap_ttls_get_status(struct eap_sm *sm, void *priv, char *buf, } -static Boolean eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_ttls_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_ttls_data *data = priv; return data->key_data != NULL && data->phase2_success; diff --git a/src/eap_peer/eap_vendor_test.c b/src/eap_peer/eap_vendor_test.c index 16e3c3956..431f44b65 100644 --- a/src/eap_peer/eap_vendor_test.c +++ b/src/eap_peer/eap_vendor_test.c @@ -75,28 +75,28 @@ static struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, reqData, &len); if (pos == NULL || len < 1) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (data->state == INIT && *pos != 1) { wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " "%d in INIT state", *pos); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (data->state == CONFIRM && *pos != 3) { wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " "%d in CONFIRM state", *pos); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (data->state == SUCCESS) { wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Unexpected message " "in SUCCESS state"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -105,17 +105,17 @@ static struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv, data->first_try = 0; wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Testing " "pending request"); - ret->ignore = TRUE; + ret->ignore = true; eloop_register_timeout(1, 0, eap_vendor_ready, sm, NULL); return NULL; } } - ret->ignore = FALSE; + ret->ignore = false; wpa_printf(MSG_DEBUG, "EAP-VENDOR-TEST: Generating Response"); - ret->allowNotifications = TRUE; + ret->allowNotifications = true; resp = eap_msg_alloc(EAP_VENDOR_ID, EAP_VENDOR_TYPE, 1, EAP_CODE_RESPONSE, eap_get_id(reqData)); @@ -138,7 +138,7 @@ static struct wpabuf * eap_vendor_test_process(struct eap_sm *sm, void *priv, } -static Boolean eap_vendor_test_isKeyAvailable(struct eap_sm *sm, void *priv) +static bool eap_vendor_test_isKeyAvailable(struct eap_sm *sm, void *priv) { struct eap_vendor_test_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c index 92d5a0235..a1e7bff19 100644 --- a/src/eap_peer/eap_wsc.c +++ b/src/eap_peer/eap_wsc.c @@ -304,9 +304,9 @@ static struct wpabuf * eap_wsc_build_msg(struct eap_wsc_data *data, u8 flags; size_t send_len, plen; - ret->ignore = FALSE; + ret->ignore = false; wpa_printf(MSG_DEBUG, "EAP-WSC: Generating Response"); - ret->allowNotifications = TRUE; + ret->allowNotifications = true; flags = 0; send_len = wpabuf_len(data->out_buf) - data->out_used; @@ -400,7 +400,7 @@ static struct wpabuf * eap_wsc_process_fragment(struct eap_wsc_data *data, if (data->in_buf == NULL && !(flags & WSC_FLAGS_LF)) { wpa_printf(MSG_DEBUG, "EAP-WSC: No Message Length field in a " "fragmented packet"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -410,7 +410,7 @@ static struct wpabuf * eap_wsc_process_fragment(struct eap_wsc_data *data, if (data->in_buf == NULL) { wpa_printf(MSG_DEBUG, "EAP-WSC: No memory for " "message"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } data->in_op_code = op_code; @@ -441,7 +441,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, reqData, &len); if (pos == NULL || len < 2) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -455,7 +455,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, if (flags & WSC_FLAGS_LF) { if (end - pos < 2) { wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } message_length = WPA_GET_BE16(pos); @@ -464,7 +464,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, if (message_length < end - pos || message_length > 50000) { wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " "Length"); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } } @@ -477,7 +477,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, if (op_code != WSC_FRAG_ACK) { wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " "in WAIT_FRAG_ACK state", op_code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); @@ -489,7 +489,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, op_code != WSC_Done && op_code != WSC_Start) { wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", op_code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } @@ -497,7 +497,7 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, if (op_code != WSC_Start) { wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " "in WAIT_START state", op_code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } wpa_printf(MSG_DEBUG, "EAP-WSC: Received start"); @@ -507,13 +507,13 @@ static struct wpabuf * eap_wsc_process(struct eap_sm *sm, void *priv, } else if (op_code == WSC_Start) { wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", op_code); - ret->ignore = TRUE; + ret->ignore = true; return NULL; } if (data->in_buf && eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { - ret->ignore = TRUE; + ret->ignore = true; return NULL; } diff --git a/src/eap_peer/ikev2.c b/src/eap_peer/ikev2.c index 7bd97b1b9..c2e6c5df5 100644 --- a/src/eap_peer/ikev2.c +++ b/src/eap_peer/ikev2.c @@ -201,7 +201,8 @@ static int ikev2_parse_proposal(struct ikev2_proposal_data *prop, const u8 *pos, const u8 *end) { const u8 *pend, *ppos; - int proposal_len, i; + int proposal_len; + unsigned int i, num; const struct ikev2_proposal *p; if (end - pos < (int) sizeof(*p)) { @@ -269,12 +270,13 @@ static int ikev2_parse_proposal(struct ikev2_proposal_data *prop, return -1; } - if (p->num_transforms == 0) { + num = p->num_transforms; + if (num == 0 || num > 255) { wpa_printf(MSG_INFO, "IKEV2: At least one transform required"); return -1; } - for (i = 0; i < (int) p->num_transforms; i++) { + for (i = 0; i < num; i++) { int tlen = ikev2_parse_transform(prop, ppos, pend); if (tlen < 0) return -1; @@ -411,7 +413,7 @@ static int ikev2_process_kei(struct ikev2_responder_data *data, wpa_hexdump_buf(MSG_DEBUG, "IKEV2: KEi Diffie-Hellman Public Value", data->i_dh_public); - + return 0; } diff --git a/src/eap_server/Makefile b/src/eap_server/Makefile index 1172b7246..cc9b76d61 100644 --- a/src/eap_server/Makefile +++ b/src/eap_server/Makefile @@ -1,13 +1,3 @@ -all: libeap_server.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libeap_server.a - -install: - @echo Nothing to be made. - -include ../lib.rules - CFLAGS += -DCONFIG_HS20 LIB_OBJS= \ @@ -15,7 +5,4 @@ LIB_OBJS= \ eap_server_identity.o \ eap_server_methods.o -libeap_server.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/eap_server/eap.h b/src/eap_server/eap.h index 540b4e70b..61032cc01 100644 --- a/src/eap_server/eap.h +++ b/src/eap_server/eap.h @@ -45,43 +45,43 @@ struct eap_user { struct eap_eapol_interface { /* Lower layer to full authenticator variables */ - Boolean eapResp; /* shared with EAPOL Backend Authentication */ + bool eapResp; /* shared with EAPOL Backend Authentication */ struct wpabuf *eapRespData; - Boolean portEnabled; + bool portEnabled; int retransWhile; - Boolean eapRestart; /* shared with EAPOL Authenticator PAE */ + bool eapRestart; /* shared with EAPOL Authenticator PAE */ int eapSRTT; int eapRTTVAR; /* Full authenticator to lower layer variables */ - Boolean eapReq; /* shared with EAPOL Backend Authentication */ - Boolean eapNoReq; /* shared with EAPOL Backend Authentication */ - Boolean eapSuccess; - Boolean eapFail; - Boolean eapTimeout; + bool eapReq; /* shared with EAPOL Backend Authentication */ + bool eapNoReq; /* shared with EAPOL Backend Authentication */ + bool eapSuccess; + bool eapFail; + bool eapTimeout; struct wpabuf *eapReqData; u8 *eapKeyData; size_t eapKeyDataLen; u8 *eapSessionId; size_t eapSessionIdLen; - Boolean eapKeyAvailable; /* called keyAvailable in IEEE 802.1X-2004 */ + bool eapKeyAvailable; /* called keyAvailable in IEEE 802.1X-2004 */ /* AAA interface to full authenticator variables */ - Boolean aaaEapReq; - Boolean aaaEapNoReq; - Boolean aaaSuccess; - Boolean aaaFail; + bool aaaEapReq; + bool aaaEapNoReq; + bool aaaSuccess; + bool aaaFail; struct wpabuf *aaaEapReqData; u8 *aaaEapKeyData; size_t aaaEapKeyDataLen; - Boolean aaaEapKeyAvailable; + bool aaaEapKeyAvailable; int aaaMethodTimeout; /* Full authenticator to AAA interface variables */ - Boolean aaaEapResp; + bool aaaEapResp; struct wpabuf *aaaEapRespData; /* aaaIdentity -> eap_get_identity() */ - Boolean aaaTimeout; + bool aaaTimeout; }; struct eap_server_erp_key { @@ -124,7 +124,7 @@ struct eap_config { * callback context. */ void *eap_sim_db_priv; - Boolean backend_auth; + bool backend_auth; int eap_server; /** diff --git a/src/eap_server/eap_i.h b/src/eap_server/eap_i.h index 44896a695..28bb564e9 100644 --- a/src/eap_server/eap_i.h +++ b/src/eap_server/eap_i.h @@ -32,15 +32,14 @@ struct eap_method { struct wpabuf * (*buildReq)(struct eap_sm *sm, void *priv, u8 id); int (*getTimeout)(struct eap_sm *sm, void *priv); - Boolean (*check)(struct eap_sm *sm, void *priv, - struct wpabuf *respData); + bool (*check)(struct eap_sm *sm, void *priv, struct wpabuf *respData); void (*process)(struct eap_sm *sm, void *priv, struct wpabuf *respData); - Boolean (*isDone)(struct eap_sm *sm, void *priv); + bool (*isDone)(struct eap_sm *sm, void *priv); u8 * (*getKey)(struct eap_sm *sm, void *priv, size_t *len); /* isSuccess is not specified in draft-ietf-eap-statemachine-05.txt, * but it is useful in implementing Policy.getDecision() */ - Boolean (*isSuccess)(struct eap_sm *sm, void *priv); + bool (*isSuccess)(struct eap_sm *sm, void *priv); /** * free - Free EAP method data @@ -138,13 +137,13 @@ struct eap_sm { int methodTimeout; /* Short-term (not maintained between packets) */ - Boolean rxResp; - Boolean rxInitiate; + bool rxResp; + bool rxInitiate; int respId; enum eap_type respMethod; int respVendor; u32 respVendorMethod; - Boolean ignore; + bool ignore; enum { DECISION_SUCCESS, DECISION_FAILURE, DECISION_CONTINUE, DECISION_PASSTHROUGH, DECISION_INITIATE_REAUTH_START @@ -153,7 +152,7 @@ struct eap_sm { /* Miscellaneous variables */ const struct eap_method *m; /* selected EAP method */ /* not defined in RFC 4137 */ - Boolean changed; + bool changed; void *eapol_ctx; const struct eapol_callbacks *eapol_cb; void *eap_method_priv; @@ -169,7 +168,7 @@ struct eap_sm { int init_phase2; const struct eap_config *cfg; struct eap_config cfg_buf; - Boolean update_user; + bool update_user; unsigned int num_rounds; unsigned int num_rounds_short; @@ -183,12 +182,12 @@ struct eap_sm { struct wpabuf *assoc_wps_ie; struct wpabuf *assoc_p2p_ie; - Boolean start_reauth; + bool start_reauth; u8 peer_addr[ETH_ALEN]; - Boolean initiate_reauth_start_sent; - Boolean try_initiate_reauth; + bool initiate_reauth_start_sent; + bool try_initiate_reauth; #ifdef CONFIG_TESTING_OPTIONS u32 tls_test_flags; diff --git a/src/eap_server/eap_server.c b/src/eap_server/eap_server.c index 34ce23946..0b7a5b98c 100644 --- a/src/eap_server/eap_server.c +++ b/src/eap_server/eap_server.c @@ -9,7 +9,7 @@ * in RFC 4137. However, to support backend authentication in RADIUS * authentication server functionality, parts of backend authenticator (also * from RFC 4137) are mixed in. This functionality is enabled by setting - * backend_auth configuration variable to TRUE. + * backend_auth configuration variable to true. */ #include "includes.h" @@ -38,7 +38,7 @@ static void eap_sm_Policy_update(struct eap_sm *sm, const u8 *nak_list, static enum eap_type eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor); static int eap_sm_Policy_getDecision(struct eap_sm *sm); -static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, enum eap_type method); +static bool eap_sm_Policy_doPickUp(struct eap_sm *sm, enum eap_type method); static int eap_get_erp_send_reauth_start(struct eap_sm *sm) @@ -230,19 +230,19 @@ SM_STATE(EAP, INITIALIZE) eap_server_clear_identity(sm); } - sm->try_initiate_reauth = FALSE; + sm->try_initiate_reauth = false; sm->currentId = -1; - sm->eap_if.eapSuccess = FALSE; - sm->eap_if.eapFail = FALSE; - sm->eap_if.eapTimeout = FALSE; + sm->eap_if.eapSuccess = false; + sm->eap_if.eapFail = false; + sm->eap_if.eapTimeout = false; bin_clear_free(sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen); sm->eap_if.eapKeyData = NULL; sm->eap_if.eapKeyDataLen = 0; os_free(sm->eap_if.eapSessionId); sm->eap_if.eapSessionId = NULL; sm->eap_if.eapSessionIdLen = 0; - sm->eap_if.eapKeyAvailable = FALSE; - sm->eap_if.eapRestart = FALSE; + sm->eap_if.eapKeyAvailable = false; + sm->eap_if.eapRestart = false; /* * This is not defined in RFC 4137, but method state needs to be @@ -322,7 +322,7 @@ SM_STATE(EAP, RETRANSMIT) sm->retransCount++; if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) { if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0) - sm->eap_if.eapReq = TRUE; + sm->eap_if.eapReq = true; } wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_RETRANSMIT MACSTR, @@ -347,8 +347,8 @@ SM_STATE(EAP, RECEIVED) SM_STATE(EAP, DISCARD) { SM_ENTRY(EAP, DISCARD); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapNoReq = TRUE; + sm->eap_if.eapResp = false; + sm->eap_if.eapNoReq = true; } @@ -362,17 +362,17 @@ SM_STATE(EAP, SEND_REQUEST) sm->num_rounds_short = 0; if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0) { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = TRUE; + sm->eap_if.eapResp = false; + sm->eap_if.eapReq = true; } else { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; + sm->eap_if.eapResp = false; + sm->eap_if.eapReq = false; } } else { wpa_printf(MSG_INFO, "EAP: SEND_REQUEST - no eapReqData"); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; - sm->eap_if.eapNoReq = TRUE; + sm->eap_if.eapResp = false; + sm->eap_if.eapReq = false; + sm->eap_if.eapNoReq = true; } } @@ -382,7 +382,7 @@ SM_STATE(EAP, INTEGRITY_CHECK) SM_ENTRY(EAP, INTEGRITY_CHECK); if (!eap_hdr_len_valid(sm->eap_if.eapRespData, 1)) { - sm->ignore = TRUE; + sm->ignore = true; return; } @@ -552,7 +552,7 @@ SM_STATE(EAP, PROPOSE_METHOD) SM_ENTRY(EAP, PROPOSE_METHOD); - sm->try_initiate_reauth = FALSE; + sm->try_initiate_reauth = false; try_another_method: type = eap_sm_Policy_getNextMethod(sm, &vendor); if (vendor == EAP_VENDOR_IETF) @@ -640,7 +640,7 @@ SM_STATE(EAP, TIMEOUT_FAILURE) { SM_ENTRY(EAP, TIMEOUT_FAILURE); - sm->eap_if.eapTimeout = TRUE; + sm->eap_if.eapTimeout = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TIMEOUT_FAILURE MACSTR, MAC2STR(sm->peer_addr)); @@ -655,7 +655,7 @@ SM_STATE(EAP, FAILURE) sm->eap_if.eapReqData = eap_sm_buildFailure(sm, sm->currentId); wpabuf_free(sm->lastReqData); sm->lastReqData = NULL; - sm->eap_if.eapFail = TRUE; + sm->eap_if.eapFail = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE MACSTR, MAC2STR(sm->peer_addr)); @@ -671,8 +671,8 @@ SM_STATE(EAP, SUCCESS) wpabuf_free(sm->lastReqData); sm->lastReqData = NULL; if (sm->eap_if.eapKeyData) - sm->eap_if.eapKeyAvailable = TRUE; - sm->eap_if.eapSuccess = TRUE; + sm->eap_if.eapKeyAvailable = true; + sm->eap_if.eapSuccess = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS MACSTR, MAC2STR(sm->peer_addr)); @@ -683,8 +683,8 @@ SM_STATE(EAP, INITIATE_REAUTH_START) { SM_ENTRY(EAP, INITIATE_REAUTH_START); - sm->initiate_reauth_start_sent = TRUE; - sm->try_initiate_reauth = TRUE; + sm->initiate_reauth_start_sent = true; + sm->try_initiate_reauth = true; sm->currentId = eap_sm_nextId(sm, sm->currentId); wpa_printf(MSG_DEBUG, "EAP: building EAP-Initiate-Re-auth-Start: Identifier %d", @@ -760,7 +760,7 @@ static void erp_send_finish_reauth(struct eap_sm *sm, sm->lastReqData = NULL; if ((flags & 0x80) || !erp) { - sm->eap_if.eapFail = TRUE; + sm->eap_if.eapFail = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE MACSTR, MAC2STR(sm->peer_addr)); return; @@ -784,10 +784,10 @@ static void erp_send_finish_reauth(struct eap_sm *sm, return; } sm->eap_if.eapKeyDataLen = erp->rRK_len; - sm->eap_if.eapKeyAvailable = TRUE; + sm->eap_if.eapKeyAvailable = true; wpa_hexdump_key(MSG_DEBUG, "EAP: ERP rMSK", sm->eap_if.eapKeyData, sm->eap_if.eapKeyDataLen); - sm->eap_if.eapSuccess = TRUE; + sm->eap_if.eapSuccess = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS MACSTR, MAC2STR(sm->peer_addr)); @@ -811,7 +811,7 @@ SM_STATE(EAP, INITIATE_RECEIVED) SM_ENTRY(EAP, INITIATE_RECEIVED); - sm->rxInitiate = FALSE; + sm->rxInitiate = false; pos = eap_hdr_validate(EAP_VENDOR_IETF, (enum eap_type) EAP_ERP_TYPE_REAUTH, @@ -988,7 +988,7 @@ report_error: return; fail: - sm->ignore = TRUE; + sm->ignore = true; } #endif /* CONFIG_ERP */ @@ -1000,7 +1000,7 @@ SM_STATE(EAP, INITIALIZE_PASSTHROUGH) wpabuf_free(sm->eap_if.aaaEapRespData); sm->eap_if.aaaEapRespData = NULL; - sm->try_initiate_reauth = FALSE; + sm->try_initiate_reauth = false; } @@ -1021,7 +1021,7 @@ SM_STATE(EAP, RETRANSMIT2) sm->retransCount++; if (sm->retransCount <= sm->MaxRetrans && sm->lastReqData) { if (eap_copy_buf(&sm->eap_if.eapReqData, sm->lastReqData) == 0) - sm->eap_if.eapReq = TRUE; + sm->eap_if.eapReq = true; } wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_RETRANSMIT2 MACSTR, @@ -1041,8 +1041,8 @@ SM_STATE(EAP, RECEIVED2) SM_STATE(EAP, DISCARD2) { SM_ENTRY(EAP, DISCARD2); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapNoReq = TRUE; + sm->eap_if.eapResp = false; + sm->eap_if.eapNoReq = true; } @@ -1054,17 +1054,17 @@ SM_STATE(EAP, SEND_REQUEST2) if (sm->eap_if.eapReqData) { if (eap_copy_buf(&sm->lastReqData, sm->eap_if.eapReqData) == 0) { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = TRUE; + sm->eap_if.eapResp = false; + sm->eap_if.eapReq = true; } else { - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; + sm->eap_if.eapResp = false; + sm->eap_if.eapReq = false; } } else { wpa_printf(MSG_INFO, "EAP: SEND_REQUEST2 - no eapReqData"); - sm->eap_if.eapResp = FALSE; - sm->eap_if.eapReq = FALSE; - sm->eap_if.eapNoReq = TRUE; + sm->eap_if.eapResp = false; + sm->eap_if.eapReq = false; + sm->eap_if.eapNoReq = true; } } @@ -1103,11 +1103,11 @@ SM_STATE(EAP, AAA_IDLE) { SM_ENTRY(EAP, AAA_IDLE); - sm->eap_if.aaaFail = FALSE; - sm->eap_if.aaaSuccess = FALSE; - sm->eap_if.aaaEapReq = FALSE; - sm->eap_if.aaaEapNoReq = FALSE; - sm->eap_if.aaaEapResp = TRUE; + sm->eap_if.aaaFail = false; + sm->eap_if.aaaSuccess = false; + sm->eap_if.aaaEapReq = false; + sm->eap_if.aaaEapNoReq = false; + sm->eap_if.aaaEapResp = true; } @@ -1115,7 +1115,7 @@ SM_STATE(EAP, TIMEOUT_FAILURE2) { SM_ENTRY(EAP, TIMEOUT_FAILURE2); - sm->eap_if.eapTimeout = TRUE; + sm->eap_if.eapTimeout = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_TIMEOUT_FAILURE2 MACSTR, MAC2STR(sm->peer_addr)); @@ -1127,7 +1127,7 @@ SM_STATE(EAP, FAILURE2) SM_ENTRY(EAP, FAILURE2); eap_copy_buf(&sm->eap_if.eapReqData, sm->eap_if.aaaEapReqData); - sm->eap_if.eapFail = TRUE; + sm->eap_if.eapFail = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_FAILURE2 MACSTR, MAC2STR(sm->peer_addr)); @@ -1149,14 +1149,14 @@ SM_STATE(EAP, SUCCESS2) sm->eap_if.eapKeyDataLen = 0; } - sm->eap_if.eapSuccess = TRUE; + sm->eap_if.eapSuccess = true; /* * Start reauthentication with identity request even though we know the * previously used identity. This is needed to get reauthentication * started properly. */ - sm->start_reauth = TRUE; + sm->start_reauth = true; wpa_msg(sm->cfg->msg_ctx, MSG_INFO, WPA_EVENT_EAP_SUCCESS2 MACSTR, MAC2STR(sm->peer_addr)); @@ -1217,7 +1217,7 @@ SM_STEP(EAP) case EAP_IDLE: if (sm->eap_if.retransWhile == 0) { if (sm->try_initiate_reauth) { - sm->try_initiate_reauth = FALSE; + sm->try_initiate_reauth = false; SM_ENTER(EAP, SELECT_ACTION); } else { SM_ENTER(EAP, RETRANSMIT); @@ -1491,8 +1491,8 @@ static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp) size_t plen; /* parse rxResp, respId, respMethod */ - sm->rxResp = FALSE; - sm->rxInitiate = FALSE; + sm->rxResp = false; + sm->rxInitiate = false; sm->respId = -1; sm->respMethod = EAP_TYPE_NONE; sm->respVendor = EAP_VENDOR_IETF; @@ -1518,9 +1518,9 @@ static void eap_sm_parseEapResp(struct eap_sm *sm, const struct wpabuf *resp) sm->respId = hdr->identifier; if (hdr->code == EAP_CODE_RESPONSE) - sm->rxResp = TRUE; + sm->rxResp = true; else if (hdr->code == EAP_CODE_INITIATE) - sm->rxInitiate = TRUE; + sm->rxInitiate = true; if (plen > sizeof(*hdr)) { u8 *pos = (u8 *) (hdr + 1); @@ -1702,7 +1702,7 @@ static enum eap_type eap_sm_Policy_getNextMethod(struct eap_sm *sm, int *vendor) if (sm->identity == NULL || sm->currentId == -1) { *vendor = EAP_VENDOR_IETF; next = EAP_TYPE_IDENTITY; - sm->update_user = TRUE; + sm->update_user = true; } else if (sm->user && idx < EAP_MAX_METHODS && (sm->user->methods[idx].vendor != EAP_VENDOR_IETF || sm->user->methods[idx].method != EAP_TYPE_NONE)) { @@ -1730,7 +1730,7 @@ static int eap_sm_Policy_getDecision(struct eap_sm *sm) sm->m->isSuccess(sm, sm->eap_method_priv)) { wpa_printf(MSG_DEBUG, "EAP: getDecision: method succeeded -> " "SUCCESS"); - sm->update_user = TRUE; + sm->update_user = true; return DECISION_SUCCESS; } @@ -1738,7 +1738,7 @@ static int eap_sm_Policy_getDecision(struct eap_sm *sm) !sm->m->isSuccess(sm, sm->eap_method_priv)) { wpa_printf(MSG_DEBUG, "EAP: getDecision: method failed -> " "FAILURE"); - sm->update_user = TRUE; + sm->update_user = true; return DECISION_FAILURE; } @@ -1765,12 +1765,12 @@ static int eap_sm_Policy_getDecision(struct eap_sm *sm) sm->user->methods[0].method == EAP_TYPE_IDENTITY) { wpa_printf(MSG_DEBUG, "EAP: getDecision: stop " "identity request loop -> FAILURE"); - sm->update_user = TRUE; + sm->update_user = true; return DECISION_FAILURE; } - sm->update_user = FALSE; + sm->update_user = false; } - sm->start_reauth = FALSE; + sm->start_reauth = false; if (sm->user && sm->user_eap_method_index < EAP_MAX_METHODS && (sm->user->methods[sm->user_eap_method_index].vendor != @@ -1801,9 +1801,9 @@ static int eap_sm_Policy_getDecision(struct eap_sm *sm) } -static Boolean eap_sm_Policy_doPickUp(struct eap_sm *sm, enum eap_type method) +static bool eap_sm_Policy_doPickUp(struct eap_sm *sm, enum eap_type method) { - return method == EAP_TYPE_IDENTITY ? TRUE : FALSE; + return method == EAP_TYPE_IDENTITY; } @@ -1820,7 +1820,7 @@ int eap_server_sm_step(struct eap_sm *sm) { int res = 0; do { - sm->changed = FALSE; + sm->changed = false; SM_STEP_RUN(EAP); if (sm->changed) res = 1; diff --git a/src/eap_server/eap_server_aka.c b/src/eap_server/eap_server_aka.c index 22dd965d6..e9bf0300c 100644 --- a/src/eap_server/eap_server_aka.c +++ b/src/eap_server/eap_server_aka.c @@ -664,8 +664,8 @@ static struct wpabuf * eap_aka_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_aka_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_aka_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_aka_data *data = priv; const u8 *pos; @@ -675,25 +675,25 @@ static Boolean eap_aka_check(struct eap_sm *sm, void *priv, &len); if (pos == NULL || len < 3) { wpa_printf(MSG_INFO, "EAP-AKA: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } -static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype) +static bool eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype) { if (subtype == EAP_AKA_SUBTYPE_CLIENT_ERROR || subtype == EAP_AKA_SUBTYPE_AUTHENTICATION_REJECT) - return FALSE; + return false; switch (data->state) { case IDENTITY: if (subtype != EAP_AKA_SUBTYPE_IDENTITY) { wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; case CHALLENGE: @@ -701,30 +701,30 @@ static Boolean eap_aka_subtype_ok(struct eap_aka_data *data, u8 subtype) subtype != EAP_AKA_SUBTYPE_SYNCHRONIZATION_FAILURE) { wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; case REAUTH: if (subtype != EAP_AKA_SUBTYPE_REAUTHENTICATION) { wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; case NOTIFICATION: if (subtype != EAP_AKA_SUBTYPE_NOTIFICATION) { wpa_printf(MSG_INFO, "EAP-AKA: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; default: wpa_printf(MSG_INFO, "EAP-AKA: Unexpected state (%d) for " "processing a response", data->state); - return TRUE; + return true; } - return FALSE; + return false; } @@ -1269,7 +1269,7 @@ static void eap_aka_process(struct eap_sm *sm, void *priv, } -static Boolean eap_aka_isDone(struct eap_sm *sm, void *priv) +static bool eap_aka_isDone(struct eap_sm *sm, void *priv) { struct eap_aka_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -1308,7 +1308,7 @@ static u8 * eap_aka_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_aka_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_aka_isSuccess(struct eap_sm *sm, void *priv) { struct eap_aka_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_eke.c b/src/eap_server/eap_server_eke.c index 71fab9624..eac3245cd 100644 --- a/src/eap_server/eap_server_eke.c +++ b/src/eap_server/eap_server_eke.c @@ -380,8 +380,8 @@ static struct wpabuf * eap_eke_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_eke_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_eke_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_eke_data *data = priv; size_t len; @@ -391,28 +391,28 @@ static Boolean eap_eke_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-EKE: Invalid frame"); - return TRUE; + return true; } eke_exch = *pos; wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: EKE-Exch=%d", eke_exch); if (data->state == IDENTITY && eke_exch == EAP_EKE_ID) - return FALSE; + return false; if (data->state == COMMIT && eke_exch == EAP_EKE_COMMIT) - return FALSE; + return false; if (data->state == CONFIRM && eke_exch == EAP_EKE_CONFIRM) - return FALSE; + return false; if (eke_exch == EAP_EKE_FAILURE) - return FALSE; + return false; wpa_printf(MSG_INFO, "EAP-EKE: Unexpected EKE-Exch=%d in state=%d", eke_exch, data->state); - return TRUE; + return true; } @@ -716,7 +716,7 @@ static void eap_eke_process(struct eap_sm *sm, void *priv, } -static Boolean eap_eke_isDone(struct eap_sm *sm, void *priv) +static bool eap_eke_isDone(struct eap_sm *sm, void *priv) { struct eap_eke_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -757,7 +757,7 @@ static u8 * eap_eke_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_eke_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_eke_isSuccess(struct eap_sm *sm, void *priv) { struct eap_eke_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_fast.c b/src/eap_server/eap_server_fast.c index 0270821cc..55d48d91f 100644 --- a/src/eap_server/eap_server_fast.c +++ b/src/eap_server/eap_server_fast.c @@ -929,8 +929,8 @@ static struct wpabuf * eap_fast_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_fast_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_fast_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -938,10 +938,10 @@ static Boolean eap_fast_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_FAST, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-FAST: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -1563,7 +1563,7 @@ static void eap_fast_process(struct eap_sm *sm, void *priv, } -static Boolean eap_fast_isDone(struct eap_sm *sm, void *priv) +static bool eap_fast_isDone(struct eap_sm *sm, void *priv) { struct eap_fast_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -1614,7 +1614,7 @@ static u8 * eap_fast_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_fast_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_fast_isSuccess(struct eap_sm *sm, void *priv) { struct eap_fast_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_gpsk.c b/src/eap_server/eap_server_gpsk.c index a7742751a..4081b9f99 100644 --- a/src/eap_server/eap_server_gpsk.c +++ b/src/eap_server/eap_server_gpsk.c @@ -208,8 +208,8 @@ static struct wpabuf * eap_gpsk_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_gpsk_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_gpsk_data *data = priv; const u8 *pos; @@ -218,21 +218,21 @@ static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-GPSK: Invalid frame"); - return TRUE; + return true; } wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode=%d", *pos); if (data->state == GPSK_1 && *pos == EAP_GPSK_OPCODE_GPSK_2) - return FALSE; + return false; if (data->state == GPSK_3 && *pos == EAP_GPSK_OPCODE_GPSK_4) - return FALSE; + return false; wpa_printf(MSG_INFO, "EAP-GPSK: Unexpected opcode=%d in state=%d", *pos, data->state); - return TRUE; + return true; } @@ -560,7 +560,7 @@ static void eap_gpsk_process(struct eap_sm *sm, void *priv, } -static Boolean eap_gpsk_isDone(struct eap_sm *sm, void *priv) +static bool eap_gpsk_isDone(struct eap_sm *sm, void *priv) { struct eap_gpsk_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -601,7 +601,7 @@ static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_gpsk_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_gpsk_isSuccess(struct eap_sm *sm, void *priv) { struct eap_gpsk_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_gtc.c b/src/eap_server/eap_server_gtc.c index fcccbcbd5..6310793a7 100644 --- a/src/eap_server/eap_server_gtc.c +++ b/src/eap_server/eap_server_gtc.c @@ -74,8 +74,8 @@ static struct wpabuf * eap_gtc_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_gtc_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_gtc_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -83,10 +83,10 @@ static Boolean eap_gtc_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GTC, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-GTC: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -184,14 +184,14 @@ static void eap_gtc_process(struct eap_sm *sm, void *priv, } -static Boolean eap_gtc_isDone(struct eap_sm *sm, void *priv) +static bool eap_gtc_isDone(struct eap_sm *sm, void *priv) { struct eap_gtc_data *data = priv; return data->state != CONTINUE; } -static Boolean eap_gtc_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_gtc_isSuccess(struct eap_sm *sm, void *priv) { struct eap_gtc_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_identity.c b/src/eap_server/eap_server_identity.c index 1b1db53f2..813e1d6de 100644 --- a/src/eap_server/eap_server_identity.c +++ b/src/eap_server/eap_server_identity.c @@ -79,8 +79,8 @@ static struct wpabuf * eap_identity_buildReq(struct eap_sm *sm, void *priv, } -static Boolean eap_identity_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_identity_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -89,10 +89,10 @@ static Boolean eap_identity_check(struct eap_sm *sm, void *priv, respData, &len); if (pos == NULL) { wpa_printf(MSG_INFO, "EAP-Identity: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -127,7 +127,7 @@ static void eap_identity_process(struct eap_sm *sm, void *priv, os_free(buf); } if (sm->identity) - sm->update_user = TRUE; + sm->update_user = true; os_free(sm->identity); sm->identity = os_malloc(len ? len : 1); if (sm->identity == NULL) { @@ -140,14 +140,14 @@ static void eap_identity_process(struct eap_sm *sm, void *priv, } -static Boolean eap_identity_isDone(struct eap_sm *sm, void *priv) +static bool eap_identity_isDone(struct eap_sm *sm, void *priv) { struct eap_identity_data *data = priv; return data->state != CONTINUE; } -static Boolean eap_identity_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_identity_isSuccess(struct eap_sm *sm, void *priv) { struct eap_identity_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_ikev2.c b/src/eap_server/eap_server_ikev2.c index 897637e8e..ef3cc8ccc 100644 --- a/src/eap_server/eap_server_ikev2.c +++ b/src/eap_server/eap_server_ikev2.c @@ -236,8 +236,8 @@ static struct wpabuf * eap_ikev2_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_ikev2_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_ikev2_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -246,10 +246,10 @@ static Boolean eap_ikev2_check(struct eap_sm *sm, void *priv, &len); if (pos == NULL) { wpa_printf(MSG_INFO, "EAP-IKEV2: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -465,14 +465,14 @@ static void eap_ikev2_process(struct eap_sm *sm, void *priv, } -static Boolean eap_ikev2_isDone(struct eap_sm *sm, void *priv) +static bool eap_ikev2_isDone(struct eap_sm *sm, void *priv) { struct eap_ikev2_data *data = priv; return data->state == DONE || data->state == FAIL; } -static Boolean eap_ikev2_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_ikev2_isSuccess(struct eap_sm *sm, void *priv) { struct eap_ikev2_data *data = priv; return data->state == DONE && data->ikev2.state == IKEV2_DONE && diff --git a/src/eap_server/eap_server_md5.c b/src/eap_server/eap_server_md5.c index cf5ceb1d1..c9b500cdb 100644 --- a/src/eap_server/eap_server_md5.c +++ b/src/eap_server/eap_server_md5.c @@ -73,8 +73,8 @@ static struct wpabuf * eap_md5_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_md5_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_md5_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -82,16 +82,16 @@ static Boolean eap_md5_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MD5, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-MD5: Invalid frame"); - return TRUE; + return true; } if (*pos != CHAP_MD5_LEN || 1 + CHAP_MD5_LEN > len) { wpa_printf(MSG_INFO, "EAP-MD5: Invalid response " "(response_len=%d payload_len=%lu", *pos, (unsigned long) len); - return TRUE; + return true; } - return FALSE; + return false; } @@ -136,14 +136,14 @@ static void eap_md5_process(struct eap_sm *sm, void *priv, } -static Boolean eap_md5_isDone(struct eap_sm *sm, void *priv) +static bool eap_md5_isDone(struct eap_sm *sm, void *priv) { struct eap_md5_data *data = priv; return data->state != CONTINUE; } -static Boolean eap_md5_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_md5_isSuccess(struct eap_sm *sm, void *priv) { struct eap_md5_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_mschapv2.c b/src/eap_server/eap_server_mschapv2.c index 8a1621aff..9b3eb26ef 100644 --- a/src/eap_server/eap_server_mschapv2.c +++ b/src/eap_server/eap_server_mschapv2.c @@ -235,8 +235,8 @@ static struct wpabuf * eap_mschapv2_buildReq(struct eap_sm *sm, void *priv, } -static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_mschapv2_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_mschapv2_data *data = priv; struct eap_mschapv2_hdr *resp; @@ -247,7 +247,7 @@ static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Invalid frame"); - return TRUE; + return true; } resp = (struct eap_mschapv2_hdr *) pos; @@ -255,7 +255,7 @@ static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv, resp->op_code != MSCHAPV2_OP_RESPONSE) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Response - " "ignore op %d", resp->op_code); - return TRUE; + return true; } if (data->state == SUCCESS_REQ && @@ -263,17 +263,17 @@ static Boolean eap_mschapv2_check(struct eap_sm *sm, void *priv, resp->op_code != MSCHAPV2_OP_FAILURE) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Success or " "Failure - ignore op %d", resp->op_code); - return TRUE; + return true; } if (data->state == FAILURE_REQ && resp->op_code != MSCHAPV2_OP_FAILURE) { wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Expected Failure " "- ignore op %d", resp->op_code); - return TRUE; + return true; } - return FALSE; + return false; } @@ -531,7 +531,7 @@ static void eap_mschapv2_process(struct eap_sm *sm, void *priv, } -static Boolean eap_mschapv2_isDone(struct eap_sm *sm, void *priv) +static bool eap_mschapv2_isDone(struct eap_sm *sm, void *priv) { struct eap_mschapv2_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -564,7 +564,7 @@ static u8 * eap_mschapv2_getKey(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_mschapv2_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_mschapv2_isSuccess(struct eap_sm *sm, void *priv) { struct eap_mschapv2_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_pax.c b/src/eap_server/eap_server_pax.c index 5ed29efd1..fb089d50a 100644 --- a/src/eap_server/eap_server_pax.c +++ b/src/eap_server/eap_server_pax.c @@ -195,8 +195,8 @@ static struct wpabuf * eap_pax_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_pax_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_pax_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_pax_data *data = priv; struct eap_pax_hdr *resp; @@ -207,7 +207,7 @@ static Boolean eap_pax_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); if (pos == NULL || len < sizeof(*resp) + EAP_PAX_ICV_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: Invalid frame"); - return TRUE; + return true; } mlen = sizeof(struct eap_hdr) + 1 + len; @@ -225,14 +225,14 @@ static Boolean eap_pax_check(struct eap_sm *sm, void *priv, resp->op_code != EAP_PAX_OP_STD_2) { wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX_STD-2 - " "ignore op %d", resp->op_code); - return TRUE; + return true; } if (data->state == PAX_STD_3 && resp->op_code != EAP_PAX_OP_ACK) { wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX-ACK - " "ignore op %d", resp->op_code); - return TRUE; + return true; } if (resp->op_code != EAP_PAX_OP_STD_2 && @@ -244,38 +244,38 @@ static Boolean eap_pax_check(struct eap_sm *sm, void *priv, if (data->mac_id != resp->mac_id) { wpa_printf(MSG_DEBUG, "EAP-PAX: Expected MAC ID 0x%x, " "received 0x%x", data->mac_id, resp->mac_id); - return TRUE; + return true; } if (resp->dh_group_id != EAP_PAX_DH_GROUP_NONE) { wpa_printf(MSG_INFO, "EAP-PAX: Expected DH Group ID 0x%x, " "received 0x%x", EAP_PAX_DH_GROUP_NONE, resp->dh_group_id); - return TRUE; + return true; } if (resp->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) { wpa_printf(MSG_INFO, "EAP-PAX: Expected Public Key ID 0x%x, " "received 0x%x", EAP_PAX_PUBLIC_KEY_NONE, resp->public_key_id); - return TRUE; + return true; } if (resp->flags & EAP_PAX_FLAGS_MF) { /* TODO: add support for reassembling fragments */ wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported"); - return TRUE; + return true; } if (resp->flags & EAP_PAX_FLAGS_CE) { wpa_printf(MSG_INFO, "EAP-PAX: Unexpected CE flag"); - return TRUE; + return true; } if (data->keys_set) { if (len - sizeof(*resp) < EAP_PAX_ICV_LEN) { wpa_printf(MSG_INFO, "EAP-PAX: No ICV in the packet"); - return TRUE; + return true; } icv = wpabuf_mhead_u8(respData) + mlen - EAP_PAX_ICV_LEN; wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN); @@ -285,18 +285,18 @@ static Boolean eap_pax_check(struct eap_sm *sm, void *priv, NULL, 0, NULL, 0, icvbuf) < 0) { wpa_printf(MSG_INFO, "EAP-PAX: Failed to calculate ICV"); - return TRUE; + return true; } if (os_memcmp_const(icvbuf, icv, EAP_PAX_ICV_LEN) != 0) { wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV"); wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV", icvbuf, EAP_PAX_ICV_LEN); - return TRUE; + return true; } } - return FALSE; + return false; } @@ -513,7 +513,7 @@ static void eap_pax_process(struct eap_sm *sm, void *priv, } -static Boolean eap_pax_isDone(struct eap_sm *sm, void *priv) +static bool eap_pax_isDone(struct eap_sm *sm, void *priv) { struct eap_pax_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -563,7 +563,7 @@ static u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_pax_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_pax_isSuccess(struct eap_sm *sm, void *priv) { struct eap_pax_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_peap.c b/src/eap_server/eap_server_peap.c index 02d8b8e88..f234f6fa5 100644 --- a/src/eap_server/eap_server_peap.c +++ b/src/eap_server/eap_server_peap.c @@ -569,8 +569,8 @@ static struct wpabuf * eap_peap_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_peap_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_peap_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -578,10 +578,10 @@ static Boolean eap_peap_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PEAP, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-PEAP: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -1289,7 +1289,7 @@ static void eap_peap_process(struct eap_sm *sm, void *priv, } -static Boolean eap_peap_isDone(struct eap_sm *sm, void *priv) +static bool eap_peap_isDone(struct eap_sm *sm, void *priv) { struct eap_peap_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -1383,7 +1383,7 @@ static u8 * eap_peap_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_peap_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_peap_isSuccess(struct eap_sm *sm, void *priv) { struct eap_peap_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_psk.c b/src/eap_server/eap_server_psk.c index 511973c94..f55f70dd8 100644 --- a/src/eap_server/eap_server_psk.c +++ b/src/eap_server/eap_server_psk.c @@ -171,8 +171,8 @@ static struct wpabuf * eap_psk_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_psk_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_psk_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_psk_data *data = priv; size_t len; @@ -182,7 +182,7 @@ static Boolean eap_psk_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); - return TRUE; + return true; } t = EAP_PSK_FLAGS_GET_T(*pos); @@ -191,22 +191,22 @@ static Boolean eap_psk_check(struct eap_sm *sm, void *priv, if (data->state == PSK_1 && t != 1) { wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-2 - " "ignore T=%d", t); - return TRUE; + return true; } if (data->state == PSK_3 && t != 3) { wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-4 - " "ignore T=%d", t); - return TRUE; + return true; } if ((t == 1 && len < sizeof(struct eap_psk_hdr_2)) || (t == 3 && len < sizeof(struct eap_psk_hdr_4))) { wpa_printf(MSG_DEBUG, "EAP-PSK: Too short frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -433,7 +433,7 @@ static void eap_psk_process(struct eap_sm *sm, void *priv, } -static Boolean eap_psk_isDone(struct eap_sm *sm, void *priv) +static bool eap_psk_isDone(struct eap_sm *sm, void *priv) { struct eap_psk_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -474,7 +474,7 @@ static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_psk_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_psk_isSuccess(struct eap_sm *sm, void *priv) { struct eap_psk_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_pwd.c b/src/eap_server/eap_server_pwd.c index 6bf3a23d0..81cddca60 100644 --- a/src/eap_server/eap_server_pwd.c +++ b/src/eap_server/eap_server_pwd.c @@ -530,8 +530,8 @@ eap_pwd_build_req(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_pwd_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_pwd_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_pwd_data *data = priv; const u8 *pos; @@ -540,7 +540,7 @@ static Boolean eap_pwd_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PWD, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-pwd: Invalid frame"); - return TRUE; + return true; } wpa_printf(MSG_DEBUG, "EAP-pwd: Received frame: exch = %d, len = %d", @@ -548,20 +548,20 @@ static Boolean eap_pwd_check(struct eap_sm *sm, void *priv, if (data->state == PWD_ID_Req && ((EAP_PWD_GET_EXCHANGE(*pos)) == EAP_PWD_OPCODE_ID_EXCH)) - return FALSE; + return false; if (data->state == PWD_Commit_Req && ((EAP_PWD_GET_EXCHANGE(*pos)) == EAP_PWD_OPCODE_COMMIT_EXCH)) - return FALSE; + return false; if (data->state == PWD_Confirm_Req && ((EAP_PWD_GET_EXCHANGE(*pos)) == EAP_PWD_OPCODE_CONFIRM_EXCH)) - return FALSE; + return false; wpa_printf(MSG_INFO, "EAP-pwd: Unexpected opcode=%d in state=%d", *pos, data->state); - return TRUE; + return true; } @@ -1003,14 +1003,14 @@ static u8 * eap_pwd_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_pwd_is_success(struct eap_sm *sm, void *priv) +static bool eap_pwd_is_success(struct eap_sm *sm, void *priv) { struct eap_pwd_data *data = priv; return data->state == SUCCESS; } -static Boolean eap_pwd_is_done(struct eap_sm *sm, void *priv) +static bool eap_pwd_is_done(struct eap_sm *sm, void *priv) { struct eap_pwd_data *data = priv; return (data->state == SUCCESS) || (data->state == FAILURE); diff --git a/src/eap_server/eap_server_sake.c b/src/eap_server/eap_server_sake.c index 56cfbfb32..8c39e63b9 100644 --- a/src/eap_server/eap_server_sake.c +++ b/src/eap_server/eap_server_sake.c @@ -232,8 +232,8 @@ static struct wpabuf * eap_sake_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_sake_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_sake_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_sake_data *data = priv; struct eap_sake_hdr *resp; @@ -244,7 +244,7 @@ static Boolean eap_sake_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, respData, &len); if (pos == NULL || len < sizeof(struct eap_sake_hdr)) { wpa_printf(MSG_INFO, "EAP-SAKE: Invalid frame"); - return TRUE; + return true; } resp = (struct eap_sake_hdr *) pos; @@ -254,33 +254,33 @@ static Boolean eap_sake_check(struct eap_sm *sm, void *priv, if (version != EAP_SAKE_VERSION) { wpa_printf(MSG_INFO, "EAP-SAKE: Unknown version %d", version); - return TRUE; + return true; } if (session_id != data->session_id) { wpa_printf(MSG_INFO, "EAP-SAKE: Session ID mismatch (%d,%d)", session_id, data->session_id); - return TRUE; + return true; } wpa_printf(MSG_DEBUG, "EAP-SAKE: Received frame: subtype=%d", subtype); if (data->state == IDENTITY && subtype == EAP_SAKE_SUBTYPE_IDENTITY) - return FALSE; + return false; if (data->state == CHALLENGE && subtype == EAP_SAKE_SUBTYPE_CHALLENGE) - return FALSE; + return false; if (data->state == CONFIRM && subtype == EAP_SAKE_SUBTYPE_CONFIRM) - return FALSE; + return false; if (subtype == EAP_SAKE_SUBTYPE_AUTH_REJECT) - return FALSE; + return false; wpa_printf(MSG_INFO, "EAP-SAKE: Unexpected subtype=%d in state=%d", subtype, data->state); - return TRUE; + return true; } @@ -456,7 +456,7 @@ static void eap_sake_process(struct eap_sm *sm, void *priv, } -static Boolean eap_sake_isDone(struct eap_sm *sm, void *priv) +static bool eap_sake_isDone(struct eap_sm *sm, void *priv) { struct eap_sake_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -497,7 +497,7 @@ static u8 * eap_sake_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_sake_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_sake_isSuccess(struct eap_sm *sm, void *priv) { struct eap_sake_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_sim.c b/src/eap_server/eap_server_sim.c index d7ac87ce5..8a6828962 100644 --- a/src/eap_server/eap_server_sim.c +++ b/src/eap_server/eap_server_sim.c @@ -360,8 +360,8 @@ static struct wpabuf * eap_sim_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_sim_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_sim_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -369,55 +369,55 @@ static Boolean eap_sim_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, respData, &len); if (pos == NULL || len < 3) { wpa_printf(MSG_INFO, "EAP-SIM: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } -static Boolean eap_sim_unexpected_subtype(struct eap_sim_data *data, - u8 subtype) +static bool eap_sim_unexpected_subtype(struct eap_sim_data *data, + u8 subtype) { if (subtype == EAP_SIM_SUBTYPE_CLIENT_ERROR) - return FALSE; + return false; switch (data->state) { case START: if (subtype != EAP_SIM_SUBTYPE_START) { wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; case CHALLENGE: if (subtype != EAP_SIM_SUBTYPE_CHALLENGE) { wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; case REAUTH: if (subtype != EAP_SIM_SUBTYPE_REAUTHENTICATION) { wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; case NOTIFICATION: if (subtype != EAP_SIM_SUBTYPE_NOTIFICATION) { wpa_printf(MSG_INFO, "EAP-SIM: Unexpected response " "subtype %d", subtype); - return TRUE; + return true; } break; default: wpa_printf(MSG_INFO, "EAP-SIM: Unexpected state (%d) for " "processing a response", data->state); - return TRUE; + return true; } - return FALSE; + return false; } @@ -794,7 +794,7 @@ static void eap_sim_process(struct eap_sm *sm, void *priv, } -static Boolean eap_sim_isDone(struct eap_sm *sm, void *priv) +static bool eap_sim_isDone(struct eap_sm *sm, void *priv) { struct eap_sim_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -833,7 +833,7 @@ static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_sim_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_sim_isSuccess(struct eap_sm *sm, void *priv) { struct eap_sim_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_teap.c b/src/eap_server/eap_server_teap.c index a2cbf7a7b..691b44a8d 100644 --- a/src/eap_server/eap_server_teap.c +++ b/src/eap_server/eap_server_teap.c @@ -64,7 +64,7 @@ struct eap_teap_data { struct wpabuf *pending_phase2_resp; struct wpabuf *server_outer_tlvs; struct wpabuf *peer_outer_tlvs; - u8 *identity; /* from PAC-Opaque */ + u8 *identity; /* from PAC-Opaque or client certificate */ size_t identity_len; int eap_seq; int tnc_started; @@ -365,7 +365,9 @@ static void * eap_teap_init(struct eap_sm *sm) data->teap_version = EAP_TEAP_VERSION; data->state = START; - if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_TYPE_TEAP)) { + if (eap_server_tls_ssl_init(sm, &data->ssl, + sm->cfg->eap_teap_auth == 2 ? 2 : 0, + EAP_TYPE_TEAP)) { wpa_printf(MSG_INFO, "EAP-TEAP: Failed to initialize SSL."); eap_teap_reset(sm, data); return NULL; @@ -502,6 +504,19 @@ static int eap_teap_phase1_done(struct eap_sm *sm, struct eap_teap_data *data) wpa_printf(MSG_DEBUG, "EAP-TEAP: Phase 1 done, starting Phase 2"); + if (!data->identity && sm->cfg->eap_teap_auth == 2) { + const char *subject; + + subject = tls_connection_get_peer_subject(data->ssl.conn); + if (subject) { + wpa_printf(MSG_DEBUG, + "EAP-TEAP: Peer subject from Phase 1 client certificate: '%s'", + subject); + data->identity = (u8 *) os_strdup(subject); + data->identity_len = os_strlen(subject); + } + } + data->tls_cs = tls_connection_get_cipher_suite(data->ssl.conn); wpa_printf(MSG_DEBUG, "EAP-TEAP: TLS cipher suite 0x%04x", data->tls_cs); @@ -965,8 +980,8 @@ static struct wpabuf * eap_teap_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_teap_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_teap_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -974,10 +989,10 @@ static Boolean eap_teap_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TEAP, respData, &len); if (!pos || len < 1) { wpa_printf(MSG_INFO, "EAP-TEAP: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -1775,9 +1790,10 @@ static int eap_teap_process_phase2_start(struct eap_sm *sm, next_vendor = EAP_VENDOR_IETF; next_type = EAP_TYPE_NONE; eap_teap_state(data, PHASE2_METHOD); - } else if (sm->cfg->eap_teap_pac_no_inner) { + } else if (sm->cfg->eap_teap_pac_no_inner || + sm->cfg->eap_teap_auth == 2) { wpa_printf(MSG_DEBUG, - "EAP-TEAP: Used PAC and identity already known - skip inner auth"); + "EAP-TEAP: Used PAC or client certificate and identity already known - skip inner auth"); data->skipped_inner_auth = 1; /* FIX: Need to derive CMK here. However, how is that * supposed to be done? RFC 7170 does not tell that for @@ -1974,7 +1990,7 @@ static void eap_teap_process(struct eap_sm *sm, void *priv, } -static Boolean eap_teap_isDone(struct eap_sm *sm, void *priv) +static bool eap_teap_isDone(struct eap_sm *sm, void *priv) { struct eap_teap_data *data = priv; @@ -2032,7 +2048,7 @@ static u8 * eap_teap_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_teap_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_teap_isSuccess(struct eap_sm *sm, void *priv) { struct eap_teap_data *data = priv; diff --git a/src/eap_server/eap_server_tls.c b/src/eap_server/eap_server_tls.c index c64cebb40..769fd1fe0 100644 --- a/src/eap_server/eap_server_tls.c +++ b/src/eap_server/eap_server_tls.c @@ -226,8 +226,8 @@ check_established: } -static Boolean eap_tls_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_tls_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_tls_data *data = priv; const u8 *pos; @@ -246,10 +246,10 @@ static Boolean eap_tls_check(struct eap_sm *sm, void *priv, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -346,7 +346,7 @@ static void eap_tls_process(struct eap_sm *sm, void *priv, } -static Boolean eap_tls_isDone(struct eap_sm *sm, void *priv) +static bool eap_tls_isDone(struct eap_sm *sm, void *priv) { struct eap_tls_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -431,7 +431,7 @@ static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_tls_isSuccess(struct eap_sm *sm, void *priv) { struct eap_tls_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_tnc.c b/src/eap_server/eap_server_tnc.c index f6cdcb1ef..36fb5c34d 100644 --- a/src/eap_server/eap_server_tnc.c +++ b/src/eap_server/eap_server_tnc.c @@ -320,8 +320,8 @@ static struct wpabuf * eap_tnc_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_tnc_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_tnc_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { struct eap_tnc_data *data = priv; const u8 *pos; @@ -331,29 +331,29 @@ static Boolean eap_tnc_check(struct eap_sm *sm, void *priv, &len); if (pos == NULL) { wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame"); - return TRUE; + return true; } if (len == 0 && data->state != WAIT_FRAG_ACK) { wpa_printf(MSG_INFO, "EAP-TNC: Invalid frame (empty)"); - return TRUE; + return true; } if (len == 0) - return FALSE; /* Fragment ACK does not include flags */ + return false; /* Fragment ACK does not include flags */ if ((*pos & EAP_TNC_VERSION_MASK) != EAP_TNC_VERSION) { wpa_printf(MSG_DEBUG, "EAP-TNC: Unsupported version %d", *pos & EAP_TNC_VERSION_MASK); - return TRUE; + return true; } if (*pos & EAP_TNC_FLAGS_START) { wpa_printf(MSG_DEBUG, "EAP-TNC: Peer used Start flag"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -537,14 +537,14 @@ static void eap_tnc_process(struct eap_sm *sm, void *priv, } -static Boolean eap_tnc_isDone(struct eap_sm *sm, void *priv) +static bool eap_tnc_isDone(struct eap_sm *sm, void *priv) { struct eap_tnc_data *data = priv; return data->state == DONE || data->state == FAIL; } -static Boolean eap_tnc_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_tnc_isSuccess(struct eap_sm *sm, void *priv) { struct eap_tnc_data *data = priv; return data->state == DONE; diff --git a/src/eap_server/eap_server_ttls.c b/src/eap_server/eap_server_ttls.c index 721835dbf..2f0c041d5 100644 --- a/src/eap_server/eap_server_ttls.c +++ b/src/eap_server/eap_server_ttls.c @@ -509,8 +509,8 @@ static struct wpabuf * eap_ttls_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_ttls_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_ttls_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -518,10 +518,10 @@ static Boolean eap_ttls_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TTLS, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-TTLS: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -1260,7 +1260,7 @@ static void eap_ttls_process(struct eap_sm *sm, void *priv, } -static Boolean eap_ttls_isDone(struct eap_sm *sm, void *priv) +static bool eap_ttls_isDone(struct eap_sm *sm, void *priv) { struct eap_ttls_data *data = priv; return data->state == SUCCESS || data->state == FAILURE; @@ -1290,7 +1290,7 @@ static u8 * eap_ttls_getKey(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_ttls_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_ttls_isSuccess(struct eap_sm *sm, void *priv) { struct eap_ttls_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_vendor_test.c b/src/eap_server/eap_server_vendor_test.c index 963997759..77860411b 100644 --- a/src/eap_server/eap_server_vendor_test.c +++ b/src/eap_server/eap_server_vendor_test.c @@ -88,8 +88,8 @@ static struct wpabuf * eap_vendor_test_buildReq(struct eap_sm *sm, void *priv, } -static Boolean eap_vendor_test_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_vendor_test_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -97,10 +97,10 @@ static Boolean eap_vendor_test_check(struct eap_sm *sm, void *priv, pos = eap_hdr_validate(EAP_VENDOR_ID, EAP_VENDOR_TYPE, respData, &len); if (pos == NULL || len < 1) { wpa_printf(MSG_INFO, "EAP-VENDOR-TEST: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -130,7 +130,7 @@ static void eap_vendor_test_process(struct eap_sm *sm, void *priv, } -static Boolean eap_vendor_test_isDone(struct eap_sm *sm, void *priv) +static bool eap_vendor_test_isDone(struct eap_sm *sm, void *priv) { struct eap_vendor_test_data *data = priv; return data->state == SUCCESS; @@ -158,7 +158,7 @@ static u8 * eap_vendor_test_getKey(struct eap_sm *sm, void *priv, size_t *len) } -static Boolean eap_vendor_test_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_vendor_test_isSuccess(struct eap_sm *sm, void *priv) { struct eap_vendor_test_data *data = priv; return data->state == SUCCESS; diff --git a/src/eap_server/eap_server_wsc.c b/src/eap_server/eap_server_wsc.c index 364c089aa..fc70cf196 100644 --- a/src/eap_server/eap_server_wsc.c +++ b/src/eap_server/eap_server_wsc.c @@ -270,8 +270,8 @@ static struct wpabuf * eap_wsc_buildReq(struct eap_sm *sm, void *priv, u8 id) } -static Boolean eap_wsc_check(struct eap_sm *sm, void *priv, - struct wpabuf *respData) +static bool eap_wsc_check(struct eap_sm *sm, void *priv, + struct wpabuf *respData) { const u8 *pos; size_t len; @@ -280,10 +280,10 @@ static Boolean eap_wsc_check(struct eap_sm *sm, void *priv, respData, &len); if (pos == NULL || len < 2) { wpa_printf(MSG_INFO, "EAP-WSC: Invalid frame"); - return TRUE; + return true; } - return FALSE; + return false; } @@ -462,17 +462,17 @@ static void eap_wsc_process(struct eap_sm *sm, void *priv, } -static Boolean eap_wsc_isDone(struct eap_sm *sm, void *priv) +static bool eap_wsc_isDone(struct eap_sm *sm, void *priv) { struct eap_wsc_data *data = priv; return data->state == FAIL; } -static Boolean eap_wsc_isSuccess(struct eap_sm *sm, void *priv) +static bool eap_wsc_isSuccess(struct eap_sm *sm, void *priv) { /* EAP-WSC will always result in EAP-Failure */ - return FALSE; + return false; } diff --git a/src/eapol_auth/Makefile b/src/eapol_auth/Makefile index 7b927a127..c82042f43 100644 --- a/src/eapol_auth/Makefile +++ b/src/eapol_auth/Makefile @@ -1,16 +1,2 @@ -all: libeapol_auth.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libeapol_auth.a - -install: - @echo Nothing to be made. - -include ../lib.rules - LIB_OBJS = eapol_auth_sm.o eapol_auth_dump.o - -libeapol_auth.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/eapol_auth/eapol_auth_sm.c b/src/eapol_auth/eapol_auth_sm.c index 5a2ba261d..1c11cb613 100644 --- a/src/eapol_auth/eapol_auth_sm.c +++ b/src/eapol_auth/eapol_auth_sm.c @@ -56,6 +56,7 @@ static void eapol_auth_logger(struct eapol_authenticator *eapol, } +PRINTF_FORMAT(4, 5) static void eapol_auth_vlogger(struct eapol_authenticator *eapol, const u8 *addr, eapol_logger_level level, const char *fmt, ...) @@ -206,10 +207,10 @@ SM_STATE(AUTH_PAE, INITIALIZE) * get here on disconnection event without advancing to the * AUTHENTICATING state to clear keyRun before the IEEE 802.11 RSN * authenticator state machine runs and that may advance from - * AUTHENTICATION2 to INITPMK if keyRun = TRUE has been left from the + * AUTHENTICATION2 to INITPMK if keyRun = true has been left from the * last association. This can be avoided by clearing keyRun here. */ - sm->keyRun = FALSE; + sm->keyRun = false; } @@ -229,7 +230,7 @@ SM_STATE(AUTH_PAE, DISCONNECTED) sm->authPortStatus = Unauthorized; setPortUnauthorized(); sm->reAuthCount = 0; - sm->eapolLogoff = FALSE; + sm->eapolLogoff = false; if (!from_initialize) { sm->eapol->cb.finished(sm->eapol->conf.ctx, sm->sta, 0, sm->flags & EAPOL_SM_PREAUTH, @@ -251,7 +252,7 @@ SM_STATE(AUTH_PAE, RESTART) SM_ENTRY_MA(AUTH_PAE, RESTART, auth_pae); - sm->eap_if->eapRestart = TRUE; + sm->eap_if->eapRestart = true; } @@ -262,7 +263,7 @@ SM_STATE(AUTH_PAE, CONNECTING) SM_ENTRY_MA(AUTH_PAE, CONNECTING, auth_pae); - sm->reAuthenticate = FALSE; + sm->reAuthenticate = false; sm->reAuthCount++; } @@ -277,7 +278,7 @@ SM_STATE(AUTH_PAE, HELD) sm->authPortStatus = Unauthorized; setPortUnauthorized(); sm->quietWhile = sm->quietPeriod; - sm->eapolLogoff = FALSE; + sm->eapolLogoff = false; eapol_auth_vlogger(sm->eapol, sm->addr, EAPOL_LOGGER_WARNING, "authentication failed - EAP type: %d (%s)", @@ -324,13 +325,13 @@ SM_STATE(AUTH_PAE, AUTHENTICATING) { SM_ENTRY_MA(AUTH_PAE, AUTHENTICATING, auth_pae); - sm->eapolStart = FALSE; - sm->authSuccess = FALSE; - sm->authFail = FALSE; - sm->authTimeout = FALSE; - sm->authStart = TRUE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; + sm->eapolStart = false; + sm->authSuccess = false; + sm->authFail = false; + sm->authTimeout = false; + sm->authStart = true; + sm->keyRun = false; + sm->keyDone = false; } @@ -347,9 +348,9 @@ SM_STATE(AUTH_PAE, ABORTING) SM_ENTRY_MA(AUTH_PAE, ABORTING, auth_pae); - sm->authAbort = TRUE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; + sm->authAbort = true; + sm->keyRun = false; + sm->keyDone = false; } @@ -360,7 +361,7 @@ SM_STATE(AUTH_PAE, FORCE_AUTH) sm->authPortStatus = Authorized; setPortAuthorized(); sm->portMode = ForceAuthorized; - sm->eapolStart = FALSE; + sm->eapolStart = false; txCannedSuccess(); } @@ -372,7 +373,7 @@ SM_STATE(AUTH_PAE, FORCE_UNAUTH) sm->authPortStatus = Unauthorized; setPortUnauthorized(); sm->portMode = ForceUnauthorized; - sm->eapolStart = FALSE; + sm->eapolStart = false; txCannedFail(); } @@ -457,8 +458,8 @@ SM_STATE(BE_AUTH, INITIALIZE) SM_ENTRY_MA(BE_AUTH, INITIALIZE, be_auth); abortAuth(); - sm->eap_if->eapNoReq = FALSE; - sm->authAbort = FALSE; + sm->eap_if->eapNoReq = false; + sm->authAbort = false; } @@ -467,7 +468,7 @@ SM_STATE(BE_AUTH, REQUEST) SM_ENTRY_MA(BE_AUTH, REQUEST, be_auth); txReq(); - sm->eap_if->eapReq = FALSE; + sm->eap_if->eapReq = false; sm->backendOtherRequestsToSupplicant++; /* @@ -481,7 +482,7 @@ SM_STATE(BE_AUTH, REQUEST) * EAP-Request from the main EAP method. This can be avoided by * clearing eapolEap here. */ - sm->eapolEap = FALSE; + sm->eapolEap = false; } @@ -489,11 +490,11 @@ SM_STATE(BE_AUTH, RESPONSE) { SM_ENTRY_MA(BE_AUTH, RESPONSE, be_auth); - sm->authTimeout = FALSE; - sm->eapolEap = FALSE; - sm->eap_if->eapNoReq = FALSE; + sm->authTimeout = false; + sm->eapolEap = false; + sm->eap_if->eapNoReq = false; sm->aWhile = sm->serverTimeout; - sm->eap_if->eapResp = TRUE; + sm->eap_if->eapResp = true; /* sendRespToServer(); */ sm->backendResponses++; } @@ -504,8 +505,8 @@ SM_STATE(BE_AUTH, SUCCESS) SM_ENTRY_MA(BE_AUTH, SUCCESS, be_auth); txReq(); - sm->authSuccess = TRUE; - sm->keyRun = TRUE; + sm->authSuccess = true; + sm->keyRun = true; } @@ -514,7 +515,7 @@ SM_STATE(BE_AUTH, FAIL) SM_ENTRY_MA(BE_AUTH, FAIL, be_auth); txReq(); - sm->authFail = TRUE; + sm->authFail = true; } @@ -522,7 +523,7 @@ SM_STATE(BE_AUTH, TIMEOUT) { SM_ENTRY_MA(BE_AUTH, TIMEOUT, be_auth); - sm->authTimeout = TRUE; + sm->authTimeout = true; } @@ -530,7 +531,7 @@ SM_STATE(BE_AUTH, IDLE) { SM_ENTRY_MA(BE_AUTH, IDLE, be_auth); - sm->authStart = FALSE; + sm->authStart = false; } @@ -538,7 +539,7 @@ SM_STATE(BE_AUTH, IGNORE) { SM_ENTRY_MA(BE_AUTH, IGNORE, be_auth); - sm->eap_if->eapNoReq = FALSE; + sm->eap_if->eapNoReq = false; } @@ -621,7 +622,7 @@ SM_STATE(REAUTH_TIMER, REAUTHENTICATE) { SM_ENTRY_MA(REAUTH_TIMER, REAUTHENTICATE, reauth_timer); - sm->reAuthenticate = TRUE; + sm->reAuthenticate = true; sm->eapol->cb.eapol_event(sm->eapol->conf.ctx, sm->sta, EAPOL_AUTH_REAUTHENTICATE); } @@ -648,6 +649,8 @@ SM_STEP(REAUTH_TIMER) +#ifdef CONFIG_WEP + /* Authenticator Key Transmit state machine */ SM_STATE(AUTH_KEY_TX, NO_KEY_TRANSMIT) @@ -661,8 +664,8 @@ SM_STATE(AUTH_KEY_TX, KEY_TRANSMIT) SM_ENTRY_MA(AUTH_KEY_TX, KEY_TRANSMIT, auth_key_tx); txKey(); - sm->eap_if->eapKeyAvailable = FALSE; - sm->keyDone = TRUE; + sm->eap_if->eapKeyAvailable = false; + sm->keyDone = true; } @@ -703,7 +706,7 @@ SM_STATE(KEY_RX, KEY_RECEIVE) SM_ENTRY_MA(KEY_RX, KEY_RECEIVE, key_rx); processKey(); - sm->rxKey = FALSE; + sm->rxKey = false; } @@ -726,6 +729,8 @@ SM_STEP(KEY_RX) } } +#endif /* CONFIG_WEP */ + /* Controlled Directions state machine */ @@ -803,7 +808,7 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, sm->reauth_timer_state = REAUTH_TIMER_INITIALIZE; sm->reAuthPeriod = eapol->conf.eap_reauth_period; - sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0 ? TRUE : FALSE; + sm->reAuthEnabled = eapol->conf.eap_reauth_period > 0; sm->auth_key_tx_state = AUTH_KEY_TX_NO_KEY_TRANSMIT; @@ -813,15 +818,17 @@ eapol_auth_alloc(struct eapol_authenticator *eapol, const u8 *addr, sm->portControl = Auto; +#ifdef CONFIG_WEP if (!eapol->conf.wpa && (eapol->default_wep_key || eapol->conf.individual_wep_key_len > 0)) - sm->keyTxEnabled = TRUE; + sm->keyTxEnabled = true; else - sm->keyTxEnabled = FALSE; +#endif /* CONFIG_WEP */ + sm->keyTxEnabled = false; if (eapol->conf.wpa) - sm->portValid = FALSE; + sm->portValid = false; else - sm->portValid = TRUE; + sm->portValid = true; os_memset(&eap_sess, 0, sizeof(eap_sess)); eap_sess.assoc_wps_ie = assoc_wps_ie; @@ -910,10 +917,12 @@ restart: SM_STEP_RUN(BE_AUTH); if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(REAUTH_TIMER); +#ifdef CONFIG_WEP if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(AUTH_KEY_TX); if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(KEY_RX); +#endif /* CONFIG_WEP */ if (sm->initializing || eapol_sm_sta_entry_alive(eapol, addr)) SM_STEP_RUN(CTRL_DIR); @@ -941,7 +950,7 @@ restart: /* TODO: find a better location for this */ if (sm->eap_if->aaaEapResp) { - sm->eap_if->aaaEapResp = FALSE; + sm->eap_if->aaaEapResp = false; if (sm->eap_if->aaaEapRespData == NULL) { wpa_printf(MSG_DEBUG, "EAPOL: aaaEapResp set, " "but no aaaEapRespData available"); @@ -988,14 +997,14 @@ void eapol_auth_step(struct eapol_state_machine *sm) static void eapol_auth_initialize(struct eapol_state_machine *sm) { - sm->initializing = TRUE; + sm->initializing = true; /* Initialize the state machines by asserting initialize and then * deasserting it after one step */ - sm->initialize = TRUE; + sm->initialize = true; eapol_sm_step_run(sm); - sm->initialize = FALSE; + sm->initialize = false; eapol_sm_step_run(sm); - sm->initializing = FALSE; + sm->initializing = false; /* Start one second tick for port timers state machine */ eloop_cancel_timeout(eapol_port_timers_tick, NULL, sm); @@ -1083,7 +1092,7 @@ void eapol_auth_reauthenticate(struct eapol_state_machine *sm) { wpa_printf(MSG_DEBUG, "EAPOL: External reauthentication trigger for " MACSTR, MAC2STR(sm->addr)); - sm->reAuthenticate = TRUE; + sm->reAuthenticate = true; eapol_auth_step(sm); } @@ -1136,9 +1145,9 @@ int eapol_auth_set_conf(struct eapol_state_machine *sm, const char *param, if (os_strcasecmp(param, "reAuthEnabled") == 0) { if (os_strcmp(value, "TRUE") == 0) - sm->reAuthEnabled = TRUE; + sm->reAuthEnabled = true; else if (os_strcmp(value, "FALSE") == 0) - sm->reAuthEnabled = FALSE; + sm->reAuthEnabled = false; else return -1; eapol_auth_step(sm); @@ -1147,9 +1156,9 @@ int eapol_auth_set_conf(struct eapol_state_machine *sm, const char *param, if (os_strcasecmp(param, "KeyTransmissionEnabled") == 0) { if (os_strcmp(value, "TRUE") == 0) - sm->keyTxEnabled = TRUE; + sm->keyTxEnabled = true; else if (os_strcmp(value, "FALSE") == 0) - sm->keyTxEnabled = FALSE; + sm->keyTxEnabled = false; else return -1; eapol_auth_step(sm); @@ -1167,7 +1176,9 @@ static int eapol_auth_conf_clone(struct eapol_auth_config *dst, dst->ctx = src->ctx; dst->eap_reauth_period = src->eap_reauth_period; dst->wpa = src->wpa; +#ifdef CONFIG_WEP dst->individual_wep_key_len = src->individual_wep_key_len; +#endif /* CONFIG_WEP */ os_free(dst->eap_req_id_text); if (src->eap_req_id_text) { dst->eap_req_id_text = os_memdup(src->eap_req_id_text, @@ -1221,10 +1232,12 @@ struct eapol_authenticator * eapol_auth_init(struct eapol_auth_config *conf, return NULL; } +#ifdef CONFIG_WEP if (conf->individual_wep_key_len > 0) { /* use key0 in individual key and key1 in broadcast key */ eapol->default_wep_key_idx = 1; } +#endif /* CONFIG_WEP */ eapol->cb.eapol_send = cb->eapol_send; eapol->cb.aaa_send = cb->aaa_send; @@ -1249,6 +1262,8 @@ void eapol_auth_deinit(struct eapol_authenticator *eapol) return; eapol_auth_conf_free(&eapol->conf); +#ifdef CONFIG_WEP os_free(eapol->default_wep_key); +#endif /* CONFIG_WEP */ os_free(eapol); } diff --git a/src/eapol_auth/eapol_auth_sm_i.h b/src/eapol_auth/eapol_auth_sm_i.h index 04386b2ce..3c6898310 100644 --- a/src/eapol_auth/eapol_auth_sm_i.h +++ b/src/eapol_auth/eapol_auth_sm_i.h @@ -43,23 +43,23 @@ struct eapol_state_machine { int reAuthWhen; /* global variables */ - Boolean authAbort; - Boolean authFail; + bool authAbort; + bool authFail; PortState authPortStatus; - Boolean authStart; - Boolean authTimeout; - Boolean authSuccess; - Boolean eapolEap; - Boolean initialize; - Boolean keyDone; - Boolean keyRun; - Boolean keyTxEnabled; + bool authStart; + bool authTimeout; + bool authSuccess; + bool eapolEap; + bool initialize; + bool keyDone; + bool keyRun; + bool keyTxEnabled; PortTypes portControl; - Boolean portValid; - Boolean reAuthenticate; + bool portValid; + bool reAuthenticate; /* Port Timers state machine */ - /* 'Boolean tick' implicitly handled as registered timeout */ + /* 'bool tick' implicitly handled as registered timeout */ /* Authenticator PAE state machine */ enum { AUTH_PAE_INITIALIZE, AUTH_PAE_DISCONNECTED, AUTH_PAE_CONNECTING, @@ -67,8 +67,8 @@ struct eapol_state_machine { AUTH_PAE_ABORTING, AUTH_PAE_HELD, AUTH_PAE_FORCE_AUTH, AUTH_PAE_FORCE_UNAUTH, AUTH_PAE_RESTART } auth_pae_state; /* variables */ - Boolean eapolLogoff; - Boolean eapolStart; + bool eapolLogoff; + bool eapolStart; PortTypes portMode; unsigned int reAuthCount; /* constants */ @@ -109,7 +109,7 @@ struct eapol_state_machine { } reauth_timer_state; /* constants */ unsigned int reAuthPeriod; /* default 3600 s */ - Boolean reAuthEnabled; + bool reAuthEnabled; /* Authenticator Key Transmit state machine */ enum { AUTH_KEY_TX_NO_KEY_TRANSMIT, AUTH_KEY_TX_KEY_TRANSMIT @@ -118,14 +118,14 @@ struct eapol_state_machine { /* Key Receive state machine */ enum { KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE } key_rx_state; /* variables */ - Boolean rxKey; + bool rxKey; /* Controlled Directions state machine */ enum { CTRL_DIR_FORCE_BOTH, CTRL_DIR_IN_OR_BOTH } ctrl_dir_state; /* variables */ ControlledDirection adminControlledDirections; ControlledDirection operControlledDirections; - Boolean operEdge; + bool operEdge; /* Authenticator Statistics Table */ Counter dot1xAuthEapolFramesRx; @@ -161,8 +161,8 @@ struct eapol_state_machine { struct eap_sm *eap; - Boolean initializing; /* in process of initializing state machines */ - Boolean changed; + bool initializing; /* in process of initializing state machines */ + bool changed; struct eapol_authenticator *eapol; diff --git a/src/eapol_supp/Makefile b/src/eapol_supp/Makefile index 80db9d486..67a11857b 100644 --- a/src/eapol_supp/Makefile +++ b/src/eapol_supp/Makefile @@ -1,18 +1,5 @@ -all: libeapol_supp.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libeapol_supp.a - -install: - @echo Nothing to be made. - -include ../lib.rules - CFLAGS += -DIEEE8021X_EAPOL LIB_OBJS = eapol_supp_sm.o -libeapol_supp.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/eapol_supp/eapol_supp_sm.c b/src/eapol_supp/eapol_supp_sm.c index f1ca0a859..861eea2ae 100644 --- a/src/eapol_supp/eapol_supp_sm.c +++ b/src/eapol_supp/eapol_supp_sm.c @@ -38,21 +38,21 @@ struct eapol_sm { int timer_tick_enabled; /* Global variables */ - Boolean eapFail; - Boolean eapolEap; - Boolean eapSuccess; - Boolean initialize; - Boolean keyDone; - Boolean keyRun; + bool eapFail; + bool eapolEap; + bool eapSuccess; + bool initialize; + bool keyDone; + bool keyRun; PortControl portControl; - Boolean portEnabled; + bool portEnabled; PortStatus suppPortStatus; /* dot1xSuppControlledPortStatus */ - Boolean portValid; - Boolean suppAbort; - Boolean suppFail; - Boolean suppStart; - Boolean suppSuccess; - Boolean suppTimeout; + bool portValid; + bool suppAbort; + bool suppFail; + bool suppStart; + bool suppSuccess; + bool suppTimeout; /* Supplicant PAE state machine */ enum { @@ -69,10 +69,10 @@ struct eapol_sm { SUPP_PAE_S_FORCE_UNAUTH = 10 } SUPP_PAE_state; /* dot1xSuppPaeState */ /* Variables */ - Boolean userLogoff; - Boolean logoffSent; + bool userLogoff; + bool logoffSent; unsigned int startCount; - Boolean eapRestart; + bool eapRestart; PortControl sPortMode; /* Constants */ unsigned int heldPeriod; /* dot1xSuppHeldPeriod */ @@ -85,7 +85,7 @@ struct eapol_sm { KEY_RX_NO_KEY_RECEIVE, KEY_RX_KEY_RECEIVE } KEY_RX_state; /* Variables */ - Boolean rxKey; + bool rxKey; /* Supplicant Backend state machine */ enum { @@ -100,9 +100,9 @@ struct eapol_sm { SUPP_BE_SUCCESS = 8 } SUPP_BE_state; /* dot1xSuppBackendPaeState */ /* Variables */ - Boolean eapNoResp; - Boolean eapReq; - Boolean eapResp; + bool eapNoResp; + bool eapReq; + bool eapResp; /* Constants */ unsigned int authPeriod; /* dot1xSuppAuthPeriod */ @@ -120,30 +120,30 @@ struct eapol_sm { unsigned char dot1xSuppLastEapolFrameSource[6]; /* Miscellaneous variables (not defined in IEEE 802.1X-2004) */ - Boolean changed; + bool changed; struct eap_sm *eap; struct eap_peer_config *config; - Boolean initial_req; + bool initial_req; u8 *last_rx_key; size_t last_rx_key_len; struct wpabuf *eapReqData; /* for EAP */ - Boolean altAccept; /* for EAP */ - Boolean altReject; /* for EAP */ - Boolean eapTriggerStart; - Boolean replay_counter_valid; + bool altAccept; /* for EAP */ + bool altReject; /* for EAP */ + bool eapTriggerStart; + bool replay_counter_valid; u8 last_replay_counter[16]; struct eapol_config conf; struct eapol_ctx *ctx; enum { EAPOL_CB_IN_PROGRESS = 0, EAPOL_CB_SUCCESS, EAPOL_CB_FAILURE } cb_status; - Boolean cached_pmk; + bool cached_pmk; - Boolean unicast_key_received, broadcast_key_received; + bool unicast_key_received, broadcast_key_received; - Boolean force_authorized_update; + bool force_authorized_update; #ifdef CONFIG_EAP_PROXY - Boolean use_eap_proxy; + bool use_eap_proxy; struct eap_proxy_sm *eap_proxy; #endif /* CONFIG_EAP_PROXY */ }; @@ -200,6 +200,15 @@ static void eapol_port_timers_tick(void *eloop_ctx, void *timeout_ctx) } +static int eapol_sm_confirm_auth(struct eapol_sm *sm) +{ + if (!sm->ctx->confirm_auth_cb) + return 0; + + return sm->ctx->confirm_auth_cb(sm->ctx->ctx); +} + + static void eapol_enable_timer_tick(struct eapol_sm *sm) { if (sm->timer_tick_enabled) @@ -215,7 +224,7 @@ SM_STATE(SUPP_PAE, LOGOFF) { SM_ENTRY(SUPP_PAE, LOGOFF); eapol_sm_txLogoff(sm); - sm->logoffSent = TRUE; + sm->logoffSent = true; eapol_sm_set_port_unauthorized(sm); } @@ -225,13 +234,13 @@ SM_STATE(SUPP_PAE, DISCONNECTED) SM_ENTRY(SUPP_PAE, DISCONNECTED); sm->sPortMode = Auto; sm->startCount = 0; - sm->eapTriggerStart = FALSE; - sm->logoffSent = FALSE; + sm->eapTriggerStart = false; + sm->logoffSent = false; eapol_sm_set_port_unauthorized(sm); - sm->suppAbort = TRUE; + sm->suppAbort = true; - sm->unicast_key_received = FALSE; - sm->broadcast_key_received = FALSE; + sm->unicast_key_received = false; + sm->broadcast_key_received = false; /* * IEEE Std 802.1X-2004 does not clear heldWhile here, but doing so @@ -254,7 +263,7 @@ SM_STATE(SUPP_PAE, CONNECTING) send_start = 1; if (sm->ctx->preauth) send_start = 1; - sm->eapTriggerStart = FALSE; + sm->eapTriggerStart = false; if (send_start) { sm->startWhen = sm->startPeriod; @@ -277,7 +286,7 @@ SM_STATE(SUPP_PAE, CONNECTING) } } eapol_enable_timer_tick(sm); - sm->eapolEap = FALSE; + sm->eapolEap = false; if (send_start) eapol_sm_txStart(sm); } @@ -287,12 +296,12 @@ SM_STATE(SUPP_PAE, AUTHENTICATING) { SM_ENTRY(SUPP_PAE, AUTHENTICATING); sm->startCount = 0; - sm->suppSuccess = FALSE; - sm->suppFail = FALSE; - sm->suppTimeout = FALSE; - sm->keyRun = FALSE; - sm->keyDone = FALSE; - sm->suppStart = TRUE; + sm->suppSuccess = false; + sm->suppFail = false; + sm->suppTimeout = false; + sm->keyRun = false; + sm->keyDone = false; + sm->suppStart = true; } @@ -316,17 +325,22 @@ SM_STATE(SUPP_PAE, AUTHENTICATED) SM_STATE(SUPP_PAE, RESTART) { + if (eapol_sm_confirm_auth(sm)) { + /* Don't process restart, we are already reconnecting */ + return; + } + SM_ENTRY(SUPP_PAE, RESTART); - sm->eapRestart = TRUE; + sm->eapRestart = true; if (sm->altAccept) { /* * Prevent EAP peer state machine from failing due to prior - * external EAP success notification (altSuccess=TRUE in the + * external EAP success notification (altSuccess=true in the * IDLE state could result in a transition to the FAILURE state. */ wpa_printf(MSG_DEBUG, "EAPOL: Clearing prior altAccept TRUE"); - sm->eapSuccess = FALSE; - sm->altAccept = FALSE; + sm->eapSuccess = false; + sm->altAccept = false; } } @@ -398,7 +412,7 @@ SM_STEP(SUPP_PAE) wpa_printf(MSG_DEBUG, "EAPOL: IEEE 802.1X for " "plaintext connection; no EAPOL-Key frames " "required"); - sm->portValid = TRUE; + sm->portValid = true; if (sm->ctx->eapol_done_cb) sm->ctx->eapol_done_cb(sm->ctx->ctx); } @@ -445,7 +459,7 @@ SM_STATE(KEY_RX, KEY_RECEIVE) { SM_ENTRY(KEY_RX, KEY_RECEIVE); eapol_sm_processKey(sm); - sm->rxKey = FALSE; + sm->rxKey = false; } @@ -472,7 +486,7 @@ SM_STATE(SUPP_BE, REQUEST) { SM_ENTRY(SUPP_BE, REQUEST); sm->authWhile = 0; - sm->eapReq = TRUE; + sm->eapReq = true; eapol_sm_getSuppRsp(sm); } @@ -481,15 +495,15 @@ SM_STATE(SUPP_BE, RESPONSE) { SM_ENTRY(SUPP_BE, RESPONSE); eapol_sm_txSuppRsp(sm); - sm->eapResp = FALSE; + sm->eapResp = false; } SM_STATE(SUPP_BE, SUCCESS) { SM_ENTRY(SUPP_BE, SUCCESS); - sm->keyRun = TRUE; - sm->suppSuccess = TRUE; + sm->keyRun = true; + sm->suppSuccess = true; #ifdef CONFIG_EAP_PROXY if (sm->use_eap_proxy) { @@ -499,7 +513,7 @@ SM_STATE(SUPP_BE, SUCCESS) /* New key received - clear IEEE 802.1X EAPOL-Key replay * counter */ - sm->replay_counter_valid = FALSE; + sm->replay_counter_valid = false; session_id = eap_proxy_get_eap_session_id( sm->eap_proxy, &session_id_len); @@ -520,7 +534,7 @@ SM_STATE(SUPP_BE, SUCCESS) if (eap_key_available(sm->eap)) { /* New key received - clear IEEE 802.1X EAPOL-Key replay * counter */ - sm->replay_counter_valid = FALSE; + sm->replay_counter_valid = false; } } @@ -528,22 +542,22 @@ SM_STATE(SUPP_BE, SUCCESS) SM_STATE(SUPP_BE, FAIL) { SM_ENTRY(SUPP_BE, FAIL); - sm->suppFail = TRUE; + sm->suppFail = true; } SM_STATE(SUPP_BE, TIMEOUT) { SM_ENTRY(SUPP_BE, TIMEOUT); - sm->suppTimeout = TRUE; + sm->suppTimeout = true; } SM_STATE(SUPP_BE, IDLE) { SM_ENTRY(SUPP_BE, IDLE); - sm->suppStart = FALSE; - sm->initial_req = TRUE; + sm->suppStart = false; + sm->initial_req = true; } @@ -551,7 +565,7 @@ SM_STATE(SUPP_BE, INITIALIZE) { SM_ENTRY(SUPP_BE, INITIALIZE); eapol_sm_abortSupp(sm); - sm->suppAbort = FALSE; + sm->suppAbort = false; /* * IEEE Std 802.1X-2004 does not clear authWhile here, but doing so @@ -569,9 +583,9 @@ SM_STATE(SUPP_BE, RECEIVE) SM_ENTRY(SUPP_BE, RECEIVE); sm->authWhile = sm->authPeriod; eapol_enable_timer_tick(sm); - sm->eapolEap = FALSE; - sm->eapNoResp = FALSE; - sm->initial_req = FALSE; + sm->eapolEap = false; + sm->eapNoResp = false; + sm->initial_req = false; } @@ -678,6 +692,7 @@ struct eap_key_data { static void eapol_sm_processKey(struct eapol_sm *sm) { +#ifdef CONFIG_WEP #ifndef CONFIG_FIPS struct ieee802_1x_hdr *hdr; struct ieee802_1x_eapol_key *key; @@ -816,7 +831,7 @@ static void eapol_sm_processKey(struct eapol_sm *sm) return; } - sm->replay_counter_valid = TRUE; + sm->replay_counter_valid = true; os_memcpy(sm->last_replay_counter, key->replay_counter, IEEE8021X_REPLAY_COUNTER_LEN); @@ -828,16 +843,16 @@ static void eapol_sm_processKey(struct eapol_sm *sm) if (sm->ctx->set_wep_key && sm->ctx->set_wep_key(sm->ctx->ctx, - key->key_index & IEEE8021X_KEY_INDEX_FLAG, + !!(key->key_index & IEEE8021X_KEY_INDEX_FLAG), key->key_index & IEEE8021X_KEY_INDEX_MASK, datakey, key_len) < 0) { wpa_printf(MSG_WARNING, "EAPOL: Failed to set WEP key to the " " driver."); } else { if (key->key_index & IEEE8021X_KEY_INDEX_FLAG) - sm->unicast_key_received = TRUE; + sm->unicast_key_received = true; else - sm->broadcast_key_received = TRUE; + sm->broadcast_key_received = true; if ((sm->unicast_key_received || !(sm->conf.required_keys & EAPOL_REQUIRE_KEY_UNICAST)) && @@ -846,12 +861,13 @@ static void eapol_sm_processKey(struct eapol_sm *sm) { wpa_printf(MSG_DEBUG, "EAPOL: all required EAPOL-Key " "frames received"); - sm->portValid = TRUE; + sm->portValid = true; if (sm->ctx->eapol_done_cb) sm->ctx->eapol_done_cb(sm->ctx->ctx); } } #endif /* CONFIG_FIPS */ +#endif /* CONFIG_WEP */ } @@ -933,7 +949,7 @@ static void eapol_sm_set_port_authorized(struct eapol_sm *sm) int cb; cb = sm->suppPortStatus != Authorized || sm->force_authorized_update; - sm->force_authorized_update = FALSE; + sm->force_authorized_update = false; sm->suppPortStatus = Authorized; if (cb && sm->ctx->port_cb) sm->ctx->port_cb(sm->ctx->ctx, 1); @@ -945,7 +961,7 @@ static void eapol_sm_set_port_unauthorized(struct eapol_sm *sm) int cb; cb = sm->suppPortStatus != Unauthorized || sm->force_authorized_update; - sm->force_authorized_update = FALSE; + sm->force_authorized_update = false; sm->suppPortStatus = Unauthorized; if (cb && sm->ctx->port_cb) sm->ctx->port_cb(sm->ctx->ctx, 0); @@ -969,7 +985,7 @@ void eapol_sm_step(struct eapol_sm *sm) * allow events (e.g., SIGTERM) to stop the program cleanly if the * state machine were to generate a busy loop. */ for (i = 0; i < 100; i++) { - sm->changed = FALSE; + sm->changed = false; SM_STEP_RUN(SUPP_PAE); SM_STEP_RUN(KEY_RX); SM_STEP_RUN(SUPP_BE); @@ -977,11 +993,11 @@ void eapol_sm_step(struct eapol_sm *sm) if (sm->use_eap_proxy) { /* Drive the EAP proxy state machine */ if (eap_proxy_sm_step(sm->eap_proxy, sm->eap)) - sm->changed = TRUE; + sm->changed = true; } else #endif /* CONFIG_EAP_PROXY */ if (eap_peer_sm_step(sm->eap)) - sm->changed = TRUE; + sm->changed = true; if (!sm->changed) break; } @@ -1354,7 +1370,7 @@ int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, if (sm->eapReqData) { wpa_printf(MSG_DEBUG, "EAPOL: Received EAP-Packet " "frame"); - sm->eapolEap = TRUE; + sm->eapolEap = true; #ifdef CONFIG_EAP_PROXY if (sm->use_eap_proxy) { eap_proxy_packet_update( @@ -1395,7 +1411,7 @@ int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, "frame"); os_memcpy(sm->last_rx_key, buf, data_len); sm->last_rx_key_len = data_len; - sm->rxKey = TRUE; + sm->rxKey = true; eapol_sm_step(sm); } break; @@ -1438,14 +1454,14 @@ void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) * * Notify EAPOL state machine about new portEnabled value. */ -void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled) +void eapol_sm_notify_portEnabled(struct eapol_sm *sm, bool enabled) { if (sm == NULL) return; wpa_printf(MSG_DEBUG, "EAPOL: External notification - " "portEnabled=%d", enabled); if (sm->portEnabled != enabled) - sm->force_authorized_update = TRUE; + sm->force_authorized_update = true; sm->portEnabled = enabled; eapol_sm_step(sm); } @@ -1458,7 +1474,7 @@ void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled) * * Notify EAPOL state machine about new portValid value. */ -void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid) +void eapol_sm_notify_portValid(struct eapol_sm *sm, bool valid) { if (sm == NULL) return; @@ -1472,15 +1488,15 @@ void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid) /** * eapol_sm_notify_eap_success - Notification of external EAP success trigger * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @success: %TRUE = set success, %FALSE = clear success + * @success: %true = set success, %false = clear success * * Notify the EAPOL state machine that external event has forced EAP state to - * success (success = %TRUE). This can be cleared by setting success = %FALSE. + * success (success = %true). This can be cleared by setting success = %false. * * This function is called to update EAP state when WPA-PSK key handshake has * been completed successfully since WPA-PSK does not use EAP state machine. */ -void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success) +void eapol_sm_notify_eap_success(struct eapol_sm *sm, bool success) { if (sm == NULL) return; @@ -1497,12 +1513,12 @@ void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success) /** * eapol_sm_notify_eap_fail - Notification of external EAP failure trigger * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() - * @fail: %TRUE = set failure, %FALSE = clear failure + * @fail: %true = set failure, %false = clear failure * * Notify EAPOL state machine that external event has forced EAP state to - * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE. + * failure (fail = %true). This can be cleared by setting fail = %false. */ -void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) +void eapol_sm_notify_eap_fail(struct eapol_sm *sm, bool fail) { if (sm == NULL) return; @@ -1643,7 +1659,7 @@ const u8 * eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len) * * Notify EAPOL state machines that user requested logon/logoff. */ -void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) +void eapol_sm_notify_logoff(struct eapol_sm *sm, bool logoff) { if (sm) { sm->userLogoff = logoff; @@ -1668,7 +1684,7 @@ void eapol_sm_notify_cached(struct eapol_sm *sm) if (sm == NULL) return; wpa_printf(MSG_DEBUG, "EAPOL: PMKSA caching was used - skip EAPOL"); - sm->eapSuccess = TRUE; + sm->eapSuccess = true; eap_notify_success(sm->eap); eapol_sm_step(sm); } @@ -1685,7 +1701,7 @@ void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm) if (sm == NULL) return; wpa_printf(MSG_DEBUG, "RSN: Trying to use cached PMKSA"); - sm->cached_pmk = TRUE; + sm->cached_pmk = true; } @@ -1695,7 +1711,7 @@ static void eapol_sm_abort_cached(struct eapol_sm *sm) "doing full EAP authentication"); if (sm == NULL) return; - sm->cached_pmk = FALSE; + sm->cached_pmk = false; sm->SUPP_PAE_state = SUPP_PAE_CONNECTING; eapol_sm_set_port_unauthorized(sm); @@ -1774,8 +1790,8 @@ void eapol_sm_notify_ctrl_response(struct eapol_sm *sm) wpa_printf(MSG_DEBUG, "EAPOL: received control response (user " "input) notification - retrying pending EAP " "Request"); - sm->eapolEap = TRUE; - sm->eapReq = TRUE; + sm->eapolEap = true; + sm->eapReq = true; eapol_sm_step(sm); } } @@ -1844,11 +1860,11 @@ static struct wpabuf * eapol_sm_get_eapReqData(void *ctx) } -static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) +static bool eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) { struct eapol_sm *sm = ctx; if (sm == NULL) - return FALSE; + return false; switch (variable) { case EAPOL_eapSuccess: return sm->eapSuccess; @@ -1871,12 +1887,12 @@ static Boolean eapol_sm_get_bool(void *ctx, enum eapol_bool_var variable) case EAPOL_eapTriggerStart: return sm->eapTriggerStart; } - return FALSE; + return false; } static void eapol_sm_set_bool(void *ctx, enum eapol_bool_var variable, - Boolean value) + bool value) { struct eapol_sm *sm = ctx; if (sm == NULL) @@ -1978,8 +1994,8 @@ static void eapol_sm_notify_pending(void *ctx) if (sm->eapReqData && !sm->eapReq) { wpa_printf(MSG_DEBUG, "EAPOL: received notification from EAP " "state machine - retrying pending EAP Request"); - sm->eapolEap = TRUE; - sm->eapReq = TRUE; + sm->eapolEap = true; + sm->eapReq = true; eapol_sm_step(sm); } } @@ -2125,7 +2141,7 @@ struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) } #ifdef CONFIG_EAP_PROXY - sm->use_eap_proxy = FALSE; + sm->use_eap_proxy = false; sm->eap_proxy = eap_proxy_init(sm, &eapol_cb, sm->ctx->msg_ctx); if (sm->eap_proxy == NULL) { wpa_printf(MSG_ERROR, "Unable to initialize EAP Proxy"); @@ -2133,10 +2149,10 @@ struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) #endif /* CONFIG_EAP_PROXY */ /* Initialize EAPOL state machines */ - sm->force_authorized_update = TRUE; - sm->initialize = TRUE; + sm->force_authorized_update = true; + sm->initialize = true; eapol_sm_step(sm); - sm->initialize = FALSE; + sm->initialize = false; eapol_sm_step(sm); if (eloop_register_timeout(1, 0, eapol_port_timers_tick, NULL, sm) == 0) diff --git a/src/eapol_supp/eapol_supp_sm.h b/src/eapol_supp/eapol_supp_sm.h index c9d7522d5..753b947ad 100644 --- a/src/eapol_supp/eapol_supp_sm.h +++ b/src/eapol_supp/eapol_supp_sm.h @@ -298,6 +298,15 @@ struct eapol_ctx { * @len: Length of anonymous identity in octets */ void (*set_anon_id)(void *ctx, const u8 *id, size_t len); + + /** + * confirm_auth_cb - Callback confirming if we can install a new PTK + * @ctx: eapol_ctx from eap_peer_sm_init() call + * Returns: 0 when authentication can continue, -1 when reconnecting + * + * Automatically triggers a reconnect when not. + */ + int (*confirm_auth_cb)(void *ctx); }; @@ -316,16 +325,16 @@ void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod, int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, size_t len); void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm); -void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled); -void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid); -void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success); -void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail); +void eapol_sm_notify_portEnabled(struct eapol_sm *sm, bool enabled); +void eapol_sm_notify_portValid(struct eapol_sm *sm, bool valid); +void eapol_sm_notify_eap_success(struct eapol_sm *sm, bool success); +void eapol_sm_notify_eap_fail(struct eapol_sm *sm, bool fail); void eapol_sm_notify_config(struct eapol_sm *sm, struct eap_peer_config *config, const struct eapol_config *conf); int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len); const u8 * eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len); -void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff); +void eapol_sm_notify_logoff(struct eapol_sm *sm, bool logoff); void eapol_sm_notify_cached(struct eapol_sm *sm); void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm); void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx); @@ -388,18 +397,18 @@ static inline void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) { } static inline void eapol_sm_notify_portEnabled(struct eapol_sm *sm, - Boolean enabled) + bool enabled) { } static inline void eapol_sm_notify_portValid(struct eapol_sm *sm, - Boolean valid) + bool valid) { } static inline void eapol_sm_notify_eap_success(struct eapol_sm *sm, - Boolean success) + bool success) { } -static inline void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) +static inline void eapol_sm_notify_eap_fail(struct eapol_sm *sm, bool fail) { } static inline void eapol_sm_notify_config(struct eapol_sm *sm, @@ -416,7 +425,7 @@ eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len) { return NULL; } -static inline void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) +static inline void eapol_sm_notify_logoff(struct eapol_sm *sm, bool logoff) { } static inline void eapol_sm_notify_cached(struct eapol_sm *sm) diff --git a/src/fst/fst.c b/src/fst/fst.c index fbe1175ac..21ef3d8b7 100644 --- a/src/fst/fst.c +++ b/src/fst/fst.c @@ -20,7 +20,7 @@ struct dl_list fst_global_ctrls_list; static void fst_ctrl_iface_notify_peer_state_change(struct fst_iface *iface, - Boolean connected, + bool connected, const u8 *peer_addr) { union fst_event_extra extra; @@ -42,7 +42,7 @@ struct fst_iface * fst_attach(const char *ifname, const u8 *own_addr, struct fst_group *g; struct fst_group *group = NULL; struct fst_iface *iface = NULL; - Boolean new_group = FALSE; + bool new_group = false; WPA_ASSERT(ifname != NULL); WPA_ASSERT(iface_obj != NULL); @@ -62,7 +62,7 @@ struct fst_iface * fst_attach(const char *ifname, const u8 *own_addr, cfg->group_id); return NULL; } - new_group = TRUE; + new_group = true; } iface = fst_iface_create(group, ifname, own_addr, iface_obj, cfg); @@ -166,7 +166,7 @@ void fst_global_del_ctrl(struct fst_ctrl_handle *h) void fst_rx_action(struct fst_iface *iface, const struct ieee80211_mgmt *mgmt, size_t len) { - if (fst_iface_is_connected(iface, mgmt->sa, FALSE)) + if (fst_iface_is_connected(iface, mgmt->sa, false)) fst_session_on_action_rx(iface, mgmt, len); else wpa_printf(MSG_DEBUG, @@ -187,7 +187,7 @@ void fst_notify_peer_connected(struct fst_iface *iface, const u8 *addr) fst_printf_iface(iface, MSG_DEBUG, MACSTR " became connected", MAC2STR(addr)); - fst_ctrl_iface_notify_peer_state_change(iface, TRUE, addr); + fst_ctrl_iface_notify_peer_state_change(iface, true, addr); } @@ -203,12 +203,12 @@ void fst_notify_peer_disconnected(struct fst_iface *iface, const u8 *addr) fst_printf_iface(iface, MSG_DEBUG, MACSTR " became disconnected", MAC2STR(addr)); - fst_ctrl_iface_notify_peer_state_change(iface, FALSE, addr); + fst_ctrl_iface_notify_peer_state_change(iface, false, addr); } -Boolean fst_are_ifaces_aggregated(struct fst_iface *iface1, - struct fst_iface *iface2) +bool fst_are_ifaces_aggregated(struct fst_iface *iface1, + struct fst_iface *iface2) { return fst_iface_get_group(iface1) == fst_iface_get_group(iface2); } diff --git a/src/fst/fst.h b/src/fst/fst.h index 7ba60d545..2410a6ef1 100644 --- a/src/fst/fst.h +++ b/src/fst/fst.h @@ -113,24 +113,24 @@ struct fst_wpa_obj { * get_peer_first - Get MAC address of the 1st connected STA * @ctx: User context %ctx * @get_ctx: Context to be used for %get_peer_next call - * @mb_only: %TRUE if only multi-band capable peer should be reported + * @mb_only: %true if only multi-band capable peer should be reported * Returns: Address of the 1st connected STA, %NULL if no STAs connected */ const u8 * (*get_peer_first)(void *ctx, struct fst_get_peer_ctx **get_ctx, - Boolean mb_only); + bool mb_only); /** * get_peer_next - Get MAC address of the next connected STA * @ctx: User context %ctx * @get_ctx: Context received from %get_peer_first or previous * %get_peer_next call - * @mb_only: %TRUE if only multi-band capable peer should be reported + * @mb_only: %true if only multi-band capable peer should be reported * Returns: Address of the next connected STA, %NULL if no more STAs * connected */ const u8 * (*get_peer_next)(void *ctx, struct fst_get_peer_ctx **get_ctx, - Boolean mb_only); + bool mb_only); }; /** @@ -273,11 +273,11 @@ void fst_notify_peer_disconnected(struct fst_iface *iface, const u8 *addr); * @iface1: 1st FST interface object * @iface1: 2nd FST interface object * - * Returns: %TRUE if the interfaces belong to the same FST group, - * %FALSE otherwise + * Returns: %true if the interfaces belong to the same FST group, + * %false otherwise */ -Boolean fst_are_ifaces_aggregated(struct fst_iface *iface1, - struct fst_iface *iface2); +bool fst_are_ifaces_aggregated(struct fst_iface *iface1, + struct fst_iface *iface2); /** * fst_update_mac_addr - Notify FST about MAC address change diff --git a/src/fst/fst_ctrl_aux.h b/src/fst/fst_ctrl_aux.h index 0aff5d061..ab80b6fc4 100644 --- a/src/fst/fst_ctrl_aux.h +++ b/src/fst/fst_ctrl_aux.h @@ -54,12 +54,12 @@ enum fst_initiator { union fst_event_extra { struct fst_event_extra_iface_state { - Boolean attached; + bool attached; char ifname[FST_MAX_INTERFACE_SIZE]; char group_id[FST_MAX_GROUP_ID_SIZE]; } iface_state; /* for EVENT_FST_IFACE_STATE_CHANGED */ struct fst_event_extra_peer_state { - Boolean connected; + bool connected; char ifname[FST_MAX_INTERFACE_SIZE]; u8 addr[ETH_ALEN]; } peer_state; /* for EVENT_PEER_STATE_CHANGED */ diff --git a/src/fst/fst_ctrl_iface.c b/src/fst/fst_ctrl_iface.c index 7df3362b6..45607b6d9 100644 --- a/src/fst/fst_ctrl_iface.c +++ b/src/fst/fst_ctrl_iface.c @@ -32,8 +32,8 @@ static struct fst_group * get_fst_group_by_id(const char *id) /* notifications */ -static Boolean format_session_state_extra(const union fst_event_extra *extra, - char *buffer, size_t size) +static bool format_session_state_extra(const union fst_event_extra *extra, + char *buffer, size_t size) { int len; char reject_str[32] = FST_CTRL_PVAL_NONE; @@ -42,7 +42,7 @@ static Boolean format_session_state_extra(const union fst_event_extra *extra, ss = &extra->session_state; if (ss->new_state != FST_SESSION_STATE_INITIAL) - return TRUE; + return true; switch (ss->extra.to_initial.reason) { case REASON_REJECT: @@ -183,10 +183,10 @@ static int session_get(const char *session_id, char *buf, size_t buflen) return os_snprintf(buf, buflen, "FAIL\n"); } - old_peer_addr = fst_session_get_peer_addr(s, TRUE); - new_peer_addr = fst_session_get_peer_addr(s, FALSE); - new_iface = fst_session_get_iface(s, FALSE); - old_iface = fst_session_get_iface(s, TRUE); + old_peer_addr = fst_session_get_peer_addr(s, true); + new_peer_addr = fst_session_get_peer_addr(s, false); + new_iface = fst_session_get_iface(s, false); + old_iface = fst_session_get_iface(s, true); return os_snprintf(buf, buflen, FST_CSG_PNAME_OLD_PEER_ADDR "=" MACSTR "\n" @@ -227,13 +227,13 @@ static int session_set(const char *session_id, char *buf, size_t buflen) p++; if (os_strncasecmp(p, FST_CSS_PNAME_OLD_IFNAME, q - p) == 0) { - ret = fst_session_set_str_ifname(s, q + 1, TRUE); + ret = fst_session_set_str_ifname(s, q + 1, true); } else if (os_strncasecmp(p, FST_CSS_PNAME_NEW_IFNAME, q - p) == 0) { - ret = fst_session_set_str_ifname(s, q + 1, FALSE); + ret = fst_session_set_str_ifname(s, q + 1, false); } else if (os_strncasecmp(p, FST_CSS_PNAME_OLD_PEER_ADDR, q - p) == 0) { - ret = fst_session_set_str_peer_addr(s, q + 1, TRUE); + ret = fst_session_set_str_peer_addr(s, q + 1, true); } else if (os_strncasecmp(p, FST_CSS_PNAME_NEW_PEER_ADDR, q - p) == 0) { - ret = fst_session_set_str_peer_addr(s, q + 1, FALSE); + ret = fst_session_set_str_peer_addr(s, q + 1, false); } else if (os_strncasecmp(p, FST_CSS_PNAME_LLT, q - p) == 0) { ret = fst_session_set_str_llt(s, q + 1); } else { @@ -539,8 +539,8 @@ static int iface_peers(const char *group_id, char *buf, size_t buflen) if (!found) return os_snprintf(buf, buflen, "FAIL\n"); - addr = fst_iface_get_peer_first(f, &ctx, FALSE); - for (; addr != NULL; addr = fst_iface_get_peer_next(f, &ctx, FALSE)) { + addr = fst_iface_get_peer_first(f, &ctx, false); + for (; addr != NULL; addr = fst_iface_get_peer_next(f, &ctx, false)) { int res; res = os_snprintf(buf + ret, buflen - ret, MACSTR "\n", @@ -692,7 +692,7 @@ static int print_band(unsigned num, struct fst_iface *iface, const u8 *addr, static void fst_ctrl_iface_on_iface_state_changed(struct fst_iface *i, - Boolean attached) + bool attached) { union fst_event_extra extra; @@ -710,14 +710,14 @@ static void fst_ctrl_iface_on_iface_state_changed(struct fst_iface *i, static int fst_ctrl_iface_on_iface_added(struct fst_iface *i) { - fst_ctrl_iface_on_iface_state_changed(i, TRUE); + fst_ctrl_iface_on_iface_state_changed(i, true); return 0; } static void fst_ctrl_iface_on_iface_removed(struct fst_iface *i) { - fst_ctrl_iface_on_iface_state_changed(i, FALSE); + fst_ctrl_iface_on_iface_state_changed(i, false); } @@ -749,7 +749,7 @@ int fst_ctrl_iface_mb_info(const u8 *addr, char *buf, size_t buflen) foreach_fst_group(g) { foreach_fst_group_iface(g, f) { - if (fst_iface_is_connected(f, addr, TRUE)) { + if (fst_iface_is_connected(f, addr, true)) { ret += print_band(num++, f, addr, buf + ret, buflen - ret); } @@ -789,7 +789,7 @@ int fst_ctrl_iface_receive(const char *cmd, char *reply, size_t reply_size) const struct fst_command *c; const char *p; const char *temp; - Boolean non_spaces_found; + bool non_spaces_found; for (c = commands; c->name; c++) { if (os_strncasecmp(cmd, c->name, os_strlen(c->name)) != 0) @@ -800,10 +800,10 @@ int fst_ctrl_iface_receive(const char *cmd, char *reply, size_t reply_size) return os_snprintf(reply, reply_size, "FAIL\n"); p++; temp = p; - non_spaces_found = FALSE; + non_spaces_found = false; while (*temp) { if (!isspace(*temp)) { - non_spaces_found = TRUE; + non_spaces_found = true; break; } temp++; @@ -818,18 +818,18 @@ int fst_ctrl_iface_receive(const char *cmd, char *reply, size_t reply_size) } -int fst_read_next_int_param(const char *params, Boolean *valid, char **endp) +int fst_read_next_int_param(const char *params, bool *valid, char **endp) { int ret = -1; const char *curp; - *valid = FALSE; + *valid = false; *endp = (char *) params; curp = params; if (*curp) { ret = (int) strtol(curp, endp, 0); if (!**endp || isspace(**endp)) - *valid = TRUE; + *valid = true; } return ret; @@ -887,7 +887,7 @@ int fst_parse_attach_command(const char *cmd, char *ifname, size_t ifname_size, { char *pos; char *endp; - Boolean is_valid; + bool is_valid; int val; if (fst_read_next_text_param(cmd, ifname, ifname_size, &endp) || diff --git a/src/fst/fst_ctrl_iface.h b/src/fst/fst_ctrl_iface.h index 4d0cd9fce..354b81fc7 100644 --- a/src/fst/fst_ctrl_iface.h +++ b/src/fst/fst_ctrl_iface.h @@ -30,7 +30,7 @@ fst_ctrl_iface_mb_info(const u8 *addr, char *buf, size_t buflen) #endif /* CONFIG_FST */ -int fst_read_next_int_param(const char *params, Boolean *valid, char **endp); +int fst_read_next_int_param(const char *params, bool *valid, char **endp); int fst_read_next_text_param(const char *params, char *buf, size_t buflen, char **endp); int fst_read_peer_addr(const char *mac, u8 *peer_addr); diff --git a/src/fst/fst_group.c b/src/fst/fst_group.c index a4ae016d9..d1c401497 100644 --- a/src/fst/fst_group.c +++ b/src/fst/fst_group.c @@ -305,7 +305,7 @@ fst_group_get_peer_other_connection_1(struct fst_iface *iface, if (other_iface == iface || band_id != fst_iface_get_band_id(other_iface)) continue; - if (fst_iface_is_connected(other_iface, tmp_peer_addr, FALSE)) { + if (fst_iface_is_connected(other_iface, tmp_peer_addr, false)) { os_memcpy(other_peer_addr, tmp_peer_addr, ETH_ALEN); return other_iface; } @@ -347,10 +347,10 @@ fst_group_get_peer_other_connection_2(struct fst_iface *iface, band_id != fst_iface_get_band_id(other_iface)) continue; cur_peer_addr = fst_iface_get_peer_first(other_iface, &ctx, - TRUE); + true); for (; cur_peer_addr; cur_peer_addr = fst_iface_get_peer_next(other_iface, &ctx, - TRUE)) { + true)) { cur_mbie = fst_iface_get_peer_mb_ie(other_iface, cur_peer_addr); if (!cur_mbie) @@ -493,9 +493,9 @@ void fst_group_delete(struct fst_group *group) } -Boolean fst_group_delete_if_empty(struct fst_group *group) +bool fst_group_delete_if_empty(struct fst_group *group) { - Boolean is_empty = !fst_group_has_ifaces(group) && + bool is_empty = !fst_group_has_ifaces(group) && !fst_session_global_get_first_by_group(group); if (is_empty) diff --git a/src/fst/fst_group.h b/src/fst/fst_group.h index 00aee9c8c..4a9ff3e82 100644 --- a/src/fst/fst_group.h +++ b/src/fst/fst_group.h @@ -29,7 +29,7 @@ void fst_group_delete(struct fst_group *g); void fst_group_update_ie(struct fst_group *g); -static inline Boolean fst_group_has_ifaces(struct fst_group *g) +static inline bool fst_group_has_ifaces(struct fst_group *g) { return !dl_list_empty(&g->ifaces); } @@ -44,7 +44,7 @@ static inline const char * fst_group_get_id(struct fst_group *g) return g->group_id; } -Boolean fst_group_delete_if_empty(struct fst_group *group); +bool fst_group_delete_if_empty(struct fst_group *group); struct fst_iface * fst_group_get_iface_by_name(struct fst_group *g, const char *ifname); struct fst_iface * diff --git a/src/fst/fst_iface.c b/src/fst/fst_iface.c index 35e83cb7b..90c5fc035 100644 --- a/src/fst/fst_iface.c +++ b/src/fst/fst_iface.c @@ -49,17 +49,17 @@ void fst_iface_delete(struct fst_iface *i) } -Boolean fst_iface_is_connected(struct fst_iface *iface, const u8 *addr, - Boolean mb_only) +bool fst_iface_is_connected(struct fst_iface *iface, const u8 *addr, + bool mb_only) { struct fst_get_peer_ctx *ctx; const u8 *a = fst_iface_get_peer_first(iface, &ctx, mb_only); for (; a != NULL; a = fst_iface_get_peer_next(iface, &ctx, mb_only)) if (os_memcmp(addr, a, ETH_ALEN) == 0) - return TRUE; + return true; - return FALSE; + return false; } diff --git a/src/fst/fst_iface.h b/src/fst/fst_iface.h index cbaa7d817..af7156cb2 100644 --- a/src/fst/fst_iface.h +++ b/src/fst/fst_iface.h @@ -111,20 +111,20 @@ static inline void fst_iface_update_mb_ie(struct fst_iface *i, static inline const u8 * fst_iface_get_peer_first(struct fst_iface *i, struct fst_get_peer_ctx **ctx, - Boolean mb_only) + bool mb_only) { return i->iface_obj.get_peer_first(i->iface_obj.ctx, ctx, mb_only); } static inline const u8 * fst_iface_get_peer_next(struct fst_iface *i, struct fst_get_peer_ctx **ctx, - Boolean mb_only) + bool mb_only) { return i->iface_obj.get_peer_next(i->iface_obj.ctx, ctx, mb_only); } -Boolean fst_iface_is_connected(struct fst_iface *iface, const u8 *addr, - Boolean mb_only); +bool fst_iface_is_connected(struct fst_iface *iface, const u8 *addr, + bool mb_only); void fst_iface_attach_mbie(struct fst_iface *i, struct wpabuf *mbie); enum mb_band_id fst_iface_get_band_id(struct fst_iface *i); diff --git a/src/fst/fst_session.c b/src/fst/fst_session.c index a02a93e76..e42a85c04 100644 --- a/src/fst/fst_session.c +++ b/src/fst/fst_session.c @@ -71,7 +71,7 @@ struct fst_session { * specific session object */ struct fst_group *group; enum fst_session_state state; - Boolean stt_armed; + bool stt_armed; }; static struct dl_list global_sessions_list; @@ -145,12 +145,12 @@ static u32 fst_find_free_session_id(void) struct fst_session *s; for (i = 0; i < (u32) -1; i++) { - Boolean in_use = FALSE; + bool in_use = false; foreach_fst_session(s) { if (s->id == global_session_id) { fst_session_global_inc_id(); - in_use = TRUE; + in_use = true; break; } } @@ -184,7 +184,7 @@ static void fst_session_stt_arm(struct fst_session *s) /* Action frames sometimes get delayed. Use relaxed timeout (2*) */ eloop_register_timeout(0, 2 * TU_TO_US(FST_DEFAULT_SESSION_TIMEOUT_TU), fst_session_timeout_handler, NULL, s); - s->stt_armed = TRUE; + s->stt_armed = true; } @@ -192,12 +192,12 @@ static void fst_session_stt_disarm(struct fst_session *s) { if (s->stt_armed) { eloop_cancel_timeout(fst_session_timeout_handler, NULL, s); - s->stt_armed = FALSE; + s->stt_armed = false; } } -static Boolean fst_session_is_in_transition(struct fst_session *s) +static bool fst_session_is_in_transition(struct fst_session *s) { /* See spec, 10.32.2.2 Transitioning between states */ return s->stt_armed; @@ -267,7 +267,7 @@ static void fst_session_reset_ex(struct fst_session *s, enum fst_reason reason) } -static int fst_session_send_action(struct fst_session *s, Boolean old_iface, +static int fst_session_send_action(struct fst_session *s, bool old_iface, const void *payload, size_t size, const struct wpabuf *extra_buf) { @@ -344,11 +344,11 @@ static int fst_session_send_tear_down(struct fst_session *s) td.action = FST_ACTION_TEAR_DOWN; td.fsts_id = host_to_le32(s->data.fsts_id); - res = fst_session_send_action(s, TRUE, &td, sizeof(td), NULL); + res = fst_session_send_action(s, true, &td, sizeof(td), NULL); if (!res) - fst_printf_sframe(s, TRUE, MSG_INFO, "FST TearDown sent"); + fst_printf_sframe(s, true, MSG_INFO, "FST TearDown sent"); else - fst_printf_sframe(s, TRUE, MSG_ERROR, + fst_printf_sframe(s, true, MSG_ERROR, "failed to send FST TearDown"); return res; @@ -481,10 +481,10 @@ static void fst_session_handle_setup_request(struct fst_iface *iface, return; } - fst_session_set_iface(s, iface, TRUE); - fst_session_set_peer_addr(s, mgmt->sa, TRUE); - fst_session_set_iface(s, new_iface, FALSE); - fst_session_set_peer_addr(s, new_iface_peer_addr, FALSE); + fst_session_set_iface(s, iface, true); + fst_session_set_peer_addr(s, mgmt->sa, true); + fst_session_set_iface(s, new_iface, false); + fst_session_set_peer_addr(s, new_iface_peer_addr, false); fst_session_set_llt(s, FST_LLT_VAL_TO_MS(le_to_host32(req->llt))); s->data.pending_setup_req_dlgt = req->dialog_token; s->data.fsts_id = le_to_host32(req->stie.fsts_id); @@ -687,8 +687,8 @@ static void fst_session_handle_ack_request(struct fst_session *s, res.dialog_token = req->dialog_token; res.fsts_id = req->fsts_id; - if (!fst_session_send_action(s, FALSE, &res, sizeof(res), NULL)) { - fst_printf_sframe(s, FALSE, MSG_INFO, "FST Ack Response sent"); + if (!fst_session_send_action(s, false, &res, sizeof(res), NULL)) { + fst_printf_sframe(s, false, MSG_INFO, "FST Ack Response sent"); fst_session_stt_disarm(s); fst_session_set_state(s, FST_SESSION_STATE_TRANSITION_DONE, NULL); @@ -785,7 +785,7 @@ struct fst_session * fst_session_create(struct fst_group *g) void fst_session_set_iface(struct fst_session *s, struct fst_iface *iface, - Boolean is_old) + bool is_old) { if (is_old) s->data.old_iface = iface; @@ -802,7 +802,7 @@ void fst_session_set_llt(struct fst_session *s, u32 llt) void fst_session_set_peer_addr(struct fst_session *s, const u8 *addr, - Boolean is_old) + bool is_old) { u8 *a = is_old ? s->data.old_peer_addr : s->data.new_peer_addr; @@ -850,14 +850,14 @@ int fst_session_initiate_setup(struct fst_session *s) } if (!fst_iface_is_connected(s->data.old_iface, s->data.old_peer_addr, - FALSE)) { + false)) { fst_printf_session(s, MSG_ERROR, "The preset old peer address is not connected"); return -EINVAL; } if (!fst_iface_is_connected(s->data.new_iface, s->data.new_peer_addr, - FALSE)) { + false)) { fst_printf_session(s, MSG_ERROR, "The preset new peer address is not connected"); return -EINVAL; @@ -905,12 +905,12 @@ int fst_session_initiate_setup(struct fst_session *s) req.stie.old_band_op = 1; req.stie.old_band_setup = 0; - res = fst_session_send_action(s, TRUE, &req, sizeof(req), + res = fst_session_send_action(s, true, &req, sizeof(req), fst_iface_get_mbie(s->data.old_iface)); if (!res) { s->data.fsts_id = fsts_id; s->data.pending_setup_req_dlgt = dialog_token; - fst_printf_sframe(s, TRUE, MSG_INFO, "FST Setup Request sent"); + fst_printf_sframe(s, true, MSG_INFO, "FST Setup Request sent"); fst_session_set_state(s, FST_SESSION_STATE_SETUP_COMPLETION, NULL); @@ -955,7 +955,7 @@ int fst_session_respond(struct fst_session *s, u8 status_code) } if (!fst_iface_is_connected(s->data.old_iface, - s->data.old_peer_addr, FALSE)) { + s->data.old_peer_addr, false)) { fst_printf_session(s, MSG_ERROR, "The preset peer address is not in the peer list"); return -EINVAL; @@ -1000,15 +1000,15 @@ int fst_session_respond(struct fst_session *s, u8 status_code) status_code); } - if (fst_session_send_action(s, TRUE, &res, sizeof(res), + if (fst_session_send_action(s, true, &res, sizeof(res), fst_iface_get_mbie(s->data.old_iface))) { - fst_printf_sframe(s, TRUE, MSG_ERROR, + fst_printf_sframe(s, true, MSG_ERROR, "cannot send FST Setup Response with code %d", status_code); return -EINVAL; } - fst_printf_sframe(s, TRUE, MSG_INFO, "FST Setup Response sent"); + fst_printf_sframe(s, true, MSG_INFO, "FST Setup Response sent"); if (status_code != WLAN_STATUS_SUCCESS) { union fst_session_state_switch_extra evext = { @@ -1053,14 +1053,14 @@ int fst_session_initiate_switch(struct fst_session *s) req.dialog_token = dialog_token; req.fsts_id = host_to_le32(s->data.fsts_id); - res = fst_session_send_action(s, FALSE, &req, sizeof(req), NULL); + res = fst_session_send_action(s, false, &req, sizeof(req), NULL); if (!res) { - fst_printf_sframe(s, FALSE, MSG_INFO, "FST Ack Request sent"); + fst_printf_sframe(s, false, MSG_INFO, "FST Ack Request sent"); fst_session_set_state(s, FST_SESSION_STATE_TRANSITION_DONE, NULL); fst_session_stt_arm(s); } else { - fst_printf_sframe(s, FALSE, MSG_ERROR, + fst_printf_sframe(s, false, MSG_ERROR, "Cannot send FST Ack Request"); } @@ -1091,7 +1091,7 @@ void fst_session_handle_action(struct fst_session *s, break; case FST_ACTION_ON_CHANNEL_TUNNEL: default: - fst_printf_sframe(s, FALSE, MSG_ERROR, + fst_printf_sframe(s, false, MSG_ERROR, "Unsupported FST Action frame"); break; } @@ -1137,7 +1137,7 @@ struct fst_group * fst_session_get_group(struct fst_session *s) } -struct fst_iface * fst_session_get_iface(struct fst_session *s, Boolean is_old) +struct fst_iface * fst_session_get_iface(struct fst_session *s, bool is_old) { return is_old ? s->data.old_iface : s->data.new_iface; } @@ -1149,7 +1149,7 @@ u32 fst_session_get_id(struct fst_session *s) } -const u8 * fst_session_get_peer_addr(struct fst_session *s, Boolean is_old) +const u8 * fst_session_get_peer_addr(struct fst_session *s, bool is_old) { return is_old ? s->data.old_peer_addr : s->data.new_peer_addr; } @@ -1232,7 +1232,7 @@ void fst_session_on_action_rx(struct fst_iface *iface, int fst_session_set_str_ifname(struct fst_session *s, const char *ifname, - Boolean is_old) + bool is_old) { struct fst_group *g = fst_session_get_group(s); struct fst_iface *i; @@ -1252,7 +1252,7 @@ int fst_session_set_str_ifname(struct fst_session *s, const char *ifname, int fst_session_set_str_peer_addr(struct fst_session *s, const char *mac, - Boolean is_old) + bool is_old) { u8 peer_addr[ETH_ALEN]; int res = fst_read_peer_addr(mac, peer_addr); @@ -1330,11 +1330,11 @@ static int get_group_fill_session(struct fst_group **g, struct fst_session *s) if (!s->data.old_iface) return -EINVAL; - old_addr = fst_iface_get_peer_first(s->data.old_iface, &ctx, TRUE); + old_addr = fst_iface_get_peer_first(s->data.old_iface, &ctx, true); if (!old_addr) return -EINVAL; - new_addr = fst_iface_get_peer_first(s->data.new_iface, &ctx, TRUE); + new_addr = fst_iface_get_peer_first(s->data.new_iface, &ctx, true); if (!new_addr) return -EINVAL; @@ -1350,7 +1350,7 @@ static int get_group_fill_session(struct fst_group **g, struct fst_session *s) int fst_test_req_send_fst_request(const char *params) { int fsts_id; - Boolean is_valid; + bool is_valid; char *endp; struct fst_setup_req req; struct fst_session s; @@ -1394,7 +1394,7 @@ int fst_test_req_send_fst_request(const char *params) req.stie.new_band_id = req.stie.old_band_id; } - return fst_session_send_action(&s, TRUE, &req, sizeof(req), + return fst_session_send_action(&s, true, &req, sizeof(req), s.data.old_iface->mb_ie); } @@ -1402,7 +1402,7 @@ int fst_test_req_send_fst_request(const char *params) int fst_test_req_send_fst_response(const char *params) { int fsts_id; - Boolean is_valid; + bool is_valid; char *endp; struct fst_setup_res res; struct fst_session s; @@ -1437,7 +1437,7 @@ int fst_test_req_send_fst_response(const char *params) * If some session has just received an FST Setup Request, then * use the correct dialog token copied from this request. */ - _s = fst_find_session_in_progress(fst_session_get_peer_addr(&s, TRUE), + _s = fst_find_session_in_progress(fst_session_get_peer_addr(&s, true), g); res.dialog_token = (_s && fst_session_is_ready_pending(_s)) ? _s->data.pending_setup_req_dlgt : g->dialog_token; @@ -1469,7 +1469,7 @@ int fst_test_req_send_fst_response(const char *params) res.stie.new_band_id = res.stie.old_band_id; } - return fst_session_send_action(&s, TRUE, &res, sizeof(res), + return fst_session_send_action(&s, true, &res, sizeof(res), s.data.old_iface->mb_ie); } @@ -1477,7 +1477,7 @@ int fst_test_req_send_fst_response(const char *params) int fst_test_req_send_ack_request(const char *params) { int fsts_id; - Boolean is_valid; + bool is_valid; char *endp; struct fst_ack_req req; struct fst_session s; @@ -1498,14 +1498,14 @@ int fst_test_req_send_ack_request(const char *params) req.dialog_token = g->dialog_token; req.fsts_id = host_to_le32(fsts_id); - return fst_session_send_action(&s, FALSE, &req, sizeof(req), NULL); + return fst_session_send_action(&s, false, &req, sizeof(req), NULL); } int fst_test_req_send_ack_response(const char *params) { int fsts_id; - Boolean is_valid; + bool is_valid; char *endp; struct fst_ack_res res; struct fst_session s; @@ -1526,14 +1526,14 @@ int fst_test_req_send_ack_response(const char *params) res.dialog_token = g->dialog_token; res.fsts_id = host_to_le32(fsts_id); - return fst_session_send_action(&s, FALSE, &res, sizeof(res), NULL); + return fst_session_send_action(&s, false, &res, sizeof(res), NULL); } int fst_test_req_send_tear_down(const char *params) { int fsts_id; - Boolean is_valid; + bool is_valid; char *endp; struct fst_tear_down td; struct fst_session s; @@ -1553,14 +1553,14 @@ int fst_test_req_send_tear_down(const char *params) td.action = FST_ACTION_TEAR_DOWN; td.fsts_id = host_to_le32(fsts_id); - return fst_session_send_action(&s, TRUE, &td, sizeof(td), NULL); + return fst_session_send_action(&s, true, &td, sizeof(td), NULL); } u32 fst_test_req_get_fsts_id(const char *params) { int sid; - Boolean is_valid; + bool is_valid; char *endp; struct fst_session *s; diff --git a/src/fst/fst_session.h b/src/fst/fst_session.h index 1162de4b3..e43d0ea39 100644 --- a/src/fst/fst_session.h +++ b/src/fst/fst_session.h @@ -24,10 +24,10 @@ fst_session_global_get_first_by_group(struct fst_group *g); struct fst_session * fst_session_create(struct fst_group *g); void fst_session_set_iface(struct fst_session *s, struct fst_iface *iface, - Boolean is_old); + bool is_old); void fst_session_set_llt(struct fst_session *s, u32 llt); void fst_session_set_peer_addr(struct fst_session *s, const u8 *addr, - Boolean is_old); + bool is_old); int fst_session_initiate_setup(struct fst_session *s); int fst_session_respond(struct fst_session *s, u8 status_code); int fst_session_initiate_switch(struct fst_session *s); @@ -39,8 +39,8 @@ void fst_session_reset(struct fst_session *s); void fst_session_delete(struct fst_session *s); struct fst_group * fst_session_get_group(struct fst_session *s); -struct fst_iface * fst_session_get_iface(struct fst_session *s, Boolean is_old); -const u8 * fst_session_get_peer_addr(struct fst_session *s, Boolean is_old); +struct fst_iface * fst_session_get_iface(struct fst_session *s, bool is_old); +const u8 * fst_session_get_peer_addr(struct fst_session *s, bool is_old); u32 fst_session_get_id(struct fst_session *s); u32 fst_session_get_llt(struct fst_session *s); enum fst_session_state fst_session_get_state(struct fst_session *s); @@ -57,9 +57,9 @@ void fst_session_on_action_rx(struct fst_iface *iface, int fst_session_set_str_ifname(struct fst_session *s, const char *ifname, - Boolean is_old); + bool is_old); int fst_session_set_str_peer_addr(struct fst_session *s, const char *mac, - Boolean is_old); + bool is_old); int fst_session_set_str_llt(struct fst_session *s, const char *llt_str); #ifdef CONFIG_FST_TEST diff --git a/src/l2_packet/Makefile b/src/l2_packet/Makefile index 47925b790..c616626bd 100644 --- a/src/l2_packet/Makefile +++ b/src/l2_packet/Makefile @@ -1,16 +1,3 @@ -all: libl2_packet.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libl2_packet.a - -install: - @echo Nothing to be made. - -include ../lib.rules - LIB_OBJS = l2_packet_linux.o -libl2_packet.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/l2_packet/l2_packet.h b/src/l2_packet/l2_packet.h index 53871774b..6a862806f 100644 --- a/src/l2_packet/l2_packet.h +++ b/src/l2_packet/l2_packet.h @@ -61,6 +61,10 @@ enum l2_packet_filter_type { * points to len bytes of the payload after the layer 2 header and similarly, * TX buffers start with payload. This behavior can be changed by setting * l2_hdr=1 to include the layer 2 header in the data buffer. + * + * IF rx_callback is NULL, receive operation is not opened at all, i.e., only + * the TX path and additional helper functions for fetching MAC and IP + * addresses can be used. */ struct l2_packet_data * l2_packet_init( const char *ifname, const u8 *own_addr, unsigned short protocol, diff --git a/src/l2_packet/l2_packet_freebsd.c b/src/l2_packet/l2_packet_freebsd.c index aa8364827..60de9fe6b 100644 --- a/src/l2_packet/l2_packet_freebsd.c +++ b/src/l2_packet/l2_packet_freebsd.c @@ -84,7 +84,7 @@ static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) packet = pcap_next(pcap, &hdr); - if (packet == NULL || hdr.caplen < sizeof(*ethhdr)) + if (!l2->rx_callback || !packet || hdr.caplen < sizeof(*ethhdr)) return; ethhdr = (struct l2_ethhdr *) packet; diff --git a/src/l2_packet/l2_packet_linux.c b/src/l2_packet/l2_packet_linux.c index 138dcafcf..7897bc026 100644 --- a/src/l2_packet/l2_packet_linux.c +++ b/src/l2_packet/l2_packet_linux.c @@ -312,7 +312,8 @@ struct l2_packet_data * l2_packet_init( ll.sll_family = PF_PACKET; ll.sll_ifindex = ifr.ifr_ifindex; ll.sll_protocol = htons(protocol); - if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) { + if (rx_callback && + bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) { wpa_printf(MSG_ERROR, "%s: bind[PF_PACKET]: %s", __func__, strerror(errno)); close(l2->fd); @@ -329,7 +330,8 @@ struct l2_packet_data * l2_packet_init( } os_memcpy(l2->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); - eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); + if (rx_callback) + eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); return l2; } diff --git a/src/l2_packet/l2_packet_ndis.c b/src/l2_packet/l2_packet_ndis.c index 716778164..4a4b639fd 100644 --- a/src/l2_packet/l2_packet_ndis.c +++ b/src/l2_packet/l2_packet_ndis.c @@ -294,7 +294,8 @@ static void l2_packet_callback(struct l2_packet_data *l2) } rx_src = ethhdr->h_source; - l2->rx_callback(l2->rx_callback_ctx, rx_src, rx_buf, rx_len); + if (l2->rx_callback) + l2->rx_callback(l2->rx_callback_ctx, rx_src, rx_buf, rx_len); #ifndef _WIN32_WCE l2_ndisuio_start_read(l2, 1); #endif /* _WIN32_WCE */ diff --git a/src/l2_packet/l2_packet_none.c b/src/l2_packet/l2_packet_none.c index 307fc6daa..bc7a4e82d 100644 --- a/src/l2_packet/l2_packet_none.c +++ b/src/l2_packet/l2_packet_none.c @@ -84,7 +84,7 @@ struct l2_packet_data * l2_packet_init( * TODO: open connection for receiving frames */ l2->fd = -1; - if (l2->fd >= 0) + if (rx_callback && l2->fd >= 0) eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); return l2; @@ -112,7 +112,7 @@ void l2_packet_deinit(struct l2_packet_data *l2) eloop_unregister_read_sock(l2->fd); /* TODO: close connection */ } - + os_free(l2); } diff --git a/src/l2_packet/l2_packet_pcap.c b/src/l2_packet/l2_packet_pcap.c index 423c099fd..c2b17fcf8 100644 --- a/src/l2_packet/l2_packet_pcap.c +++ b/src/l2_packet/l2_packet_pcap.c @@ -127,7 +127,7 @@ static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) packet = pcap_next(pcap, &hdr); - if (packet == NULL || hdr.caplen < sizeof(*ethhdr)) + if (!l2->rx_callback || !packet || hdr.caplen < sizeof(*ethhdr)) return; ethhdr = (struct l2_ethhdr *) packet; @@ -152,7 +152,7 @@ static void l2_packet_receive_cb(u_char *user, const struct pcap_pkthdr *hdr, unsigned char *buf; size_t len; - if (pkt_data == NULL || hdr->caplen < sizeof(*ethhdr)) + if (!l2->rx_callback || !pkt_data || hdr->caplen < sizeof(*ethhdr)) return; ethhdr = (struct l2_ethhdr *) pkt_data; diff --git a/src/l2_packet/l2_packet_privsep.c b/src/l2_packet/l2_packet_privsep.c index ce86802c2..014a45f34 100644 --- a/src/l2_packet/l2_packet_privsep.c +++ b/src/l2_packet/l2_packet_privsep.c @@ -216,7 +216,8 @@ struct l2_packet_data * l2_packet_init( } os_memcpy(l2->own_addr, reply, ETH_ALEN); - eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); + if (rx_callback) + eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); return l2; diff --git a/src/l2_packet/l2_packet_winpcap.c b/src/l2_packet/l2_packet_winpcap.c index 74085a316..3452051f5 100644 --- a/src/l2_packet/l2_packet_winpcap.c +++ b/src/l2_packet/l2_packet_winpcap.c @@ -224,6 +224,9 @@ struct l2_packet_data * l2_packet_init( return NULL; } + if (!rx_callback) + return l2; + l2->rx_avail = CreateEvent(NULL, TRUE, FALSE, NULL); l2->rx_done = CreateEvent(NULL, TRUE, FALSE, NULL); l2->rx_notify = CreateEvent(NULL, TRUE, FALSE, NULL); diff --git a/src/lib.rules b/src/lib.rules index a46315442..947617b07 100644 --- a/src/lib.rules +++ b/src/lib.rules @@ -1,10 +1,8 @@ -ifndef CC -CC=gcc -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif +_LIBMK := $(lastword $(wordlist 1,$(shell expr $(words $(MAKEFILE_LIST)) - 1),$(MAKEFILE_LIST))) +_LIBNAME := $(notdir $(patsubst %/,%,$(dir $(abspath $(_LIBMK))))) +ALL := $(OUT)lib$(_LIBNAME).a +LIB_RULES := $(lastword $(MAKEFILE_LIST)) +include $(dir $(LIB_RULES))build.rules ifdef TEST_FUZZ CFLAGS += -DCONFIG_NO_RANDOM_POOL @@ -14,18 +12,18 @@ endif CFLAGS += $(FUZZ_CFLAGS) CFLAGS += -I.. -I../utils +_OBJS_VAR := LIB_OBJS +include ../objs.mk -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif -ifeq ($(QUIET), 1) -Q=@ -E=true -endif +$(ALL): $(LIB_OBJS) + @$(E) " AR $(notdir $@)" + $(Q)$(AR) crT $@ $? -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< +install-default: + @echo Nothing to be made. + +%: %-default + @true + +clean: common-clean + $(Q)rm -f *~ *.o *.d *.gcno *.gcda *.gcov $(ALL) diff --git a/src/objs.mk b/src/objs.mk new file mode 100644 index 000000000..a3040b21b --- /dev/null +++ b/src/objs.mk @@ -0,0 +1,3 @@ +$(_OBJS_VAR) := $(call BUILDOBJ,$($(_OBJS_VAR))) +-include $(filter-out %.a,$($(_OBJS_VAR):%.o=%.d)) +_DIRS += $(dir $($(_OBJS_VAR))) diff --git a/src/p2p/Makefile b/src/p2p/Makefile index 5587fcf28..4d1618006 100644 --- a/src/p2p/Makefile +++ b/src/p2p/Makefile @@ -1,13 +1,3 @@ -all: libp2p.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libp2p.a - -install: - @echo Nothing to be made. - -include ../lib.rules - CFLAGS += -DCONFIG_WIFI_DISPLAY CFLAGS += -DCONFIG_WPS_NFC @@ -23,7 +13,4 @@ LIB_OBJS= \ p2p_sd.o \ p2p_utils.o -libp2p.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index b7a5eae35..6b92a6d23 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -2913,6 +2913,14 @@ void p2p_group_formation_failed(struct p2p_data *p2p) } +bool is_p2p_6ghz_disabled(struct p2p_data *p2p) +{ + if (p2p) + return p2p->cfg->p2p_6ghz_disable; + return false; +} + + struct p2p_data * p2p_init(const struct p2p_config *cfg) { struct p2p_data *p2p; @@ -3974,6 +3982,7 @@ static void p2p_timeout_wait_peer_idle(struct p2p_data *p2p) } p2p_dbg(p2p, "Go to Listen state while waiting for the peer to become ready for GO Negotiation"); + p2p->cfg->stop_listen(p2p->cfg->cb_ctx); p2p_set_state(p2p, P2P_WAIT_PEER_CONNECT); p2p_listen_in_find(p2p, 0); } diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 2dae6c6ec..ed8beab19 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -500,6 +500,11 @@ struct p2p_config { */ struct p2p_channel *pref_chan; + /** + * p2p_6ghz_disable - Disable 6GHz for P2P operations + */ + bool p2p_6ghz_disable; + /** * pri_dev_type - Primary Device Type (see WPS) */ @@ -2100,6 +2105,8 @@ void p2p_update_channel_list(struct p2p_data *p2p, const struct p2p_channels *chan, const struct p2p_channels *cli_chan); +bool is_p2p_6ghz_disabled(struct p2p_data *p2p); + /** * p2p_set_best_channels - Update best channel information * @p2p: P2P module context from p2p_init() diff --git a/src/pae/ieee802_1x_cp.c b/src/pae/ieee802_1x_cp.c index 69e57587d..cf41d8dbf 100644 --- a/src/pae/ieee802_1x_cp.c +++ b/src/pae/ieee802_1x_cp.c @@ -31,50 +31,50 @@ struct ieee802_1x_cp_sm { CP_SECURED, CP_RECEIVE, CP_RECEIVING, CP_READY, CP_TRANSMIT, CP_TRANSMITTING, CP_ABANDON, CP_RETIRE } CP_state; - Boolean changed; + bool changed; /* CP -> Client */ - Boolean port_valid; + bool port_valid; /* Logon -> CP */ enum connect_type connect; /* KaY -> CP */ - Boolean chgd_server; /* clear by CP */ - Boolean elected_self; + bool chgd_server; /* clear by CP */ + bool elected_self; enum confidentiality_offset cipher_offset; u64 cipher_suite; - Boolean new_sak; /* clear by CP */ + bool new_sak; /* clear by CP */ struct ieee802_1x_mka_ki distributed_ki; u8 distributed_an; - Boolean using_receive_sas; - Boolean all_receiving; - Boolean server_transmitting; - Boolean using_transmit_sa; + bool using_receive_sas; + bool all_receiving; + bool server_transmitting; + bool using_transmit_sa; /* CP -> KaY */ struct ieee802_1x_mka_ki *lki; u8 lan; - Boolean ltx; - Boolean lrx; + bool ltx; + bool lrx; struct ieee802_1x_mka_ki *oki; u8 oan; - Boolean otx; - Boolean orx; + bool otx; + bool orx; /* CP -> SecY */ - Boolean protect_frames; + bool protect_frames; enum validate_frames validate_frames; - Boolean replay_protect; + bool replay_protect; u32 replay_window; u64 current_cipher_suite; enum confidentiality_offset confidentiality_offset; - Boolean controlled_port_enabled; + bool controlled_port_enabled; /* SecY -> CP */ - Boolean port_enabled; /* SecY->CP */ + bool port_enabled; /* SecY->CP */ /* private */ u32 transmit_when; @@ -109,23 +109,23 @@ SM_STATE(CP, INIT) { SM_ENTRY(CP, INIT); - sm->controlled_port_enabled = FALSE; + sm->controlled_port_enabled = false; secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled); - sm->port_valid = FALSE; + sm->port_valid = false; os_free(sm->lki); sm->lki = NULL; - sm->ltx = FALSE; - sm->lrx = FALSE; + sm->ltx = false; + sm->lrx = false; os_free(sm->oki); sm->oki = NULL; - sm->otx = FALSE; - sm->orx = FALSE; + sm->otx = false; + sm->orx = false; - sm->port_enabled = TRUE; - sm->chgd_server = FALSE; + sm->port_enabled = true; + sm->chgd_server = false; } @@ -133,8 +133,8 @@ SM_STATE(CP, CHANGE) { SM_ENTRY(CP, CHANGE); - sm->port_valid = FALSE; - sm->controlled_port_enabled = FALSE; + sm->port_valid = false; + sm->controlled_port_enabled = false; secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled); if (sm->lki) @@ -147,15 +147,15 @@ SM_STATE(CP, CHANGE) */ os_free(sm->oki); sm->oki = NULL; - sm->otx = FALSE; - sm->orx = FALSE; + sm->otx = false; + sm->orx = false; sm->oan = 0; ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan, sm->otx, sm->orx); os_free(sm->lki); sm->lki = NULL; - sm->lrx = FALSE; - sm->ltx = FALSE; + sm->lrx = false; + sm->ltx = false; sm->lan = 0; ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan, sm->ltx, sm->lrx); @@ -166,12 +166,12 @@ SM_STATE(CP, ALLOWED) { SM_ENTRY(CP, ALLOWED); - sm->protect_frames = FALSE; - sm->replay_protect = FALSE; + sm->protect_frames = false; + sm->replay_protect = false; sm->validate_frames = Checked; - sm->port_valid = FALSE; - sm->controlled_port_enabled = TRUE; + sm->port_valid = false; + sm->controlled_port_enabled = true; secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled); secy_cp_control_protect_frames(sm->kay, sm->protect_frames); @@ -185,12 +185,12 @@ SM_STATE(CP, AUTHENTICATED) { SM_ENTRY(CP, AUTHENTICATED); - sm->protect_frames = FALSE; - sm->replay_protect = FALSE; + sm->protect_frames = false; + sm->replay_protect = false; sm->validate_frames = Checked; - sm->port_valid = FALSE; - sm->controlled_port_enabled = TRUE; + sm->port_valid = false; + sm->controlled_port_enabled = true; secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled); secy_cp_control_protect_frames(sm->kay, sm->protect_frames); @@ -204,7 +204,7 @@ SM_STATE(CP, SECURED) { SM_ENTRY(CP, SECURED); - sm->chgd_server = FALSE; + sm->chgd_server = false; sm->protect_frames = sm->kay->macsec_protect; sm->replay_protect = sm->kay->macsec_replay_protect; @@ -216,7 +216,7 @@ SM_STATE(CP, SECURED) sm->confidentiality_offset = sm->cipher_offset; - sm->port_valid = TRUE; + sm->port_valid = true; secy_cp_control_confidentiality_offset(sm->kay, sm->confidentiality_offset); @@ -238,14 +238,14 @@ SM_STATE(CP, RECEIVE) } os_memcpy(sm->lki, &sm->distributed_ki, sizeof(*sm->lki)); sm->lan = sm->distributed_an; - sm->ltx = FALSE; - sm->lrx = FALSE; + sm->ltx = false; + sm->lrx = false; ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan, sm->ltx, sm->lrx); ieee802_1x_kay_create_sas(sm->kay, sm->lki); ieee802_1x_kay_enable_rx_sas(sm->kay, sm->lki); - sm->new_sak = FALSE; - sm->all_receiving = FALSE; + sm->new_sak = false; + sm->all_receiving = false; } @@ -253,7 +253,7 @@ SM_STATE(CP, RECEIVING) { SM_ENTRY(CP, RECEIVING); - sm->lrx = TRUE; + sm->lrx = true; ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan, sm->ltx, sm->lrx); sm->transmit_when = sm->transmit_delay; @@ -264,8 +264,8 @@ SM_STATE(CP, RECEIVING) * but the CP will transmit from RECEIVING to READY under * the !electedSelf when KaY is not key server */ ieee802_1x_cp_sm_step(sm); - sm->using_receive_sas = FALSE; - sm->server_transmitting = FALSE; + sm->using_receive_sas = false; + sm->server_transmitting = false; } @@ -281,14 +281,14 @@ SM_STATE(CP, TRANSMIT) { SM_ENTRY(CP, TRANSMIT); - sm->controlled_port_enabled = TRUE; + sm->controlled_port_enabled = true; secy_cp_control_enable_port(sm->kay, sm->controlled_port_enabled); - sm->ltx = TRUE; + sm->ltx = true; ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan, sm->ltx, sm->lrx); ieee802_1x_kay_enable_tx_sas(sm->kay, sm->lki); - sm->all_receiving = FALSE; - sm->server_transmitting = FALSE; + sm->all_receiving = false; + sm->server_transmitting = false; } @@ -296,21 +296,21 @@ SM_STATE(CP, TRANSMITTING) { SM_ENTRY(CP, TRANSMITTING); sm->retire_when = sm->orx ? sm->retire_delay : 0; - sm->otx = FALSE; + sm->otx = false; ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan, sm->otx, sm->orx); ieee802_1x_kay_enable_new_info(sm->kay); eloop_cancel_timeout(ieee802_1x_cp_retire_when_timeout, sm, NULL); eloop_register_timeout(sm->retire_when / 1000, 0, ieee802_1x_cp_retire_when_timeout, sm, NULL); - sm->using_transmit_sa = FALSE; + sm->using_transmit_sa = false; } SM_STATE(CP, ABANDON) { SM_ENTRY(CP, ABANDON); - sm->lrx = FALSE; + sm->lrx = false; ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan, sm->ltx, sm->lrx); ieee802_1x_kay_delete_sas(sm->kay, sm->lki); @@ -337,8 +337,8 @@ SM_STATE(CP, RETIRE) ieee802_1x_kay_set_old_sa_attr(sm->kay, sm->oki, sm->oan, sm->otx, sm->orx); sm->lki = NULL; - sm->ltx = FALSE; - sm->lrx = FALSE; + sm->ltx = false; + sm->lrx = false; sm->lan = 0; ieee802_1x_kay_set_latest_sa_attr(sm->kay, sm->lki, sm->lan, sm->ltx, sm->lrx); @@ -455,23 +455,23 @@ struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay) sm->kay = kay; - sm->port_valid = FALSE; + sm->port_valid = false; - sm->chgd_server = FALSE; + sm->chgd_server = false; sm->protect_frames = kay->macsec_protect; sm->validate_frames = kay->macsec_validate; sm->replay_protect = kay->macsec_replay_protect; sm->replay_window = kay->macsec_replay_window; - sm->controlled_port_enabled = FALSE; + sm->controlled_port_enabled = false; sm->lki = NULL; - sm->lrx = FALSE; - sm->ltx = FALSE; + sm->lrx = false; + sm->ltx = false; sm->oki = NULL; - sm->orx = FALSE; - sm->otx = FALSE; + sm->orx = false; + sm->otx = false; sm->current_cipher_suite = default_cs_id; sm->cipher_suite = default_cs_id; @@ -480,7 +480,7 @@ struct ieee802_1x_cp_sm * ieee802_1x_cp_sm_init(struct ieee802_1x_kay *kay) sm->transmit_delay = MKA_LIFE_TIME; sm->retire_delay = MKA_SAK_RETIRE_TIME; sm->CP_state = CP_BEGIN; - sm->changed = FALSE; + sm->changed = false; wpa_printf(MSG_DEBUG, "CP: state machine created"); @@ -588,14 +588,14 @@ void ieee802_1x_cp_signal_chgdserver(void *cp_ctx) { struct ieee802_1x_cp_sm *sm = cp_ctx; - sm->chgd_server = TRUE; + sm->chgd_server = true; } /** * ieee802_1x_cp_set_electedself - */ -void ieee802_1x_cp_set_electedself(void *cp_ctx, Boolean status) +void ieee802_1x_cp_set_electedself(void *cp_ctx, bool status) { struct ieee802_1x_cp_sm *sm = cp_ctx; sm->elected_self = status; @@ -628,7 +628,7 @@ void ieee802_1x_cp_set_offset(void *cp_ctx, enum confidentiality_offset offset) void ieee802_1x_cp_signal_newsak(void *cp_ctx) { struct ieee802_1x_cp_sm *sm = cp_ctx; - sm->new_sak = TRUE; + sm->new_sak = true; } @@ -656,7 +656,7 @@ void ieee802_1x_cp_set_distributedan(void *cp_ctx, u8 an) /** * ieee802_1x_cp_set_usingreceivesas - */ -void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status) +void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, bool status) { struct ieee802_1x_cp_sm *sm = cp_ctx; sm->using_receive_sas = status; @@ -666,7 +666,7 @@ void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status) /** * ieee802_1x_cp_set_allreceiving - */ -void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status) +void ieee802_1x_cp_set_allreceiving(void *cp_ctx, bool status) { struct ieee802_1x_cp_sm *sm = cp_ctx; sm->all_receiving = status; @@ -676,7 +676,7 @@ void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status) /** * ieee802_1x_cp_set_servertransmitting - */ -void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status) +void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, bool status) { struct ieee802_1x_cp_sm *sm = cp_ctx; sm->server_transmitting = status; @@ -686,7 +686,7 @@ void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status) /** * ieee802_1x_cp_set_usingtransmitsas - */ -void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, Boolean status) +void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, bool status) { struct ieee802_1x_cp_sm *sm = cp_ctx; sm->using_transmit_sa = status; diff --git a/src/pae/ieee802_1x_cp.h b/src/pae/ieee802_1x_cp.h index a357b278f..94110c877 100644 --- a/src/pae/ieee802_1x_cp.h +++ b/src/pae/ieee802_1x_cp.h @@ -24,16 +24,16 @@ void ieee802_1x_cp_connect_unauthenticated(void *cp_ctx); void ieee802_1x_cp_connect_authenticated(void *cp_ctx); void ieee802_1x_cp_connect_secure(void *cp_ctx); void ieee802_1x_cp_signal_chgdserver(void *cp_ctx); -void ieee802_1x_cp_set_electedself(void *cp_ctx, Boolean status); +void ieee802_1x_cp_set_electedself(void *cp_ctx, bool status); void ieee802_1x_cp_set_ciphersuite(void *cp_ctx, u64 cs); void ieee802_1x_cp_set_offset(void *cp_ctx, enum confidentiality_offset offset); void ieee802_1x_cp_signal_newsak(void *cp_ctx); void ieee802_1x_cp_set_distributedki(void *cp_ctx, const struct ieee802_1x_mka_ki *dki); void ieee802_1x_cp_set_distributedan(void *cp_ctx, u8 an); -void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, Boolean status); -void ieee802_1x_cp_set_allreceiving(void *cp_ctx, Boolean status); -void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, Boolean status); -void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, Boolean status); +void ieee802_1x_cp_set_usingreceivesas(void *cp_ctx, bool status); +void ieee802_1x_cp_set_allreceiving(void *cp_ctx, bool status); +void ieee802_1x_cp_set_servertransmitting(void *cp_ctx, bool status); +void ieee802_1x_cp_set_usingtransmitas(void *cp_ctx, bool status); #endif /* IEEE802_1X_CP_H */ diff --git a/src/pae/ieee802_1x_kay.c b/src/pae/ieee802_1x_kay.c index 3dbd3caa7..2fe88ac0c 100644 --- a/src/pae/ieee802_1x_kay.c +++ b/src/pae/ieee802_1x_kay.c @@ -354,7 +354,7 @@ ieee802_1x_kay_get_live_peer(struct ieee802_1x_mka_participant *participant, /** * ieee802_1x_kay_is_in_potential_peer */ -static Boolean +static bool ieee802_1x_kay_is_in_potential_peer( struct ieee802_1x_mka_participant *participant, const u8 *mi) { @@ -365,7 +365,7 @@ ieee802_1x_kay_is_in_potential_peer( /** * ieee802_1x_kay_is_in_live_peer */ -static Boolean +static bool ieee802_1x_kay_is_in_live_peer( struct ieee802_1x_mka_participant *participant, const u8 *mi) { @@ -426,8 +426,8 @@ u64 mka_sci_u64(struct ieee802_1x_mka_sci *sci) } -static Boolean sci_equal(const struct ieee802_1x_mka_sci *a, - const struct ieee802_1x_mka_sci *b) +static bool sci_equal(const struct ieee802_1x_mka_sci *a, + const struct ieee802_1x_mka_sci *b) { return os_memcmp(a, b, sizeof(struct ieee802_1x_mka_sci)) == 0; } @@ -486,7 +486,7 @@ ieee802_1x_kay_init_receive_sa(struct receive_sc *psc, u8 an, u32 lowest_pn, psa->sc = psc; os_get_time(&psa->created_time); - psa->in_use = FALSE; + psa->in_use = false; dl_list_add(&psc->sa_list, &psa->list); wpa_printf(MSG_DEBUG, @@ -534,7 +534,7 @@ ieee802_1x_kay_init_receive_sc(const struct ieee802_1x_mka_sci *psci) os_memcpy(&psc->sci, psci, sizeof(psc->sci)); os_get_time(&psc->created_time); - psc->receiving = FALSE; + psc->receiving = false; dl_list_init(&psc->sa_list); wpa_printf(MSG_DEBUG, "KaY: Create receive SC: SCI %s", @@ -594,7 +594,7 @@ ieee802_1x_kay_create_peer(const u8 *mi, u32 mn) os_memcpy(peer->mi, mi, MI_LEN); peer->mn = mn; peer->expire = time(NULL) + MKA_LIFE_TIME / 1000; - peer->sak_used = FALSE; + peer->sak_used = false; peer->missing_sak_use_count = 0; return peer; @@ -706,11 +706,11 @@ ieee802_1x_kay_move_live_peer(struct ieee802_1x_mka_participant *participant, /** * ieee802_1x_mka_basic_body_present - */ -static Boolean +static bool ieee802_1x_mka_basic_body_present( struct ieee802_1x_mka_participant *participant) { - return TRUE; + return true; } @@ -774,14 +774,14 @@ ieee802_1x_mka_encode_basic_body( } -static Boolean +static bool reset_participant_mi(struct ieee802_1x_mka_participant *participant) { if (os_get_random(participant->mi, sizeof(participant->mi)) < 0) - return FALSE; + return false; participant->mn = 0; - return TRUE; + return true; } @@ -888,13 +888,13 @@ ieee802_1x_mka_decode_basic_body(struct ieee802_1x_kay *kay, const u8 *mka_msg, peer->macsec_desired = body->macsec_desired; peer->macsec_capability = body->macsec_capability; - peer->is_key_server = (Boolean) body->key_server; + peer->is_key_server = body->key_server; peer->key_server_priority = body->priority; } else if (peer->mn < be_to_host32(body->actor_mn)) { peer->mn = be_to_host32(body->actor_mn); peer->macsec_desired = body->macsec_desired; peer->macsec_capability = body->macsec_capability; - peer->is_key_server = (Boolean) body->key_server; + peer->is_key_server = body->key_server; peer->key_server_priority = body->priority; } else { wpa_printf(MSG_WARNING, @@ -909,7 +909,7 @@ ieee802_1x_mka_decode_basic_body(struct ieee802_1x_kay *kay, const u8 *mka_msg, /** * ieee802_1x_mka_live_peer_body_present */ -static Boolean +static bool ieee802_1x_mka_live_peer_body_present( struct ieee802_1x_mka_participant *participant) { @@ -969,7 +969,7 @@ ieee802_1x_mka_encode_live_peer_body( /** * ieee802_1x_mka_potential_peer_body_present */ -static Boolean +static bool ieee802_1x_mka_potential_peer_body_present( struct ieee802_1x_mka_participant *participant) { @@ -1030,7 +1030,7 @@ ieee802_1x_mka_encode_potential_peer_body( /** * ieee802_1x_mka_i_in_peerlist - */ -static Boolean +static bool ieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant *participant, const u8 *mka_msg, size_t msg_len) { @@ -1055,7 +1055,7 @@ ieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant *participant, left_len, MKA_HDR_LEN, MKA_ALIGN_LENGTH(body_len), DEFAULT_ICV_LEN); - return FALSE; + return false; } if (body_type != MKA_LIVE_PEER_LIST && @@ -1096,12 +1096,12 @@ ieee802_1x_mka_i_in_peerlist(struct ieee802_1x_mka_participant *participant, if (mn == participant->mn || (participant->mn > 1 && mn == participant->mn - 1)) - return TRUE; + return true; } } } - return FALSE; + return false; } @@ -1116,7 +1116,7 @@ static int ieee802_1x_mka_decode_live_peer_body( struct ieee802_1x_kay_peer *peer; size_t body_len; size_t i; - Boolean is_included; + bool is_included; is_included = ieee802_1x_kay_is_in_live_peer( participant, participant->current_peer_id.mi); @@ -1209,7 +1209,7 @@ ieee802_1x_mka_decode_potential_peer_body( /** * ieee802_1x_mka_sak_use_body_present */ -static Boolean +static bool ieee802_1x_mka_sak_use_body_present( struct ieee802_1x_mka_participant *participant) { @@ -1296,12 +1296,12 @@ ieee802_1x_mka_encode_sak_use_body( set_mka_param_body_len(body, length - MKA_HDR_LEN); if (length == MKA_HDR_LEN) { - body->ptx = TRUE; - body->prx = TRUE; + body->ptx = true; + body->prx = true; body->lan = 0; - body->lrx = FALSE; - body->ltx = FALSE; - body->delay_protect = FALSE; + body->lrx = false; + body->ltx = false; + body->delay_protect = false; return 0; } @@ -1321,13 +1321,13 @@ ieee802_1x_mka_encode_sak_use_body( if (llpn > kay->pn_exhaustion) { wpa_printf(MSG_WARNING, "KaY: My LLPN exhaustion"); - participant->new_sak = TRUE; + participant->new_sak = true; } } else { if (olpn > kay->pn_exhaustion) { wpa_printf(MSG_WARNING, "KaY: My OLPN exhaustion"); - participant->new_sak = TRUE; + participant->new_sak = true; } } } @@ -1347,23 +1347,23 @@ ieee802_1x_mka_encode_sak_use_body( body->oan = participant->oan; if (participant->oki.kn != participant->lki.kn && participant->oki.kn != 0) { - body->otx = TRUE; - body->orx = TRUE; + body->otx = true; + body->orx = true; os_memcpy(body->osrv_mi, participant->oki.mi, sizeof(body->osrv_mi)); body->okn = host_to_be32(participant->oki.kn); } else { - body->otx = FALSE; - body->orx = FALSE; + body->otx = false; + body->orx = false; } /* set CP's variable */ if (body->ltx) { - kay->tx_enable = TRUE; - kay->port_enable = TRUE; + kay->tx_enable = true; + kay->port_enable = true; } if (body->lrx) - kay->rx_enable = TRUE; + kay->rx_enable = true; ieee802_1x_mka_dump_sak_use_body(body); return 0; @@ -1485,26 +1485,26 @@ ieee802_1x_mka_decode_sak_use_body( */ if (participant->is_key_server) { struct ieee802_1x_kay_peer *peer_iter; - Boolean all_receiving = TRUE; + bool all_receiving = true; /* Distributed keys are equal from above comparison. */ - peer->sak_used = TRUE; + peer->sak_used = true; dl_list_for_each(peer_iter, &participant->live_peers, struct ieee802_1x_kay_peer, list) { if (!peer_iter->sak_used) { - all_receiving = FALSE; + all_receiving = false; break; } } if (all_receiving) { - participant->to_dist_sak = FALSE; - ieee802_1x_cp_set_allreceiving(kay->cp, TRUE); + participant->to_dist_sak = false; + ieee802_1x_cp_set_allreceiving(kay->cp, true); ieee802_1x_cp_sm_step(kay->cp); } } else if (peer->is_key_server) { if (body->ltx) { - ieee802_1x_cp_set_servertransmitting(kay->cp, TRUE); + ieee802_1x_cp_set_servertransmitting(kay->cp, true); ieee802_1x_cp_sm_step(kay->cp); } } @@ -1516,7 +1516,7 @@ ieee802_1x_mka_decode_sak_use_body( * has already been exhausted. */ if (participant->is_key_server && lpn > kay->pn_exhaustion) { - participant->new_sak = TRUE; + participant->new_sak = true; wpa_printf(MSG_WARNING, "KaY: Peer LPN exhaustion"); } @@ -1528,14 +1528,14 @@ ieee802_1x_mka_decode_sak_use_body( if (body->delay_protect) { struct receive_sc *rxsc; struct receive_sa *rxsa; - Boolean found = FALSE; + bool found = false; dl_list_for_each(rxsc, &participant->rxsc_list, struct receive_sc, list) { dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list) { if (sa_key && rxsa->pkey == sa_key) { - found = TRUE; + found = true; break; } } @@ -1570,7 +1570,7 @@ ieee802_1x_mka_decode_sak_use_body( /** * ieee802_1x_mka_dist_sak_body_present */ -static Boolean +static bool ieee802_1x_mka_dist_sak_body_present( struct ieee802_1x_mka_participant *participant) { @@ -1663,8 +1663,8 @@ ieee802_1x_mka_encode_dist_sak_body( */ static void ieee802_1x_kay_init_data_key(struct data_key *pkey) { - pkey->transmits = TRUE; - pkey->receives = TRUE; + pkey->transmits = true; + pkey->receives = true; os_get_time(&pkey->created_time); pkey->next_pn = 1; @@ -1730,21 +1730,21 @@ ieee802_1x_mka_decode_dist_sak_body( } if (body_len == 0) { - kay->authenticated = TRUE; - kay->secured = FALSE; - kay->failed = FALSE; - participant->advised_desired = FALSE; + kay->authenticated = true; + kay->secured = false; + kay->failed = false; + participant->advised_desired = false; ieee802_1x_cp_connect_authenticated(kay->cp); ieee802_1x_cp_sm_step(kay->cp); wpa_printf(MSG_WARNING, "KaY: The Key server advise no MACsec"); - participant->to_use_sak = FALSE; + participant->to_use_sak = false; return 0; } - participant->advised_desired = TRUE; - kay->authenticated = FALSE; - kay->secured = TRUE; - kay->failed = FALSE; + participant->advised_desired = true; + kay->authenticated = false; + kay->secured = true; + kay->failed = false; ieee802_1x_cp_connect_secure(kay->cp); ieee802_1x_cp_sm_step(kay->cp); @@ -1825,7 +1825,7 @@ ieee802_1x_mka_decode_dist_sak_body( ieee802_1x_cp_sm_step(kay->cp); kay->rcvd_keys++; - participant->to_use_sak = TRUE; + participant->to_use_sak = true; return 0; } @@ -1834,10 +1834,10 @@ ieee802_1x_mka_decode_dist_sak_body( /** * ieee802_1x_mka_icv_body_present */ -static Boolean +static bool ieee802_1x_mka_icv_body_present(struct ieee802_1x_mka_participant *participant) { - return TRUE; + return true; } @@ -2002,7 +2002,7 @@ struct mka_param_body_handler { int (*body_rx)(struct ieee802_1x_mka_participant *participant, const u8 *mka_msg, size_t msg_len); int (*body_length)(struct ieee802_1x_mka_participant *participant); - Boolean (*body_present)(struct ieee802_1x_mka_participant *participant); + bool (*body_present)(struct ieee802_1x_mka_participant *participant); }; @@ -2229,7 +2229,7 @@ ieee802_1x_kay_generate_new_sak(struct ieee802_1x_mka_participant *participant) dl_list_for_each(peer, &participant->live_peers, struct ieee802_1x_kay_peer, list) - peer->sak_used = FALSE; + peer->sak_used = false; kay->dist_kn++; kay->dist_an++; @@ -2269,13 +2269,13 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant) struct ieee802_1x_kay_peer *peer; struct ieee802_1x_kay_peer *key_server = NULL; struct ieee802_1x_kay *kay = participant->kay; - Boolean i_is_key_server; + bool i_is_key_server; int priority_comparison; if (participant->is_obliged_key_server) { - participant->new_sak = TRUE; - participant->to_dist_sak = FALSE; - ieee802_1x_cp_set_electedself(kay->cp, TRUE); + participant->new_sak = true; + participant->to_dist_sak = false; + ieee802_1x_cp_set_electedself(kay->cp, true); return 0; } @@ -2295,7 +2295,7 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant) } /* elect the key server between me and the above elected peer */ - i_is_key_server = FALSE; + i_is_key_server = false; if (key_server && participant->can_be_key_server) { struct ieee802_1x_kay_peer tmp; @@ -2303,29 +2303,29 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant) os_memcpy(&tmp.sci, &kay->actor_sci, sizeof(tmp.sci)); priority_comparison = compare_priorities(&tmp, key_server); if (priority_comparison < 0) { - i_is_key_server = TRUE; + i_is_key_server = true; } else if (priority_comparison == 0) { wpa_printf(MSG_WARNING, "KaY: Cannot elect key server between me and peer, duplicate MAC detected"); key_server = NULL; } } else if (participant->can_be_key_server) { - i_is_key_server = TRUE; + i_is_key_server = true; } if (i_is_key_server) { - ieee802_1x_cp_set_electedself(kay->cp, TRUE); + ieee802_1x_cp_set_electedself(kay->cp, true); if (!sci_equal(&kay->key_server_sci, &kay->actor_sci)) { ieee802_1x_cp_signal_chgdserver(kay->cp); ieee802_1x_cp_sm_step(kay->cp); } - participant->is_key_server = TRUE; - participant->principal = TRUE; - participant->new_sak = TRUE; + participant->is_key_server = true; + participant->principal = true; + participant->new_sak = true; wpa_printf(MSG_DEBUG, "KaY: I am elected as key server"); - participant->to_dist_sak = FALSE; - participant->is_elected = TRUE; + participant->to_dist_sak = false; + participant->is_elected = true; os_memcpy(&kay->key_server_sci, &kay->actor_sci, sizeof(kay->key_server_sci)); @@ -2334,23 +2334,23 @@ ieee802_1x_kay_elect_key_server(struct ieee802_1x_mka_participant *participant) wpa_printf(MSG_DEBUG, "KaY: Peer %s was elected as the key server", mi_txt(key_server->mi)); - ieee802_1x_cp_set_electedself(kay->cp, FALSE); + ieee802_1x_cp_set_electedself(kay->cp, false); if (!sci_equal(&kay->key_server_sci, &key_server->sci)) { ieee802_1x_cp_signal_chgdserver(kay->cp); ieee802_1x_cp_sm_step(kay->cp); } - participant->is_key_server = FALSE; - participant->principal = TRUE; - participant->is_elected = TRUE; + participant->is_key_server = false; + participant->principal = true; + participant->is_elected = true; os_memcpy(&kay->key_server_sci, &key_server->sci, sizeof(kay->key_server_sci)); kay->key_server_priority = key_server->key_server_priority; } else { - participant->principal = FALSE; - participant->is_key_server = FALSE; - participant->is_elected = FALSE; + participant->principal = false; + participant->is_key_server = false; + participant->is_elected = false; } return 0; @@ -2370,24 +2370,24 @@ ieee802_1x_kay_decide_macsec_use( struct ieee802_1x_kay *kay = participant->kay; struct ieee802_1x_kay_peer *peer; enum macsec_cap less_capability; - Boolean has_peer; + bool has_peer; if (!participant->is_key_server) return -1; /* key server self is MACsec-desired and requesting MACsec */ if (!kay->macsec_desired) { - participant->advised_desired = FALSE; + participant->advised_desired = false; return -1; } if (kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) { - participant->advised_desired = FALSE; + participant->advised_desired = false; return -1; } less_capability = kay->macsec_capable; /* at least one of peers is MACsec-desired and requesting MACsec */ - has_peer = FALSE; + has_peer = false; dl_list_for_each(peer, &participant->live_peers, struct ieee802_1x_kay_peer, list) { if (!peer->macsec_desired) @@ -2398,24 +2398,24 @@ ieee802_1x_kay_decide_macsec_use( less_capability = (less_capability < peer->macsec_capability) ? less_capability : peer->macsec_capability; - has_peer = TRUE; + has_peer = true; } if (has_peer) { - participant->advised_desired = TRUE; + participant->advised_desired = true; participant->advised_capability = less_capability; - kay->authenticated = FALSE; - kay->secured = TRUE; - kay->failed = FALSE; + kay->authenticated = false; + kay->secured = true; + kay->failed = false; ieee802_1x_cp_connect_secure(kay->cp); ieee802_1x_cp_sm_step(kay->cp); } else { - participant->advised_desired = FALSE; + participant->advised_desired = false; participant->advised_capability = MACSEC_CAP_NOT_IMPLEMENTED; - participant->to_use_sak = FALSE; - kay->authenticated = TRUE; - kay->secured = FALSE; - kay->failed = FALSE; + participant->to_use_sak = false; + kay->authenticated = true; + kay->secured = false; + kay->failed = false; kay->ltx_kn = 0; kay->ltx_an = 0; kay->lrx_kn = 0; @@ -2514,8 +2514,8 @@ ieee802_1x_participant_send_mkpdu( l2_packet_send(kay->l2_mka, NULL, 0, wpabuf_head(buf), wpabuf_len(buf)); wpabuf_free(buf); - kay->active = TRUE; - participant->active = TRUE; + kay->active = true; + participant->active = true; return 0; } @@ -2541,7 +2541,7 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx) struct ieee802_1x_kay *kay; struct ieee802_1x_kay_peer *peer, *pre_peer; time_t now = time(NULL); - Boolean lp_changed; + bool lp_changed; struct receive_sc *rxsc, *pre_rxsc; struct transmit_sa *txsa, *pre_txsa; @@ -2565,7 +2565,7 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx) } } - lp_changed = FALSE; + lp_changed = false; dl_list_for_each_safe(peer, pre_peer, &participant->live_peers, struct ieee802_1x_kay_peer, list) { if (now > peer->expire) { @@ -2583,25 +2583,25 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx) } dl_list_del(&peer->list); os_free(peer); - lp_changed = TRUE; + lp_changed = true; } } if (lp_changed) { if (dl_list_empty(&participant->live_peers)) { - participant->advised_desired = FALSE; + participant->advised_desired = false; participant->advised_capability = MACSEC_CAP_NOT_IMPLEMENTED; - participant->to_use_sak = FALSE; - participant->ltx = FALSE; - participant->lrx = FALSE; - participant->otx = FALSE; - participant->orx = FALSE; - participant->is_key_server = FALSE; - participant->is_elected = FALSE; - kay->authenticated = FALSE; - kay->secured = FALSE; - kay->failed = FALSE; + participant->to_use_sak = false; + participant->ltx = false; + participant->lrx = false; + participant->otx = false; + participant->orx = false; + participant->is_key_server = false; + participant->is_elected = false; + kay->authenticated = false; + kay->secured = false; + kay->failed = false; kay->ltx_kn = 0; kay->ltx_an = 0; kay->lrx_kn = 0; @@ -2638,9 +2638,9 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx) if (participant->new_sak && participant->is_key_server) { if (!ieee802_1x_kay_generate_new_sak(participant)) - participant->to_dist_sak = TRUE; + participant->to_dist_sak = true; - participant->new_sak = FALSE; + participant->new_sak = false; } if (participant->retry_count < MAX_RETRY_CNT || @@ -2656,9 +2656,9 @@ static void ieee802_1x_participant_timer(void *eloop_ctx, void *timeout_ctx) return; delete_mka: - kay->authenticated = FALSE; - kay->secured = FALSE; - kay->failed = TRUE; + kay->authenticated = false; + kay->secured = false; + kay->failed = true; ieee802_1x_kay_delete_mka(kay, &participant->ckn); } @@ -2672,8 +2672,8 @@ ieee802_1x_kay_init_transmit_sa(struct transmit_sc *psc, u8 an, u32 next_PN, { struct transmit_sa *psa; - key->tx_latest = TRUE; - key->rx_latest = TRUE; + key->tx_latest = true; + key->rx_latest = true; psa = os_zalloc(sizeof(*psa)); if (!psa) { @@ -2683,9 +2683,9 @@ ieee802_1x_kay_init_transmit_sa(struct transmit_sc *psc, u8 an, u32 next_PN, if (key->confidentiality_offset >= CONFIDENTIALITY_OFFSET_0 && key->confidentiality_offset <= CONFIDENTIALITY_OFFSET_50) - psa->confidentiality = TRUE; + psa->confidentiality = true; else - psa->confidentiality = FALSE; + psa->confidentiality = false; psa->an = an; ieee802_1x_kay_use_data_key(key); @@ -2694,7 +2694,7 @@ ieee802_1x_kay_init_transmit_sa(struct transmit_sc *psc, u8 an, u32 next_PN, psa->sc = psc; os_get_time(&psa->created_time); - psa->in_use = FALSE; + psa->in_use = false; dl_list_add(&psc->sa_list, &psa->list); wpa_printf(MSG_DEBUG, @@ -2736,9 +2736,9 @@ ieee802_1x_kay_init_transmit_sc(const struct ieee802_1x_mka_sci *sci) os_memcpy(&psc->sci, sci, sizeof(psc->sci)); os_get_time(&psc->created_time); - psc->transmitting = FALSE; - psc->encoding_sa = FALSE; - psc->enciphering_sa = FALSE; + psc->transmitting = false; + psc->encoding_sa = false; + psc->enciphering_sa = false; dl_list_init(&psc->sa_list); wpa_printf(MSG_DEBUG, "KaY: Create transmit SC - SCI: %s", @@ -2772,7 +2772,7 @@ ieee802_1x_kay_deinit_transmit_sc( */ int ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay *kay, struct ieee802_1x_mka_ki *lki, u8 lan, - Boolean ltx, Boolean lrx) + bool ltx, bool lrx) { struct ieee802_1x_mka_participant *principal; @@ -2807,7 +2807,7 @@ int ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay *kay, */ int ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay *kay, struct ieee802_1x_mka_ki *oki, - u8 oan, Boolean otx, Boolean orx) + u8 oan, bool otx, bool orx) { struct ieee802_1x_mka_participant *principal; @@ -2883,13 +2883,13 @@ int ieee802_1x_kay_create_sas(struct ieee802_1x_kay *kay, latest_sak = NULL; dl_list_for_each(sa_key, &principal->sak_list, struct data_key, list) { if (is_ki_equal(&sa_key->key_identifier, lki)) { - sa_key->rx_latest = TRUE; - sa_key->tx_latest = TRUE; + sa_key->rx_latest = true; + sa_key->tx_latest = true; latest_sak = sa_key; - principal->to_use_sak = TRUE; + principal->to_use_sak = true; } else { - sa_key->rx_latest = FALSE; - sa_key->tx_latest = FALSE; + sa_key->rx_latest = false; + sa_key->tx_latest = false; } } if (!latest_sak) { @@ -2993,10 +2993,10 @@ int ieee802_1x_kay_enable_tx_sas(struct ieee802_1x_kay *kay, dl_list_for_each(txsa, &principal->txsc->sa_list, struct transmit_sa, list) { if (is_ki_equal(&txsa->pkey->key_identifier, lki)) { - txsa->in_use = TRUE; + txsa->in_use = true; secy_enable_transmit_sa(kay, txsa); ieee802_1x_cp_set_usingtransmitas( - principal->kay->cp, TRUE); + principal->kay->cp, true); ieee802_1x_cp_sm_step(principal->kay->cp); } } @@ -3023,10 +3023,10 @@ int ieee802_1x_kay_enable_rx_sas(struct ieee802_1x_kay *kay, dl_list_for_each(rxsa, &rxsc->sa_list, struct receive_sa, list) { if (is_ki_equal(&rxsa->pkey->key_identifier, lki)) { - rxsa->in_use = TRUE; + rxsa->in_use = true; secy_enable_receive_sa(kay, rxsa); ieee802_1x_cp_set_usingreceivesas( - principal->kay->cp, TRUE); + principal->kay->cp, true); ieee802_1x_cp_sm_step(principal->kay->cp); } } @@ -3208,10 +3208,10 @@ static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay, u8 body_type; int i; const u8 *pos; - Boolean handled[256]; - Boolean bad_sak_use = FALSE; /* Error detected while processing SAK Use - * parameter set */ - Boolean i_in_peerlist, is_in_live_peer, is_in_potential_peer; + bool handled[256]; + bool bad_sak_use = false; /* Error detected while processing SAK Use + * parameter set */ + bool i_in_peerlist, is_in_live_peer, is_in_potential_peer; wpa_printf(MSG_DEBUG, "KaY: Decode received MKPDU (ifname=%s)", kay->if_name); @@ -3268,9 +3268,9 @@ static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay, * Each parameter set should be present only once. */ for (i = 0; i < 256; i++) - handled[i] = FALSE; + handled[i] = false; - handled[0] = TRUE; + handled[0] = true; for (; left_len > MKA_HDR_LEN + DEFAULT_ICV_LEN; pos += body_len + MKA_HDR_LEN, left_len -= body_len + MKA_HDR_LEN) { @@ -3296,7 +3296,7 @@ static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay, continue; } - handled[body_type] = TRUE; + handled[body_type] = true; if (body_type < ARRAY_SIZE(mka_body_handler) && mka_body_handler[body_type].body_rx) { if (mka_body_handler[body_type].body_rx @@ -3317,7 +3317,7 @@ static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay, * that it somehow processes DIST-SAK before * SAK-USE, just ignore SAK-USE failures if * DIST-SAK is also present in this MKPDU. */ - bad_sak_use = TRUE; + bad_sak_use = true; } } else { wpa_printf(MSG_ERROR, @@ -3386,9 +3386,9 @@ static int ieee802_1x_kay_decode_mkpdu(struct ieee802_1x_kay *kay, * from 'potential_peers' to 'live_peers'. */ } - kay->active = TRUE; + kay->active = true; participant->retry_count = 0; - participant->active = TRUE; + participant->active = true; return 0; } @@ -3455,7 +3455,7 @@ static void kay_l2_receive(void *ctx, const u8 *src_addr, const u8 *buf, */ struct ieee802_1x_kay * ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, - Boolean macsec_replay_protect, u32 macsec_replay_window, + bool macsec_replay_protect, u32 macsec_replay_window, u16 port, u8 priority, const char *ifname, const u8 *addr) { struct ieee802_1x_kay *kay; @@ -3472,12 +3472,12 @@ ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, kay->ctx = ctx; - kay->enable = TRUE; - kay->active = FALSE; + kay->enable = true; + kay->active = false; - kay->authenticated = FALSE; - kay->secured = FALSE; - kay->failed = FALSE; + kay->authenticated = false; + kay->secured = false; + kay->failed = false; kay->policy = policy; os_strlcpy(kay->if_name, ifname, IFNAMSIZ); @@ -3509,23 +3509,23 @@ ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, if (policy == DO_NOT_SECURE || kay->macsec_capable == MACSEC_CAP_NOT_IMPLEMENTED) { kay->macsec_capable = MACSEC_CAP_NOT_IMPLEMENTED; - kay->macsec_desired = FALSE; - kay->macsec_protect = FALSE; - kay->macsec_encrypt = FALSE; + kay->macsec_desired = false; + kay->macsec_protect = false; + kay->macsec_encrypt = false; kay->macsec_validate = Disabled; - kay->macsec_replay_protect = FALSE; + kay->macsec_replay_protect = false; kay->macsec_replay_window = 0; kay->macsec_confidentiality = CONFIDENTIALITY_NONE; kay->mka_hello_time = MKA_HELLO_TIME; } else { - kay->macsec_desired = TRUE; - kay->macsec_protect = TRUE; + kay->macsec_desired = true; + kay->macsec_protect = true; if (kay->macsec_capable >= MACSEC_CAP_INTEG_AND_CONF && policy == SHOULD_ENCRYPT) { - kay->macsec_encrypt = TRUE; + kay->macsec_encrypt = true; kay->macsec_confidentiality = CONFIDENTIALITY_OFFSET_0; } else { /* SHOULD_SECURE */ - kay->macsec_encrypt = FALSE; + kay->macsec_encrypt = false; kay->macsec_confidentiality = CONFIDENTIALITY_NONE; } kay->macsec_validate = Strict; @@ -3623,7 +3623,7 @@ struct ieee802_1x_mka_participant * ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, const struct mka_key_name *ckn, const struct mka_key *cak, u32 life, - enum mka_created_mode mode, Boolean is_authenticator) + enum mka_created_mode mode, bool is_authenticator) { struct ieee802_1x_mka_participant *participant; unsigned int usecs; @@ -3671,40 +3671,40 @@ ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, switch (mode) { case EAP_EXCHANGE: if (is_authenticator) { - participant->is_obliged_key_server = TRUE; - participant->can_be_key_server = TRUE; - participant->is_key_server = TRUE; - participant->principal = TRUE; + participant->is_obliged_key_server = true; + participant->can_be_key_server = true; + participant->is_key_server = true; + participant->principal = true; os_memcpy(&kay->key_server_sci, &kay->actor_sci, sizeof(kay->key_server_sci)); kay->key_server_priority = kay->actor_priority; - participant->is_elected = TRUE; + participant->is_elected = true; } else { - participant->is_obliged_key_server = FALSE; - participant->can_be_key_server = FALSE; - participant->is_key_server = FALSE; - participant->is_elected = TRUE; + participant->is_obliged_key_server = false; + participant->can_be_key_server = false; + participant->is_key_server = false; + participant->is_elected = true; } break; default: - participant->is_obliged_key_server = FALSE; - participant->can_be_key_server = TRUE; - participant->is_key_server = TRUE; - participant->is_elected = FALSE; + participant->is_obliged_key_server = false; + participant->can_be_key_server = true; + participant->is_key_server = true; + participant->is_elected = false; break; } - participant->cached = FALSE; + participant->cached = false; - participant->active = FALSE; - participant->participant = FALSE; - participant->retain = FALSE; + participant->active = false; + participant->participant = false; + participant->retain = false; participant->activate = DEFAULT; if (participant->is_key_server) - participant->principal = TRUE; + participant->principal = true; dl_list_init(&participant->live_peers); dl_list_init(&participant->potential_peers); @@ -3717,13 +3717,13 @@ ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, wpa_printf(MSG_DEBUG, "KaY: Selected random MI: %s", mi_txt(participant->mi)); - participant->lrx = FALSE; - participant->ltx = FALSE; - participant->orx = FALSE; - participant->otx = FALSE; - participant->to_dist_sak = FALSE; - participant->to_use_sak = FALSE; - participant->new_sak = FALSE; + participant->lrx = false; + participant->ltx = false; + participant->orx = false; + participant->otx = false; + participant->to_dist_sak = false; + participant->to_use_sak = false; + participant->new_sak = false; dl_list_init(&participant->sak_list); participant->new_key = NULL; dl_list_init(&participant->rxsc_list); @@ -3856,8 +3856,7 @@ ieee802_1x_kay_delete_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn) * ieee802_1x_kay_mka_participate - */ void ieee802_1x_kay_mka_participate(struct ieee802_1x_kay *kay, - struct mka_key_name *ckn, - Boolean status) + struct mka_key_name *ckn, bool status) { struct ieee802_1x_mka_participant *participant; @@ -3887,7 +3886,7 @@ ieee802_1x_kay_new_sak(struct ieee802_1x_kay *kay) if (!participant) return -1; - participant->new_sak = TRUE; + participant->new_sak = true; wpa_printf(MSG_DEBUG, "KaY: new SAK signal"); return 0; @@ -3916,7 +3915,7 @@ ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay, return -2; if (cs_index == 0) - kay->macsec_desired = FALSE; + kay->macsec_desired = false; kay->macsec_csindex = cs_index; kay->macsec_capable = cipher_suite_tbl[kay->macsec_csindex].capable; @@ -3930,7 +3929,7 @@ ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay, participant = ieee802_1x_kay_get_principal_participant(kay); if (participant) { wpa_printf(MSG_INFO, "KaY: Cipher Suite changed"); - participant->new_sak = TRUE; + participant->new_sak = true; } return 0; @@ -4044,7 +4043,7 @@ int ieee802_1x_kay_get_status(struct ieee802_1x_kay *kay, char *buf, } -static const char * true_false(Boolean val) +static const char * true_false(bool val) { return val ? "true" : "false"; } @@ -4067,7 +4066,7 @@ static const char * activate_control_txt(enum activate_ctrl activate) } -static char * mka_mib_peer(struct dl_list *peers, Boolean live, char *buf, +static char * mka_mib_peer(struct dl_list *peers, bool live, char *buf, char *end) { char *pos = buf; @@ -4134,8 +4133,8 @@ int ieee802_1x_kay_get_mib(struct ieee802_1x_kay *kay, char *buf, pos2 += res; pos = pos2; - pos = mka_mib_peer(&p->live_peers, TRUE, pos, end); - pos = mka_mib_peer(&p->potential_peers, FALSE, pos, end); + pos = mka_mib_peer(&p->live_peers, true, pos, end); + pos = mka_mib_peer(&p->potential_peers, false, pos, end); } return pos - buf; diff --git a/src/pae/ieee802_1x_kay.h b/src/pae/ieee802_1x_kay.h index 3367d3aaa..1d3c2acb7 100644 --- a/src/pae/ieee802_1x_kay.h +++ b/src/pae/ieee802_1x_kay.h @@ -62,14 +62,14 @@ struct data_key { struct ieee802_1x_mka_ki key_identifier; enum confidentiality_offset confidentiality_offset; u8 an; - Boolean transmits; - Boolean receives; + bool transmits; + bool receives; struct os_time created_time; u32 next_pn; /* not defined data */ - Boolean rx_latest; - Boolean tx_latest; + bool rx_latest; + bool tx_latest; int user; @@ -79,7 +79,7 @@ struct data_key { /* TransmitSC in IEEE Std 802.1AE-2006, Figure 10-6 */ struct transmit_sc { struct ieee802_1x_mka_sci sci; /* const SCI sci */ - Boolean transmitting; /* bool transmitting (read only) */ + bool transmitting; /* bool transmitting (read only) */ struct os_time created_time; /* Time createdTime */ @@ -93,14 +93,14 @@ struct transmit_sc { /* TransmitSA in IEEE Std 802.1AE-2006, Figure 10-6 */ struct transmit_sa { - Boolean in_use; /* bool inUse (read only) */ + bool in_use; /* bool inUse (read only) */ u32 next_pn; /* PN nextPN (read only) */ struct os_time created_time; /* Time createdTime */ - Boolean enable_transmit; /* bool EnableTransmit */ + bool enable_transmit; /* bool EnableTransmit */ u8 an; - Boolean confidentiality; + bool confidentiality; struct data_key *pkey; struct transmit_sc *sc; @@ -110,7 +110,7 @@ struct transmit_sa { /* ReceiveSC in IEEE Std 802.1AE-2006, Figure 10-6 */ struct receive_sc { struct ieee802_1x_mka_sci sci; /* const SCI sci */ - Boolean receiving; /* bool receiving (read only) */ + bool receiving; /* bool receiving (read only) */ struct os_time created_time; /* Time createdTime */ @@ -120,8 +120,8 @@ struct receive_sc { /* ReceiveSA in IEEE Std 802.1AE-2006, Figure 10-6 */ struct receive_sa { - Boolean enable_receive; /* bool enableReceive */ - Boolean in_use; /* bool inUse (read only) */ + bool enable_receive; /* bool enableReceive */ + bool in_use; /* bool inUse (read only) */ u32 next_pn; /* PN nextPN (read only) */ u32 lowest_pn; /* PN lowestPN (read only) */ @@ -142,11 +142,11 @@ struct ieee802_1x_kay_ctx { int (*macsec_init)(void *ctx, struct macsec_init_params *params); int (*macsec_deinit)(void *ctx); int (*macsec_get_capability)(void *priv, enum macsec_cap *cap); - int (*enable_protect_frames)(void *ctx, Boolean enabled); - int (*enable_encrypt)(void *ctx, Boolean enabled); - int (*set_replay_protect)(void *ctx, Boolean enabled, u32 window); + int (*enable_protect_frames)(void *ctx, bool enabled); + int (*enable_encrypt)(void *ctx, bool enabled); + int (*set_replay_protect)(void *ctx, bool enabled, u32 window); int (*set_current_cipher_suite)(void *ctx, u64 cs); - int (*enable_controlled_port)(void *ctx, Boolean enabled); + int (*enable_controlled_port)(void *ctx, bool enabled); int (*get_receive_lowest_pn)(void *ctx, struct receive_sa *sa); int (*get_transmit_next_pn)(void *ctx, struct transmit_sa *sa); int (*set_transmit_next_pn)(void *ctx, struct transmit_sa *sa); @@ -169,12 +169,12 @@ struct ieee802_1x_kay_ctx { }; struct ieee802_1x_kay { - Boolean enable; - Boolean active; + bool enable; + bool active; - Boolean authenticated; - Boolean secured; - Boolean failed; + bool authenticated; + bool secured; + bool failed; struct ieee802_1x_mka_sci actor_sci; u8 actor_priority; @@ -182,10 +182,10 @@ struct ieee802_1x_kay { u8 key_server_priority; enum macsec_cap macsec_capable; - Boolean macsec_desired; - Boolean macsec_protect; - Boolean macsec_encrypt; - Boolean macsec_replay_protect; + bool macsec_desired; + bool macsec_protect; + bool macsec_encrypt; + bool macsec_replay_protect; u32 macsec_replay_window; enum validate_frames macsec_validate; enum confidentiality_offset macsec_confidentiality; @@ -203,8 +203,8 @@ struct ieee802_1x_kay { /* not defined in IEEE802.1X */ struct ieee802_1x_kay_ctx *ctx; - Boolean is_key_server; - Boolean is_obliged_key_server; + bool is_key_server; + bool is_obliged_key_server; char if_name[IFNAMSIZ]; unsigned int macsec_csindex; /* MACsec cipher suite table index */ @@ -219,9 +219,9 @@ struct ieee802_1x_kay { u8 algo_agility[4]; u32 pn_exhaustion; - Boolean port_enable; - Boolean rx_enable; - Boolean tx_enable; + bool port_enable; + bool rx_enable; + bool tx_enable; struct dl_list participant_list; enum macsec_policy policy; @@ -239,7 +239,7 @@ u64 mka_sci_u64(struct ieee802_1x_mka_sci *sci); struct ieee802_1x_kay * ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy, - Boolean macsec_replay_protect, u32 macsec_replay_window, + bool macsec_replay_protect, u32 macsec_replay_window, u16 port, u8 priority, const char *ifname, const u8 *addr); void ieee802_1x_kay_deinit(struct ieee802_1x_kay *kay); @@ -248,22 +248,22 @@ ieee802_1x_kay_create_mka(struct ieee802_1x_kay *kay, const struct mka_key_name *ckn, const struct mka_key *cak, u32 life, enum mka_created_mode mode, - Boolean is_authenticator); + bool is_authenticator); void ieee802_1x_kay_delete_mka(struct ieee802_1x_kay *kay, struct mka_key_name *ckn); void ieee802_1x_kay_mka_participate(struct ieee802_1x_kay *kay, struct mka_key_name *ckn, - Boolean status); + bool status); int ieee802_1x_kay_new_sak(struct ieee802_1x_kay *kay); int ieee802_1x_kay_change_cipher_suite(struct ieee802_1x_kay *kay, unsigned int cs_index); int ieee802_1x_kay_set_latest_sa_attr(struct ieee802_1x_kay *kay, struct ieee802_1x_mka_ki *lki, u8 lan, - Boolean ltx, Boolean lrx); + bool ltx, bool lrx); int ieee802_1x_kay_set_old_sa_attr(struct ieee802_1x_kay *kay, struct ieee802_1x_mka_ki *oki, - u8 oan, Boolean otx, Boolean orx); + u8 oan, bool otx, bool orx); int ieee802_1x_kay_create_sas(struct ieee802_1x_kay *kay, struct ieee802_1x_mka_ki *lki); int ieee802_1x_kay_delete_sas(struct ieee802_1x_kay *kay, diff --git a/src/pae/ieee802_1x_kay_i.h b/src/pae/ieee802_1x_kay_i.h index f9cd3f41b..7a041692a 100644 --- a/src/pae/ieee802_1x_kay_i.h +++ b/src/pae/ieee802_1x_kay_i.h @@ -46,11 +46,11 @@ struct ieee802_1x_kay_peer { u8 mi[MI_LEN]; u32 mn; time_t expire; - Boolean is_key_server; + bool is_key_server; u8 key_server_priority; - Boolean macsec_desired; + bool macsec_desired; enum macsec_cap macsec_capability; - Boolean sak_used; + bool sak_used; int missing_sak_use_count; struct dl_list list; }; @@ -87,18 +87,18 @@ struct ieee802_1x_mka_participant { /* used for active and potential participant */ struct mka_key_name ckn; struct mka_key cak; - Boolean cached; + bool cached; /* used by management to monitor and control activation */ - Boolean active; - Boolean participant; - Boolean retain; + bool active; + bool participant; + bool retain; enum mka_created_mode mode; enum activate_ctrl { DEFAULT, DISABLED, ON_OPER_UP, ALWAYS } activate; /* used for active participant */ - Boolean principal; + bool principal; struct dl_list live_peers; struct dl_list potential_peers; @@ -110,18 +110,18 @@ struct ieee802_1x_mka_participant { struct ieee802_1x_mka_ki lki; u8 lan; - Boolean ltx; - Boolean lrx; + bool ltx; + bool lrx; struct ieee802_1x_mka_ki oki; u8 oan; - Boolean otx; - Boolean orx; + bool otx; + bool orx; - Boolean is_key_server; - Boolean is_obliged_key_server; - Boolean can_be_key_server; - Boolean is_elected; + bool is_key_server; + bool is_obliged_key_server; + bool can_be_key_server; + bool is_elected; struct dl_list sak_list; struct dl_list rxsc_list; @@ -137,11 +137,11 @@ struct ieee802_1x_mka_participant { time_t cak_life; time_t mka_life; - Boolean to_dist_sak; - Boolean to_use_sak; - Boolean new_sak; + bool to_dist_sak; + bool to_use_sak; + bool new_sak; - Boolean advised_desired; + bool advised_desired; enum macsec_cap advised_capability; struct data_key *new_key; diff --git a/src/pae/ieee802_1x_secy_ops.c b/src/pae/ieee802_1x_secy_ops.c index 84ee42b05..0f36e6b53 100644 --- a/src/pae/ieee802_1x_secy_ops.c +++ b/src/pae/ieee802_1x_secy_ops.c @@ -25,7 +25,7 @@ int secy_cp_control_validate_frames(struct ieee802_1x_kay *kay, } -int secy_cp_control_protect_frames(struct ieee802_1x_kay *kay, Boolean enabled) +int secy_cp_control_protect_frames(struct ieee802_1x_kay *kay, bool enabled) { struct ieee802_1x_kay_ctx *ops; @@ -45,7 +45,7 @@ int secy_cp_control_protect_frames(struct ieee802_1x_kay *kay, Boolean enabled) } -int secy_cp_control_encrypt(struct ieee802_1x_kay *kay, Boolean enabled) +int secy_cp_control_encrypt(struct ieee802_1x_kay *kay, bool enabled) { struct ieee802_1x_kay_ctx *ops; @@ -65,7 +65,7 @@ int secy_cp_control_encrypt(struct ieee802_1x_kay *kay, Boolean enabled) } -int secy_cp_control_replay(struct ieee802_1x_kay *kay, Boolean enabled, u32 win) +int secy_cp_control_replay(struct ieee802_1x_kay *kay, bool enabled, u32 win) { struct ieee802_1x_kay_ctx *ops; @@ -113,7 +113,7 @@ int secy_cp_control_confidentiality_offset(struct ieee802_1x_kay *kay, } -int secy_cp_control_enable_port(struct ieee802_1x_kay *kay, Boolean enabled) +int secy_cp_control_enable_port(struct ieee802_1x_kay *kay, bool enabled) { struct ieee802_1x_kay_ctx *ops; @@ -333,7 +333,7 @@ int secy_enable_receive_sa(struct ieee802_1x_kay *kay, struct receive_sa *rxsa) return -1; } - rxsa->enable_receive = TRUE; + rxsa->enable_receive = true; return ops->enable_receive_sa(ops->ctx, rxsa); } @@ -355,7 +355,7 @@ int secy_disable_receive_sa(struct ieee802_1x_kay *kay, struct receive_sa *rxsa) return -1; } - rxsa->enable_receive = FALSE; + rxsa->enable_receive = false; return ops->disable_receive_sa(ops->ctx, rxsa); } @@ -462,7 +462,7 @@ int secy_enable_transmit_sa(struct ieee802_1x_kay *kay, return -1; } - txsa->enable_transmit = TRUE; + txsa->enable_transmit = true; return ops->enable_transmit_sa(ops->ctx, txsa); } @@ -485,7 +485,7 @@ int secy_disable_transmit_sa(struct ieee802_1x_kay *kay, return -1; } - txsa->enable_transmit = FALSE; + txsa->enable_transmit = false; return ops->disable_transmit_sa(ops->ctx, txsa); } @@ -509,9 +509,9 @@ int secy_init_macsec(struct ieee802_1x_kay *kay) return -1; } - params.use_es = FALSE; - params.use_scb = FALSE; - params.always_include_sci = TRUE; + params.use_es = false; + params.use_scb = false; + params.always_include_sci = true; ret = ops->macsec_init(ops->ctx, ¶ms); diff --git a/src/pae/ieee802_1x_secy_ops.h b/src/pae/ieee802_1x_secy_ops.h index 2d112ba7c..18c06f665 100644 --- a/src/pae/ieee802_1x_secy_ops.h +++ b/src/pae/ieee802_1x_secy_ops.h @@ -20,13 +20,13 @@ int secy_deinit_macsec(struct ieee802_1x_kay *kay); /****** CP -> SecY ******/ int secy_cp_control_validate_frames(struct ieee802_1x_kay *kay, enum validate_frames vf); -int secy_cp_control_protect_frames(struct ieee802_1x_kay *kay, Boolean flag); -int secy_cp_control_encrypt(struct ieee802_1x_kay *kay, Boolean enabled); -int secy_cp_control_replay(struct ieee802_1x_kay *kay, Boolean flag, u32 win); +int secy_cp_control_protect_frames(struct ieee802_1x_kay *kay, bool flag); +int secy_cp_control_encrypt(struct ieee802_1x_kay *kay, bool enabled); +int secy_cp_control_replay(struct ieee802_1x_kay *kay, bool flag, u32 win); int secy_cp_control_current_cipher_suite(struct ieee802_1x_kay *kay, u64 cs); int secy_cp_control_confidentiality_offset(struct ieee802_1x_kay *kay, enum confidentiality_offset co); -int secy_cp_control_enable_port(struct ieee802_1x_kay *kay, Boolean flag); +int secy_cp_control_enable_port(struct ieee802_1x_kay *kay, bool flag); /****** KaY -> SecY *******/ int secy_get_capability(struct ieee802_1x_kay *kay, enum macsec_cap *cap); diff --git a/src/radius/.gitignore b/src/radius/.gitignore deleted file mode 100644 index a89a1f927..000000000 --- a/src/radius/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libradius.a diff --git a/src/radius/Makefile b/src/radius/Makefile index 3ad4751df..8cfb33d35 100644 --- a/src/radius/Makefile +++ b/src/radius/Makefile @@ -1,14 +1,3 @@ -all: libradius.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libradius.a - -install: - @echo Nothing to be made. - - -include ../lib.rules - CFLAGS += -DCONFIG_IPV6 LIB_OBJS= \ @@ -17,7 +6,4 @@ LIB_OBJS= \ radius_das.o \ radius_server.o -libradius.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/radius/radius.c b/src/radius/radius.c index 07240ea22..be16e27b9 100644 --- a/src/radius/radius.c +++ b/src/radius/radius.c @@ -609,7 +609,7 @@ static int radius_msg_add_attr_to_array(struct radius_msg *msg, { if (msg->attr_used >= msg->attr_size) { size_t *nattr_pos; - int nlen = msg->attr_size * 2; + size_t nlen = msg->attr_size * 2; nattr_pos = os_realloc_array(msg->attr_pos, nlen, sizeof(*msg->attr_pos)); diff --git a/src/radius/radius_server.c b/src/radius/radius_server.c index c17e53b14..971fe91b1 100644 --- a/src/radius/radius_server.c +++ b/src/radius/radius_server.c @@ -657,8 +657,8 @@ radius_server_get_new_session(struct radius_server_data *data, return NULL; } sess->eap_if = eap_get_interface(sess->eap); - sess->eap_if->eapRestart = TRUE; - sess->eap_if->portEnabled = TRUE; + sess->eap_if->eapRestart = true; + sess->eap_if->portEnabled = true; RADIUS_DEBUG("New session 0x%x initialized", sess->sess_id); @@ -909,13 +909,13 @@ radius_server_encapsulate_eap(struct radius_server_data *data, u16 reason = WLAN_REASON_IEEE_802_1X_AUTH_FAILED; if (sess->eap_if->eapFail) { - sess->eap_if->eapFail = FALSE; + sess->eap_if->eapFail = false; code = RADIUS_CODE_ACCESS_REJECT; } else if (sess->eap_if->eapSuccess) { - sess->eap_if->eapSuccess = FALSE; + sess->eap_if->eapSuccess = false; code = RADIUS_CODE_ACCESS_ACCEPT; } else { - sess->eap_if->eapReq = FALSE; + sess->eap_if->eapReq = false; code = RADIUS_CODE_ACCESS_CHALLENGE; } @@ -1443,7 +1443,7 @@ static int radius_server_request(struct radius_server_data *data, wpabuf_free(sess->eap_if->eapRespData); sess->eap_if->eapRespData = eap; - sess->eap_if->eapResp = TRUE; + sess->eap_if->eapResp = true; eap_server_sm_step(sess->eap); if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess || @@ -2207,7 +2207,7 @@ radius_server_init(struct radius_server_conf *conf) dl_list_init(&data->erp_keys); os_get_reltime(&data->start_time); data->conf_ctx = conf->conf_ctx; - conf->eap_cfg->backend_auth = TRUE; + conf->eap_cfg->backend_auth = true; conf->eap_cfg->eap_server = 1; data->ipv6 = conf->ipv6; data->get_eap_user = conf->get_eap_user; diff --git a/src/rsn_supp/Makefile b/src/rsn_supp/Makefile index eea0efba9..d14d736c1 100644 --- a/src/rsn_supp/Makefile +++ b/src/rsn_supp/Makefile @@ -1,13 +1,3 @@ -all: librsn_supp.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov librsn_supp.a - -install: - @echo Nothing to be made. - -include ../lib.rules - CFLAGS += -DCONFIG_IEEE80211R CFLAGS += -DCONFIG_TDLS CFLAGS += -DCONFIG_WNM @@ -21,7 +11,4 @@ LIB_OBJS= \ wpa.o \ wpa_ie.o -librsn_supp.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c index cd4b0508f..e481dd5d6 100644 --- a/src/rsn_supp/pmksa_cache.c +++ b/src/rsn_supp/pmksa_cache.c @@ -267,7 +267,10 @@ pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa, entry->network_ctx, entry->akmp); wpa_sm_add_pmkid(pmksa->sm, entry->network_ctx, entry->aa, entry->pmkid, entry->fils_cache_id_set ? entry->fils_cache_id : NULL, - entry->pmk, entry->pmk_len); + entry->pmk, entry->pmk_len, + pmksa->sm->dot11RSNAConfigPMKLifetime, + pmksa->sm->dot11RSNAConfigPMKReauthThreshold, + entry->akmp); return entry; } @@ -371,9 +374,12 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa, { struct rsn_pmksa_cache_entry *new_entry; os_time_t old_expiration = old_entry->expiration; + const u8 *pmkid = NULL; + if (wpa_key_mgmt_sae(old_entry->akmp)) + pmkid = old_entry->pmkid; new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len, - NULL, NULL, 0, + pmkid, NULL, 0, aa, pmksa->sm->own_addr, old_entry->network_ctx, old_entry->akmp, old_entry->fils_cache_id_set ? @@ -413,6 +419,20 @@ pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx, while (entry) { if (entry->network_ctx == network_ctx && (!akmp || entry->akmp == akmp)) { + struct os_reltime now; + + if (wpa_key_mgmt_sae(entry->akmp) && + os_get_reltime(&now) == 0 && + entry->reauth_time < now.sec) { + wpa_printf(MSG_DEBUG, + "RSN: Do not clone PMKSA cache entry for " + MACSTR + " since its reauth threshold has passed", + MAC2STR(entry->aa)); + entry = entry->next; + continue; + } + entry = pmksa_cache_clone_entry(pmksa, entry, aa); if (entry) { wpa_printf(MSG_DEBUG, "RSN: added " @@ -466,6 +486,9 @@ void pmksa_cache_clear_current(struct wpa_sm *sm) { if (sm == NULL) return; + if (sm->cur_pmksa) + wpa_printf(MSG_DEBUG, + "RSN: Clear current PMKSA entry selection"); sm->cur_pmksa = NULL; } @@ -516,6 +539,20 @@ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, network_ctx, fils_cache_id); if (sm->cur_pmksa) { + struct os_reltime now; + + if (wpa_key_mgmt_sae(sm->cur_pmksa->akmp) && + os_get_reltime(&now) == 0 && + sm->cur_pmksa->reauth_time < now.sec) { + wpa_printf(MSG_DEBUG, + "RSN: Do not allow PMKSA cache entry for " + MACSTR + " to be used for SAE since its reauth threshold has passed", + MAC2STR(sm->cur_pmksa->aa)); + sm->cur_pmksa = NULL; + return -1; + } + wpa_hexdump(MSG_DEBUG, "RSN: PMKSA cache entry found - PMKID", sm->cur_pmksa->pmkid, PMKID_LEN); return 0; diff --git a/src/rsn_supp/pmksa_cache.h b/src/rsn_supp/pmksa_cache.h index 6c49fa924..83faa0584 100644 --- a/src/rsn_supp/pmksa_cache.h +++ b/src/rsn_supp/pmksa_cache.h @@ -28,6 +28,7 @@ struct rsn_pmksa_cache_entry { */ u8 fils_cache_id[2]; unsigned int fils_cache_id_set:1; + unsigned int dpp_pfs:1; os_time_t reauth_time; diff --git a/src/rsn_supp/preauth.c b/src/rsn_supp/preauth.c index a7ca2ed8b..1a38bf6bc 100644 --- a/src/rsn_supp/preauth.c +++ b/src/rsn_supp/preauth.c @@ -252,9 +252,9 @@ int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6); os_memcpy(sm->preauth_bssid, dst, ETH_ALEN); - eapol_sm_notify_portValid(sm->preauth_eapol, TRUE); + eapol_sm_notify_portValid(sm->preauth_eapol, true); /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(sm->preauth_eapol, TRUE); + eapol_sm_notify_portEnabled(sm->preauth_eapol, true); eloop_register_timeout(sm->dot11RSNAConfigSATimeout, 0, rsn_preauth_timeout, sm, NULL); @@ -349,7 +349,8 @@ void rsn_preauth_candidate_process(struct wpa_sm *sm) * PMKIDs again, so report the existing data now. */ if (p) { wpa_sm_add_pmkid(sm, NULL, candidate->bssid, p->pmkid, - NULL, p->pmk, p->pmk_len); + NULL, p->pmk, p->pmk_len, 0, 0, + p->akmp); } dl_list_del(&candidate->list); diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index bb8973942..7c4ef191c 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -227,7 +227,7 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) wpa_printf(MSG_DEBUG, "TDLS: Configure pairwise key for peer " MACSTR, MAC2STR(peer->addr)); - if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1, rsc, sizeof(rsc), + if (wpa_sm_set_key(sm, alg, peer->addr, 0, 1, rsc, sizeof(rsc), peer->tpk.tk, key_len, KEY_FLAG_PAIRWISE_RX_TX) < 0) { wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the " @@ -1155,7 +1155,7 @@ skip_rsnie: rbuf = os_zalloc(buf_len + 1); if (rbuf == NULL) { wpa_tdls_peer_free(sm, peer); - return -1; + return -2; } pos = rbuf; @@ -1174,7 +1174,7 @@ skip_rsnie: "TDLS: Failed to get random data for initiator Nonce"); os_free(rbuf); wpa_tdls_peer_free(sm, peer); - return -1; + return -2; } peer->tk_set = 0; /* A new nonce results in a new TK */ wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake", @@ -1926,7 +1926,10 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, peer->initiator = 1; wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL, NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0); - wpa_tdls_send_tpk_m1(sm, peer); + if (wpa_tdls_send_tpk_m1(sm, peer) == -2) { + peer = NULL; + goto error; + } } if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) && @@ -2654,6 +2657,7 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr) { struct wpa_tdls_peer *peer; int tdls_prohibited = sm->tdls_prohibited; + int res; if (sm->tdls_disabled || !sm->tdls_supported) return -1; @@ -2693,8 +2697,10 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr) peer->tpk_in_progress = 1; - if (wpa_tdls_send_tpk_m1(sm, peer) < 0) { - wpa_tdls_disable_peer_link(sm, peer); + res = wpa_tdls_send_tpk_m1(sm, peer); + if (res < 0) { + if (res != -2) + wpa_tdls_disable_peer_link(sm, peer); return -1; } @@ -2807,6 +2813,11 @@ int wpa_tdls_init(struct wpa_sm *sm) if (sm == NULL) return -1; + if (sm->l2_tdls) { + l2_packet_deinit(sm->l2_tdls); + sm->l2_tdls = NULL; + } + sm->l2_tdls = l2_packet_init(sm->bridge_ifname ? sm->bridge_ifname : sm->ifname, sm->own_addr, diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index b4dfb4863..52fc61656 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -21,6 +21,8 @@ #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/ocv.h" +#include "common/dpp.h" +#include "common/wpa_ctrl.h" #include "eap_common/eap_defs.h" #include "eapol_supp/eapol_supp_sm.h" #include "drivers/driver.h" @@ -183,6 +185,14 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) int key_info, ver; u8 bssid[ETH_ALEN], *rbuf, *key_mic, *mic; + if (pairwise && sm->wpa_deny_ptk0_rekey && !sm->use_ext_key_id && + wpa_sm_get_state(sm) == WPA_COMPLETED) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: PTK0 rekey not allowed, reconnecting"); + wpa_sm_reconnect(sm); + return; + } + if (wpa_use_akm_defined(sm->key_mgmt)) ver = WPA_KEY_INFO_TYPE_AKM_DEFINED; else if (wpa_key_mgmt_ft(sm->key_mgmt) || @@ -590,7 +600,7 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, sm->pmk_len > 32) { wpa_printf(MSG_DEBUG, "OWE: Force SHA256 for PTK derivation"); - akmp = WPA_KEY_MGMT_PSK_SHA256; + akmp |= WPA_KEY_MGMT_PSK_SHA256; } #endif /* CONFIG_OWE */ return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", @@ -600,6 +610,51 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, } +static int wpa_handle_ext_key_id(struct wpa_sm *sm, + struct wpa_eapol_ie_parse *kde) +{ + if (sm->ext_key_id) { + u16 key_id; + + if (!kde->key_id) { + wpa_msg(sm->ctx->msg_ctx, + sm->use_ext_key_id ? MSG_INFO : MSG_DEBUG, + "RSN: No Key ID in Extended Key ID handshake"); + sm->keyidx_active = 0; + return sm->use_ext_key_id ? -1 : 0; + } + + key_id = kde->key_id[0] & 0x03; + if (key_id > 1) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Invalid Extended Key ID: %d", key_id); + return -1; + } + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "RSN: Using Extended Key ID %d", key_id); + sm->keyidx_active = key_id; + sm->use_ext_key_id = 1; + } else { + if (kde->key_id && (kde->key_id[0] & 0x03)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Non-zero Extended Key ID Key ID in PTK0 handshake"); + return -1; + } + + if (kde->key_id) { + /* This is not supposed to be included here, but ignore + * the case of matching Key ID 0 just in case. */ + wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, + "RSN: Extended Key ID Key ID 0 in PTK0 handshake"); + } + sm->keyidx_active = 0; + sm->use_ext_key_id = 0; + } + + return 0; +} + + static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, @@ -618,6 +673,14 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, return; } + if (sm->wpa_deny_ptk0_rekey && !sm->use_ext_key_id && + wpa_sm_get_state(sm) == WPA_COMPLETED) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: PTK0 rekey not allowed, reconnecting"); + wpa_sm_reconnect(sm); + return; + } + wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way " "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); @@ -676,7 +739,8 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 3 + sm->assoc_rsnxe_len + - 2 + RSN_SELECTOR_LEN + 1); + 2 + RSN_SELECTOR_LEN + 1 + + 2 + RSN_SELECTOR_LEN + 2); if (!kde_buf) goto failed; os_memcpy(kde_buf, kde, kde_len); @@ -693,6 +757,14 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, "Failed to get channel info for OCI element in EAPOL-Key 2/4"); goto failed; } +#ifdef CONFIG_TESTING_OPTIONS + if (sm->oci_freq_override_eapol) { + wpa_printf(MSG_INFO, + "TEST: Override OCI KDE frequency %d -> %d MHz", + ci.frequency, sm->oci_freq_override_eapol); + ci.frequency = sm->oci_freq_override_eapol; + } +#endif /* CONFIG_TESTING_OPTIONS */ if (ocv_insert_oci_kde(&ci, &pos) < 0) goto failed; @@ -721,6 +793,27 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, } #endif /* CONFIG_P2P */ +#ifdef CONFIG_DPP2 + if (DPP_VERSION > 1 && sm->key_mgmt == WPA_KEY_MGMT_DPP) { + u8 *pos; + + wpa_printf(MSG_DEBUG, "DPP: Add DPP KDE into EAPOL-Key 2/4"); + pos = kde + kde_len; + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = RSN_SELECTOR_LEN + 2; + RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_DPP); + pos += RSN_SELECTOR_LEN; + *pos++ = DPP_VERSION; /* Protocol Version */ + *pos = 0; /* Flags */ + if (sm->dpp_pfs == 0) + *pos |= DPP_KDE_PFS_ALLOWED; + else if (sm->dpp_pfs == 1) + *pos |= DPP_KDE_PFS_ALLOWED | DPP_KDE_PFS_REQUIRED; + pos++; + kde_len = pos - kde; + } +#endif /* CONFIG_DPP2 */ + if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce, kde, kde_len, ptk) < 0) goto failed; @@ -757,11 +850,11 @@ static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, wpa_sm_mlme_setprotection( sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); - eapol_sm_notify_portValid(sm->eapol, TRUE); + eapol_sm_notify_portValid(sm->eapol, true); if (wpa_key_mgmt_wpa_psk(sm->key_mgmt) || sm->key_mgmt == WPA_KEY_MGMT_DPP || sm->key_mgmt == WPA_KEY_MGMT_OWE) - eapol_sm_notify_eap_success(sm->eapol, TRUE); + eapol_sm_notify_eap_success(sm->eapol, true); /* * Start preauthentication after a short wait to avoid a * possible race condition between the data receive and key @@ -844,13 +937,14 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen); } - if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen, - sm->ptk.tk, keylen, + if (wpa_sm_set_key(sm, alg, sm->bssid, sm->keyidx_active, 1, key_rsc, + rsclen, sm->ptk.tk, keylen, KEY_FLAG_PAIRWISE | key_flag) < 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to set PTK to the " - "driver (alg=%d keylen=%d bssid=" MACSTR ")", - alg, keylen, MAC2STR(sm->bssid)); + "WPA: Failed to set PTK to the driver (alg=%d keylen=%d bssid=" + MACSTR " idx=%d key_flag=0x%x)", + alg, keylen, MAC2STR(sm->bssid), + sm->keyidx_active, key_flag); return -1; } @@ -864,7 +958,23 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, sm, NULL); } + return 0; +} + +static int wpa_supplicant_activate_ptk(struct wpa_sm *sm) +{ + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Activate PTK (idx=%d bssid=" MACSTR ")", + sm->keyidx_active, MAC2STR(sm->bssid)); + + if (wpa_sm_set_key(sm, 0, sm->bssid, sm->keyidx_active, 0, NULL, 0, + NULL, 0, KEY_FLAG_PAIRWISE_RX_TX_MODIFY) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to activate PTK for TX (idx=%d bssid=" + MACSTR ")", sm->keyidx_active, MAC2STR(sm->bssid)); + return -1; + } return 0; } @@ -1140,14 +1250,66 @@ static int wpa_supplicant_install_igtk(struct wpa_sm *sm, } +static int wpa_supplicant_install_bigtk(struct wpa_sm *sm, + const struct wpa_bigtk_kde *bigtk, + int wnm_sleep) +{ + size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher); + u16 keyidx = WPA_GET_LE16(bigtk->keyid); + + /* Detect possible key reinstallation */ + if ((sm->bigtk.bigtk_len == len && + os_memcmp(sm->bigtk.bigtk, bigtk->bigtk, + sm->bigtk.bigtk_len) == 0) || + (sm->bigtk_wnm_sleep.bigtk_len == len && + os_memcmp(sm->bigtk_wnm_sleep.bigtk, bigtk->bigtk, + sm->bigtk_wnm_sleep.bigtk_len) == 0)) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Not reinstalling already in-use BIGTK to the driver (keyidx=%d)", + keyidx); + return 0; + } + + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: BIGTK keyid %d pn " COMPACT_MACSTR, + keyidx, MAC2STR(bigtk->pn)); + wpa_hexdump_key(MSG_DEBUG, "WPA: BIGTK", bigtk->bigtk, len); + if (keyidx < 6 || keyidx > 7) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Invalid BIGTK KeyID %d", keyidx); + return -1; + } + if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher), + broadcast_ether_addr, + keyidx, 0, bigtk->pn, sizeof(bigtk->pn), + bigtk->bigtk, len, KEY_FLAG_GROUP_RX) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to configure BIGTK to the driver"); + return -1; + } + + if (wnm_sleep) { + sm->bigtk_wnm_sleep.bigtk_len = len; + os_memcpy(sm->bigtk_wnm_sleep.bigtk, bigtk->bigtk, + sm->bigtk_wnm_sleep.bigtk_len); + } else { + sm->bigtk.bigtk_len = len; + os_memcpy(sm->bigtk.bigtk, bigtk->bigtk, sm->bigtk.bigtk_len); + } + + return 0; +} + + static int ieee80211w_set_keys(struct wpa_sm *sm, struct wpa_eapol_ie_parse *ie) { + size_t len; + if (!wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher)) return 0; if (ie->igtk) { - size_t len; const struct wpa_igtk_kde *igtk; len = wpa_cipher_key_len(sm->mgmt_group_cipher); @@ -1159,6 +1321,18 @@ static int ieee80211w_set_keys(struct wpa_sm *sm, return -1; } + if (ie->bigtk && sm->beacon_prot) { + const struct wpa_bigtk_kde *bigtk; + + len = wpa_cipher_key_len(sm->mgmt_group_cipher); + if (ie->bigtk_len != WPA_BIGTK_KDE_PREFIX_LEN + len) + return -1; + + bigtk = (const struct wpa_bigtk_kde *) ie->bigtk; + if (wpa_supplicant_install_bigtk(sm, bigtk, 0) < 0) + return -1; + } + return 0; } @@ -1345,11 +1519,10 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm, wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: Could not find AP from " "the scan results"); - } else { - wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, - "WPA: Found the current AP from " - "updated scan results"); + return -1; } + wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Found the current AP from updated scan results"); } if (ie->wpa_ie == NULL && ie->rsn_ie == NULL && @@ -1393,6 +1566,11 @@ static int wpa_supplicant_validate_ie(struct wpa_sm *sm, os_memcmp(sm->ap_rsnxe, ie->rsnxe, sm->ap_rsnxe_len) != 0))) { wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: RSNXE mismatch between Beacon/ProbeResp and EAPOL-Key msg 3/4"); + wpa_hexdump(MSG_INFO, "RSNXE in Beacon/ProbeResp", + sm->ap_rsnxe, sm->ap_rsnxe_len); + wpa_hexdump(MSG_INFO, "RSNXE in EAPOL-Key msg 3/4", + ie->rsnxe, ie->rsnxe_len); + wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS); return -1; } @@ -1499,6 +1677,9 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) goto failed; + if (wpa_handle_ext_key_id(sm, &ie)) + goto failed; + if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: ANonce from message 1 of 4-Way Handshake " @@ -1536,14 +1717,33 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "%s", - ocv_errorstr); + ci.seg1_idx) != OCI_SUCCESS) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE + "addr=" MACSTR " frame=eapol-key-m3 error=%s", + MAC2STR(sm->bssid), ocv_errorstr); return; } } #endif /* CONFIG_OCV */ +#ifdef CONFIG_DPP2 + if (DPP_VERSION > 1 && ie.dpp_kde) { + wpa_printf(MSG_DEBUG, + "DPP: peer Protocol Version %u Flags 0x%x", + ie.dpp_kde[0], ie.dpp_kde[1]); + if (sm->key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_pfs != 2 && + (ie.dpp_kde[1] & DPP_KDE_PFS_ALLOWED) && !sm->dpp_z) { + wpa_printf(MSG_INFO, + "DPP: Peer indicated it supports PFS and local configuration allows this, but PFS was not negotiated for the association"); + goto failed; + } + } +#endif /* CONFIG_DPP2 */ + + if (sm->use_ext_key_id && + wpa_supplicant_install_ptk(sm, key, KEY_FLAG_RX)) + goto failed; + if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, &sm->ptk) < 0) { goto failed; @@ -1555,7 +1755,14 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, sm->renew_snonce = 1; if (key_info & WPA_KEY_INFO_INSTALL) { - if (wpa_supplicant_install_ptk(sm, key, KEY_FLAG_RX_TX)) + int res; + + if (sm->use_ext_key_id) + res = wpa_supplicant_activate_ptk(sm); + else + res = wpa_supplicant_install_ptk(sm, key, + KEY_FLAG_RX_TX); + if (res) goto failed; } @@ -1563,7 +1770,7 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, wpa_sm_mlme_setprotection( sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX, MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); - eapol_sm_notify_portValid(sm->eapol, TRUE); + eapol_sm_notify_portValid(sm->eapol, true); } wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); @@ -1611,6 +1818,8 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, sm->cur_pmksa = sa; } + if (ie.transition_disable) + wpa_sm_transition_disable(sm, ie.transition_disable[0]); sm->msg_3_of_4_ok = 1; return; @@ -1627,6 +1836,7 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, { int maxkeylen; struct wpa_eapol_ie_parse ie; + u16 gtk_len; wpa_hexdump_key(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen); @@ -1642,7 +1852,20 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, "WPA: No GTK IE in Group Key msg 1/2"); return -1; } - maxkeylen = gd->gtk_len = ie.gtk_len - 2; + gtk_len = ie.gtk_len; + if (gtk_len < 2) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Invalid GTK KDE length (%u) in Group Key msg 1/2", + gtk_len); + return -1; + } + gtk_len -= 2; + if (gtk_len > sizeof(gd->gtk)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Too long GTK in GTK KDE (len=%u)", gtk_len); + return -1; + } + maxkeylen = gd->gtk_len = gtk_len; #ifdef CONFIG_OCV if (wpa_sm_ocv_enabled(sm)) { @@ -1656,31 +1879,26 @@ static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, if (ocv_verify_tx_params(ie.oci, ie.oci_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "%s", - ocv_errorstr); + ci.seg1_idx) != OCI_SUCCESS) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE + "addr=" MACSTR " frame=eapol-key-g1 error=%s", + MAC2STR(sm->bssid), ocv_errorstr); return -1; } } #endif /* CONFIG_OCV */ if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, - gd->gtk_len, maxkeylen, + gtk_len, maxkeylen, &gd->key_rsc_len, &gd->alg)) return -1; wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in group key handshake", - ie.gtk, ie.gtk_len); + ie.gtk, 2 + gtk_len); gd->keyidx = ie.gtk[0] & 0x3; gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm, !!(ie.gtk[0] & BIT(2))); - if (ie.gtk_len - 2 > sizeof(gd->gtk)) { - wpa_msg(sm->ctx->msg_ctx, MSG_INFO, - "RSN: Too long GTK in GTK IE (len=%lu)", - (unsigned long) ie.gtk_len - 2); - return -1; - } - os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2); + os_memcpy(gd->gtk, ie.gtk + 2, gtk_len); if (ieee80211w_set_keys(sm, &ie) < 0) wpa_msg(sm->ctx->msg_ctx, MSG_INFO, @@ -1829,6 +2047,15 @@ static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, os_free(rbuf); return -1; } +#ifdef CONFIG_TESTING_OPTIONS + if (sm->oci_freq_override_eapol_g2) { + wpa_printf(MSG_INFO, + "TEST: Override OCI KDE frequency %d -> %d MHz", + ci.frequency, + sm->oci_freq_override_eapol_g2); + ci.frequency = sm->oci_freq_override_eapol_g2; + } +#endif /* CONFIG_TESTING_OPTIONS */ pos = key_mic + mic_len + 2; /* Key Data */ if (ocv_insert_oci_kde(&ci, &pos) < 0) { @@ -2232,13 +2459,16 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, u8 *tmp = NULL; int ret = -1; u8 *mic, *key_data; - size_t mic_len, keyhdrlen; + size_t mic_len, keyhdrlen, pmk_len; #ifdef CONFIG_IEEE80211R sm->ft_completed = 0; #endif /* CONFIG_IEEE80211R */ - mic_len = wpa_mic_len(sm->key_mgmt, sm->pmk_len); + pmk_len = sm->pmk_len; + if (!pmk_len && sm->cur_pmksa) + pmk_len = sm->cur_pmksa->pmk_len; + mic_len = wpa_mic_len(sm->key_mgmt, pmk_len); keyhdrlen = sizeof(*key) + mic_len + 2; if (len < sizeof(*hdr) + keyhdrlen) { @@ -2534,7 +2764,8 @@ static u32 wpa_key_mgmt_suite(struct wpa_sm *sm) int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) { char pmkid_txt[PMKID_LEN * 2 + 1]; - int rsna, ret; + bool rsna; + int ret; size_t len; if (sm->cur_pmksa) { @@ -2543,12 +2774,9 @@ int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) } else pmkid_txt[0] = '\0'; - if ((wpa_key_mgmt_wpa_psk(sm->key_mgmt) || - wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) && - sm->proto == WPA_PROTO_RSN) - rsna = 1; - else - rsna = 0; + rsna = (wpa_key_mgmt_wpa_psk(sm->key_mgmt) || + wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) && + sm->proto == WPA_PROTO_RSN; ret = os_snprintf(buf, buflen, "dot11RSNAOptionImplemented=TRUE\n" @@ -2751,7 +2979,7 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) * Clear portValid to kick EAPOL state machine to re-enter * AUTHENTICATED state to get the EAPOL port Authorized. */ - eapol_sm_notify_portValid(sm->eapol, FALSE); + eapol_sm_notify_portValid(sm->eapol, false); wpa_supplicant_key_neg_complete(sm, sm->bssid, 1); /* Prepare for the next transition */ @@ -2797,6 +3025,8 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) #ifdef CONFIG_P2P os_memset(sm->p2p_ip_addr, 0, sizeof(sm->p2p_ip_addr)); #endif /* CONFIG_P2P */ + + sm->keyidx_active = 0; } @@ -2828,6 +3058,7 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm) /* Keys are not needed in the WPA state machine anymore */ wpa_sm_drop_sa(sm); + sm->keyidx_active = 0; sm->msg_3_of_4_ok = 0; os_memset(sm->bssid, 0, ETH_ALEN); @@ -2960,6 +3191,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) sm->fils_cache_id_set = 0; } #endif /* CONFIG_FILS */ + sm->beacon_prot = config->beacon_prot; } else { sm->network_ctx = NULL; sm->allowed_pairwise_cipher = 0; @@ -2971,6 +3203,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) sm->p2p = 0; sm->wpa_rsc_relaxation = 0; sm->owe_ptk_workaround = 0; + sm->beacon_prot = 0; } } @@ -3076,6 +3309,40 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, case WPA_PARAM_SAE_PWE: sm->sae_pwe = value; break; + case WPA_PARAM_SAE_PK: + sm->sae_pk = value; + break; + case WPA_PARAM_DENY_PTK0_REKEY: + sm->wpa_deny_ptk0_rekey = value; + break; + case WPA_PARAM_EXT_KEY_ID: + sm->ext_key_id = value; + break; + case WPA_PARAM_USE_EXT_KEY_ID: + sm->use_ext_key_id = value; + break; +#ifdef CONFIG_TESTING_OPTIONS + case WPA_PARAM_FT_RSNXE_USED: + sm->ft_rsnxe_used = value; + break; + case WPA_PARAM_OCI_FREQ_EAPOL: + sm->oci_freq_override_eapol = value; + break; + case WPA_PARAM_OCI_FREQ_EAPOL_G2: + sm->oci_freq_override_eapol_g2 = value; + break; + case WPA_PARAM_OCI_FREQ_FT_ASSOC: + sm->oci_freq_override_ft_assoc = value; + break; + case WPA_PARAM_OCI_FREQ_FILS_ASSOC: + sm->oci_freq_override_fils_assoc = value; + break; +#endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_DPP2 + case WPA_PARAM_DPP_PFS: + sm->dpp_pfs = value; + break; +#endif /* CONFIG_DPP2 */ default: break; } @@ -3113,6 +3380,15 @@ int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, return pos - buf; pos += ret; +#ifdef CONFIG_DPP2 + if (sm->key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) { + ret = os_snprintf(pos, end - pos, "dpp_pfs=1\n"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_DPP2 */ + if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) { struct wpa_ie_data rsn; if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) @@ -3150,6 +3426,18 @@ int wpa_sm_pmf_enabled(struct wpa_sm *sm) } +int wpa_sm_ext_key_id(struct wpa_sm *sm) +{ + return sm ? sm->ext_key_id : 0; +} + + +int wpa_sm_ext_key_id_active(struct wpa_sm *sm) +{ + return sm ? sm->use_ext_key_id : 0; +} + + int wpa_sm_ocv_enabled(struct wpa_sm *sm) { struct wpa_ie_data rsn; @@ -3593,6 +3881,13 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf) igtk = (const struct wpa_igtk_kde *) (buf + 2); if (wpa_supplicant_install_igtk(sm, igtk, 1) < 0) return -1; + } else if (subelem_id == WNM_SLEEP_SUBELEM_BIGTK) { + const struct wpa_bigtk_kde *bigtk; + + bigtk = (const struct wpa_bigtk_kde *) (buf + 2); + if (sm->beacon_prot && + wpa_supplicant_install_bigtk(sm, bigtk, 1) < 0) + return -1; } else { wpa_printf(MSG_DEBUG, "Unknown element id"); return -1; @@ -3776,13 +4071,13 @@ struct wpabuf * fils_build_auth(struct wpa_sm *sm, int dh_group, const u8 *md) wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION); wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN); - /* FILS Wrapped Data */ + /* Wrapped Data */ sm->fils_erp_pmkid_set = 0; if (erp_msg) { wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */ wpabuf_put_u8(buf, 1 + wpabuf_len(erp_msg)); /* Length */ /* Element ID Extension */ - wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_WRAPPED_DATA); + wpabuf_put_u8(buf, WLAN_EID_EXT_WRAPPED_DATA); wpabuf_put_buf(buf, erp_msg); /* Calculate pending PMKID here so that we do not need to * maintain a copy of the EAP-Initiate/Reauth message. */ @@ -3987,16 +4282,16 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data, goto fail; } - /* FILS Wrapped Data */ - if (!sm->cur_pmksa && elems.fils_wrapped_data) { + /* Wrapped Data */ + if (!sm->cur_pmksa && elems.wrapped_data) { u8 rmsk[ERP_MAX_KEY_LEN]; size_t rmsk_len; wpa_hexdump(MSG_DEBUG, "FILS: Wrapped Data", - elems.fils_wrapped_data, - elems.fils_wrapped_data_len); - eapol_sm_process_erp_finish(sm->eapol, elems.fils_wrapped_data, - elems.fils_wrapped_data_len); + elems.wrapped_data, + elems.wrapped_data_len); + eapol_sm_process_erp_finish(sm->eapol, elems.wrapped_data, + elems.wrapped_data_len); if (eapol_sm_failed(sm->eapol)) goto fail; @@ -4158,6 +4453,8 @@ static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf) capab |= WPA_CAPABILITY_MFPR; if (sm->ocv) capab |= WPA_CAPABILITY_OCVC; + if (sm->ext_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; wpabuf_put_le16(buf, capab); /* PMKID Count */ @@ -4179,10 +4476,6 @@ static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf) return -1; } sm->pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; - wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", - sm->pmk_r0, sm->pmk_r0_len); - wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name", - sm->pmk_r0_name, WPA_PMK_NAME_LEN); wpa_printf(MSG_DEBUG, "FILS+FT: R1KH-ID: " MACSTR, MAC2STR(sm->r1kh_id)); pos = wpabuf_put(buf, WPA_PMK_NAME_LEN); @@ -4191,8 +4484,6 @@ static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf) wpa_printf(MSG_WARNING, "FILS+FT: Could not derive PMKR1Name"); return -1; } - wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name, - WPA_PMK_NAME_LEN); os_memcpy(pos, sm->pmk_r1_name, WPA_PMK_NAME_LEN); if (sm->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { @@ -4303,6 +4594,15 @@ struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek, wpabuf_free(buf); return NULL; } +#ifdef CONFIG_TESTING_OPTIONS + if (sm->oci_freq_override_fils_assoc) { + wpa_printf(MSG_INFO, + "TEST: Override OCI KDE frequency %d -> %d MHz", + ci.frequency, + sm->oci_freq_override_fils_assoc); + ci.frequency = sm->oci_freq_override_fils_assoc; + } +#endif /* CONFIG_TESTING_OPTIONS */ pos = wpabuf_put(buf, OCV_OCI_EXTENDED_LEN); if (ocv_insert_extended_oci(&ci, pos) < 0) { @@ -4507,8 +4807,10 @@ int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len) if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "FILS: %s", ocv_errorstr); + ci.seg1_idx) != OCI_SUCCESS) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE + "addr=" MACSTR " frame=fils-assoc error=%s", + MAC2STR(sm->bssid), ocv_errorstr); goto fail; } } @@ -4585,6 +4887,7 @@ int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len) keylen, (long unsigned int) sm->ptk.tk_len); goto fail; } + rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher); wpa_hexdump_key(MSG_DEBUG, "FILS: Set TK to driver", sm->ptk.tk, keylen); @@ -4613,6 +4916,9 @@ int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len) sm->fils_completed = 1; forced_memzero(&gd, sizeof(gd)); + if (kde.transition_disable) + wpa_sm_transition_disable(sm, kde.transition_disable[0]); + return 0; fail: forced_memzero(&gd, sizeof(gd)); diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index ceae721aa..2142772d7 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -27,6 +27,7 @@ struct wpa_sm_ctx { void (*set_state)(void *ctx, enum wpa_states state); enum wpa_states (*get_state)(void *ctx); void (*deauthenticate)(void * ctx, u16 reason_code); + void (*reconnect)(void *ctx); int (*set_key)(void *ctx, enum wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, @@ -41,7 +42,8 @@ struct wpa_sm_ctx { size_t *msg_len, void **data_pos); int (*add_pmkid)(void *ctx, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id, - const u8 *pmk, size_t pmk_len); + const u8 *pmk, size_t pmk_len, u32 pmk_lifetime, + u8 pmk_reauth_threshold, int akmp); int (*remove_pmkid)(void *ctx, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id); void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob); @@ -84,6 +86,7 @@ struct wpa_sm_ctx { void (*fils_hlp_rx)(void *ctx, const u8 *dst, const u8 *src, const u8 *pkt, size_t pkt_len); int (*channel_info)(void *ctx, struct wpa_channel_info *ci); + void (*transition_disable)(void *ctx, u8 bitmap); }; @@ -100,6 +103,16 @@ enum wpa_sm_conf_params { WPA_PARAM_MFP, WPA_PARAM_OCV, WPA_PARAM_SAE_PWE, + WPA_PARAM_SAE_PK, + WPA_PARAM_DENY_PTK0_REKEY, + WPA_PARAM_EXT_KEY_ID, + WPA_PARAM_USE_EXT_KEY_ID, + WPA_PARAM_FT_RSNXE_USED, + WPA_PARAM_DPP_PFS, + WPA_PARAM_OCI_FREQ_EAPOL, + WPA_PARAM_OCI_FREQ_EAPOL_G2, + WPA_PARAM_OCI_FREQ_FT_ASSOC, + WPA_PARAM_OCI_FREQ_FILS_ASSOC, }; struct rsn_supp_config { @@ -111,10 +124,12 @@ struct rsn_supp_config { const u8 *ssid; size_t ssid_len; int wpa_ptk_rekey; + int wpa_deny_ptk0_rekey; int p2p; int wpa_rsc_relaxation; int owe_ptk_workaround; const u8 *fils_cache_id; + int beacon_prot; }; #ifndef CONFIG_NO_WPA @@ -150,6 +165,8 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, int verbose); int wpa_sm_pmf_enabled(struct wpa_sm *sm); +int wpa_sm_ext_key_id(struct wpa_sm *sm); +int wpa_sm_ext_key_id_active(struct wpa_sm *sm); int wpa_sm_ocv_enabled(struct wpa_sm *sm); void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise); @@ -296,6 +313,16 @@ static inline int wpa_sm_pmf_enabled(struct wpa_sm *sm) return 0; } +static inline int wpa_sm_ext_key_id(struct wpa_sm *sm) +{ + return 0; +} + +static inline int wpa_sm_ext_key_id_active(struct wpa_sm *sm) +{ + return 0; +} + static inline int wpa_sm_ocv_enabled(struct wpa_sm *sm) { return 0; diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 8a8c545d3..bf73376b6 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -15,6 +15,7 @@ #include "common/ieee802_11_defs.h" #include "common/ieee802_11_common.h" #include "common/ocv.h" +#include "common/wpa_ctrl.h" #include "drivers/driver.h" #include "wpa.h" #include "wpa_i.h" @@ -50,17 +51,11 @@ int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, sm->r0kh_id, sm->r0kh_id_len, sm->own_addr, sm->pmk_r0, sm->pmk_r0_name, use_sha384) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", sm->pmk_r0, sm->pmk_r0_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", - sm->pmk_r0_name, WPA_PMK_NAME_LEN); sm->pmk_r1_len = sm->pmk_r0_len; if (wpa_derive_pmk_r1(sm->pmk_r0, sm->pmk_r0_len, sm->pmk_r0_name, sm->r1kh_id, sm->own_addr, sm->pmk_r1, sm->pmk_r1_name) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, sm->pmk_r1_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name, - WPA_PMK_NAME_LEN); return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, anonce, sm->own_addr, sm->bssid, sm->pmk_r1_name, ptk, ptk_name, sm->key_mgmt, sm->pairwise_cipher); @@ -82,23 +77,30 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) if (sm == NULL) return 0; + if (!get_ie(ies, ies_len, WLAN_EID_MOBILITY_DOMAIN)) { + os_free(sm->assoc_resp_ies); + sm->assoc_resp_ies = NULL; + sm->assoc_resp_ies_len = 0; + os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN); + os_memset(sm->r0kh_id, 0, FT_R0KH_ID_MAX_LEN); + sm->r0kh_id_len = 0; + os_memset(sm->r1kh_id, 0, FT_R1KH_ID_LEN); + return 0; + } + use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); if (wpa_ft_parse_ies(ies, ies_len, &ft, use_sha384) < 0) return -1; - if (ft.mdie && ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) + if (ft.mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) return -1; - if (ft.mdie) { - wpa_hexdump(MSG_DEBUG, "FT: Mobility domain", - ft.mdie, MOBILITY_DOMAIN_ID_LEN); - os_memcpy(sm->mobility_domain, ft.mdie, - MOBILITY_DOMAIN_ID_LEN); - sm->mdie_ft_capab = ft.mdie[MOBILITY_DOMAIN_ID_LEN]; - wpa_printf(MSG_DEBUG, "FT: Capability and Policy: 0x%02x", - sm->mdie_ft_capab); - } else - os_memset(sm->mobility_domain, 0, MOBILITY_DOMAIN_ID_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Mobility domain", + ft.mdie, MOBILITY_DOMAIN_ID_LEN); + os_memcpy(sm->mobility_domain, ft.mdie, MOBILITY_DOMAIN_ID_LEN); + sm->mdie_ft_capab = ft.mdie[MOBILITY_DOMAIN_ID_LEN]; + wpa_printf(MSG_DEBUG, "FT: Capability and Policy: 0x%02x", + sm->mdie_ft_capab); if (ft.r0kh_id) { wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", @@ -125,10 +127,10 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) sm->assoc_resp_ies = os_malloc(ft.mdie_len + 2 + ft.ftie_len + 2); if (sm->assoc_resp_ies) { u8 *pos = sm->assoc_resp_ies; - if (ft.mdie) { - os_memcpy(pos, ft.mdie - 2, ft.mdie_len + 2); - pos += ft.mdie_len + 2; - } + + os_memcpy(pos, ft.mdie - 2, ft.mdie_len + 2); + pos += ft.mdie_len + 2; + if (ft.ftie) { os_memcpy(pos, ft.ftie - 2, ft.ftie_len + 2); pos += ft.ftie_len + 2; @@ -155,6 +157,7 @@ int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) * @ric_ies: Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request or %NULL * @ric_ies_len: Length of ric_ies buffer in octets * @ap_mdie: Mobility Domain IE from the target AP + * @omit_rsnxe: Whether RSNXE is omitted from Reassociation Request frame * Returns: Pointer to buffer with IEs or %NULL on failure * * Caller is responsible for freeing the returned buffer with os_free(); @@ -164,16 +167,16 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, const u8 *kck, size_t kck_len, const u8 *target_ap, const u8 *ric_ies, size_t ric_ies_len, - const u8 *ap_mdie) + const u8 *ap_mdie, int omit_rsnxe) { size_t buf_len; u8 *buf, *pos, *ftie_len, *ftie_pos, *fte_mic, *elem_count; struct rsn_mdie *mdie; struct rsn_ie_hdr *rsnie; - u16 capab; int mdie_len; u8 rsnxe[10]; size_t rsnxe_len; + int rsnxe_used; int res; sm->ft_completed = 0; @@ -249,14 +252,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, pos += RSN_SELECTOR_LEN; /* RSN Capabilities */ - capab = 0; - if (sm->mfp) - capab |= WPA_CAPABILITY_MFPC; - if (sm->mfp == 2) - capab |= WPA_CAPABILITY_MFPR; - if (sm->ocv) - capab |= WPA_CAPABILITY_OCVC; - WPA_PUT_LE16(pos, capab); + WPA_PUT_LE16(pos, rsn_supp_capab(sm)); pos += 2; /* PMKID Count */ @@ -302,10 +298,20 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, ftie_pos = pos; *pos++ = WLAN_EID_FAST_BSS_TRANSITION; ftie_len = pos++; + rsnxe_used = wpa_key_mgmt_sae(sm->key_mgmt) && anonce && + (sm->sae_pwe == 1 || sm->sae_pwe == 2); +#ifdef CONFIG_TESTING_OPTIONS + if (anonce && sm->ft_rsnxe_used) { + rsnxe_used = sm->ft_rsnxe_used == 1; + wpa_printf(MSG_DEBUG, "TESTING: FT: Force RSNXE Used %d", + rsnxe_used); + } +#endif /* CONFIG_TESTING_OPTIONS */ if (wpa_key_mgmt_sha384(sm->key_mgmt)) { struct rsn_ftie_sha384 *ftie; ftie = (struct rsn_ftie_sha384 *) pos; + ftie->mic_control[0] = !!rsnxe_used; fte_mic = ftie->mic; elem_count = &ftie->mic_control[1]; pos += sizeof(*ftie); @@ -316,6 +322,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, struct rsn_ftie *ftie; ftie = (struct rsn_ftie *) pos; + ftie->mic_control[0] = !!rsnxe_used; fte_mic = ftie->mic; elem_count = &ftie->mic_control[1]; pos += sizeof(*ftie); @@ -346,6 +353,14 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, os_free(buf); return NULL; } +#ifdef CONFIG_TESTING_OPTIONS + if (sm->oci_freq_override_ft_assoc) { + wpa_printf(MSG_INFO, + "TEST: Override OCI KDE frequency %d -> %d MHz", + ci.frequency, sm->oci_freq_override_ft_assoc); + ci.frequency = sm->oci_freq_override_ft_assoc; + } +#endif /* CONFIG_TESTING_OPTIONS */ *pos++ = FTIE_SUBELEM_OCI; *pos++ = OCV_OCI_LEN; @@ -363,12 +378,16 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, pos += ric_ies_len; } - res = wpa_gen_rsnxe(sm, rsnxe, sizeof(rsnxe)); - if (res < 0) { - os_free(buf); - return NULL; + if (omit_rsnxe) { + rsnxe_len = 0; + } else { + res = wpa_gen_rsnxe(sm, rsnxe, sizeof(rsnxe)); + if (res < 0) { + os_free(buf); + return NULL; + } + rsnxe_len = res; } - rsnxe_len = res; if (kck) { /* @@ -451,7 +470,7 @@ int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie) } ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, - NULL, 0, sm->bssid, NULL, 0, mdie); + NULL, 0, sm->bssid, NULL, 0, mdie, 0); if (ft_ies) { wpa_sm_update_ft_ies(sm, sm->mobility_domain, ft_ies, ft_ies_len); @@ -625,9 +644,6 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, sm->pmk_r1_name) < 0) return -1; sm->pmk_r1_len = sm->pmk_r0_len; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", sm->pmk_r1, sm->pmk_r1_len); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", - sm->pmk_r1_name, WPA_PMK_NAME_LEN); bssid = target_ap; if (wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, sm->snonce, @@ -647,7 +663,8 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, sm->pmk_r1_name, kck, kck_len, bssid, ric_ies, ric_ies_len, - parse.mdie ? parse.mdie - 2 : NULL); + parse.mdie ? parse.mdie - 2 : NULL, + !sm->ap_rsnxe); if (ft_ies) { wpa_sm_update_ft_ies(sm, sm->mobility_domain, ft_ies, ft_ies_len); @@ -855,6 +872,74 @@ static int wpa_ft_process_igtk_subelem(struct wpa_sm *sm, const u8 *igtk_elem, } +static int wpa_ft_process_bigtk_subelem(struct wpa_sm *sm, const u8 *bigtk_elem, + size_t bigtk_elem_len) +{ + u8 bigtk[WPA_BIGTK_MAX_LEN]; + size_t bigtk_len; + u16 keyidx; + const u8 *kek; + size_t kek_len; + + if (!sm->beacon_prot || !bigtk_elem || + (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC && + sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_128 && + sm->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256 && + sm->mgmt_group_cipher != WPA_CIPHER_BIP_CMAC_256)) + return 0; + + if (wpa_key_mgmt_fils(sm->key_mgmt)) { + kek = sm->ptk.kek2; + kek_len = sm->ptk.kek2_len; + } else { + kek = sm->ptk.kek; + kek_len = sm->ptk.kek_len; + } + + wpa_hexdump_key(MSG_DEBUG, "FT: Received BIGTK in Reassoc Resp", + bigtk_elem, bigtk_elem_len); + + bigtk_len = wpa_cipher_key_len(sm->mgmt_group_cipher); + if (bigtk_elem_len != 2 + 6 + 1 + bigtk_len + 8) { + wpa_printf(MSG_DEBUG, + "FT: Invalid BIGTK sub-elem length %lu", + (unsigned long) bigtk_elem_len); + return -1; + } + if (bigtk_elem[8] != bigtk_len) { + wpa_printf(MSG_DEBUG, + "FT: Invalid BIGTK sub-elem Key Length %d", + bigtk_elem[8]); + return -1; + } + + if (aes_unwrap(kek, kek_len, bigtk_len / 8, bigtk_elem + 9, bigtk)) { + wpa_printf(MSG_WARNING, + "FT: AES unwrap failed - could not decrypt BIGTK"); + return -1; + } + + /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */ + + keyidx = WPA_GET_LE16(bigtk_elem); + + wpa_hexdump_key(MSG_DEBUG, "FT: BIGTK from Reassoc Resp", bigtk, + bigtk_len); + if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher), + broadcast_ether_addr, keyidx, 0, + bigtk_elem + 2, 6, bigtk, bigtk_len, + KEY_FLAG_GROUP_RX) < 0) { + wpa_printf(MSG_WARNING, + "WPA: Failed to set BIGTK to the driver"); + forced_memzero(bigtk, sizeof(bigtk)); + return -1; + } + forced_memzero(bigtk, sizeof(bigtk)); + + return 0; +} + + int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len, const u8 *src_addr) { @@ -867,6 +952,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, int use_sha384 = wpa_key_mgmt_sha384(sm->key_mgmt); const u8 *anonce, *snonce, *fte_mic; u8 fte_elem_count; + int own_rsnxe_used, rsnxe_used; wpa_hexdump(MSG_DEBUG, "FT: Response IEs", ies, ies_len); @@ -905,6 +991,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, anonce = ftie->anonce; snonce = ftie->snonce; + rsnxe_used = ftie->mic_control[0] & 0x01; fte_elem_count = ftie->mic_control[1]; fte_mic = ftie->mic; } else { @@ -918,6 +1005,7 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, anonce = ftie->anonce; snonce = ftie->snonce; + rsnxe_used = ftie->mic_control[0] & 0x01; fte_elem_count = ftie->mic_control[1]; fte_mic = ftie->mic; } @@ -1015,6 +1103,58 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, return -1; } + if (rsnxe_used && !sm->ap_rsnxe) { + wpa_printf(MSG_INFO, + "FT: FTE indicated that AP uses RSNXE, but RSNXE was not included in Beacon/Probe Response frames"); + return -1; + } + + if (!sm->ap_rsn_ie) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "FT: No RSNE for this AP known - trying to get from scan results"); + if (wpa_sm_get_beacon_ie(sm) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "FT: Could not find AP from the scan results"); + return -1; + } + wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, + "FT: Found the current AP from updated scan results"); + } + + if (sm->ap_rsn_ie && + wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt), + sm->ap_rsn_ie, sm->ap_rsn_ie_len, + parse.rsn - 2, parse.rsn_len + 2)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "FT: RSNE mismatch between Beacon/ProbeResp and FT protocol Reassociation Response frame"); + wpa_hexdump(MSG_INFO, "RSNE in Beacon/ProbeResp", + sm->ap_rsn_ie, sm->ap_rsn_ie_len); + wpa_hexdump(MSG_INFO, + "RSNE in FT protocol Reassociation Response frame", + parse.rsn ? parse.rsn - 2 : NULL, + parse.rsn ? parse.rsn_len + 2 : 0); + return -1; + } + + own_rsnxe_used = wpa_key_mgmt_sae(sm->key_mgmt) && + (sm->sae_pwe == 1 || sm->sae_pwe == 2); + if ((sm->ap_rsnxe && !parse.rsnxe && own_rsnxe_used) || + (!sm->ap_rsnxe && parse.rsnxe) || + (sm->ap_rsnxe && parse.rsnxe && + (sm->ap_rsnxe_len != 2 + parse.rsnxe_len || + os_memcmp(sm->ap_rsnxe, parse.rsnxe - 2, + sm->ap_rsnxe_len) != 0))) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "FT: RSNXE mismatch between Beacon/ProbeResp and FT protocol Reassociation Response frame"); + wpa_hexdump(MSG_INFO, "RSNXE in Beacon/ProbeResp", + sm->ap_rsnxe, sm->ap_rsnxe_len); + wpa_hexdump(MSG_INFO, + "RSNXE in FT protocol Reassociation Response frame", + parse.rsnxe ? parse.rsnxe - 2 : NULL, + parse.rsnxe ? parse.rsnxe_len + 2 : 0); + return -1; + } + #ifdef CONFIG_OCV if (wpa_sm_ocv_enabled(sm)) { struct wpa_channel_info ci; @@ -1027,8 +1167,10 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, if (ocv_verify_tx_params(parse.oci, parse.oci_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "%s", ocv_errorstr); + ci.seg1_idx) != OCI_SUCCESS) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, OCV_FAILURE + "addr=" MACSTR " frame=ft-assoc error=%s", + MAC2STR(sm->bssid), ocv_errorstr); return -1; } } @@ -1036,10 +1178,9 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, sm->ft_reassoc_completed = 1; - if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) - return -1; - - if (wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0) + if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0 || + wpa_ft_process_igtk_subelem(sm, parse.igtk, parse.igtk_len) < 0 || + wpa_ft_process_bigtk_subelem(sm, parse.bigtk, parse.bigtk_len) < 0) return -1; if (sm->set_ptk_after_assoc) { @@ -1086,7 +1227,7 @@ int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap, } ft_ies = wpa_ft_gen_req_ies(sm, &ft_ies_len, NULL, sm->pmk_r0_name, - NULL, 0, target_ap, NULL, 0, mdie); + NULL, 0, target_ap, NULL, 0, mdie, 0); if (ft_ies) { sm->over_the_ds_in_progress = 1; os_memcpy(sm->target_ap, target_ap, ETH_ALEN); diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index e088a5aa7..96b07fc68 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -33,6 +33,8 @@ struct wpa_sm { struct wpa_gtk gtk_wnm_sleep; struct wpa_igtk igtk; struct wpa_igtk igtk_wnm_sleep; + struct wpa_bigtk bigtk; + struct wpa_bigtk bigtk_wnm_sleep; struct eapol_sm *eapol; /* EAPOL state machine from upper level code */ @@ -61,9 +63,15 @@ struct wpa_sm { u8 ssid[32]; size_t ssid_len; int wpa_ptk_rekey; + int wpa_deny_ptk0_rekey:1; int p2p; int wpa_rsc_relaxation; int owe_ptk_workaround; + int beacon_prot; + int ext_key_id; /* whether Extended Key ID is enabled */ + int use_ext_key_id; /* whether Extended Key ID has been detected + * to be used */ + int keyidx_active; /* Key ID for the active TK */ u8 own_addr[ETH_ALEN]; const char *ifname; @@ -87,6 +95,7 @@ struct wpa_sm { int mfp; /* 0 = disabled, 1 = optional, 2 = mandatory */ int ocv; /* Operating Channel Validation */ int sae_pwe; /* SAE PWE generation options */ + int sae_pk; /* whether SAE-PK is used */ u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */ size_t assoc_wpa_ie_len; @@ -145,6 +154,11 @@ struct wpa_sm { #ifdef CONFIG_TESTING_OPTIONS struct wpabuf *test_assoc_ie; + int ft_rsnxe_used; + unsigned int oci_freq_override_eapol; + unsigned int oci_freq_override_eapol_g2; + unsigned int oci_freq_override_ft_assoc; + unsigned int oci_freq_override_fils_assoc; #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_FILS @@ -174,6 +188,7 @@ struct wpa_sm { #ifdef CONFIG_DPP2 struct wpabuf *dpp_z; + int dpp_pfs; #endif /* CONFIG_DPP2 */ }; @@ -207,6 +222,12 @@ static inline int wpa_sm_set_key(struct wpa_sm *sm, enum wpa_alg alg, seq, seq_len, key, key_len, key_flag); } +static inline void wpa_sm_reconnect(struct wpa_sm *sm) +{ + WPA_ASSERT(sm->ctx->reconnect); + sm->ctx->reconnect(sm->ctx->ctx); +} + static inline void * wpa_sm_get_network_ctx(struct wpa_sm *sm) { WPA_ASSERT(sm->ctx->get_network_ctx); @@ -250,11 +271,13 @@ static inline u8 * wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type, static inline int wpa_sm_add_pmkid(struct wpa_sm *sm, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *cache_id, const u8 *pmk, - size_t pmk_len) + size_t pmk_len, u32 pmk_lifetime, + u8 pmk_reauth_threshold, int akmp) { WPA_ASSERT(sm->ctx->add_pmkid); return sm->ctx->add_pmkid(sm->ctx->ctx, network_ctx, bssid, pmkid, - cache_id, pmk, pmk_len); + cache_id, pmk, pmk_len, pmk_lifetime, + pmk_reauth_threshold, akmp); } static inline int wpa_sm_remove_pmkid(struct wpa_sm *sm, void *network_ctx, @@ -412,6 +435,12 @@ static inline int wpa_sm_channel_info(struct wpa_sm *sm, return sm->ctx->channel_info(sm->ctx->ctx, ci); } +static inline void wpa_sm_transition_disable(struct wpa_sm *sm, u8 bitmap) +{ + if (sm->ctx->transition_disable) + sm->ctx->transition_disable(sm->ctx->ctx, bitmap); +} + int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk, int ver, const u8 *dest, u16 proto, diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index 03c0d7e85..20fdd6987 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -105,6 +105,23 @@ static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len, } +u16 rsn_supp_capab(struct wpa_sm *sm) +{ + u16 capab = 0; + + if (sm->mfp) + capab |= WPA_CAPABILITY_MFPC; + if (sm->mfp == 2) + capab |= WPA_CAPABILITY_MFPR; + if (sm->ocv) + capab |= WPA_CAPABILITY_OCVC; + if (sm->ext_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; + + return capab; +} + + static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, int pairwise_cipher, int group_cipher, int key_mgmt, int mgmt_group_cipher, @@ -112,7 +129,6 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, { u8 *pos; struct rsn_ie_hdr *hdr; - u16 capab; u32 suite; if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN + @@ -214,14 +230,7 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, pos += RSN_SELECTOR_LEN; /* RSN Capabilities */ - capab = 0; - if (sm->mfp) - capab |= WPA_CAPABILITY_MFPC; - if (sm->mfp == 2) - capab |= WPA_CAPABILITY_MFPR; - if (sm->ocv) - capab |= WPA_CAPABILITY_OCVC; - WPA_PUT_LE16(pos, capab); + WPA_PUT_LE16(pos, rsn_supp_capab(sm)); pos += 2; if (sm->cur_pmksa) { @@ -348,7 +357,7 @@ int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len) if (!wpa_key_mgmt_sae(sm->key_mgmt)) return 0; /* SAE not in use */ - if (sm->sae_pwe != 1 && sm->sae_pwe != 2) + if (sm->sae_pwe != 1 && sm->sae_pwe != 2 && !sm->sae_pk) return 0; /* no supported extended RSN capabilities */ if (rsnxe_len < 3) @@ -358,7 +367,12 @@ int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len) *pos++ = 1; /* bits 0-3 = 0 since only one octet of Extended RSN Capabilities is * used for now */ - *pos++ = BIT(WLAN_RSNX_CAPAB_SAE_H2E); + *pos = BIT(WLAN_RSNX_CAPAB_SAE_H2E); +#ifdef CONFIG_SAE_PK + if (sm->sae_pk) + *pos |= BIT(WLAN_RSNX_CAPAB_SAE_PK); +#endif /* CONFIG_SAE_PK */ + pos++; return pos - rsnxe; } diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h index 6dc6cf560..83a6727fe 100644 --- a/src/rsn_supp/wpa_ie.h +++ b/src/rsn_supp/wpa_ie.h @@ -13,5 +13,6 @@ struct wpa_sm; int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len); int wpa_gen_rsnxe(struct wpa_sm *sm, u8 *rsnxe, size_t rsnxe_len); +u16 rsn_supp_capab(struct wpa_sm *sm); #endif /* WPA_IE_H */ diff --git a/src/tls/.gitignore b/src/tls/.gitignore deleted file mode 100644 index d43242d73..000000000 --- a/src/tls/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libtls.a diff --git a/src/tls/Makefile b/src/tls/Makefile index 52a890a15..c84fbe859 100644 --- a/src/tls/Makefile +++ b/src/tls/Makefile @@ -1,14 +1,3 @@ -all: libtls.a - -clean: - rm -f *~ *.o *.d libtls.a - -install: - @echo Nothing to be made. - - -include ../lib.rules - CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH CFLAGS += -DCONFIG_CRYPTO_INTERNAL CFLAGS += -DCONFIG_TLSV11 @@ -33,8 +22,4 @@ LIB_OBJS= \ tlsv1_server_write.o \ x509v3.o - -libtls.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/tls/pkcs1.c b/src/tls/pkcs1.c index 141ac50df..654c01b76 100644 --- a/src/tls/pkcs1.c +++ b/src/tls/pkcs1.c @@ -157,6 +157,7 @@ int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, plain[0] != 0x00 || plain[1] != 0x01) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure"); + wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len); return -1; } @@ -165,6 +166,7 @@ int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, if (plain[2] != 0xff) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature " "PS (BT=01)"); + wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len); return -1; } while (pos < plain + len && *pos == 0xff) @@ -174,12 +176,14 @@ int pkcs1_decrypt_public_key(struct crypto_rsa_key *key, /* PKCS #1 v1.5, 8.1: At least eight octets long PS */ wpa_printf(MSG_INFO, "LibTomCrypt: Too short signature " "padding"); + wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len); return -1; } if (pos + 16 /* min hash len */ >= plain + len || *pos != 0x00) { wpa_printf(MSG_INFO, "LibTomCrypt: Invalid signature EB " "structure (2)"); + wpa_hexdump_key(MSG_DEBUG, "Signature EB", plain, len); return -1; } pos++; diff --git a/src/tls/rsa.c b/src/tls/rsa.c index 3525eb991..1b01f5843 100644 --- a/src/tls/rsa.c +++ b/src/tls/rsa.c @@ -285,7 +285,7 @@ int crypto_rsa_exptmod(const u8 *in, size_t inlen, u8 *out, size_t *outlen, if (use_private) { /* - * Decrypt (or sign) using Chinese remainer theorem to speed + * Decrypt (or sign) using Chinese remainder theorem to speed * up calculation. This is equivalent to tmp = tmp^d mod n * (which would require more CPU to calculate directly). * diff --git a/src/tls/x509v3.c b/src/tls/x509v3.c index 5c8ac5676..d2e685cb3 100644 --- a/src/tls/x509v3.c +++ b/src/tls/x509v3.c @@ -264,7 +264,8 @@ static int x509_parse_public_key(const u8 *buf, size_t len, return -1; pos = hdr.payload; if (*pos) { - wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", + wpa_printf(MSG_DEBUG, + "X509: BITSTRING (subjectPublicKey) - %d unused bits", *pos); /* * TODO: should this be rejected? X.509 certificates are @@ -1851,7 +1852,8 @@ struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len) } pos = hdr.payload; if (*pos) { - wpa_printf(MSG_DEBUG, "X509: BITSTRING - %d unused bits", + wpa_printf(MSG_DEBUG, + "X509: BITSTRING (signatureValue) - %d unused bits", *pos); /* PKCS #1 v1.5 10.2.1: * It is an error if the length in bits of the signature S is diff --git a/src/utils/.gitignore b/src/utils/.gitignore deleted file mode 100644 index 833734f88..000000000 --- a/src/utils/.gitignore +++ /dev/null @@ -1 +0,0 @@ -libutils.a diff --git a/src/utils/Makefile b/src/utils/Makefile index 1ee2bee67..e8ad997ee 100644 --- a/src/utils/Makefile +++ b/src/utils/Makefile @@ -1,14 +1,3 @@ -all: libutils.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libutils.a - -install: - @echo Nothing to be made. - - -include ../lib.rules - #CFLAGS += -DWPA_TRACE CFLAGS += -DCONFIG_IPV6 CFLAGS += -DCONFIG_DEBUG_FILE @@ -37,7 +26,4 @@ LIB_OBJS += edit.o #LIB_OBJS += pcsc_funcs.o -libutils.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/utils/base64.c b/src/utils/base64.c index a17d2d36d..0d121c198 100644 --- a/src/utils/base64.c +++ b/src/utils/base64.c @@ -9,6 +9,7 @@ #include "includes.h" #include +#include "utils/common.h" #include "os.h" #include "base64.h" @@ -18,6 +19,10 @@ static const char base64_url_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; +#define BASE64_PAD BIT(0) +#define BASE64_LF BIT(1) + + static char * base64_gen_encode(const unsigned char *src, size_t len, size_t *out_len, const char *table, int add_pad) { @@ -29,7 +34,7 @@ static char * base64_gen_encode(const unsigned char *src, size_t len, if (len >= SIZE_MAX / 4) return NULL; olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */ - if (add_pad) + if (add_pad & BASE64_LF) olen += olen / 72; /* line feeds */ olen++; /* nul termination */ if (olen < len) @@ -49,7 +54,7 @@ static char * base64_gen_encode(const unsigned char *src, size_t len, *pos++ = table[in[2] & 0x3f]; in += 3; line_len += 4; - if (add_pad && line_len >= 72) { + if ((add_pad & BASE64_LF) && line_len >= 72) { *pos++ = '\n'; line_len = 0; } @@ -59,19 +64,19 @@ static char * base64_gen_encode(const unsigned char *src, size_t len, *pos++ = table[(in[0] >> 2) & 0x3f]; if (end - in == 1) { *pos++ = table[((in[0] & 0x03) << 4) & 0x3f]; - if (add_pad) + if (add_pad & BASE64_PAD) *pos++ = '='; } else { *pos++ = table[(((in[0] & 0x03) << 4) | (in[1] >> 4)) & 0x3f]; *pos++ = table[((in[1] & 0x0f) << 2) & 0x3f]; } - if (add_pad) + if (add_pad & BASE64_PAD) *pos++ = '='; line_len += 4; } - if (add_pad && line_len) + if ((add_pad & BASE64_LF) && line_len) *pos++ = '\n'; *pos = '\0'; @@ -164,7 +169,14 @@ static unsigned char * base64_gen_decode(const char *src, size_t len, */ char * base64_encode(const void *src, size_t len, size_t *out_len) { - return base64_gen_encode(src, len, out_len, base64_table, 1); + return base64_gen_encode(src, len, out_len, base64_table, + BASE64_PAD | BASE64_LF); +} + + +char * base64_encode_no_lf(const void *src, size_t len, size_t *out_len) +{ + return base64_gen_encode(src, len, out_len, base64_table, BASE64_PAD); } diff --git a/src/utils/base64.h b/src/utils/base64.h index 6216f44e5..d545b2931 100644 --- a/src/utils/base64.h +++ b/src/utils/base64.h @@ -10,6 +10,7 @@ #define BASE64_H char * base64_encode(const void *src, size_t len, size_t *out_len); +char * base64_encode_no_lf(const void *src, size_t len, size_t *out_len); unsigned char * base64_decode(const char *src, size_t len, size_t *out_len); char * base64_url_encode(const void *src, size_t len, size_t *out_len); unsigned char * base64_url_decode(const char *src, size_t len, size_t *out_len); diff --git a/src/utils/browser-android.c b/src/utils/browser-android.c index 71a165269..26c83d630 100644 --- a/src/utils/browser-android.c +++ b/src/utils/browser-android.c @@ -62,7 +62,7 @@ static void http_req(void *ctx, struct http_request *req) } -int hs20_web_browser(const char *url) +int hs20_web_browser(const char *url, int ignore_tls) { struct http_server *http; struct in_addr addr; diff --git a/src/utils/browser-system.c b/src/utils/browser-system.c index aed39706c..d87d97b5a 100644 --- a/src/utils/browser-system.c +++ b/src/utils/browser-system.c @@ -62,7 +62,7 @@ static void http_req(void *ctx, struct http_request *req) } -int hs20_web_browser(const char *url) +int hs20_web_browser(const char *url, int ignore_tls) { struct http_server *http; struct in_addr addr; diff --git a/src/utils/browser-wpadebug.c b/src/utils/browser-wpadebug.c index dfb4b6797..d32a85bdf 100644 --- a/src/utils/browser-wpadebug.c +++ b/src/utils/browser-wpadebug.c @@ -63,7 +63,7 @@ static void http_req(void *ctx, struct http_request *req) } -int hs20_web_browser(const char *url) +int hs20_web_browser(const char *url, int ignore_tls) { struct http_server *http; struct in_addr addr; diff --git a/src/utils/browser.c b/src/utils/browser.c index ad0b382fb..c0f4380c4 100644 --- a/src/utils/browser.c +++ b/src/utils/browser.c @@ -7,7 +7,11 @@ */ #include "includes.h" +#ifdef USE_WEBKIT2 +#include +#else /* USE_WEBKIT2 */ #include +#endif /* USE_WEBKIT2 */ #include "common.h" #include "browser.h" @@ -15,16 +19,20 @@ struct browser_context { GtkWidget *win; + WebKitWebView *view; int success; int progress; char *hover_link; char *title; + int gtk_main_started; + int quit_gtk_main; }; static void win_cb_destroy(GtkWidget *win, struct browser_context *ctx) { wpa_printf(MSG_DEBUG, "BROWSER:%s", __func__); - gtk_main_quit(); + if (ctx->gtk_main_started) + gtk_main_quit(); } @@ -50,6 +58,142 @@ static void browser_update_title(struct browser_context *ctx) } +static void process_request_starting_uri(struct browser_context *ctx, + const char *uri) +{ + int quit = 0; + + if (g_str_has_prefix(uri, "osu://")) { + ctx->success = atoi(uri + 6); + quit = 1; + } else if (g_str_has_prefix(uri, "http://localhost:12345")) { + /* + * This is used as a special trigger to indicate that the + * user exchange has been completed. + */ + ctx->success = 1; + quit = 1; + } + + if (quit) { + if (ctx->gtk_main_started) { + gtk_main_quit(); + ctx->gtk_main_started = 0; + } else { + ctx->quit_gtk_main = 1; + } + } +} + + +#ifdef USE_WEBKIT2 + +static void view_cb_notify_estimated_load_progress(WebKitWebView *view, + GParamSpec *pspec, + struct browser_context *ctx) +{ + ctx->progress = 100 * webkit_web_view_get_estimated_load_progress(view); + wpa_printf(MSG_DEBUG, "BROWSER:%s progress=%d", __func__, + ctx->progress); + browser_update_title(ctx); +} + + +static void view_cb_resource_load_starting(WebKitWebView *view, + WebKitWebResource *res, + WebKitURIRequest *req, + struct browser_context *ctx) +{ + const gchar *uri = webkit_uri_request_get_uri(req); + + wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); + process_request_starting_uri(ctx, uri); +} + + +static gboolean view_cb_decide_policy(WebKitWebView *view, + WebKitPolicyDecision *policy, + WebKitPolicyDecisionType type, + struct browser_context *ctx) +{ + wpa_printf(MSG_DEBUG, "BROWSER:%s type=%d", __func__, type); + switch (type) { + case WEBKIT_POLICY_DECISION_TYPE_RESPONSE: { + /* This function makes webkit send a download signal for all + * unknown mime types. */ + WebKitResponsePolicyDecision *response; + + response = WEBKIT_RESPONSE_POLICY_DECISION(policy); + if (!webkit_response_policy_decision_is_mime_type_supported( + response)) { + webkit_policy_decision_download(policy); + return TRUE; + } + break; + } + case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION: { + WebKitNavigationPolicyDecision *d; + WebKitNavigationAction *a; + WebKitURIRequest *req; + const gchar *uri; + + d = WEBKIT_NAVIGATION_POLICY_DECISION(policy); + a = webkit_navigation_policy_decision_get_navigation_action(d); + req = webkit_navigation_action_get_request(a); + uri = webkit_uri_request_get_uri(req); + wpa_printf(MSG_DEBUG, "BROWSER:%s navigation action: uri=%s", + __func__, uri); + process_request_starting_uri(ctx, uri); + break; + } + default: + break; + } + + return FALSE; +} + + +static void view_cb_mouse_target_changed(WebKitWebView *view, + WebKitHitTestResult *h, + guint modifiers, + struct browser_context *ctx) +{ + WebKitHitTestResultContext hc = webkit_hit_test_result_get_context(h); + const char *uri = NULL; + + if (hc & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK) + uri = webkit_hit_test_result_get_link_uri(h); + else if (hc & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE) + uri = webkit_hit_test_result_get_image_uri(h); + else if (hc & WEBKIT_HIT_TEST_RESULT_CONTEXT_MEDIA) + uri = webkit_hit_test_result_get_media_uri(h); + + wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri ? uri : "N/A"); + os_free(ctx->hover_link); + if (uri) + ctx->hover_link = os_strdup(uri); + else + ctx->hover_link = NULL; + + browser_update_title(ctx); +} + + +static void view_cb_notify_title(WebKitWebView *view, GParamSpec *ps, + struct browser_context *ctx) +{ + const char *title; + + title = webkit_web_view_get_title(ctx->view); + wpa_printf(MSG_DEBUG, "BROWSER:%s title=%s", __func__, title); + os_free(ctx->title); + ctx->title = os_strdup(title); + browser_update_title(ctx); +} + +#else /* USE_WEBKIT2 */ + static void view_cb_notify_progress(WebKitWebView *view, GParamSpec *pspec, struct browser_context *ctx) { @@ -66,6 +210,10 @@ static void view_cb_notify_load_status(WebKitWebView *view, GParamSpec *pspec, int status = webkit_web_view_get_load_status(view); wpa_printf(MSG_DEBUG, "BROWSER:%s load-status=%d uri=%s", __func__, status, webkit_web_view_get_uri(view)); + if (ctx->quit_gtk_main) { + gtk_main_quit(); + ctx->gtk_main_started = 0; + } } @@ -77,21 +225,12 @@ static void view_cb_resource_request_starting(WebKitWebView *view, struct browser_context *ctx) { const gchar *uri = webkit_network_request_get_uri(req); + wpa_printf(MSG_DEBUG, "BROWSER:%s uri=%s", __func__, uri); if (g_str_has_suffix(uri, "/favicon.ico")) webkit_network_request_set_uri(req, "about:blank"); - if (g_str_has_prefix(uri, "osu://")) { - ctx->success = atoi(uri + 6); - gtk_main_quit(); - } - if (g_str_has_prefix(uri, "http://localhost:12345")) { - /* - * This is used as a special trigger to indicate that the - * user exchange has been completed. - */ - ctx->success = 1; - gtk_main_quit(); - } + + process_request_starting_uri(ctx, uri); } @@ -147,23 +286,32 @@ static void view_cb_title_changed(WebKitWebView *view, WebKitWebFrame *frame, browser_update_title(ctx); } +#endif /* USE_WEBKIT2 */ -int hs20_web_browser(const char *url) + +int hs20_web_browser(const char *url, int ignore_tls) { GtkWidget *scroll; - SoupSession *s; WebKitWebView *view; +#ifdef USE_WEBKIT2 + WebKitSettings *settings; +#else /* USE_WEBKIT2 */ WebKitWebSettings *settings; + SoupSession *s; +#endif /* USE_WEBKIT2 */ struct browser_context ctx; memset(&ctx, 0, sizeof(ctx)); if (!gtk_init_check(NULL, NULL)) return -1; +#ifndef USE_WEBKIT2 s = webkit_get_default_session(); g_object_set(G_OBJECT(s), "ssl-ca-file", "/etc/ssl/certs/ca-certificates.crt", NULL); - g_object_set(G_OBJECT(s), "ssl-strict", FALSE, NULL); + if (ignore_tls) + g_object_set(G_OBJECT(s), "ssl-strict", FALSE, NULL); +#endif /* USE_WEBKIT2 */ ctx.win = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_role(GTK_WINDOW(ctx.win), "Hotspot 2.0 client"); @@ -177,10 +325,24 @@ int hs20_web_browser(const char *url) G_CALLBACK(win_cb_destroy), &ctx); view = WEBKIT_WEB_VIEW(webkit_web_view_new()); - g_signal_connect(G_OBJECT(view), "notify::progress", - G_CALLBACK(view_cb_notify_progress), &ctx); + ctx.view = view; +#ifdef USE_WEBKIT2 + g_signal_connect(G_OBJECT(view), "notify::estimated-load-progress", + G_CALLBACK(view_cb_notify_estimated_load_progress), + &ctx); + g_signal_connect(G_OBJECT(view), "resource-load-started", + G_CALLBACK(view_cb_resource_load_starting), &ctx); + g_signal_connect(G_OBJECT(view), "decide-policy", + G_CALLBACK(view_cb_decide_policy), &ctx); + g_signal_connect(G_OBJECT(view), "mouse-target-changed", + G_CALLBACK(view_cb_mouse_target_changed), &ctx); + g_signal_connect(G_OBJECT(view), "notify::title", + G_CALLBACK(view_cb_notify_title), &ctx); +#else /* USE_WEBKIT2 */ g_signal_connect(G_OBJECT(view), "notify::load-status", G_CALLBACK(view_cb_notify_load_status), &ctx); + g_signal_connect(G_OBJECT(view), "notify::progress", + G_CALLBACK(view_cb_notify_progress), &ctx); g_signal_connect(G_OBJECT(view), "resource-request-starting", G_CALLBACK(view_cb_resource_request_starting), &ctx); g_signal_connect(G_OBJECT(view), "mime-type-policy-decision-requested", @@ -191,6 +353,7 @@ int hs20_web_browser(const char *url) G_CALLBACK(view_cb_hovering_over_link), &ctx); g_signal_connect(G_OBJECT(view), "title-changed", G_CALLBACK(view_cb_title_changed), &ctx); +#endif /* USE_WEBKIT2 */ gtk_container_add(GTK_CONTAINER(scroll), GTK_WIDGET(view)); gtk_container_add(GTK_CONTAINER(ctx.win), GTK_WIDGET(scroll)); @@ -205,8 +368,19 @@ int hs20_web_browser(const char *url) "hs20-client/1.0", NULL); g_object_set(G_OBJECT(settings), "auto-load-images", TRUE, NULL); +#ifdef USE_WEBKIT2 + if (ignore_tls) { + WebKitWebContext *wkctx; + + wkctx = webkit_web_context_get_default(); + webkit_web_context_set_tls_errors_policy( + wkctx, WEBKIT_TLS_ERRORS_POLICY_IGNORE); + } +#endif /* USE_WEBKIT2 */ + webkit_web_view_load_uri(view, url); + ctx.gtk_main_started = 1; gtk_main(); gtk_widget_destroy(ctx.win); while (gtk_events_pending()) diff --git a/src/utils/browser.h b/src/utils/browser.h index aaa0eed26..3af13b9a1 100644 --- a/src/utils/browser.h +++ b/src/utils/browser.h @@ -10,12 +10,12 @@ #define BROWSER_H #ifdef CONFIG_NO_BROWSER -static inline int hs20_web_browser(const char *url) +static inline int hs20_web_browser(const char *url, int ignore_tls) { return -1; } #else /* CONFIG_NO_BROWSER */ -int hs20_web_browser(const char *url); +int hs20_web_browser(const char *url, int ignore_tls); #endif /* CONFIG_NO_BROWSER */ #endif /* BROWSER_H */ diff --git a/src/utils/common.c b/src/utils/common.c index 27bf435d9..2c1275193 100644 --- a/src/utils/common.c +++ b/src/utils/common.c @@ -7,6 +7,7 @@ */ #include "includes.h" +#include #include "common/ieee802_11_defs.h" #include "common.h" @@ -790,6 +791,10 @@ int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value) */ pos = value; while (pos && pos[0]) { + if (count == UINT_MAX) { + os_free(freq); + return -1; + } n = os_realloc_array(freq, count + 1, sizeof(struct wpa_freq_range)); if (n == NULL) { @@ -874,9 +879,10 @@ char * freq_range_list_str(const struct wpa_freq_range_list *list) } -int int_array_len(const int *a) +size_t int_array_len(const int *a) { - int i; + size_t i; + for (i = 0; a && a[i]; i++) ; return i; @@ -885,12 +891,21 @@ int int_array_len(const int *a) void int_array_concat(int **res, const int *a) { - int reslen, alen, i; + size_t reslen, alen, i, max_size; int *n; reslen = int_array_len(*res); alen = int_array_len(a); - + max_size = (size_t) -1; + if (alen >= max_size - reslen) { + /* This should not really happen, but if it did, something + * would overflow. Do not try to merge the arrays; instead, make + * this behave like memory allocation failure to avoid messing + * up memory. */ + os_free(*res); + *res = NULL; + return; + } n = os_realloc_array(*res, reslen + alen + 1, sizeof(int)); if (n == NULL) { os_free(*res); @@ -918,8 +933,7 @@ static int freq_cmp(const void *a, const void *b) void int_array_sort_unique(int *a) { - int alen; - int i, j; + size_t alen, i, j; if (a == NULL) return; @@ -944,7 +958,7 @@ void int_array_sort_unique(int *a) void int_array_add_unique(int **res, int a) { - int reslen; + size_t reslen, max_size; int *n; for (reslen = 0; *res && (*res)[reslen]; reslen++) { @@ -952,6 +966,16 @@ void int_array_add_unique(int **res, int a) return; /* already in the list */ } + max_size = (size_t) -1; + if (reslen > max_size - 2) { + /* This should not really happen in practice, but if it did, + * something would overflow. Do not try to add the new value; + * instead, make this behave like memory allocation failure to + * avoid messing up memory. */ + os_free(*res); + *res = NULL; + return; + } n = os_realloc_array(*res, reslen + 2, sizeof(int)); if (n == NULL) { os_free(*res); diff --git a/src/utils/common.h b/src/utils/common.h index 833469a52..45f72bb30 100644 --- a/src/utils/common.h +++ b/src/utils/common.h @@ -482,7 +482,8 @@ int hexstr2bin(const char *hex, u8 *buf, size_t len); void inc_byte_array(u8 *counter, size_t len); void buf_shift_right(u8 *buf, size_t len, size_t bits); void wpa_get_ntp_timestamp(u8 *buf); -int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...); +int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...) + PRINTF_FORMAT(3, 4); int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len, char sep); int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len); @@ -547,7 +548,7 @@ int freq_range_list_includes(const struct wpa_freq_range_list *list, unsigned int freq); char * freq_range_list_str(const struct wpa_freq_range_list *list); -int int_array_len(const int *a); +size_t int_array_len(const int *a); void int_array_concat(int **res, const int *a); void int_array_sort_unique(int *a); void int_array_add_unique(int **res, int a); diff --git a/src/utils/eloop.c b/src/utils/eloop.c index bb375be10..b353ab0e4 100644 --- a/src/utils/eloop.c +++ b/src/utils/eloop.c @@ -68,7 +68,7 @@ struct eloop_signal { }; struct eloop_sock_table { - int count; + size_t count; struct eloop_sock *table; eloop_event_type type; int changed; @@ -77,10 +77,10 @@ struct eloop_sock_table { struct eloop_data { int max_sock; - int count; /* sum of all table counts */ + size_t count; /* sum of all table counts */ #ifdef CONFIG_ELOOP_POLL - int max_pollfd_map; /* number of pollfds_map currently allocated */ - int max_poll_fds; /* number of pollfds currently allocated */ + size_t max_pollfd_map; /* number of pollfds_map currently allocated */ + size_t max_poll_fds; /* number of pollfds currently allocated */ struct pollfd *pollfds; struct pollfd **pollfds_map; #endif /* CONFIG_ELOOP_POLL */ @@ -90,12 +90,12 @@ struct eloop_data { #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ #ifdef CONFIG_ELOOP_EPOLL int epollfd; - int epoll_max_event_num; + size_t epoll_max_event_num; struct epoll_event *epoll_events; #endif /* CONFIG_ELOOP_EPOLL */ #ifdef CONFIG_ELOOP_KQUEUE int kqueuefd; - int kqueue_nevents; + size_t kqueue_nevents; struct kevent *kqueue_events; #endif /* CONFIG_ELOOP_KQUEUE */ struct eloop_sock_table readers; @@ -104,7 +104,7 @@ struct eloop_data { struct dl_list timeout; - int signal_count; + size_t signal_count; struct eloop_signal *signals; int signaled; int pending_terminate; @@ -125,7 +125,8 @@ static void eloop_sigsegv_handler(int sig) static void eloop_trace_sock_add_ref(struct eloop_sock_table *table) { - int i; + size_t i; + if (table == NULL || table->table == NULL) return; for (i = 0; i < table->count; i++) { @@ -139,7 +140,8 @@ static void eloop_trace_sock_add_ref(struct eloop_sock_table *table) static void eloop_trace_sock_remove_ref(struct eloop_sock_table *table) { - int i; + size_t i; + if (table == NULL || table->table == NULL) return; for (i = 0; i < table->count; i++) { @@ -266,7 +268,7 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, #endif /* CONFIG_ELOOP_EPOLL */ #if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE) struct eloop_sock *temp_table; - int next; + size_t next; #endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */ struct eloop_sock *tmp; int new_max_sock; @@ -280,7 +282,7 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, return -1; #ifdef CONFIG_ELOOP_POLL - if (new_max_sock >= eloop.max_pollfd_map) { + if ((size_t) new_max_sock >= eloop.max_pollfd_map) { struct pollfd **nmap; nmap = os_realloc_array(eloop.pollfds_map, new_max_sock + 50, sizeof(struct pollfd *)); @@ -293,7 +295,8 @@ static int eloop_sock_table_add_sock(struct eloop_sock_table *table, if (eloop.count + 1 > eloop.max_poll_fds) { struct pollfd *n; - int nmax = eloop.count + 1 + 50; + size_t nmax = eloop.count + 1 + 50; + n = os_realloc_array(eloop.pollfds, nmax, sizeof(struct pollfd)); if (n == NULL) @@ -385,7 +388,7 @@ static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, #ifdef CONFIG_ELOOP_KQUEUE struct kevent ke; #endif /* CONFIG_ELOOP_KQUEUE */ - int i; + size_t i; if (table == NULL || table->table == NULL || table->count == 0) return; @@ -444,7 +447,7 @@ static int eloop_sock_table_set_fds(struct eloop_sock_table *readers, struct pollfd **pollfds_map, int max_pollfd_map) { - int i; + size_t i; int nxt = 0; int fd; struct pollfd *pfd; @@ -519,7 +522,7 @@ static int eloop_sock_table_dispatch_table(struct eloop_sock_table *table, int max_pollfd_map, short int revents) { - int i; + size_t i; struct pollfd *pfd; if (!table || !table->table) @@ -572,7 +575,7 @@ static void eloop_sock_table_dispatch(struct eloop_sock_table *readers, static void eloop_sock_table_set_fds(struct eloop_sock_table *table, fd_set *fds) { - int i; + size_t i; FD_ZERO(fds); @@ -589,7 +592,7 @@ static void eloop_sock_table_set_fds(struct eloop_sock_table *table, static void eloop_sock_table_dispatch(struct eloop_sock_table *table, fd_set *fds) { - int i; + size_t i; if (table == NULL || table->table == NULL) return; @@ -653,7 +656,8 @@ static void eloop_sock_table_dispatch(struct kevent *events, int nfds) static int eloop_sock_table_requeue(struct eloop_sock_table *table) { - int i, r; + size_t i; + int r; r = 0; for (i = 0; i < table->count && table->table; i++) { @@ -694,7 +698,8 @@ int eloop_sock_requeue(void) static void eloop_sock_table_destroy(struct eloop_sock_table *table) { if (table) { - int i; + size_t i; + for (i = 0; i < table->count && table->table; i++) { wpa_printf(MSG_INFO, "ELOOP: remaining socket: " "sock=%d eloop_data=%p user_data=%p " @@ -968,7 +973,7 @@ static void eloop_handle_alarm(int sig) static void eloop_handle_signal(int sig) { - int i; + size_t i; #ifndef CONFIG_NATIVE_WINDOWS if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) { @@ -992,7 +997,7 @@ static void eloop_handle_signal(int sig) static void eloop_process_pending_signals(void) { - int i; + size_t i; if (eloop.signaled == 0) return; diff --git a/src/utils/eloop_win.c b/src/utils/eloop_win.c index 9c8b12be8..74eaa33ec 100644 --- a/src/utils/eloop_win.c +++ b/src/utils/eloop_win.c @@ -54,7 +54,7 @@ struct eloop_data { struct dl_list timeout; - int signal_count; + size_t signal_count; struct eloop_signal *signals; int signaled; int pending_terminate; @@ -422,7 +422,7 @@ int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs, #if 0 static void eloop_handle_signal(int sig) { - int i; + size_t i; eloop.signaled++; for (i = 0; i < eloop.signal_count; i++) { @@ -437,7 +437,7 @@ static void eloop_handle_signal(int sig) static void eloop_process_pending_signals(void) { - int i; + size_t i; if (eloop.signaled == 0) return; @@ -517,7 +517,7 @@ int eloop_register_signal_terminate(eloop_signal_handler handler, eloop.term_signal.handler = handler; eloop.term_signal.user_data = user_data; - + return 0; } diff --git a/src/utils/http-utils.h b/src/utils/http-utils.h index 8d4399a37..d9fc925a2 100644 --- a/src/utils/http-utils.h +++ b/src/utils/http-utils.h @@ -28,11 +28,11 @@ struct http_logo { struct http_cert { char **dnsname; - unsigned int num_dnsname; + size_t num_dnsname; struct http_othername *othername; - unsigned int num_othername; + size_t num_othername; struct http_logo *logo; - unsigned int num_logo; + size_t num_logo; }; int soap_init_client(struct http_ctx *ctx, const char *address, diff --git a/src/utils/includes.h b/src/utils/includes.h index 75513fc8c..741fc9c14 100644 --- a/src/utils/includes.h +++ b/src/utils/includes.h @@ -18,6 +18,7 @@ #include #include +#include #include #include #include diff --git a/src/utils/json.c b/src/utils/json.c index 5a0edf211..dd12f1b6e 100644 --- a/src/utils/json.c +++ b/src/utils/json.c @@ -528,6 +528,28 @@ struct wpabuf * json_get_member_base64url(struct json_token *json, } +struct wpabuf * json_get_member_base64(struct json_token *json, + const char *name) +{ + struct json_token *token; + unsigned char *buf; + size_t buflen; + struct wpabuf *ret; + + token = json_get_member(json, name); + if (!token || token->type != JSON_STRING) + return NULL; + buf = base64_decode(token->string, os_strlen(token->string), &buflen); + if (!buf) + return NULL; + ret = wpabuf_alloc_ext_data(buf, buflen); + if (!ret) + os_free(buf); + + return ret; +} + + static const char * json_type_str(enum json_type type) { switch (type) { @@ -620,6 +642,20 @@ int json_add_base64url(struct wpabuf *json, const char *name, const void *val, } +int json_add_base64(struct wpabuf *json, const char *name, const void *val, + size_t len) +{ + char *b64; + + b64 = base64_encode_no_lf(val, len, NULL); + if (!b64) + return -1; + json_add_string(json, name, b64); + os_free(b64); + return 0; +} + + void json_start_object(struct wpabuf *json, const char *name) { if (name) diff --git a/src/utils/json.h b/src/utils/json.h index ca4a2e47e..8448bb0c5 100644 --- a/src/utils/json.h +++ b/src/utils/json.h @@ -37,6 +37,8 @@ void json_free(struct json_token *json); struct json_token * json_get_member(struct json_token *json, const char *name); struct wpabuf * json_get_member_base64url(struct json_token *json, const char *name); +struct wpabuf * json_get_member_base64(struct json_token *json, + const char *name); void json_print_tree(struct json_token *root, char *buf, size_t buflen); void json_add_int(struct wpabuf *json, const char *name, int val); void json_add_string(struct wpabuf *json, const char *name, const char *val); @@ -44,6 +46,8 @@ int json_add_string_escape(struct wpabuf *json, const char *name, const void *val, size_t len); int json_add_base64url(struct wpabuf *json, const char *name, const void *val, size_t len); +int json_add_base64(struct wpabuf *json, const char *name, const void *val, + size_t len); void json_start_object(struct wpabuf *json, const char *name); void json_end_object(struct wpabuf *json); void json_start_array(struct wpabuf *json, const char *name); diff --git a/src/utils/list.h b/src/utils/list.h index 85aa5e39c..aa62c0881 100644 --- a/src/utils/list.h +++ b/src/utils/list.h @@ -46,12 +46,12 @@ static inline void dl_list_del(struct dl_list *item) item->prev = NULL; } -static inline int dl_list_empty(struct dl_list *list) +static inline int dl_list_empty(const struct dl_list *list) { return list->next == list; } -static inline unsigned int dl_list_len(struct dl_list *list) +static inline unsigned int dl_list_len(const struct dl_list *list) { struct dl_list *item; int count = 0; @@ -76,8 +76,8 @@ static inline unsigned int dl_list_len(struct dl_list *list) dl_list_entry((list)->prev, type, member)) #define dl_list_for_each(item, list, type, member) \ - for (item = dl_list_first((list), type, member); \ - item && item != dl_list_entry((list), type, member); \ + for (item = dl_list_entry((list)->next, type, member); \ + &item->member != (list); \ item = dl_list_entry(item->member.next, type, member)) #define dl_list_for_each_safe(item, n, list, type, member) \ diff --git a/src/utils/os_unix.c b/src/utils/os_unix.c index dd504f3ab..1de37204d 100644 --- a/src/utils/os_unix.c +++ b/src/utils/os_unix.c @@ -39,7 +39,7 @@ static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list); struct os_alloc_trace { unsigned int magic; - struct dl_list list; + struct dl_list list __attribute__((aligned(16))); size_t len; WPA_TRACE_INFO } __attribute__((aligned(16))); @@ -337,6 +337,8 @@ char * os_rel2abs_path(const char *rel_path) int os_program_init(void) { + unsigned int seed; + #ifdef ANDROID /* * We ignore errors here since errors are normal if we @@ -365,6 +367,9 @@ int os_program_init(void) capset(&header, &cap); #endif /* ANDROID */ + if (os_get_random((unsigned char *) &seed, sizeof(seed)) == 0) + srandom(seed); + return 0; } diff --git a/src/utils/state_machine.h b/src/utils/state_machine.h index a51431578..204c8a85a 100644 --- a/src/utils/state_machine.h +++ b/src/utils/state_machine.h @@ -9,7 +9,7 @@ * implement a state machine. In addition to including this header file, each * file implementing a state machine must define STATE_MACHINE_DATA to be the * data structure including state variables (enum machine_state, - * Boolean changed), and STATE_MACHINE_DEBUG_PREFIX to be a string that is used + * bool changed), and STATE_MACHINE_DEBUG_PREFIX to be a string that is used * as a prefix for all debug messages. If SM_ENTRY_MA macro is used to define * a group of state machines with shared data structure, STATE_MACHINE_ADDR * needs to be defined to point to the MAC address used in debug output. @@ -45,7 +45,7 @@ static void sm_ ## machine ## _ ## state ## _Enter(STATE_MACHINE_DATA *sm, \ */ #define SM_ENTRY(machine, state) \ if (!global || sm->machine ## _state != machine ## _ ## state) { \ - sm->changed = TRUE; \ + sm->changed = true; \ wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " #machine \ " entering state " #state); \ } \ @@ -64,7 +64,7 @@ sm->machine ## _state = machine ## _ ## state; */ #define SM_ENTRY_M(machine, _state, data) \ if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ - sm->changed = TRUE; \ + sm->changed = true; \ wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " \ #machine " entering state " #_state); \ } \ @@ -82,7 +82,7 @@ sm->data ## _ ## state = machine ## _ ## _state; */ #define SM_ENTRY_MA(machine, _state, data) \ if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ - sm->changed = TRUE; \ + sm->changed = true; \ wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " MACSTR " " \ #machine " entering state " #_state, \ MAC2STR(STATE_MACHINE_ADDR)); \ diff --git a/src/utils/utils_module_tests.c b/src/utils/utils_module_tests.c index f75d4065d..365f21fb1 100644 --- a/src/utils/utils_module_tests.c +++ b/src/utils/utils_module_tests.c @@ -226,7 +226,7 @@ static int int_array_tests(void) int test3[] = { 1, 1, 1, -1, 2, 3, 4, 1, 2, 0 }; int test3_res[] = { -1, 1, 2, 3, 4, 0 }; int errors = 0; - int len; + size_t len; wpa_printf(MSG_INFO, "int_array tests"); diff --git a/src/utils/wpabuf.h b/src/utils/wpabuf.h index 01da41b32..b2a54b22f 100644 --- a/src/utils/wpabuf.h +++ b/src/utils/wpabuf.h @@ -70,6 +70,21 @@ static inline size_t wpabuf_tailroom(const struct wpabuf *buf) return buf->size - buf->used; } +/** + * wpabuf_cmp - Check if two buffers contain the same data + * @a: wpabuf buffer + * @b: wpabuf buffer + * Returns: 0 if the two buffers contain the same data and non-zero otherwise + */ +static inline int wpabuf_cmp(const struct wpabuf *a, const struct wpabuf *b) +{ + if (!a && !b) + return 0; + if (a && b && wpabuf_size(a) == wpabuf_size(b)) + return os_memcmp(a->buf, b->buf, wpabuf_size(a)); + return -1; +} + /** * wpabuf_head - Get pointer to the head of the buffer data * @buf: wpabuf buffer diff --git a/src/wps/Makefile b/src/wps/Makefile index 4806fe8da..cddc6865a 100644 --- a/src/wps/Makefile +++ b/src/wps/Makefile @@ -1,13 +1,3 @@ -all: libwps.a - -clean: - rm -f *~ *.o *.d *.gcno *.gcda *.gcov libwps.a - -install: - @echo Nothing to be made. - -include ../lib.rules - CFLAGS += -DCONFIG_P2P CFLAGS += -DCONFIG_WPS_OOB CFLAGS += -DCONFIG_WPS_NFC @@ -35,7 +25,4 @@ LIB_OBJS= \ wps_upnp_ssdp.o \ wps_upnp_web.o -libwps.a: $(LIB_OBJS) - $(AR) crT $@ $? - --include $(OBJS:%.o=%.d) +include ../lib.rules diff --git a/src/wps/wps.h b/src/wps/wps.h index 3b56da74d..93888b011 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -394,11 +394,6 @@ struct wps_registrar_config { */ int disable_auto_conf; - /** - * static_wep_only - Whether the BSS supports only static WEP - */ - int static_wep_only; - /** * dualband - Whether this is a concurrent dualband AP */ diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c index 5ec7133af..f37225676 100644 --- a/src/wps/wps_attr_build.c +++ b/src/wps/wps_attr_build.c @@ -310,6 +310,9 @@ int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg) auth_types &= ~WPS_AUTH_WPA; auth_types &= ~WPS_AUTH_WPA2; auth_types &= ~WPS_AUTH_SHARED; +#ifdef CONFIG_NO_TKIP + auth_types &= ~WPS_AUTH_WPAPSK; +#endif /* CONFIG_NO_TKIP */ #ifdef CONFIG_WPS_TESTING if (wps_force_auth_types_in_use) { wpa_printf(MSG_DEBUG, @@ -331,6 +334,9 @@ int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg) { u16 encr_types = WPS_ENCR_TYPES; encr_types &= ~WPS_ENCR_WEP; +#ifdef CONFIG_NO_TKIP + encr_types &= ~WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ #ifdef CONFIG_WPS_TESTING if (wps_force_encr_types_in_use) { wpa_printf(MSG_DEBUG, diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c index 80ed603fc..819cd43f6 100644 --- a/src/wps/wps_enrollee.c +++ b/src/wps/wps_enrollee.c @@ -880,6 +880,17 @@ static int wps_process_ap_settings_e(struct wps_data *wps, cred.auth_type |= WPS_AUTH_WPA2PSK; } +#ifdef CONFIG_NO_TKIP + if (cred.encr_type & WPS_ENCR_TKIP) { + wpa_printf(MSG_DEBUG, "WPS: Disable encr_type TKIP"); + cred.encr_type &= ~WPS_ENCR_TKIP; + } + if (cred.auth_type & WPS_AUTH_WPAPSK) { + wpa_printf(MSG_DEBUG, "WPS: Disable auth_type WPAPSK"); + cred.auth_type &= ~WPS_AUTH_WPAPSK; + } +#endif /* CONFIG_NO_TKIP */ + if (wps->wps->cred_cb) { cred.cred_attr = wpabuf_head(attrs); cred.cred_attr_len = wpabuf_len(attrs); diff --git a/src/wps/wps_er.c b/src/wps/wps_er.c index 6bded1432..31d2e50e4 100644 --- a/src/wps/wps_er.c +++ b/src/wps/wps_er.c @@ -1298,7 +1298,7 @@ wps_er_init(struct wps_context *wps, const char *ifname, const char *filter) "with %s", filter); } if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text, - er->mac_addr)) { + NULL, er->mac_addr)) { wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " "for %s. Does it have IP address?", er->ifname); wps_er_deinit(er, NULL, NULL); diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index fb6c71d7e..9e1ee36da 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -173,7 +173,6 @@ struct wps_registrar { int sel_reg_union; int sel_reg_dev_password_id_override; int sel_reg_config_methods_override; - int static_wep_only; int dualband; int force_per_enrollee_psk; @@ -697,7 +696,6 @@ wps_registrar_init(struct wps_context *wps, reg->disable_auto_conf = cfg->disable_auto_conf; reg->sel_reg_dev_password_id_override = -1; reg->sel_reg_config_methods_override = -1; - reg->static_wep_only = cfg->static_wep_only; reg->dualband = cfg->dualband; reg->force_per_enrollee_psk = cfg->force_per_enrollee_psk; @@ -1390,28 +1388,6 @@ static int wps_set_ie(struct wps_registrar *reg) return -1; } - if (reg->static_wep_only) { - /* - * Windows XP and Vista clients can get confused about - * EAP-Identity/Request when they probe the network with - * EAPOL-Start. In such a case, they may assume the network is - * using IEEE 802.1X and prompt user for a certificate while - * the correct (non-WPS) behavior would be to ask for the - * static WEP key. As a workaround, use Microsoft Provisioning - * IE to advertise that legacy 802.1X is not supported. - */ - const u8 ms_wps[7] = { - WLAN_EID_VENDOR_SPECIFIC, 5, - /* Microsoft Provisioning IE (00:50:f2:5) */ - 0x00, 0x50, 0xf2, 5, - 0x00 /* no legacy 802.1X or MS WPS */ - }; - wpa_printf(MSG_DEBUG, "WPS: Add Microsoft Provisioning IE " - "into Beacon/Probe Response frames"); - wpabuf_put_data(beacon, ms_wps, sizeof(ms_wps)); - wpabuf_put_data(probe, ms_wps, sizeof(ms_wps)); - } - return wps_cb_set_ie(reg, beacon, probe); } @@ -1701,8 +1677,10 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) wps->wps->auth_types, wps->auth_type); if (wps->auth_type & WPS_AUTH_WPA2PSK) wps->auth_type = WPS_AUTH_WPA2PSK; +#ifndef CONFIG_NO_TKIP else if (wps->auth_type & WPS_AUTH_WPAPSK) wps->auth_type = WPS_AUTH_WPAPSK; +#endif /* CONFIG_NO_TKIP */ else if (wps->auth_type & WPS_AUTH_OPEN) wps->auth_type = WPS_AUTH_OPEN; else { @@ -1724,8 +1702,10 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) wps->auth_type == WPS_AUTH_WPAPSK) { if (wps->encr_type & WPS_ENCR_AES) wps->encr_type = WPS_ENCR_AES; +#ifndef CONFIG_NO_TKIP else if (wps->encr_type & WPS_ENCR_TKIP) wps->encr_type = WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ else { wpa_printf(MSG_DEBUG, "WPS: No suitable encryption " "type for WPA/WPA2"); @@ -3502,6 +3482,7 @@ static void wps_registrar_set_selected_timeout(void *eloop_ctx, "unselect internal Registrar"); reg->selected_registrar = 0; reg->pbc = 0; + wps_registrar_expire_pins(reg); wps_registrar_selected_registrar_changed(reg, 0); } diff --git a/src/wps/wps_upnp.c b/src/wps/wps_upnp.c index 6e10e4bc0..ff58cb938 100644 --- a/src/wps/wps_upnp.c +++ b/src/wps/wps_upnp.c @@ -303,6 +303,14 @@ static void subscr_addr_free_all(struct subscription *s) } +static int local_network_addr(struct upnp_wps_device_sm *sm, + struct sockaddr_in *addr) +{ + return (addr->sin_addr.s_addr & sm->netmask.s_addr) == + (sm->ip_addr & sm->netmask.s_addr); +} + + /* subscr_addr_add_url -- add address(es) for one url to subscription */ static void subscr_addr_add_url(struct subscription *s, const char *url, size_t url_len) @@ -320,9 +328,14 @@ static void subscr_addr_add_url(struct subscription *s, const char *url, int rerr; size_t host_len, path_len; - /* url MUST begin with http: */ - if (url_len < 7 || os_strncasecmp(url, "http://", 7)) + /* URL MUST begin with HTTP scheme. In addition, limit the length of + * the URL to 700 characters which is around the limit that was + * implicitly enforced for more than 10 years due to a bug in + * generating the event messages. */ + if (url_len < 7 || os_strncasecmp(url, "http://", 7) || url_len > 700) { + wpa_printf(MSG_DEBUG, "WPS UPnP: Reject an unacceptable URL"); goto fail; + } url += 7; url_len -= 7; @@ -381,6 +394,7 @@ static void subscr_addr_add_url(struct subscription *s, const char *url, for (rp = result; rp; rp = rp->ai_next) { struct subscr_addr *a; + struct sockaddr_in *addr = (struct sockaddr_in *) rp->ai_addr; /* Limit no. of address to avoid denial of service attack */ if (dl_list_len(&s->addr_list) >= MAX_ADDR_PER_SUBSCRIPTION) { @@ -389,6 +403,13 @@ static void subscr_addr_add_url(struct subscription *s, const char *url, break; } + if (!local_network_addr(s->sm, addr)) { + wpa_printf(MSG_INFO, + "WPS UPnP: Ignore a delivery URL that points to another network %s", + inet_ntoa(addr->sin_addr)); + continue; + } + a = os_zalloc(sizeof(*a) + alloc_len); if (a == NULL) break; @@ -841,7 +862,7 @@ fail: } -#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) #include #include #include @@ -882,7 +903,7 @@ static int eth_get(const char *device, u8 ea[ETH_ALEN]) } return 0; } -#endif /* __FreeBSD__ */ +#endif /* __FreeBSD__ || __APPLE__ */ /** @@ -890,11 +911,12 @@ static int eth_get(const char *device, u8 ea[ETH_ALEN]) * @net_if: Selected network interface name * @ip_addr: Buffer for returning IP address in network byte order * @ip_addr_text: Buffer for returning a pointer to allocated IP address text + * @netmask: Buffer for returning netmask or %NULL if not needed * @mac: Buffer for returning MAC address * Returns: 0 on success, -1 on failure */ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, - u8 mac[ETH_ALEN]) + struct in_addr *netmask, u8 mac[ETH_ALEN]) { struct ifreq req; int sock = -1; @@ -920,6 +942,19 @@ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, in_addr.s_addr = *ip_addr; os_snprintf(*ip_addr_text, 16, "%s", inet_ntoa(in_addr)); + if (netmask) { + os_memset(&req, 0, sizeof(req)); + os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name)); + if (ioctl(sock, SIOCGIFNETMASK, &req) < 0) { + wpa_printf(MSG_ERROR, + "WPS UPnP: SIOCGIFNETMASK failed: %d (%s)", + errno, strerror(errno)); + goto fail; + } + addr = (struct sockaddr_in *) &req.ifr_addr; + netmask->s_addr = addr->sin_addr.s_addr; + } + #ifdef __linux__ os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name)); if (ioctl(sock, SIOCGIFHWADDR, &req) < 0) { @@ -928,7 +963,7 @@ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, goto fail; } os_memcpy(mac, req.ifr_addr.sa_data, 6); -#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) if (eth_get(net_if, mac) < 0) { wpa_printf(MSG_ERROR, "WPS UPnP: Failed to get MAC address"); goto fail; @@ -1026,11 +1061,15 @@ static int upnp_wps_device_start(struct upnp_wps_device_sm *sm, char *net_if) /* Determine which IP and mac address we're using */ if (get_netif_info(net_if, &sm->ip_addr, &sm->ip_addr_text, - sm->mac_addr)) { + &sm->netmask, sm->mac_addr)) { wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " "for %s. Does it have IP address?", net_if); goto fail; } + wpa_printf(MSG_DEBUG, "WPS UPnP: Local IP address %s netmask %s hwaddr " + MACSTR, + sm->ip_addr_text, inet_ntoa(sm->netmask), + MAC2STR(sm->mac_addr)); /* Listen for incoming TCP connections so that others * can fetch our "xml files" from us. diff --git a/src/wps/wps_upnp_ap.c b/src/wps/wps_upnp_ap.c index cca390530..b6c9478ff 100644 --- a/src/wps/wps_upnp_ap.c +++ b/src/wps/wps_upnp_ap.c @@ -76,8 +76,10 @@ int upnp_er_set_selected_registrar(struct wps_registrar *reg, void upnp_er_remove_notification(struct wps_registrar *reg, struct subscription *s) { + bool was_sel_reg = s->selected_registrar; + s->selected_registrar = 0; eloop_cancel_timeout(upnp_er_set_selected_timeout, s, reg); - if (reg) + if (reg && was_sel_reg) wps_registrar_selected_registrar_changed(reg, 0); } diff --git a/src/wps/wps_upnp_event.c b/src/wps/wps_upnp_event.c index d7e6edcc6..c0d9e41d9 100644 --- a/src/wps/wps_upnp_event.c +++ b/src/wps/wps_upnp_event.c @@ -147,7 +147,8 @@ static struct wpabuf * event_build_message(struct wps_event_ *e) struct wpabuf *buf; char *b; - buf = wpabuf_alloc(1000 + wpabuf_len(e->data)); + buf = wpabuf_alloc(1000 + os_strlen(e->addr->path) + + wpabuf_len(e->data)); if (buf == NULL) return NULL; wpabuf_printf(buf, "NOTIFY %s HTTP/1.1\r\n", e->addr->path); @@ -293,7 +294,7 @@ static int event_send_start(struct subscription *s) buf = event_build_message(e); if (buf == NULL) { - event_retry(e, 0); + event_addr_failure(e); return -1; } @@ -301,7 +302,7 @@ static int event_send_start(struct subscription *s) event_http_cb, e); if (e->http_event == NULL) { wpabuf_free(buf); - event_retry(e, 0); + event_addr_failure(e); return -1; } diff --git a/src/wps/wps_upnp_i.h b/src/wps/wps_upnp_i.h index e87a93232..6ead7b4e9 100644 --- a/src/wps/wps_upnp_i.h +++ b/src/wps/wps_upnp_i.h @@ -128,6 +128,7 @@ struct upnp_wps_device_sm { u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */ char *ip_addr_text; /* IP address of network i.f. we use */ unsigned ip_addr; /* IP address of network i.f. we use (host order) */ + struct in_addr netmask; int multicast_sd; /* send multicast messages over this socket */ int ssdp_sd; /* receive discovery UPD packets on socket */ int ssdp_sd_registered; /* nonzero if we must unregister */ @@ -158,7 +159,7 @@ struct subscription * subscription_find(struct upnp_wps_device_sm *sm, const u8 uuid[UUID_LEN]); void subscr_addr_delete(struct subscr_addr *a); int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, - u8 mac[ETH_ALEN]); + struct in_addr *netmask, u8 mac[ETH_ALEN]); /* wps_upnp_ssdp.c */ void msearchreply_state_machine_stop(struct advertisement_state_machine *a); diff --git a/tests/.gitignore b/tests/.gitignore index 7bbf25cca..f3c8ac941 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,16 +1,3 @@ -test-aes -test-asn1 -test-base64 -test-https -test-https_server -test-list -test-md4 -test-md5 -test-milenage -test-ms_funcs -test-printf -test-rc4 -test-sha1 -test-sha256 -test-x509 -test-x509v3 +test-* +!test-*.[ch] +!test-*.sh diff --git a/tests/Makefile b/tests/Makefile index ee07921a4..2d2343b64 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,9 +1,10 @@ -TESTS=test-base64 test-md4 test-milenage \ +ALL=test-base64 test-md4 test-milenage \ test-rsa-sig-ver \ test-sha1 \ - test-sha256 test-aes test-asn1 test-x509 test-x509v3 test-list test-rc4 + test-https test-https_server \ + test-sha256 test-aes test-x509v3 test-list test-rc4 -all: $(TESTS) +include ../src/build.rules ifdef LIBFUZZER CC=clang @@ -14,18 +15,6 @@ LDFLAGS += -fsanitize=fuzzer,address,signed-integer-overflow,unsigned-integer-ov TEST_FUZZ=y endif -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - ifdef TEST_FUZZ CFLAGS += -DCONFIG_NO_RANDOM_POOL CFLAGS += -DTEST_FUZZ @@ -41,121 +30,59 @@ CFLAGS += -I../src/utils SLIBS = ../src/utils/libutils.a DLIBS = ../src/crypto/libcrypto.a \ - ../src/common/libcommon.a \ - ../src/ap/libap.a \ - ../src/eapol_auth/libeapol_auth.a \ - ../src/eapol_supp/libeapol_supp.a \ - ../src/eap_peer/libeap_peer.a \ - ../src/eap_server/libeap_server.a \ - ../src/eap_common/libeap_common.a \ - ../src/radius/libradius.a \ - ../src/l2_packet/libl2_packet.a \ - ../src/wps/libwps.a \ - ../src/rsn_supp/librsn_supp.a \ ../src/tls/libtls.a +_OBJS_VAR := LLIBS +include ../src/objs.mk +_OBJS_VAR := SLIBS +include ../src/objs.mk +_OBJS_VAR := DLIBS +include ../src/objs.mk + LIBS = $(SLIBS) $(DLIBS) LLIBS = -Wl,--start-group $(DLIBS) -Wl,--end-group $(SLIBS) # glibc < 2.17 needs -lrt for clock_gettime() LLIBS += -lrt -../src/utils/libutils.a: - $(MAKE) -C ../src/utils - -../src/common/libcommon.a: - $(MAKE) -C ../src/common - -../src/crypto/libcrypto.a: - $(MAKE) -C ../src/crypto - -../src/tls/libtls.a: - $(MAKE) -C ../src/tls - -../src/ap/libap.a: - $(MAKE) -C ../src/ap - -../src/radius/libradius.a: - $(MAKE) -C ../src/radius - -../src/l2_packet/libl2_packet.a: - $(MAKE) -C ../src/l2_packet - -../src/wps/libwps.a: - $(MAKE) -C ../src/wps - -../src/eap_peer/libeap_peer.a: - $(MAKE) -C ../src/eap_peer - -../src/eap_server/libeap_server.a: - $(MAKE) -C ../src/eap_server - -../src/eap_common/libeap_common.a: - $(MAKE) -C ../src/eap_common - -../src/eapol_auth/libeapol_auth.a: - $(MAKE) -C ../src/eapol_auth - -../src/eapol_supp/libeapol_supp.a: - $(MAKE) -C ../src/eapol_supp - -../src/rsn_supp/librsn_supp.a: - $(MAKE) -C ../src/rsn_supp - - -test-aes: test-aes.o $(LIBS) +test-aes: $(call BUILDOBJ,test-aes.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-asn1: test-asn1.o $(LIBS) +test-base64: $(call BUILDOBJ,test-base64.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-base64: test-base64.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) - -test-eapol: test-eapol.o $(LIBS) +test-https: $(call BUILDOBJ,test-https.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) -test-https: test-https.o $(LIBS) +test-https_server: $(call BUILDOBJ,test-https_server.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) -test-https_server: test-https_server.o $(LIBS) +test-list: $(call BUILDOBJ,test-list.o) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) + +test-md4: $(call BUILDOBJ,test-md4.o) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) + +test-milenage: $(call BUILDOBJ,test-milenage.o) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) + +test-rc4: $(call BUILDOBJ,test-rc4.o) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) + +test-rsa-sig-ver: $(call BUILDOBJ,test-rsa-sig-ver.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) -test-json: test-json.o $(LIBS) +test-sha1: $(call BUILDOBJ,test-sha1.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-list: test-list.o $(LIBS) +test-sha256: $(call BUILDOBJ,test-sha256.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) -test-md4: test-md4.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) - -test-milenage: test-milenage.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) - -test-rc4: test-rc4.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) - -test-rsa-sig-ver: test-rsa-sig-ver.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) - -test-sha1: test-sha1.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) - -test-sha256: test-sha256.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS) - -test-tls: test-tls.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) - -test-x509: test-x509.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) - -test-x509v3: test-x509v3.o $(LIBS) +test-x509v3: $(call BUILDOBJ,test-x509v3.o) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS) -run-tests: $(TESTS) +run-tests: $(ALL) ./test-aes ./test-list ./test-md4 @@ -166,14 +93,7 @@ run-tests: $(TESTS) @echo @echo All tests completed successfully. -clean: - $(MAKE) -C ../src clean - rm -f $(TESTS) *~ *.o *.d - rm -f test-eapol - rm -f test-https - rm -f test-json - rm -f test-tls +clean: common-clean + rm -f *~ rm -f test_x509v3_nist.out.* rm -f test_x509v3_nist2.out.* - --include $(OBJS:%.o=%.d) diff --git a/tests/ap-mgmt-fuzzer/.gitignore b/tests/ap-mgmt-fuzzer/.gitignore deleted file mode 100644 index 70db3e15d..000000000 --- a/tests/ap-mgmt-fuzzer/.gitignore +++ /dev/null @@ -1 +0,0 @@ -ap-mgmt-fuzzer diff --git a/tests/ap-mgmt-fuzzer/Makefile b/tests/ap-mgmt-fuzzer/Makefile deleted file mode 100644 index 1e06767c4..000000000 --- a/tests/ap-mgmt-fuzzer/Makefile +++ /dev/null @@ -1,82 +0,0 @@ -all: ap-mgmt-fuzzer - -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -SRC=../../src - -CFLAGS += -I$(SRC) -CFLAGS += -I$(SRC)/utils -CFLAGS += -DCONFIG_WNM -CFLAGS += -DCONFIG_INTERWORKING -CFLAGS += -DCONFIG_GAS -CFLAGS += -DCONFIG_HS20 -CFLAGS += -DIEEE8021X_EAPOL -CFLAGS += -DNEED_AP_MLME -CFLAGS += -DCONFIG_AIRTIME_POLICY - -$(SRC)/utils/libutils.a: - $(MAKE) -C $(SRC)/utils - -$(SRC)/common/libcommon.a: - $(MAKE) -C $(SRC)/common - -$(SRC)/crypto/libcrypto.a: - $(MAKE) -C $(SRC)/crypto - -$(SRC)/tls/libtls.a: - $(MAKE) -C $(SRC)/tls - -$(SRC)/wps/libwps.a: - $(MAKE) -C $(SRC)/wps - -$(SRC)/eap_common/libeap_common.a: - $(MAKE) -C $(SRC)/eap_common - -$(SRC)/eap_server/libeap_server.a: - $(MAKE) -C $(SRC)/eap_server - -$(SRC)/l2_packet/libl2_packet.a: - $(MAKE) -C $(SRC)/l2_packet - -$(SRC)/eapol_auth/libeapol_auth.a: - $(MAKE) -C $(SRC)/eapol_auth - -$(SRC)/ap/libap.a: - $(MAKE) -C $(SRC)/ap - -$(SRC)/radius/libradius.a: - $(MAKE) -C $(SRC)/radius - -LIBS += $(SRC)/common/libcommon.a -LIBS += $(SRC)/crypto/libcrypto.a -LIBS += $(SRC)/tls/libtls.a -LIBS += $(SRC)/wps/libwps.a -LIBS += $(SRC)/eap_server/libeap_server.a -LIBS += $(SRC)/eap_common/libeap_common.a -LIBS += $(SRC)/l2_packet/libl2_packet.a -LIBS += $(SRC)/ap/libap.a -LIBS += $(SRC)/eapol_auth/libeapol_auth.a -LIBS += $(SRC)/radius/libradius.a -LIBS += $(SRC)/utils/libutils.a - -ELIBS += $(SRC)/crypto/libcrypto.a -ELIBS += $(SRC)/tls/libtls.a - -ap-mgmt-fuzzer: ap-mgmt-fuzzer.o $(OBJS) $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) - -clean: - $(MAKE) -C $(SRC) clean - rm -f ap-mgmt-fuzzer *~ *.o *.d - --include $(OBJS:%.o=%.d) diff --git a/tests/ap-mgmt-fuzzer/ap-mgmt-fuzzer.c b/tests/ap-mgmt-fuzzer/ap-mgmt-fuzzer.c deleted file mode 100644 index 9d61b6bcc..000000000 --- a/tests/ap-mgmt-fuzzer/ap-mgmt-fuzzer.c +++ /dev/null @@ -1,194 +0,0 @@ -/* - * hostapd - Management frame fuzzer - * Copyright (c) 2015, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "ap/hostapd.h" -#include "ap/hw_features.h" -#include "ap/ieee802_11.h" -#include "ap/sta_info.h" -#include "ap/ap_list.h" - - -const struct wpa_driver_ops *const wpa_drivers[] = -{ - NULL -}; - - -struct arg_ctx { - const char *fname; - struct hostapd_iface iface; - struct hostapd_data hapd; - struct wpa_driver_ops driver; - struct hostapd_config iconf; - struct hostapd_bss_config conf; - int multi_frame; -}; - - -static void test_send_mgmt(void *eloop_data, void *user_ctx) -{ - struct arg_ctx *ctx = eloop_data; - char *data; - size_t len; - struct hostapd_frame_info fi; - - wpa_printf(MSG_INFO, "ap-mgmt-fuzzer: Send '%s'", ctx->fname); - - data = os_readfile(ctx->fname, &len); - if (!data) { - wpa_printf(MSG_ERROR, "Could not read '%s'", ctx->fname); - goto out; - } - - os_memset(&fi, 0, sizeof(fi)); - if (ctx->multi_frame) { - u8 *pos, *end; - - pos = (u8 *) data; - end = pos + len; - - while (end - pos > 2) { - u16 flen; - - flen = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < flen) - break; - wpa_hexdump(MSG_MSGDUMP, "fuzzer - frame", pos, flen); - ieee802_11_mgmt(&ctx->hapd, pos, flen, &fi); - pos += flen; - } - } else { - wpa_hexdump(MSG_MSGDUMP, "fuzzer - WNM", data, len); - ieee802_11_mgmt(&ctx->hapd, (u8 *) data, len, &fi); - } - -out: - os_free(data); - eloop_terminate(); -} - - -static struct hostapd_hw_modes * gen_modes(void) -{ - struct hostapd_hw_modes *mode; - struct hostapd_channel_data *chan; - - mode = os_zalloc(sizeof(struct hostapd_hw_modes)); - if (!mode) - return NULL; - - mode->mode = HOSTAPD_MODE_IEEE80211G; - chan = os_zalloc(sizeof(struct hostapd_channel_data)); - if (!chan) { - os_free(mode); - return NULL; - } - chan->chan = 1; - chan->freq = 2412; - mode->channels = chan; - mode->num_channels = 1; - - mode->rates = os_zalloc(sizeof(int)); - if (!mode->rates) { - os_free(chan); - os_free(mode); - return NULL; - } - mode->rates[0] = 10; - mode->num_rates = 1; - - return mode; -} - - -static int init_hapd(struct arg_ctx *ctx) -{ - struct hostapd_data *hapd = &ctx->hapd; - struct sta_info *sta; - struct hostapd_bss_config *bss; - - hapd->driver = &ctx->driver; - os_memcpy(hapd->own_addr, "\x02\x00\x00\x00\x03\x00", ETH_ALEN); - hapd->iface = &ctx->iface; - hapd->iface->conf = hostapd_config_defaults(); - if (!hapd->iface->conf) - return -1; - hapd->iface->hw_features = gen_modes(); - hapd->iface->num_hw_features = 1; - hapd->iface->current_mode = hapd->iface->hw_features; - hapd->iconf = hapd->iface->conf; - hapd->iconf->hw_mode = HOSTAPD_MODE_IEEE80211G; - hapd->iconf->channel = 1; - bss = hapd->conf = hapd->iconf->bss[0]; - hostapd_config_defaults_bss(hapd->conf); - os_memcpy(bss->ssid.ssid, "test", 4); - bss->ssid.ssid_len = 4; - bss->ssid.ssid_set = 1; - - sta = ap_sta_add(hapd, (u8 *) "\x02\x00\x00\x00\x00\x00"); - if (sta) - sta->flags |= WLAN_STA_ASSOC | WLAN_STA_WMM; - - return 0; -} - - -int main(int argc, char *argv[]) -{ - struct arg_ctx ctx; - int ret = -1; - - if (argc < 2) { - printf("usage: %s [-m] \n", argv[0]); - return -1; - } - - if (os_program_init()) - return -1; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (eloop_init()) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - - os_memset(&ctx, 0, sizeof(ctx)); - if (argc >= 3 && os_strcmp(argv[1], "-m") == 0) { - ctx.multi_frame = 1; - ctx.fname = argv[2]; - } else { - ctx.fname = argv[1]; - } - if (init_hapd(&ctx)) - goto fail; - - eloop_register_timeout(0, 0, test_send_mgmt, &ctx, NULL); - - wpa_printf(MSG_DEBUG, "Starting eloop"); - eloop_run(); - wpa_printf(MSG_DEBUG, "eloop done"); - hostapd_free_stas(&ctx.hapd); - hostapd_free_hw_features(ctx.hapd.iface->hw_features, - ctx.hapd.iface->num_hw_features); - - ret = 0; -fail: - hostapd_config_free(ctx.hapd.iconf); - ap_list_deinit(&ctx.iface); - eloop_destroy(); - os_program_deinit(); - - return ret; -} diff --git a/tests/ap-mgmt-fuzzer/auth.dat b/tests/ap-mgmt-fuzzer/auth.dat deleted file mode 100644 index 0eb36e5aa..000000000 Binary files a/tests/ap-mgmt-fuzzer/auth.dat and /dev/null differ diff --git a/tests/ap-mgmt-fuzzer/multi.dat b/tests/ap-mgmt-fuzzer/multi.dat deleted file mode 100644 index 29d074e0c..000000000 Binary files a/tests/ap-mgmt-fuzzer/multi.dat and /dev/null differ diff --git a/tests/ap-mgmt-fuzzer/probe-req.dat b/tests/ap-mgmt-fuzzer/probe-req.dat deleted file mode 100644 index a5fba77ad..000000000 Binary files a/tests/ap-mgmt-fuzzer/probe-req.dat and /dev/null differ diff --git a/tests/build/build-hostapd-internal.config b/tests/build/build-hostapd-internal.config index 33a2f5bd2..421977eed 100644 --- a/tests/build/build-hostapd-internal.config +++ b/tests/build/build-hostapd-internal.config @@ -43,7 +43,6 @@ CONFIG_VLAN_NETLINK=y CONFIG_LIBNL32=y CONFIG_LIBNL3_ROUTE=y CONFIG_IEEE80211R=y -CONFIG_IEEE80211N=y CONFIG_IEEE80211AC=y CONFIG_WPS=y diff --git a/tests/build/build-hostapd-minimal.config b/tests/build/build-hostapd-minimal.config index bd7e1847c..b62857b79 100644 --- a/tests/build/build-hostapd-minimal.config +++ b/tests/build/build-hostapd-minimal.config @@ -13,5 +13,3 @@ CFLAGS += -DCONFIG_NO_HOSTAPD_LOGGER CONFIG_NO_AES_EXTRAS=y CFLAGS += -Os - -CONFIG_IEEE80211N=y diff --git a/tests/build/build-wpa_supplicant-internal.config b/tests/build/build-wpa_supplicant-internal.config index ba55e8ffe..574fb4b18 100644 --- a/tests/build/build-wpa_supplicant-internal.config +++ b/tests/build/build-wpa_supplicant-internal.config @@ -47,7 +47,6 @@ CONFIG_OCSP=y #CONFIG_CTRL_IFACE_DBUS_INTRO=y CONFIG_IEEE80211R=y -CONFIG_IEEE80211N=y CONFIG_IEEE80211AC=y CONFIG_DEBUG_FILE=y diff --git a/tests/eapol-fuzzer/Makefile b/tests/eapol-fuzzer/Makefile deleted file mode 100644 index b7fff6ee3..000000000 --- a/tests/eapol-fuzzer/Makefile +++ /dev/null @@ -1,64 +0,0 @@ -all: eapol-fuzzer - -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -SRC=../../src - -CFLAGS += -I$(SRC) -CFLAGS += -DIEEE8021X_EAPOL - -$(SRC)/utils/libutils.a: - $(MAKE) -C $(SRC)/utils - -$(SRC)/common/libcommon.a: - $(MAKE) -C $(SRC)/common - -$(SRC)/crypto/libcrypto.a: - $(MAKE) -C $(SRC)/crypto - -$(SRC)/tls/libtls.a: - $(MAKE) -C $(SRC)/tls - -$(SRC)/rsn_supp/librsn_supp.a: - $(MAKE) -C $(SRC)/rsn_supp - -$(SRC)/eapol_supp/libeapol_supp.a: - $(MAKE) -C $(SRC)/eapol_supp - -$(SRC)/eap_peer/libeap_peer.a: - $(MAKE) -C $(SRC)/eap_peer - -$(SRC)/eap_common/libeap_common.a: - $(MAKE) -C $(SRC)/eap_common - -$(SRC)/l2_packet/libl2_packet.a: - $(MAKE) -C $(SRC)/l2_packet - -LIBS += $(SRC)/common/libcommon.a -LIBS += $(SRC)/crypto/libcrypto.a -LIBS += $(SRC)/tls/libtls.a -LIBS += $(SRC)/rsn_supp/librsn_supp.a -LIBS += $(SRC)/eapol_supp/libeapol_supp.a -LIBS += $(SRC)/eap_peer/libeap_peer.a -LIBS += $(SRC)/eap_common/libeap_common.a -LIBS += $(SRC)/l2_packet/libl2_packet.a -LIBS += $(SRC)/utils/libutils.a - -eapol-fuzzer: eapol-fuzzer.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group - -clean: - $(MAKE) -C $(SRC) clean - rm -f eapol-fuzzer *~ *.o *.d - --include $(OBJS:%.o=%.d) diff --git a/tests/eapol-fuzzer/eap-req-identity.dat b/tests/eapol-fuzzer/eap-req-identity.dat deleted file mode 100644 index 768b27754..000000000 Binary files a/tests/eapol-fuzzer/eap-req-identity.dat and /dev/null differ diff --git a/tests/eapol-fuzzer/eap-req-sim.dat b/tests/eapol-fuzzer/eap-req-sim.dat deleted file mode 100644 index eb854aae0..000000000 Binary files a/tests/eapol-fuzzer/eap-req-sim.dat and /dev/null differ diff --git a/tests/eapol-fuzzer/eapol-fuzzer.c b/tests/eapol-fuzzer/eapol-fuzzer.c deleted file mode 100644 index b54614991..000000000 --- a/tests/eapol-fuzzer/eapol-fuzzer.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * wpa_supplicant - EAPOL fuzzer - * Copyright (c) 2015, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "eapol_supp/eapol_supp_sm.h" -#include "rsn_supp/wpa.h" -#include "rsn_supp/wpa_i.h" - - -struct arg_ctx { - const char *fname; - struct wpa_sm *wpa; - struct eapol_sm *eapol; -}; - - -static void test_send_eapol(void *eloop_data, void *user_ctx) -{ - struct arg_ctx *ctx = eloop_data; - char *data; - size_t len; - u8 src[ETH_ALEN] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x01 }; - u8 wpa_ie[200]; - size_t wpa_ie_len; - - wpa_printf(MSG_INFO, "eapol-fuzzer: Send '%s'", ctx->fname); - - data = os_readfile(ctx->fname, &len); - if (!data) { - wpa_printf(MSG_ERROR, "Could not read '%s'", ctx->fname); - goto out; - } - - wpa_hexdump(MSG_MSGDUMP, "fuzzer - EAPOL", data, len); - - eapol_sm_notify_portEnabled(ctx->eapol, TRUE); - - wpa_sm_set_param(ctx->wpa, WPA_PARAM_PROTO, WPA_PROTO_RSN); - wpa_sm_set_param(ctx->wpa, WPA_PARAM_RSN_ENABLED, 1); - wpa_sm_set_param(ctx->wpa, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK); - wpa_sm_set_param(ctx->wpa, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP); - wpa_sm_set_param(ctx->wpa, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); - - wpa_ie_len = sizeof(wpa_ie); - wpa_sm_set_assoc_wpa_ie_default(ctx->wpa, wpa_ie, &wpa_ie_len); - - if (eapol_sm_rx_eapol(ctx->eapol, src, (u8 *) data, len) <= 0) - wpa_sm_rx_eapol(ctx->wpa, src, (u8 *) data, len); - -out: - os_free(data); - eloop_terminate(); -} - - -static void * get_network_ctx(void *arg) -{ - return (void *) 1; -} - - -static void set_state(void *arg, enum wpa_states state) -{ -} - - -static void deauthenticate(void *arg, u16 reason_code) -{ -} - - -static u8 * alloc_eapol(void *arg, u8 type, - const void *data, u16 data_len, - size_t *msg_len, void **data_pos) -{ - struct ieee802_1x_hdr *hdr; - - *msg_len = sizeof(*hdr) + data_len; - hdr = os_malloc(*msg_len); - if (hdr == NULL) - return NULL; - - hdr->version = 2; - hdr->type = type; - hdr->length = host_to_be16(data_len); - - if (data) - os_memcpy(hdr + 1, data, data_len); - else - os_memset(hdr + 1, 0, data_len); - - if (data_pos) - *data_pos = hdr + 1; - - return (u8 *) hdr; -} - - -static int ether_send(void *arg, const u8 *dest, u16 proto, - const u8 *buf, size_t len) -{ - return 0; -} - - -static int get_bssid(void *ctx, u8 *bssid) -{ - return -1; -} - - -static int eapol_send(void *ctx, int type, const u8 *buf, size_t len) -{ - return 0; -} - - -static int init_wpa(struct arg_ctx *arg) -{ - struct wpa_sm_ctx *ctx; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate WPA context."); - return -1; - } - - ctx->ctx = arg; - ctx->msg_ctx = arg; - ctx->get_network_ctx = get_network_ctx; - ctx->set_state = set_state; - ctx->deauthenticate = deauthenticate; - ctx->alloc_eapol = alloc_eapol; - ctx->ether_send = ether_send; - ctx->get_bssid = get_bssid; - - arg->wpa = wpa_sm_init(ctx); - if (!arg->wpa) - return -1; - arg->wpa->pmk_len = PMK_LEN; - return 0; -} - - -static int init_eapol(struct arg_ctx *arg) -{ - struct eapol_ctx *ctx; - - ctx = os_zalloc(sizeof(*ctx)); - if (ctx == NULL) { - wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context."); - return -1; - } - - ctx->ctx = arg; - ctx->msg_ctx = arg; - ctx->eapol_send = eapol_send; - - arg->eapol = eapol_sm_init(ctx); - return arg->eapol ? 0 : -1; -} - - -int main(int argc, char *argv[]) -{ - struct arg_ctx ctx; - int ret = -1; - - if (argc < 2) { - printf("usage: %s \n", argv[0]); - return -1; - } - - if (os_program_init()) - return -1; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (eloop_init()) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - - os_memset(&ctx, 0, sizeof(ctx)); - ctx.fname = argv[1]; - if (init_wpa(&ctx) || init_eapol(&ctx)) - goto fail; - - eloop_register_timeout(0, 0, test_send_eapol, &ctx, NULL); - - wpa_printf(MSG_DEBUG, "Starting eloop"); - eloop_run(); - wpa_printf(MSG_DEBUG, "eloop done"); - - ret = 0; -fail: - if (ctx.wpa) - wpa_sm_deinit(ctx.wpa); - if (ctx.eapol) - eapol_sm_deinit(ctx.eapol); - - eloop_destroy(); - os_program_deinit(); - - return ret; -} diff --git a/tests/eapol-fuzzer/eapol-key-m1.dat b/tests/eapol-fuzzer/eapol-key-m1.dat deleted file mode 100644 index 937721c50..000000000 Binary files a/tests/eapol-fuzzer/eapol-key-m1.dat and /dev/null differ diff --git a/tests/fuzzing/ap-mgmt/.gitignore b/tests/fuzzing/ap-mgmt/.gitignore new file mode 100644 index 000000000..8d79d3c80 --- /dev/null +++ b/tests/fuzzing/ap-mgmt/.gitignore @@ -0,0 +1 @@ +ap-mgmt diff --git a/tests/fuzzing/ap-mgmt/Makefile b/tests/fuzzing/ap-mgmt/Makefile index af5fd4f4d..74b6a02da 100644 --- a/tests/fuzzing/ap-mgmt/Makefile +++ b/tests/fuzzing/ap-mgmt/Makefile @@ -1,4 +1,4 @@ -all: ap-mgmt +ALL=ap-mgmt include ../rules.include CFLAGS += -DCONFIG_WNM @@ -24,11 +24,21 @@ LIBS += $(SRC)/utils/libutils.a ELIBS += $(SRC)/crypto/libcrypto.a ELIBS += $(SRC)/tls/libtls.a -ap-mgmt: ap-mgmt.o $(OBJS) $(LIBS) +OBJS += $(SRC)/drivers/driver_common.o + +OBJS += ap-mgmt.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + +ap-mgmt: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f ap-mgmt *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/asn1/.gitignore b/tests/fuzzing/asn1/.gitignore new file mode 100644 index 000000000..69d0e5c72 --- /dev/null +++ b/tests/fuzzing/asn1/.gitignore @@ -0,0 +1 @@ +asn1 diff --git a/tests/fuzzing/asn1/Makefile b/tests/fuzzing/asn1/Makefile index 428625934..274641a40 100644 --- a/tests/fuzzing/asn1/Makefile +++ b/tests/fuzzing/asn1/Makefile @@ -1,4 +1,4 @@ -all: asn1 +ALL=asn1 include ../rules.include OBJS += $(SRC)/utils/common.o @@ -7,12 +7,17 @@ OBJS += $(SRC)/utils/wpa_debug.o OBJS += $(SRC)/utils/wpabuf.o OBJS += $(SRC)/tls/asn1.o -asn1: asn1.o $(OBJS) $(LIBS) +OBJS += asn1.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +asn1: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: +clean: common-clean $(MAKE) -C $(SRC) clean - $(MAKE) -C $(WPAS_SRC) clean rm -f asn1 *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/dpp-uri/.gitignore b/tests/fuzzing/dpp-uri/.gitignore new file mode 100644 index 000000000..6dd276499 --- /dev/null +++ b/tests/fuzzing/dpp-uri/.gitignore @@ -0,0 +1 @@ +dpp-uri diff --git a/tests/fuzzing/dpp-uri/Makefile b/tests/fuzzing/dpp-uri/Makefile new file mode 100644 index 000000000..1c1bab631 --- /dev/null +++ b/tests/fuzzing/dpp-uri/Makefile @@ -0,0 +1,43 @@ +all: dpp-uri +include ../rules.include + +CFLAGS += -DCONFIG_DPP +CFLAGS += -DCONFIG_DPP2 +CFLAGS += -DCONFIG_SHA256 +CFLAGS += -DCONFIG_SHA384 +CFLAGS += -DCONFIG_SHA512 +CFLAGS += -DCONFIG_ECC +CFLAGS += -DCONFIG_OPENSSL_CMAC + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/utils/libutils.a + +OBJS += $(SRC)/crypto/crypto_openssl.o + +OBJS += $(SRC)/crypto/aes-ctr.o +OBJS += $(SRC)/crypto/aes-siv.o +OBJS += $(SRC)/crypto/sha256-kdf.o +OBJS += $(SRC)/crypto/sha384-kdf.o +OBJS += $(SRC)/crypto/sha512-kdf.o +OBJS += $(SRC)/tls/asn1.o +OBJS += $(SRC)/common/dpp.o +OBJS += $(SRC)/common/dpp_auth.o +OBJS += $(SRC)/common/dpp_backup.o +OBJS += $(SRC)/common/dpp_crypto.o +OBJS += $(SRC)/common/dpp_pkex.o +OBJS += $(SRC)/common/dpp_reconfig.o +OBJS += $(SRC)/common/dpp_tcp.o + +OBJS += dpp-uri.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +dpp-uri: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto + +clean: common-clean + rm -f dpp-uri *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/tests/fuzzing/dpp-uri/corpus/1.dat b/tests/fuzzing/dpp-uri/corpus/1.dat new file mode 100644 index 000000000..b2387e09a --- /dev/null +++ b/tests/fuzzing/dpp-uri/corpus/1.dat @@ -0,0 +1 @@ +DPP:K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;; \ No newline at end of file diff --git a/tests/fuzzing/dpp-uri/corpus/2.dat b/tests/fuzzing/dpp-uri/corpus/2.dat new file mode 100644 index 000000000..ee2ff90dd --- /dev/null +++ b/tests/fuzzing/dpp-uri/corpus/2.dat @@ -0,0 +1 @@ +DPP:C:81/1,115/36;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;; \ No newline at end of file diff --git a/tests/fuzzing/dpp-uri/corpus/3.dat b/tests/fuzzing/dpp-uri/corpus/3.dat new file mode 100644 index 000000000..ce7ad16f3 --- /dev/null +++ b/tests/fuzzing/dpp-uri/corpus/3.dat @@ -0,0 +1 @@ +DPP:I:SN=4774LH2b4044;M:010203040506;C:81/1,115/36;K:MDkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDIgADM2206avxHJaHXgLMkq/24e0rsrfMP9K1Tm8gx+ovP0I=;; \ No newline at end of file diff --git a/tests/fuzzing/dpp-uri/dpp-uri.c b/tests/fuzzing/dpp-uri/dpp-uri.c new file mode 100644 index 000000000..77db5b8bb --- /dev/null +++ b/tests/fuzzing/dpp-uri/dpp-uri.c @@ -0,0 +1,51 @@ +/* + * DPP URI fuzzer + * Copyright (c) 2020, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/dpp.h" +#include "../fuzzer-common.h" + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct dpp_global *dpp; + struct dpp_global_config config; + struct dpp_bootstrap_info *bi; + char *uri; + char buf[1000]; + int ret = -1; + + wpa_fuzzer_set_debug_level(); + + if (os_program_init()) + return 0; + + uri = os_malloc(size + 1); + if (!uri) + goto out; + os_memcpy(uri, data, size); + uri[size] = '\0'; + os_memset(&config, 0, sizeof(config)); + dpp = dpp_global_init(&config); + if (!dpp) + goto out; + + bi = dpp_add_qr_code(dpp, uri); + if (bi && dpp_bootstrap_info(dpp, bi->id, buf, sizeof(buf)) > 0) + wpa_printf(MSG_DEBUG, "DPP: %s", buf); + dpp_global_deinit(dpp); + + ret = 0; +out: + os_free(uri); + os_program_deinit(); + + return ret; +} diff --git a/tests/fuzzing/eap-aka-peer/.gitignore b/tests/fuzzing/eap-aka-peer/.gitignore new file mode 100644 index 000000000..d11f75fe3 --- /dev/null +++ b/tests/fuzzing/eap-aka-peer/.gitignore @@ -0,0 +1 @@ +eap-aka-peer diff --git a/tests/fuzzing/eap-aka-peer/Makefile b/tests/fuzzing/eap-aka-peer/Makefile index d1a4cd372..c964f186d 100644 --- a/tests/fuzzing/eap-aka-peer/Makefile +++ b/tests/fuzzing/eap-aka-peer/Makefile @@ -1,4 +1,4 @@ -all: eap-aka-peer +ALL=eap-aka-peer include ../rules.include CFLAGS += -DIEEE8021X_EAPOL @@ -10,12 +10,17 @@ OBJS += $(SRC)/eap_common/eap_common.o LIBS += $(SRC)/crypto/libcrypto.a LIBS += $(SRC)/utils/libutils.a -eap-aka-peer: eap-aka-peer.o $(OBJS) $(LIBS) +OBJS += eap-aka-peer.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +eap-aka-peer: $(OBJS) $(LIBS) $(Q)$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) @$(E) " LD " $@ -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f eap-aka-peer *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/eap-mschapv2-peer/.gitignore b/tests/fuzzing/eap-mschapv2-peer/.gitignore new file mode 100644 index 000000000..3368b213c --- /dev/null +++ b/tests/fuzzing/eap-mschapv2-peer/.gitignore @@ -0,0 +1 @@ +eap-mschapv2-peer diff --git a/tests/fuzzing/eap-mschapv2-peer/Makefile b/tests/fuzzing/eap-mschapv2-peer/Makefile index 801e0af81..7290e90c6 100644 --- a/tests/fuzzing/eap-mschapv2-peer/Makefile +++ b/tests/fuzzing/eap-mschapv2-peer/Makefile @@ -1,4 +1,4 @@ -all: eap-mschapv2-peer +ALL=eap-mschapv2-peer include ../rules.include CFLAGS += -DIEEE8021X_EAPOL @@ -9,12 +9,17 @@ OBJS += $(SRC)/eap_common/eap_common.o LIBS += $(SRC)/crypto/libcrypto.a LIBS += $(SRC)/utils/libutils.a -eap-mschapv2-peer: eap-mschapv2-peer.o $(OBJS) $(LIBS) +OBJS += eap-mschapv2-peer.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +eap-mschapv2-peer: $(OBJS) $(LIBS) $(Q)$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) @$(E) " LD " $@ -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f eap-mschapv2-peer *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/eap-sim-peer/.gitignore b/tests/fuzzing/eap-sim-peer/.gitignore new file mode 100644 index 000000000..ea94e26e2 --- /dev/null +++ b/tests/fuzzing/eap-sim-peer/.gitignore @@ -0,0 +1 @@ +eap-sim-peer diff --git a/tests/fuzzing/eap-sim-peer/Makefile b/tests/fuzzing/eap-sim-peer/Makefile index 302717e95..9e728e4f4 100644 --- a/tests/fuzzing/eap-sim-peer/Makefile +++ b/tests/fuzzing/eap-sim-peer/Makefile @@ -1,4 +1,4 @@ -all: eap-sim-peer +ALL=eap-sim-peer include ../rules.include CFLAGS += -DIEEE8021X_EAPOL @@ -10,12 +10,17 @@ OBJS += $(SRC)/eap_common/eap_common.o LIBS += $(SRC)/crypto/libcrypto.a LIBS += $(SRC)/utils/libutils.a -eap-sim-peer: eap-sim-peer.o $(OBJS) $(LIBS) +OBJS += eap-sim-peer.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +eap-sim-peer: $(OBJS) $(LIBS) $(Q)$(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) @$(E) " LD " $@ -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f eap-sim-peer *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/eapol-key-auth/.gitignore b/tests/fuzzing/eapol-key-auth/.gitignore new file mode 100644 index 000000000..f693f2cd0 --- /dev/null +++ b/tests/fuzzing/eapol-key-auth/.gitignore @@ -0,0 +1 @@ +eapol-key-auth diff --git a/tests/fuzzing/eapol-key-auth/Makefile b/tests/fuzzing/eapol-key-auth/Makefile index 4dca10264..bd15b91f2 100644 --- a/tests/fuzzing/eapol-key-auth/Makefile +++ b/tests/fuzzing/eapol-key-auth/Makefile @@ -1,4 +1,4 @@ -all: eapol-key-auth +ALL=eapol-key-auth include ../rules.include CFLAGS += -DCONFIG_IEEE80211R_AP @@ -17,11 +17,18 @@ LIBS += $(SRC)/eap_server/libeap_server.a LIBS += $(SRC)/ap/libap.a LIBS += $(SRC)/radius/libradius.a -eapol-key-auth: eapol-key-auth.o $(OBJS) $(LIBS) +OBJS += $(SRC)/drivers/driver_common.o + +OBJS += eapol-key-auth.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +eapol-key-auth: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f eapol-key-auth *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/eapol-key-auth/eapol-key-auth.c b/tests/fuzzing/eapol-key-auth/eapol-key-auth.c index a909114a4..bb46422c6 100644 --- a/tests/fuzzing/eapol-key-auth/eapol-key-auth.c +++ b/tests/fuzzing/eapol-key-auth/eapol-key-auth.c @@ -169,12 +169,13 @@ static void supp_eapol_key_request(void *eloop_data, void *user_ctx) static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, const u8 *addr, int idx, u8 *key, - size_t key_len) + size_t key_len, enum key_flag key_flag) { struct wpa *wpa = ctx; - wpa_printf(MSG_DEBUG, "AUTH: %s (vlan_id=%d alg=%d idx=%d key_len=%d)", - __func__, vlan_id, alg, idx, (int) key_len); + wpa_printf(MSG_DEBUG, + "AUTH: %s (vlan_id=%d alg=%d idx=%d key_len=%d key_flag=0x%x)", + __func__, vlan_id, alg, idx, (int) key_len, key_flag); if (addr) wpa_printf(MSG_DEBUG, "AUTH: addr=" MACSTR, MAC2STR(addr)); diff --git a/tests/fuzzing/eapol-key-supp/.gitignore b/tests/fuzzing/eapol-key-supp/.gitignore new file mode 100644 index 000000000..dcbbbdb02 --- /dev/null +++ b/tests/fuzzing/eapol-key-supp/.gitignore @@ -0,0 +1 @@ +eapol-key-supp diff --git a/tests/fuzzing/eapol-key-supp/Makefile b/tests/fuzzing/eapol-key-supp/Makefile index afe566584..949e2efe9 100644 --- a/tests/fuzzing/eapol-key-supp/Makefile +++ b/tests/fuzzing/eapol-key-supp/Makefile @@ -1,4 +1,4 @@ -all: eapol-key-supp +ALL=eapol-key-supp include ../rules.include CFLAGS += -DCONFIG_IEEE80211R_AP @@ -15,11 +15,16 @@ LIBS += $(SRC)/eap_common/libeap_common.a LIBS += $(SRC)/l2_packet/libl2_packet.a LIBS += $(SRC)/utils/libutils.a -eapol-key-supp: eapol-key-supp.o $(OBJS) $(LIBS) +OBJS += eapol-key-supp.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +eapol-key-supp: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f eapol-key-supp *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/eapol-key-supp/eapol-key-supp.c b/tests/fuzzing/eapol-key-supp/eapol-key-supp.c index eb565d7cf..487c889d7 100644 --- a/tests/fuzzing/eapol-key-supp/eapol-key-supp.c +++ b/tests/fuzzing/eapol-key-supp/eapol-key-supp.c @@ -175,11 +175,11 @@ static int supp_get_beacon_ie(void *ctx) static int supp_set_key(void *ctx, enum wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) + const u8 *key, size_t key_len, enum key_flag key_flag) { wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d " - "set_tx=%d)", - __func__, alg, MAC2STR(addr), key_idx, set_tx); + "set_tx=%d key_flag=0x%x)", + __func__, alg, MAC2STR(addr), key_idx, set_tx, key_flag); wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len); wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len); return 0; diff --git a/tests/fuzzing/eapol-supp/.gitignore b/tests/fuzzing/eapol-supp/.gitignore new file mode 100644 index 000000000..e370093d8 --- /dev/null +++ b/tests/fuzzing/eapol-supp/.gitignore @@ -0,0 +1 @@ +eapol-supp diff --git a/tests/fuzzing/eapol-supp/Makefile b/tests/fuzzing/eapol-supp/Makefile index 41a505d37..ea32346b2 100644 --- a/tests/fuzzing/eapol-supp/Makefile +++ b/tests/fuzzing/eapol-supp/Makefile @@ -1,4 +1,4 @@ -all: eapol-supp +ALL=eapol-supp include ../rules.include CFLAGS += -DIEEE8021X_EAPOL @@ -13,11 +13,16 @@ LIBS += $(SRC)/eap_common/libeap_common.a LIBS += $(SRC)/l2_packet/libl2_packet.a LIBS += $(SRC)/utils/libutils.a -eapol-supp: eapol-supp.o $(OBJS) $(LIBS) +OBJS += eapol-supp.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +eapol-supp: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ -Wl,--start-group $(LIBS) -Wl,--end-group -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f eapol-supp *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/eapol-supp/eapol-supp.c b/tests/fuzzing/eapol-supp/eapol-supp.c index 6f0b8cba8..94e0147ad 100644 --- a/tests/fuzzing/eapol-supp/eapol-supp.c +++ b/tests/fuzzing/eapol-supp/eapol-supp.c @@ -33,7 +33,7 @@ static void test_send_eapol(void *eloop_data, void *user_ctx) wpa_hexdump(MSG_MSGDUMP, "fuzzer - EAPOL", ctx->data, ctx->data_len); - eapol_sm_notify_portEnabled(ctx->eapol, TRUE); + eapol_sm_notify_portEnabled(ctx->eapol, true); wpa_sm_set_param(ctx->wpa, WPA_PARAM_PROTO, WPA_PROTO_RSN); wpa_sm_set_param(ctx->wpa, WPA_PARAM_RSN_ENABLED, 1); diff --git a/tests/fuzzing/json/.gitignore b/tests/fuzzing/json/.gitignore new file mode 100644 index 000000000..3c840093b --- /dev/null +++ b/tests/fuzzing/json/.gitignore @@ -0,0 +1 @@ +json diff --git a/tests/fuzzing/json/Makefile b/tests/fuzzing/json/Makefile index ffa0c5a99..9dd51a5f2 100644 --- a/tests/fuzzing/json/Makefile +++ b/tests/fuzzing/json/Makefile @@ -1,4 +1,4 @@ -all: json +ALL=json include ../rules.include OBJS += $(SRC)/utils/base64.o @@ -8,12 +8,16 @@ OBJS += $(SRC)/utils/os_unix.o OBJS += $(SRC)/utils/wpa_debug.o OBJS += $(SRC)/utils/wpabuf.o -json: json.o $(OBJS) $(LIBS) +OBJS += json.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +json: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: - $(MAKE) -C $(SRC) clean - $(MAKE) -C $(WPAS_SRC) clean +clean: common-clean rm -f json *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/p2p/.gitignore b/tests/fuzzing/p2p/.gitignore new file mode 100644 index 000000000..8bea15da4 --- /dev/null +++ b/tests/fuzzing/p2p/.gitignore @@ -0,0 +1 @@ +p2p diff --git a/tests/fuzzing/p2p/Makefile b/tests/fuzzing/p2p/Makefile index c088e32d0..acac9d38f 100644 --- a/tests/fuzzing/p2p/Makefile +++ b/tests/fuzzing/p2p/Makefile @@ -1,4 +1,4 @@ -all: p2p +ALL=p2p include ../rules.include LIBS += $(SRC)/utils/libutils.a @@ -8,11 +8,16 @@ LIBS += $(SRC)/p2p/libp2p.a LIBS += $(SRC)/tls/libtls.a LIBS += $(SRC)/wps/libwps.a -p2p: p2p.o $(OBJS) $(LIBS) +OBJS += p2p.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +p2p: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) -clean: - $(MAKE) -C $(SRC) clean +clean: common-clean rm -f p2p *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/rules.include b/tests/fuzzing/rules.include index a3b0ee0aa..e2cf577af 100644 --- a/tests/fuzzing/rules.include +++ b/tests/fuzzing/rules.include @@ -1,3 +1,6 @@ +FUZZ_RULES := $(lastword $(MAKEFILE_LIST)) +include $(dir $(FUZZ_RULES))../../src/build.rules + FUZZ_CFLAGS = ifdef LIBFUZZER @@ -18,76 +21,11 @@ CFLAGS += -DTEST_LIBFUZZER LDFLAGS += $(FUZZ_FLAGS) endif -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - WPAS_SRC=../../../wpa_supplicant SRC=../../../src CFLAGS += -I$(SRC) -I$(SRC)/utils -I$(WPAS_SRC) OBJS += ../fuzzer-common.o -$(SRC)/ap/libap.a: - $(MAKE) -C $(SRC)/ap TEST_FUZZ=y - -$(SRC)/common/libcommon.a: - $(MAKE) -C $(SRC)/common - -$(SRC)/crypto/libcrypto.a: - $(MAKE) -C $(SRC)/crypto TEST_FUZZ=y - -$(SRC)/eapol_auth/libeapol_auth.a: - $(MAKE) -C $(SRC)/eapol_auth - -$(SRC)/eapol_supp/libeapol_supp.a: - $(MAKE) -C $(SRC)/eapol_supp - -$(SRC)/eap_common/libeap_common.a: - $(MAKE) -C $(SRC)/eap_common - -$(SRC)/eap_peer/libeap_peer.a: - $(MAKE) -C $(SRC)/eap_peer - -$(SRC)/eap_server/libeap_server.a: - $(MAKE) -C $(SRC)/eap_server - -$(SRC)/l2_packet/libl2_packet.a: - $(MAKE) -C $(SRC)/l2_packet - -$(SRC)/p2p/libp2p.a: - $(MAKE) -C $(SRC)/p2p - -$(SRC)/radius/libradius.a: - $(MAKE) -C $(SRC)/radius - -$(SRC)/rsn_supp/librsn_supp.a: - $(MAKE) -C $(SRC)/rsn_supp TEST_FUZZ=y - -$(SRC)/tls/libtls.a: - $(MAKE) -C $(SRC)/tls TEST_FUZZ=y - -$(SRC)/utils/libutils.a: - $(MAKE) -C $(SRC)/utils TEST_FUZZ=y - -$(SRC)/wps/libwps.a: - $(MAKE) -C $(SRC)/wps - -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif -ifeq ($(QUIET), 1) -Q=@ -E=true -endif - -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< +# for the lib builds +export TEST_FUZZ=y diff --git a/tests/fuzzing/sae/.gitignore b/tests/fuzzing/sae/.gitignore new file mode 100644 index 000000000..1bb959165 --- /dev/null +++ b/tests/fuzzing/sae/.gitignore @@ -0,0 +1 @@ +sae diff --git a/tests/fuzzing/sae/Makefile b/tests/fuzzing/sae/Makefile new file mode 100644 index 000000000..ee4b0c0b6 --- /dev/null +++ b/tests/fuzzing/sae/Makefile @@ -0,0 +1,28 @@ +ALL=sae +include ../rules.include + +CFLAGS += -DCONFIG_SHA256 +CFLAGS += -DCONFIG_ECC + +LIBS += $(SRC)/common/libcommon.a +LIBS += $(SRC)/utils/libutils.a + +OBJS += $(SRC)/crypto/crypto_openssl.o +OBJS += $(SRC)/crypto/dh_groups.o +OBJS += $(SRC)/crypto/sha256-prf.o +OBJS += $(SRC)/crypto/sha256-kdf.o +OBJS += $(SRC)/common/dragonfly.o + +OBJS += sae.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +sae: $(OBJS) $(LIBS) + $(LDO) $(LDFLAGS) -o $@ $^ -lcrypto + +clean: common-clean + rm -f sae *~ *.o *.d ../*~ ../*.o ../*.d diff --git a/tests/fuzzing/sae/corpus/sae-commit-h2e-rejected-groups.dat b/tests/fuzzing/sae/corpus/sae-commit-h2e-rejected-groups.dat new file mode 100644 index 000000000..cd129a474 Binary files /dev/null and b/tests/fuzzing/sae/corpus/sae-commit-h2e-rejected-groups.dat differ diff --git a/tests/fuzzing/sae/corpus/sae-commit-h2e-token.dat b/tests/fuzzing/sae/corpus/sae-commit-h2e-token.dat new file mode 100644 index 000000000..b2886c70d Binary files /dev/null and b/tests/fuzzing/sae/corpus/sae-commit-h2e-token.dat differ diff --git a/tests/fuzzing/sae/corpus/sae-commit-pw-id.dat b/tests/fuzzing/sae/corpus/sae-commit-pw-id.dat new file mode 100644 index 000000000..5ca903ed2 Binary files /dev/null and b/tests/fuzzing/sae/corpus/sae-commit-pw-id.dat differ diff --git a/tests/fuzzing/sae/corpus/sae-commit-token.dat b/tests/fuzzing/sae/corpus/sae-commit-token.dat new file mode 100644 index 000000000..b25cc49f8 Binary files /dev/null and b/tests/fuzzing/sae/corpus/sae-commit-token.dat differ diff --git a/tests/fuzzing/sae/corpus/sae-commit-valid.dat b/tests/fuzzing/sae/corpus/sae-commit-valid.dat new file mode 100644 index 000000000..eadfa4993 Binary files /dev/null and b/tests/fuzzing/sae/corpus/sae-commit-valid.dat differ diff --git a/tests/fuzzing/sae/sae.c b/tests/fuzzing/sae/sae.c new file mode 100644 index 000000000..8819a4abb --- /dev/null +++ b/tests/fuzzing/sae/sae.c @@ -0,0 +1,39 @@ +/* + * SAE fuzzer + * Copyright (c) 2020, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/sae.h" +#include "../fuzzer-common.h" + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + struct sae_data sae; + u16 res; + const u8 *token = NULL; + size_t token_len = 0; + int groups[] = { 19, 0 }; + + wpa_fuzzer_set_debug_level(); + + if (os_program_init()) + return 0; + + os_memset(&sae, 0, sizeof(sae)); + res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 0); + wpa_printf(MSG_DEBUG, "sae_parse_commit(0): %u", res); + sae_clear_data(&sae); + res = sae_parse_commit(&sae, data, size, &token, &token_len, groups, 1); + wpa_printf(MSG_DEBUG, "sae_parse_commit(1): %u", res); + sae_clear_data(&sae); + os_program_deinit(); + + return 0; +} diff --git a/tests/fuzzing/tls-client/.gitignore b/tests/fuzzing/tls-client/.gitignore new file mode 100644 index 000000000..b41f93681 --- /dev/null +++ b/tests/fuzzing/tls-client/.gitignore @@ -0,0 +1 @@ +tls-client diff --git a/tests/fuzzing/tls-client/Makefile b/tests/fuzzing/tls-client/Makefile index e91125ec1..84cfa0431 100644 --- a/tests/fuzzing/tls-client/Makefile +++ b/tests/fuzzing/tls-client/Makefile @@ -1,4 +1,4 @@ -all: tls-client +ALL=tls-client include ../rules.include LIBS += $(SRC)/common/libcommon.a @@ -14,12 +14,19 @@ LIBS += $(SRC)/utils/libutils.a ELIBS += $(SRC)/crypto/libcrypto.a ELIBS += $(SRC)/tls/libtls.a -tls-client: tls-client.o $(OBJS) $(LIBS) +OBJS += tls-client.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + +tls-client: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: - $(MAKE) -C $(SRC) clean - $(MAKE) -C $(WPAS_SRC) clean +clean: common-clean rm -f tls-client *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/tls-server/.gitignore b/tests/fuzzing/tls-server/.gitignore new file mode 100644 index 000000000..341256f57 --- /dev/null +++ b/tests/fuzzing/tls-server/.gitignore @@ -0,0 +1 @@ +tls-server diff --git a/tests/fuzzing/tls-server/Makefile b/tests/fuzzing/tls-server/Makefile index dbb53e5a4..8e2400310 100644 --- a/tests/fuzzing/tls-server/Makefile +++ b/tests/fuzzing/tls-server/Makefile @@ -1,4 +1,4 @@ -all: tls-server +ALL=tls-server include ../rules.include LIBS += $(SRC)/common/libcommon.a @@ -14,12 +14,19 @@ LIBS += $(SRC)/utils/libutils.a ELIBS += $(SRC)/crypto/libcrypto.a ELIBS += $(SRC)/tls/libtls.a -tls-server: tls-server.o $(OBJS) $(LIBS) +OBJS += tls-server.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + +tls-server: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: - $(MAKE) -C $(SRC) clean - $(MAKE) -C $(WPAS_SRC) clean +clean: common-clean rm -f tls-server *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/wnm/.gitignore b/tests/fuzzing/wnm/.gitignore new file mode 100644 index 000000000..0e1d383dc --- /dev/null +++ b/tests/fuzzing/wnm/.gitignore @@ -0,0 +1 @@ +wnm diff --git a/tests/fuzzing/wnm/Makefile b/tests/fuzzing/wnm/Makefile index 2c7e2f776..73eab5387 100644 --- a/tests/fuzzing/wnm/Makefile +++ b/tests/fuzzing/wnm/Makefile @@ -1,4 +1,4 @@ -all: wnm +ALL=wnm include ../rules.include CFLAGS += -DCONFIG_WNM @@ -32,6 +32,7 @@ OBJS += $(WPAS_SRC)/interworking.o OBJS += $(WPAS_SRC)/notify.o OBJS += $(WPAS_SRC)/offchannel.o OBJS += $(WPAS_SRC)/op_classes.o +OBJS += $(WPAS_SRC)/robust_av.o OBJS += $(WPAS_SRC)/rrm.o OBJS += $(WPAS_SRC)/scan.o OBJS += $(WPAS_SRC)/wmm_ac.o @@ -41,12 +42,19 @@ OBJS += $(WPAS_SRC)/wpas_glue.o OBJS += $(SRC)/drivers/driver_common.o OBJS += $(SRC)/drivers/drivers.o -wnm: wnm.o $(OBJS) $(LIBS) +OBJS += wnm.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + +wnm: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: - $(MAKE) -C $(SRC) clean - $(MAKE) -C $(WPAS_SRC) clean +clean: common-clean rm -f wnm *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/fuzzing/x509/.gitignore b/tests/fuzzing/x509/.gitignore new file mode 100644 index 000000000..490a5d71f --- /dev/null +++ b/tests/fuzzing/x509/.gitignore @@ -0,0 +1 @@ +x509 diff --git a/tests/fuzzing/x509/Makefile b/tests/fuzzing/x509/Makefile index d7f751a9d..306473c3d 100644 --- a/tests/fuzzing/x509/Makefile +++ b/tests/fuzzing/x509/Makefile @@ -1,4 +1,4 @@ -all: x509 +ALL=x509 include ../rules.include LIBS += $(SRC)/common/libcommon.a @@ -9,12 +9,19 @@ LIBS += $(SRC)/utils/libutils.a ELIBS += $(SRC)/crypto/libcrypto.a ELIBS += $(SRC)/tls/libtls.a -x509: x509.o $(OBJS) $(LIBS) +OBJS += x509.o + +_OBJS_VAR := OBJS +include ../../../src/objs.mk + +_OBJS_VAR := LIBS +include ../../../src/objs.mk + +_OBJS_VAR := ELIBS +include ../../../src/objs.mk + +x509: $(OBJS) $(LIBS) $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) -clean: - $(MAKE) -C $(SRC) clean - $(MAKE) -C $(WPAS_SRC) clean +clean: common-clean rm -f x509 *~ *.o *.d ../*~ ../*.o ../*.d - --include $(OBJS:%.o=%.d) diff --git a/tests/hwsim/auth_serv/ca-and-crl-expired.pem b/tests/hwsim/auth_serv/ca-and-crl-expired.pem index 8c65fbe7e..dc7bf98c1 100644 --- a/tests/hwsim/auth_serv/ca-and-crl-expired.pem +++ b/tests/hwsim/auth_serv/ca-and-crl-expired.pem @@ -1,63 +1,90 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162817 (0xd8d3e3a6cbe3ccc1) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + 42:97:6c:30:8e:79:fc:7b:6a:e3:ef:9d:18:a4:74:9d:8b:5f:57:53 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Validity - Not Before: Jun 29 16:41:22 2013 GMT - Not After : Jun 27 16:41:22 2023 GMT - Subject: C=FI, O=w1.fi, CN=Root CA + Not Before: May 2 19:49:48 2020 GMT + Not After : Apr 30 19:49:48 2030 GMT + Subject: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:be:1e:86:e4:79:03:c1:d1:94:d5:d4:b3:b1:28: - 90:76:fb:b8:a6:cd:6d:1c:d1:48:f4:08:9a:67:ff: - f9:a6:54:b1:19:29:df:29:1b:cd:f1:6f:66:01:e7: - db:79:ce:c0:39:2a:25:13:26:94:0c:2c:7b:5a:2c: - 81:0f:94:ee:51:d0:75:e6:46:db:17:46:a7:15:8b: - 0e:57:0f:b0:54:76:63:12:ca:86:18:bc:1a:c3:16: - c0:70:09:d6:6b:43:39:b8:98:29:46:ac:cb:6a:ad: - 38:88:3b:07:dc:81:cd:3a:f6:1d:f6:2f:ef:1d:d7: - ae:8a:b6:d1:e7:b3:15:02:b9 + 00:bc:f4:ee:44:62:7f:62:4f:a1:81:46:ba:c4:aa: + 1e:fd:4e:d0:ed:f1:47:cb:25:5b:66:7a:86:39:91: + ca:b5:61:a7:7e:2f:3c:63:7d:39:b8:1a:9e:cb:6d: + 32:32:91:de:49:49:84:da:15:be:2b:dd:c6:bc:1f: + dc:6e:c0:2d:77:f2:d0:7b:2c:40:19:07:60:55:b0: + ff:7c:51:ef:38:d1:f0:2a:da:a8:cc:ea:d6:54:a4: + ef:be:17:44:1a:9e:33:70:57:a4:f3:06:ac:3d:ee: + 4b:2d:e5:46:25:2d:33:09:f6:49:a8:02:31:a4:65: + 9b:32:0a:67:f5:02:e1:3b:47:a6:ae:e4:f6:85:eb: + 5d:3e:02:66:dd:11:98:ac:34:72:c2:8f:25:55:4a: + 6a:ea:e8:82:2f:bd:7f:78:31:a4:5a:d7:32:bb:64: + 48:46:23:ef:c8:c9:e2:84:00:56:72:e8:4b:54:95: + 62:3a:5a:11:79:ee:40:43:9e:16:2c:cc:e6:45:f4: + bb:82:28:c2:83:35:2c:55:36:99:59:11:b1:15:d0: + 03:c1:a5:37:e1:1f:bb:43:c7:b4:b9:33:de:14:d7: + 7c:99:45:0f:c1:06:fe:b6:25:10:59:b7:72:76:7f: + 91:4b:ea:d1:b9:6a:6a:ed:dd:1b:a9:0e:a7:29:48: + b7:4d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 1a:cf:77:60:44:43:c4:55:0e:99:e0:89:aa:b9:d3:7b:32:b7: - 5c:9c:7c:ca:fe:8c:d4:94:c6:5e:f3:83:19:5f:29:59:68:a4: - 4f:dc:04:2e:b8:71:c0:6d:3b:ae:01:e4:b9:88:99:cc:ce:82: - be:6a:28:c2:ac:6a:94:c6:87:90:ed:85:3c:10:71:c5:ff:3c: - 70:64:e2:41:62:31:ea:86:7b:11:8c:93:ea:c6:f3:f3:4e:f9: - d4:f2:81:90:d7:f4:fa:a1:91:6e:d4:dd:15:3e:26:3b:ac:1e: - c3:c2:1f:ed:bb:34:bf:cb:b2:67:c6:c6:51:e8:51:22:b4:f3: - 92:e8 + Signature Algorithm: sha256WithRSAEncryption + 41:f9:c3:a3:77:11:92:55:e7:4b:4a:32:6a:31:d9:51:cf:06: + a5:39:ea:30:98:b8:8d:4f:24:c5:34:fd:c6:98:10:59:32:7e: + 57:f5:8f:ba:67:c9:fc:44:68:b3:7c:f1:af:3a:5f:0d:8f:a1: + fe:41:21:0e:e9:08:a3:63:49:66:34:4a:cd:ce:66:74:47:30: + f7:dc:82:99:21:56:82:ff:2d:12:90:7d:7a:64:22:a0:ed:fa: + 62:d9:5a:d3:97:96:0c:04:a7:47:88:da:53:b6:33:15:15:f9: + da:ee:ac:25:e9:07:02:89:bc:73:a2:c6:27:6f:1f:bd:73:b8: + 8e:f7:94:54:57:a7:8b:5b:9a:24:aa:86:d4:04:5c:8c:cb:28: + a2:45:f9:34:f0:01:20:bb:06:e8:41:14:d2:d7:ca:e8:bf:4e: + 16:72:22:a0:0c:86:ca:73:23:09:ae:71:f1:52:0c:db:b2:8a: + 4d:94:a5:fa:15:81:5b:a2:95:62:50:a1:d6:64:fe:4c:0c:60: + 8d:9b:0f:b8:41:ac:cb:31:c2:17:6c:7b:61:13:16:9a:db:64: + fc:5f:47:84:3d:d2:2e:db:0b:9e:b6:1e:85:04:c1:e5:c0:b2: + 6d:8f:f2:99:00:3a:1a:ab:02:cf:45:7a:26:c1:b0:1f:c6:b0: + d0:4d:f7:52 -----BEGIN CERTIFICATE----- -MIICLDCCAZWgAwIBAgIJANjT46bL48zBMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xMzA2 -MjkxNjQxMjJaFw0yMzA2MjcxNjQxMjJaMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEAvh6G5HkDwdGU1dSzsSiQdvu4ps1tHNFI9AiaZ//5plSxGSnfKRvN8W9m -Aefbec7AOSolEyaUDCx7WiyBD5TuUdB15kbbF0anFYsOVw+wVHZjEsqGGLwawxbA -cAnWa0M5uJgpRqzLaq04iDsH3IHNOvYd9i/vHdeuirbR57MVArkCAwEAAaNQME4w -HQYDVR0OBBYEFLiS3v2KGLMww59V8zNdtMgpikEUMB8GA1UdIwQYMBaAFLiS3v2K -GLMww59V8zNdtMgpikEUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA -Gs93YERDxFUOmeCJqrnTezK3XJx8yv6M1JTGXvODGV8pWWikT9wELrhxwG07rgHk -uYiZzM6CvmoowqxqlMaHkO2FPBBxxf88cGTiQWIx6oZ7EYyT6sbz80751PKBkNf0 -+qGRbtTdFT4mO6wew8If7bs0v8uyZ8bGUehRIrTzkug= +MIIDYDCCAkigAwIBAgIUQpdsMI55/Htq4++dGKR0nYtfV1MwDQYJKoZIhvcNAQEL +BQAwQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoMBXcx +LmZpMRAwDgYDVQQDDAdSb290IENBMB4XDTIwMDUwMjE5NDk0OFoXDTMwMDQzMDE5 +NDk0OFowQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoM +BXcxLmZpMRAwDgYDVQQDDAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAvPTuRGJ/Yk+hgUa6xKoe/U7Q7fFHyyVbZnqGOZHKtWGnfi88Y305 +uBqey20yMpHeSUmE2hW+K93GvB/cbsAtd/LQeyxAGQdgVbD/fFHvONHwKtqozOrW +VKTvvhdEGp4zcFek8wasPe5LLeVGJS0zCfZJqAIxpGWbMgpn9QLhO0emruT2hetd +PgJm3RGYrDRywo8lVUpq6uiCL71/eDGkWtcyu2RIRiPvyMnihABWcuhLVJViOloR +ee5AQ54WLMzmRfS7gijCgzUsVTaZWRGxFdADwaU34R+7Q8e0uTPeFNd8mUUPwQb+ +tiUQWbdydn+RS+rRuWpq7d0bqQ6nKUi3TQIDAQABo1AwTjAdBgNVHQ4EFgQUpP25 +ORuBs6rriB3Ugam1EXDMp+EwHwYDVR0jBBgwFoAUpP25ORuBs6rriB3Ugam1EXDM +p+EwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQfnDo3cRklXnS0oy +ajHZUc8GpTnqMJi4jU8kxTT9xpgQWTJ+V/WPumfJ/ERos3zxrzpfDY+h/kEhDukI +o2NJZjRKzc5mdEcw99yCmSFWgv8tEpB9emQioO36Ytla05eWDASnR4jaU7YzFRX5 +2u6sJekHAom8c6LGJ28fvXO4jveUVFeni1uaJKqG1ARcjMsookX5NPABILsG6EEU +0tfK6L9OFnIioAyGynMjCa5x8VIM27KKTZSl+hWBW6KVYlCh1mT+TAxgjZsPuEGs +yzHCF2x7YRMWmttk/F9HhD3SLtsLnrYehQTB5cCybY/ymQA6GqsCz0V6JsGwH8aw +0E33Ug== -----END CERTIFICATE----- -----BEGIN X509 CRL----- -MIIBBjBxAgEBMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQRcNMTkwODExMDc1ODM0WhcNMTkwODEx -MDg1ODM0WqAOMAwwCgYDVR0UBAMCARIwDQYJKoZIhvcNAQELBQADgYEAOTijPynY -c8ACRpu0+uIRjI6xIXDZqRubRvp/qrQVWtWHJWP2d6CbtaQVhZIfYFJLrLVfKyJv -WyzkLNdLw/l6rbVN5ctb+fByjjV6H99IExeYiGIuoXN++m8CTUqt77cim0TA1WkQ -bEwEY9aIN8zsXqioLvg5OBlWUfxnKmi2sQI= +MIIBmjCBgwIBATANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJGSTEQMA4GA1UE +BwwHVHV1c3VsYTEOMAwGA1UECgwFdzEuZmkxEDAOBgNVBAMMB1Jvb3QgQ0EXDTIw +MDUwMjE1MDYwN1oXDTIwMDUwMjE2MDYwN1qgDjAMMAoGA1UdFAQDAgEHMA0GCSqG +SIb3DQEBCwUAA4IBAQBpgpd1hBcONRssjbezGJDE4WC4gSpW9ufS7OgzWXky9AIq +ea5engK/LCTn0GZVwRvuDkHn0H/dS68pFoQSnrbyS7Alz8oJf/T41vKgG8sxkfra +tvezWu7x8Kaz6QQuoxoGERZhudyNoPTUYKQpqnUjlz0088j+HqBuy6uSQsDlOXI7 +dxbXU25JvJlebJEeMxd/R+8SkVmXN6OR9RO+kkm0BIjhuUc2BOToxZhPj4PS7If0 +RO5S7WSgZOyg1d0yq/EMNvfm8gT5RioC0rceBlt5FIbjg+xn4VExyg73CbeMjC8O +CRblHL1o5GK7zHTyKFZ/KUdKIc9sdB/Eehcyvo+Z -----END X509 CRL----- diff --git a/tests/hwsim/auth_serv/ca-and-crl.pem b/tests/hwsim/auth_serv/ca-and-crl.pem index ba79339e6..4e8367884 100644 --- a/tests/hwsim/auth_serv/ca-and-crl.pem +++ b/tests/hwsim/auth_serv/ca-and-crl.pem @@ -1,64 +1,90 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162817 (0xd8d3e3a6cbe3ccc1) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + 42:97:6c:30:8e:79:fc:7b:6a:e3:ef:9d:18:a4:74:9d:8b:5f:57:53 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Validity - Not Before: Jun 29 16:41:22 2013 GMT - Not After : Jun 27 16:41:22 2023 GMT - Subject: C=FI, O=w1.fi, CN=Root CA + Not Before: May 2 19:49:48 2020 GMT + Not After : Apr 30 19:49:48 2030 GMT + Subject: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:be:1e:86:e4:79:03:c1:d1:94:d5:d4:b3:b1:28: - 90:76:fb:b8:a6:cd:6d:1c:d1:48:f4:08:9a:67:ff: - f9:a6:54:b1:19:29:df:29:1b:cd:f1:6f:66:01:e7: - db:79:ce:c0:39:2a:25:13:26:94:0c:2c:7b:5a:2c: - 81:0f:94:ee:51:d0:75:e6:46:db:17:46:a7:15:8b: - 0e:57:0f:b0:54:76:63:12:ca:86:18:bc:1a:c3:16: - c0:70:09:d6:6b:43:39:b8:98:29:46:ac:cb:6a:ad: - 38:88:3b:07:dc:81:cd:3a:f6:1d:f6:2f:ef:1d:d7: - ae:8a:b6:d1:e7:b3:15:02:b9 + 00:bc:f4:ee:44:62:7f:62:4f:a1:81:46:ba:c4:aa: + 1e:fd:4e:d0:ed:f1:47:cb:25:5b:66:7a:86:39:91: + ca:b5:61:a7:7e:2f:3c:63:7d:39:b8:1a:9e:cb:6d: + 32:32:91:de:49:49:84:da:15:be:2b:dd:c6:bc:1f: + dc:6e:c0:2d:77:f2:d0:7b:2c:40:19:07:60:55:b0: + ff:7c:51:ef:38:d1:f0:2a:da:a8:cc:ea:d6:54:a4: + ef:be:17:44:1a:9e:33:70:57:a4:f3:06:ac:3d:ee: + 4b:2d:e5:46:25:2d:33:09:f6:49:a8:02:31:a4:65: + 9b:32:0a:67:f5:02:e1:3b:47:a6:ae:e4:f6:85:eb: + 5d:3e:02:66:dd:11:98:ac:34:72:c2:8f:25:55:4a: + 6a:ea:e8:82:2f:bd:7f:78:31:a4:5a:d7:32:bb:64: + 48:46:23:ef:c8:c9:e2:84:00:56:72:e8:4b:54:95: + 62:3a:5a:11:79:ee:40:43:9e:16:2c:cc:e6:45:f4: + bb:82:28:c2:83:35:2c:55:36:99:59:11:b1:15:d0: + 03:c1:a5:37:e1:1f:bb:43:c7:b4:b9:33:de:14:d7: + 7c:99:45:0f:c1:06:fe:b6:25:10:59:b7:72:76:7f: + 91:4b:ea:d1:b9:6a:6a:ed:dd:1b:a9:0e:a7:29:48: + b7:4d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 1a:cf:77:60:44:43:c4:55:0e:99:e0:89:aa:b9:d3:7b:32:b7: - 5c:9c:7c:ca:fe:8c:d4:94:c6:5e:f3:83:19:5f:29:59:68:a4: - 4f:dc:04:2e:b8:71:c0:6d:3b:ae:01:e4:b9:88:99:cc:ce:82: - be:6a:28:c2:ac:6a:94:c6:87:90:ed:85:3c:10:71:c5:ff:3c: - 70:64:e2:41:62:31:ea:86:7b:11:8c:93:ea:c6:f3:f3:4e:f9: - d4:f2:81:90:d7:f4:fa:a1:91:6e:d4:dd:15:3e:26:3b:ac:1e: - c3:c2:1f:ed:bb:34:bf:cb:b2:67:c6:c6:51:e8:51:22:b4:f3: - 92:e8 + Signature Algorithm: sha256WithRSAEncryption + 41:f9:c3:a3:77:11:92:55:e7:4b:4a:32:6a:31:d9:51:cf:06: + a5:39:ea:30:98:b8:8d:4f:24:c5:34:fd:c6:98:10:59:32:7e: + 57:f5:8f:ba:67:c9:fc:44:68:b3:7c:f1:af:3a:5f:0d:8f:a1: + fe:41:21:0e:e9:08:a3:63:49:66:34:4a:cd:ce:66:74:47:30: + f7:dc:82:99:21:56:82:ff:2d:12:90:7d:7a:64:22:a0:ed:fa: + 62:d9:5a:d3:97:96:0c:04:a7:47:88:da:53:b6:33:15:15:f9: + da:ee:ac:25:e9:07:02:89:bc:73:a2:c6:27:6f:1f:bd:73:b8: + 8e:f7:94:54:57:a7:8b:5b:9a:24:aa:86:d4:04:5c:8c:cb:28: + a2:45:f9:34:f0:01:20:bb:06:e8:41:14:d2:d7:ca:e8:bf:4e: + 16:72:22:a0:0c:86:ca:73:23:09:ae:71:f1:52:0c:db:b2:8a: + 4d:94:a5:fa:15:81:5b:a2:95:62:50:a1:d6:64:fe:4c:0c:60: + 8d:9b:0f:b8:41:ac:cb:31:c2:17:6c:7b:61:13:16:9a:db:64: + fc:5f:47:84:3d:d2:2e:db:0b:9e:b6:1e:85:04:c1:e5:c0:b2: + 6d:8f:f2:99:00:3a:1a:ab:02:cf:45:7a:26:c1:b0:1f:c6:b0: + d0:4d:f7:52 -----BEGIN CERTIFICATE----- -MIICLDCCAZWgAwIBAgIJANjT46bL48zBMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xMzA2 -MjkxNjQxMjJaFw0yMzA2MjcxNjQxMjJaMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEAvh6G5HkDwdGU1dSzsSiQdvu4ps1tHNFI9AiaZ//5plSxGSnfKRvN8W9m -Aefbec7AOSolEyaUDCx7WiyBD5TuUdB15kbbF0anFYsOVw+wVHZjEsqGGLwawxbA -cAnWa0M5uJgpRqzLaq04iDsH3IHNOvYd9i/vHdeuirbR57MVArkCAwEAAaNQME4w -HQYDVR0OBBYEFLiS3v2KGLMww59V8zNdtMgpikEUMB8GA1UdIwQYMBaAFLiS3v2K -GLMww59V8zNdtMgpikEUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA -Gs93YERDxFUOmeCJqrnTezK3XJx8yv6M1JTGXvODGV8pWWikT9wELrhxwG07rgHk -uYiZzM6CvmoowqxqlMaHkO2FPBBxxf88cGTiQWIx6oZ7EYyT6sbz80751PKBkNf0 -+qGRbtTdFT4mO6wew8If7bs0v8uyZ8bGUehRIrTzkug= +MIIDYDCCAkigAwIBAgIUQpdsMI55/Htq4++dGKR0nYtfV1MwDQYJKoZIhvcNAQEL +BQAwQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoMBXcx +LmZpMRAwDgYDVQQDDAdSb290IENBMB4XDTIwMDUwMjE5NDk0OFoXDTMwMDQzMDE5 +NDk0OFowQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoM +BXcxLmZpMRAwDgYDVQQDDAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAvPTuRGJ/Yk+hgUa6xKoe/U7Q7fFHyyVbZnqGOZHKtWGnfi88Y305 +uBqey20yMpHeSUmE2hW+K93GvB/cbsAtd/LQeyxAGQdgVbD/fFHvONHwKtqozOrW +VKTvvhdEGp4zcFek8wasPe5LLeVGJS0zCfZJqAIxpGWbMgpn9QLhO0emruT2hetd +PgJm3RGYrDRywo8lVUpq6uiCL71/eDGkWtcyu2RIRiPvyMnihABWcuhLVJViOloR +ee5AQ54WLMzmRfS7gijCgzUsVTaZWRGxFdADwaU34R+7Q8e0uTPeFNd8mUUPwQb+ +tiUQWbdydn+RS+rRuWpq7d0bqQ6nKUi3TQIDAQABo1AwTjAdBgNVHQ4EFgQUpP25 +ORuBs6rriB3Ugam1EXDMp+EwHwYDVR0jBBgwFoAUpP25ORuBs6rriB3Ugam1EXDM +p+EwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQfnDo3cRklXnS0oy +ajHZUc8GpTnqMJi4jU8kxTT9xpgQWTJ+V/WPumfJ/ERos3zxrzpfDY+h/kEhDukI +o2NJZjRKzc5mdEcw99yCmSFWgv8tEpB9emQioO36Ytla05eWDASnR4jaU7YzFRX5 +2u6sJekHAom8c6LGJ28fvXO4jveUVFeni1uaJKqG1ARcjMsookX5NPABILsG6EEU +0tfK6L9OFnIioAyGynMjCa5x8VIM27KKTZSl+hWBW6KVYlCh1mT+TAxgjZsPuEGs +yzHCF2x7YRMWmttk/F9HhD3SLtsLnrYehQTB5cCybY/ymQA6GqsCz0V6JsGwH8aw +0E33Ug== -----END CERTIFICATE----- -----BEGIN X509 CRL----- -MIIBJTCBjwIBATANBgkqhkiG9w0BAQsFADAvMQswCQYDVQQGEwJGSTEOMAwGA1UE -CgwFdzEuZmkxEDAOBgNVBAMMB1Jvb3QgQ0EXDTE1MDYyOTE5MDU1OVoXDTIzMDYy -NzE5MDU1OVowHDAaAgkA2NPjpsvjzMMXDTEzMDYyOTE2NDEyMlqgDjAMMAoGA1Ud -FAQDAgEKMA0GCSqGSIb3DQEBCwUAA4GBALN3DQj9bNTuulU/o8MH2wAATisnDSYt -WD7W9S/26AgQDK2qySvp0+vz/Li0BMafbUd+opMu1smdyirjA6rDSjC8scaoVwUo -kY2fFo7qNuUU1N3T25/UCfGu3/E3ynrBZWiQoSCX/8NvY+pzEEf8ZOKt5837VKmk -EB1U3PrnNi7m +MIIBmjCBgwIBATANBgkqhkiG9w0BAQsFADBBMQswCQYDVQQGEwJGSTEQMA4GA1UE +BwwHVHV1c3VsYTEOMAwGA1UECgwFdzEuZmkxEDAOBgNVBAMMB1Jvb3QgQ0EXDTIw +MDUwMzE0NTY1M1oXDTI4MDUwMzE0NTY1M1qgDjAMMAoGA1UdFAQDAgECMA0GCSqG +SIb3DQEBCwUAA4IBAQCaoYj8yLx4eF+bupRl0YQ7h8MlZ3nFmEJFCXlRrPurWLC0 +tUC/8mMA4GJR6CUGUTZ70pfxKoC1Uca5uMJjNkfOJu0UAnMoiGk7W3Fqbbihigku +KU48HHieHoKBFc1+95I1TDVHnaDUkoDpT5W9J9yk5XHzJC7xZC411CM2tRZrKo/h +DRyooWZ5KPT+fthgzDvGSngbMXWumWYMv33PhiMrRlwQgxdt5ECXMbsIN9nY6Sz2 +RFbR9gVA3DwQ5TCMC3UFvHOEn5WcsEeMlNGdoTEb0LbGLnAIxnvHN626HeAgfruj +6Zec54XKEBnpwBlpfENL6eWJZ+NNVkedrSYdcVM0 -----END X509 CRL----- diff --git a/tests/hwsim/auth_serv/ca-incorrect-key.pem b/tests/hwsim/auth_serv/ca-incorrect-key.pem new file mode 100644 index 000000000..ae28d447c --- /dev/null +++ b/tests/hwsim/auth_serv/ca-incorrect-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCorkTzjidMmpUN +G78W6HDErNBhAgZVX6grzX+v1l9YxzUitpwgQP319PlMdHGDtY7E1h0kwlrmifsA +6p6Ejk1o4BYzLnZtcC/nhu8zjyCakDhgvpwbzL5m6TwVsJHyAhUsmdpOZOFH/yVY +zgmN1jnKi7MTnEUgXafts5ZJ9+yf1ju1G/pMynZpcayln2ffMaiAz7YGbefjGLKe +kjgOX82UfZqqvkMu6b5u+hSRRRexDEqsQZxOT/X8iO4VL6tWu8LVU+PJ+bKSiIfW +oNgqpzAddrv0kAW59u8RCjI/eyXceywsCcEQ2V2JwjL7p4Oil4yyyxHHAi5nmQ7Z +225UszcJAgMBAAECggEAEaLGysAeE8BFvS0deYOr5qQ61SmlB+AMcSf3JadAKMQL +Jin5gNXKt6B5QCkchSzCVIoeWe2IG3ppp9rf3/QQ29ox9//vmdmU6JwO/lEEk6Ro +gJTtNWrerVvNUGc5mxfkptkfHfsmIqTmfrZsAUxYlnisrGw2PgAMwql4GRu2va84 +8ZVUVG6+WNizMetsDU1ZuGLVYL7e7YHQG34xW898mdjojv0pJ/XO0mkJvjWMnVCA ++gQrct7k3G+59ap5p9hd/1kCtFqV4E6XkdqW4bP8W+jXPwyReAxLSibU6VYZVoAV +VYpkH0f6vDxn8mfEX4llSnOADeYlahO1QkCJE7xxUQKBgQDTCMCIfrmzrfMZo/s7 +68EjGjmBYipaXIZRtIptk//2FmWkm6VHKi5rWO01BUFXFoTEP3syc6BbWhdgRawi +iM4yS/83sogE8Zl8UKKAv1kcm+HRqrJ+o02b2glcqRmLQPOKcHjNgyWV/yZYbHX0 +BE8yMXlJDBVRcNkGWBtcDuEQ7wKBgQDMn0VBUZyv6ud7vpeLa2RNl7vMyvYAu+Vo +73lWbvwldAY8md4/Oh9ZWsznpSXer0Kx0cHgGfaZw0yzazg9P25RVOmXt01t21l0 +atz82CTAkWDKT7NdXscW5aAtmsCNIpNLcScU94F9jtNKidMB+FUGhcX1gvNQoFQo +kHp0cr9HhwKBgDYGxZOsLcqMO/JSgt0iS/26lwJCqWkcyt5cBBxtiVfs//SWTEfd +yqh8ya2LPOEYyMCdJ+MQqvr4I4foDluA/pjtz9bog94QJCUpV5Dya9PhLHzK4It/ +Lz05IrBwMjPuWusURDkI3DR8b8qvabsg502IUO6cg1CoPUdcgxScUo5NAoGAbExH +nUCSi1DqX0YKcxHNrnuGO+eXt9+6lYVZVPO8pB36Rwyw4gnjGanDFT8FAg0EYZTA +5dkX+V2yNKukwlXWD1m/oDq10lTrzX/ZokDLgtfuwGTaa6qD+Ixj8H8dNhV8m8sx +ghlVAZ0cGzFC6qICbkdS9JPwL1YL9MQy63rn3fUCgYEAj3kgp+ByZJjA4fEk+CkB +V6VL+3GKEq0oc910O4flUfIRO7bOh9XOcrPyhES9Kxj5hh8UP4OTiTmnQmtqEMq0 +K5/8FojDEnh3DmCC6ZDe79vYXQB4c2MRJg1DApZiklpsLJSIjO4ZQ4H3aQQEKCQe +DOd7egyPAkD7rmwgWBvF3Nk= +-----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/ca-incorrect.der b/tests/hwsim/auth_serv/ca-incorrect.der new file mode 100644 index 000000000..75bb94d71 Binary files /dev/null and b/tests/hwsim/auth_serv/ca-incorrect.der differ diff --git a/tests/hwsim/auth_serv/ca-incorrect.pem b/tests/hwsim/auth_serv/ca-incorrect.pem index 2e9a4926a..4afabbd42 100644 --- a/tests/hwsim/auth_serv/ca-incorrect.pem +++ b/tests/hwsim/auth_serv/ca-incorrect.pem @@ -1,55 +1,79 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 10855188644662735910 (0x96a5608f1ef9f426) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FI, CN=TEST - Incorrect Root CA + Serial Number: + 59:db:b0:44:3b:5a:59:c8:8e:2b:14:38:c4:3b:60:b6:1f:a5:fe:38 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = FI, L = Tuusula, O = w1.fi, CN = TEST - Incorrect Root CA Validity - Not Before: Oct 20 16:30:06 2013 GMT - Not After : Oct 18 16:30:06 2023 GMT - Subject: C=FI, CN=TEST - Incorrect Root CA + Not Before: May 2 19:49:48 2020 GMT + Not After : Apr 30 19:49:48 2030 GMT + Subject: C = FI, L = Tuusula, O = w1.fi, CN = TEST - Incorrect Root CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:bc:0c:8e:61:1e:5b:ea:b2:6b:cc:8a:8c:38:85: - 6d:79:e0:7a:28:d1:b5:55:65:52:f8:e2:2c:74:c1: - 00:15:c6:15:84:56:08:f5:e9:eb:bc:07:8d:b7:97: - b6:73:7f:46:77:86:31:d0:f0:7f:95:d6:4a:7c:35: - 07:85:43:41:5e:f4:07:84:e6:52:cb:52:38:ef:fe: - 6a:16:84:22:45:2e:c1:a1:16:8d:d2:b3:62:c2:05: - 77:43:04:2e:d0:52:ee:db:78:10:79:44:49:92:35: - ee:99:83:aa:a0:1d:e6:3d:c3:c6:a2:8e:b6:4d:7f: - d8:11:a9:a3:bc:68:1d:a2:6f + 00:a8:ae:44:f3:8e:27:4c:9a:95:0d:1b:bf:16:e8: + 70:c4:ac:d0:61:02:06:55:5f:a8:2b:cd:7f:af:d6: + 5f:58:c7:35:22:b6:9c:20:40:fd:f5:f4:f9:4c:74: + 71:83:b5:8e:c4:d6:1d:24:c2:5a:e6:89:fb:00:ea: + 9e:84:8e:4d:68:e0:16:33:2e:76:6d:70:2f:e7:86: + ef:33:8f:20:9a:90:38:60:be:9c:1b:cc:be:66:e9: + 3c:15:b0:91:f2:02:15:2c:99:da:4e:64:e1:47:ff: + 25:58:ce:09:8d:d6:39:ca:8b:b3:13:9c:45:20:5d: + a7:ed:b3:96:49:f7:ec:9f:d6:3b:b5:1b:fa:4c:ca: + 76:69:71:ac:a5:9f:67:df:31:a8:80:cf:b6:06:6d: + e7:e3:18:b2:9e:92:38:0e:5f:cd:94:7d:9a:aa:be: + 43:2e:e9:be:6e:fa:14:91:45:17:b1:0c:4a:ac:41: + 9c:4e:4f:f5:fc:88:ee:15:2f:ab:56:bb:c2:d5:53: + e3:c9:f9:b2:92:88:87:d6:a0:d8:2a:a7:30:1d:76: + bb:f4:90:05:b9:f6:ef:11:0a:32:3f:7b:25:dc:7b: + 2c:2c:09:c1:10:d9:5d:89:c2:32:fb:a7:83:a2:97: + 8c:b2:cb:11:c7:02:2e:67:99:0e:d9:db:6e:54:b3: + 37:09 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - 3E:49:CB:A7:6A:A7:08:4F:DA:99:E4:3C:64:A2:AC:96:BE:99:E4:F2 + 0B:56:70:D1:C5:1C:DE:A7:F3:27:07:62:EA:F9:32:BD:C6:95:DD:51 X509v3 Authority Key Identifier: - keyid:3E:49:CB:A7:6A:A7:08:4F:DA:99:E4:3C:64:A2:AC:96:BE:99:E4:F2 + keyid:0B:56:70:D1:C5:1C:DE:A7:F3:27:07:62:EA:F9:32:BD:C6:95:DD:51 X509v3 Basic Constraints: CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 31:98:35:4b:d8:d2:8e:55:7a:af:06:f8:ef:6b:24:13:11:12: - b0:77:81:b9:ab:50:20:d6:78:99:3f:bc:3d:89:d4:b2:bd:7a: - 54:03:fc:a7:a4:9f:2b:09:da:75:c9:8d:4c:65:90:c5:df:fc: - 6b:48:52:f1:0a:aa:57:8a:b1:f5:fe:35:87:87:32:39:b9:ad: - 80:f0:8e:36:72:63:d5:97:20:e5:b6:06:64:31:5a:66:66:15: - 85:68:b7:9d:26:8b:46:7f:e8:1b:09:f5:c2:4a:35:7c:49:e2: - b2:dc:59:b2:91:8d:85:33:07:09:ca:78:7a:db:b3:e5:58:2c: - cc:6a + Signature Algorithm: sha256WithRSAEncryption + 9f:dd:16:ec:26:65:db:7b:49:82:83:f7:72:49:84:44:9e:b7: + ec:fa:35:53:f9:7c:fd:e1:1e:b0:ec:bc:44:45:6e:47:26:9a: + d4:03:91:e5:72:25:3d:86:93:e0:9a:9a:e2:95:f2:e9:3d:57: + 26:d4:7e:0a:36:9f:db:f0:76:09:51:98:9c:e9:96:cc:64:5e: + c6:c7:d1:59:46:da:4d:03:5a:4f:64:f6:b0:2b:f8:12:f2:a1: + 0a:f2:a4:b9:df:0e:5f:b4:f3:18:26:0e:ab:18:29:33:5c:40: + 54:48:f6:c2:37:ea:62:45:ae:d6:39:fe:75:f0:61:ff:3d:65: + 3e:65:38:e9:07:08:2f:ea:d0:80:8a:4d:0a:62:9c:ae:22:45: + aa:7e:09:be:43:ce:bd:fc:f7:8c:b4:ba:e2:52:f1:1d:79:7c: + ad:2f:09:29:82:6d:0d:64:d1:25:a3:9b:36:eb:1b:e0:f0:04: + 18:c4:29:d3:2e:c7:67:12:fa:3d:1f:81:e3:2c:5b:25:63:8c: + c8:1c:9b:bd:e6:c1:22:c8:34:17:fd:64:3a:3f:30:75:36:18: + e2:2d:49:16:07:ad:ba:ce:28:c7:df:06:81:57:55:cd:34:7b: + 81:fd:5e:97:5d:c5:d1:dd:f1:61:2d:f5:ce:06:7f:4d:2e:a4: + 5e:77:9b:d1 -----BEGIN CERTIFICATE----- -MIICLjCCAZegAwIBAgIJAJalYI8e+fQmMA0GCSqGSIb3DQEBBQUAMDAxCzAJBgNV -BAYTAkZJMSEwHwYDVQQDDBhURVNUIC0gSW5jb3JyZWN0IFJvb3QgQ0EwHhcNMTMx -MDIwMTYzMDA2WhcNMjMxMDE4MTYzMDA2WjAwMQswCQYDVQQGEwJGSTEhMB8GA1UE -AwwYVEVTVCAtIEluY29ycmVjdCBSb290IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQC8DI5hHlvqsmvMiow4hW154Hoo0bVVZVL44ix0wQAVxhWEVgj16eu8 -B423l7Zzf0Z3hjHQ8H+V1kp8NQeFQ0Fe9AeE5lLLUjjv/moWhCJFLsGhFo3Ss2LC -BXdDBC7QUu7beBB5REmSNe6Zg6qgHeY9w8aijrZNf9gRqaO8aB2ibwIDAQABo1Aw -TjAdBgNVHQ4EFgQUPknLp2qnCE/ameQ8ZKKslr6Z5PIwHwYDVR0jBBgwFoAUPknL -p2qnCE/ameQ8ZKKslr6Z5PIwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOB -gQAxmDVL2NKOVXqvBvjvayQTERKwd4G5q1Ag1niZP7w9idSyvXpUA/ynpJ8rCdp1 -yY1MZZDF3/xrSFLxCqpXirH1/jWHhzI5ua2A8I42cmPVlyDltgZkMVpmZhWFaLed -JotGf+gbCfXCSjV8SeKy3FmykY2FMwcJynh627PlWCzMag== +MIIDgjCCAmqgAwIBAgIUWduwRDtaWciOKxQ4xDtgth+l/jgwDQYJKoZIhvcNAQEL +BQAwUjELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoMBXcx +LmZpMSEwHwYDVQQDDBhURVNUIC0gSW5jb3JyZWN0IFJvb3QgQ0EwHhcNMjAwNTAy +MTk0OTQ4WhcNMzAwNDMwMTk0OTQ4WjBSMQswCQYDVQQGEwJGSTEQMA4GA1UEBwwH +VHV1c3VsYTEOMAwGA1UECgwFdzEuZmkxITAfBgNVBAMMGFRFU1QgLSBJbmNvcnJl +Y3QgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKiuRPOO +J0yalQ0bvxbocMSs0GECBlVfqCvNf6/WX1jHNSK2nCBA/fX0+Ux0cYO1jsTWHSTC +WuaJ+wDqnoSOTWjgFjMudm1wL+eG7zOPIJqQOGC+nBvMvmbpPBWwkfICFSyZ2k5k +4Uf/JVjOCY3WOcqLsxOcRSBdp+2zlkn37J/WO7Ub+kzKdmlxrKWfZ98xqIDPtgZt +5+MYsp6SOA5fzZR9mqq+Qy7pvm76FJFFF7EMSqxBnE5P9fyI7hUvq1a7wtVT48n5 +spKIh9ag2CqnMB12u/SQBbn27xEKMj97Jdx7LCwJwRDZXYnCMvung6KXjLLLEccC +LmeZDtnbblSzNwkCAwEAAaNQME4wHQYDVR0OBBYEFAtWcNHFHN6n8ycHYur5Mr3G +ld1RMB8GA1UdIwQYMBaAFAtWcNHFHN6n8ycHYur5Mr3Gld1RMAwGA1UdEwQFMAMB +Af8wDQYJKoZIhvcNAQELBQADggEBAJ/dFuwmZdt7SYKD93JJhESet+z6NVP5fP3h +HrDsvERFbkcmmtQDkeVyJT2Gk+CamuKV8uk9VybUfgo2n9vwdglRmJzplsxkXsbH +0VlG2k0DWk9k9rAr+BLyoQrypLnfDl+08xgmDqsYKTNcQFRI9sI36mJFrtY5/nXw +Yf89ZT5lOOkHCC/q0ICKTQpinK4iRap+Cb5Dzr3894y0uuJS8R15fK0vCSmCbQ1k +0SWjmzbrG+DwBBjEKdMux2cS+j0fgeMsWyVjjMgcm73mwSLINBf9ZDo/MHU2GOIt +SRYHrbrOKMffBoFXVc00e4H9XpddxdHd8WEt9c4Gf00upF53m9E= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/ca-key.pem b/tests/hwsim/auth_serv/ca-key.pem index cddf6b1cf..b66e03802 100644 --- a/tests/hwsim/auth_serv/ca-key.pem +++ b/tests/hwsim/auth_serv/ca-key.pem @@ -1,15 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQC+HobkeQPB0ZTV1LOxKJB2+7imzW0c0Uj0CJpn//mmVLEZKd8p -G83xb2YB59t5zsA5KiUTJpQMLHtaLIEPlO5R0HXmRtsXRqcViw5XD7BUdmMSyoYY -vBrDFsBwCdZrQzm4mClGrMtqrTiIOwfcgc069h32L+8d166KttHnsxUCuQIDAQAB -AoGAEPKDr8Yh0ZsvG0iUpAwrpI+XzDavrUvypt5FdVPaGzudddLHs9BosUbu3uie -JeOKOw5Is8ZSmCs267jf4FW0UKtgpnHGK2H0ba0iramzz07oK48V4y7C7nS3eJr/ -Oen6H9BW4DNXreFZ5yTRFOiQ4eD1pHqR/M/bBieDfRjakgECQQDfgiYYInio4TmM -9q/h1q5T1bGgajz5U4GInd0K2diNqVoGhSTAyRRGauH+68tPQuX7WCM1VE/lZfZL -4/dlOaRhAkEA2cHNkrFh4CAlXgtCub+psmT032AIFDEpNNT0K22XIE8savYNqs8w -aGPurrwGQflxCB19boiaKEcW5FQDkff9WQJAbUznNiw9V1D05OOKNWXX0HWTLMBn -WwIkOVwByZmo1fX4aXHY/FIZESqZpCFJRlSPxS9f4Gd/vs3y+T/dLupWYQJAJDGX -RrOfDg6px1jdzVvzC8jF/r7KePi23aYrs3Ayt1cRjfG50dNAO4moqXhtHdglFnE4 -YP/ph5pRTsA8G635eQJBAKbh0zB4HqFI2PmnKsShFBPNkK5x17nAZlYNJf2Ip4Ii -2Gjxyx4H0iBVgFYLsLB6hRBkOPpx6Jl8mJXOtFXb8lE= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC89O5EYn9iT6GB +RrrEqh79TtDt8UfLJVtmeoY5kcq1Yad+LzxjfTm4Gp7LbTIykd5JSYTaFb4r3ca8 +H9xuwC138tB7LEAZB2BVsP98Ue840fAq2qjM6tZUpO++F0QanjNwV6TzBqw97kst +5UYlLTMJ9kmoAjGkZZsyCmf1AuE7R6au5PaF610+AmbdEZisNHLCjyVVSmrq6IIv +vX94MaRa1zK7ZEhGI+/IyeKEAFZy6EtUlWI6WhF57kBDnhYszOZF9LuCKMKDNSxV +NplZEbEV0APBpTfhH7tDx7S5M94U13yZRQ/BBv62JRBZt3J2f5FL6tG5amrt3Rup +DqcpSLdNAgMBAAECggEBAJ9YofITaj8aziT545jjqfyN0c1G0vdyinCSVM0JsHtj +Xd8gsHlp6hnigRUmAdX5gw4krJ9JBLVzchvFdpwC/pUPtFabC3bP7KJ3AAzz/5vY +FwPcn8snIxYAfZi9gBY+YTyU/KphbzFO2iFbHttNEaSOCLFhIEH12XnKor5Q7mWQ +5HHlTdCzvRlGQwSdrmYctQmekdSgffF56ebZzlkwrJAF+o8NX44mcNWSausnEuds +S7Cah4dxT3Hm8luXfd1u3fCiT/p0ubMT66OVjo2cB0CIQxSpGWoIMuVrVrlzQbNt +gtQ2cred2HKizlYpCjNd2zrRHauIc2koqQTP0+yNE5UCgYEA6Fuc4Wrq/maMQiOT +QI46K5PktWArxFO152chdLpjy9qKmm0o7MjBZubRRW0kYHvtUwu15wcCH8Ctwucn +JGrvtS3lMbNy14kQG7OrT87u2J5VyXNbGxOIhoeDRxEKCbDfyA+4c7sGHMxczxPc +q6tWJ8cZeXLl8TMLacyG5aWF1WMCgYEA0C7RtPZh6J4XfsgZjO/7FoVgBp5yoche +Hc6gwHiT7qYAbDQgOq7g41jEtYoO/e8qRsxsJHJlVzYIe3WlK5IC78sk6ZS7hZ6M +LjfhnBPV1Ddtdq4w2VKY7fDYPvZK3DOc0FOIlaPicxWXUUDt0Tfud2qgYbebz+R6 +wmxqqcYM948CgYEAq6C/yGFJIpBsmY3dfpmPrhCXpsFakrGic0JiG+5xOGo8ZsSq +rfu7n15uxXFQpVPkgKrtubAbiYiw0H4dE3FJjfJQkN2TvlCnbU7RAyo+khKiGyLx +8JYFChmehie32mCjawrxm8pRQYRSKULqhIMSKF+QGX0dC4RAse041vfkWzECgYAr +tAh2EtsO+FE6Xktu2No/KhS0jwLFj8iiPURl42o6yUKBdJfnedrgHzx8V9U53cFk +R3nUVOeNXVx+fn4EHYzcRisjlgOf017ePQDxwQA8or4qEftTRBGyscLTxOSGQZeD +7GVZ9KOPQVMYzaafKzy2eP3eRatCA1b6BcSGi3shZQKBgQDA1h0rSoFoXsel8MAV +MPkGt6gzUdzKb/Qt3BOolnsIcd4Vn19uLCcLdhxRkD37MW/9/mgV+Q57DYyvS9OC +xi6q7ukgDE3YTK5WChmqJ4p0aEP4bEt6N1VIo55HCFoJy01NIJLs4VAW4y88CzDp +otex1UmIWQdfnDbIVW9NNFVTiQ== +-----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/ca.der b/tests/hwsim/auth_serv/ca.der index 09d5fa051..b03de0177 100644 Binary files a/tests/hwsim/auth_serv/ca.der and b/tests/hwsim/auth_serv/ca.der differ diff --git a/tests/hwsim/auth_serv/ca.pem b/tests/hwsim/auth_serv/ca.pem index b128893a1..7fcbdf767 100644 --- a/tests/hwsim/auth_serv/ca.pem +++ b/tests/hwsim/auth_serv/ca.pem @@ -1,55 +1,79 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162817 (0xd8d3e3a6cbe3ccc1) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + 42:97:6c:30:8e:79:fc:7b:6a:e3:ef:9d:18:a4:74:9d:8b:5f:57:53 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Validity - Not Before: Jun 29 16:41:22 2013 GMT - Not After : Jun 27 16:41:22 2023 GMT - Subject: C=FI, O=w1.fi, CN=Root CA + Not Before: May 2 19:49:48 2020 GMT + Not After : Apr 30 19:49:48 2030 GMT + Subject: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:be:1e:86:e4:79:03:c1:d1:94:d5:d4:b3:b1:28: - 90:76:fb:b8:a6:cd:6d:1c:d1:48:f4:08:9a:67:ff: - f9:a6:54:b1:19:29:df:29:1b:cd:f1:6f:66:01:e7: - db:79:ce:c0:39:2a:25:13:26:94:0c:2c:7b:5a:2c: - 81:0f:94:ee:51:d0:75:e6:46:db:17:46:a7:15:8b: - 0e:57:0f:b0:54:76:63:12:ca:86:18:bc:1a:c3:16: - c0:70:09:d6:6b:43:39:b8:98:29:46:ac:cb:6a:ad: - 38:88:3b:07:dc:81:cd:3a:f6:1d:f6:2f:ef:1d:d7: - ae:8a:b6:d1:e7:b3:15:02:b9 + 00:bc:f4:ee:44:62:7f:62:4f:a1:81:46:ba:c4:aa: + 1e:fd:4e:d0:ed:f1:47:cb:25:5b:66:7a:86:39:91: + ca:b5:61:a7:7e:2f:3c:63:7d:39:b8:1a:9e:cb:6d: + 32:32:91:de:49:49:84:da:15:be:2b:dd:c6:bc:1f: + dc:6e:c0:2d:77:f2:d0:7b:2c:40:19:07:60:55:b0: + ff:7c:51:ef:38:d1:f0:2a:da:a8:cc:ea:d6:54:a4: + ef:be:17:44:1a:9e:33:70:57:a4:f3:06:ac:3d:ee: + 4b:2d:e5:46:25:2d:33:09:f6:49:a8:02:31:a4:65: + 9b:32:0a:67:f5:02:e1:3b:47:a6:ae:e4:f6:85:eb: + 5d:3e:02:66:dd:11:98:ac:34:72:c2:8f:25:55:4a: + 6a:ea:e8:82:2f:bd:7f:78:31:a4:5a:d7:32:bb:64: + 48:46:23:ef:c8:c9:e2:84:00:56:72:e8:4b:54:95: + 62:3a:5a:11:79:ee:40:43:9e:16:2c:cc:e6:45:f4: + bb:82:28:c2:83:35:2c:55:36:99:59:11:b1:15:d0: + 03:c1:a5:37:e1:1f:bb:43:c7:b4:b9:33:de:14:d7: + 7c:99:45:0f:c1:06:fe:b6:25:10:59:b7:72:76:7f: + 91:4b:ea:d1:b9:6a:6a:ed:dd:1b:a9:0e:a7:29:48: + b7:4d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 1a:cf:77:60:44:43:c4:55:0e:99:e0:89:aa:b9:d3:7b:32:b7: - 5c:9c:7c:ca:fe:8c:d4:94:c6:5e:f3:83:19:5f:29:59:68:a4: - 4f:dc:04:2e:b8:71:c0:6d:3b:ae:01:e4:b9:88:99:cc:ce:82: - be:6a:28:c2:ac:6a:94:c6:87:90:ed:85:3c:10:71:c5:ff:3c: - 70:64:e2:41:62:31:ea:86:7b:11:8c:93:ea:c6:f3:f3:4e:f9: - d4:f2:81:90:d7:f4:fa:a1:91:6e:d4:dd:15:3e:26:3b:ac:1e: - c3:c2:1f:ed:bb:34:bf:cb:b2:67:c6:c6:51:e8:51:22:b4:f3: - 92:e8 + Signature Algorithm: sha256WithRSAEncryption + 41:f9:c3:a3:77:11:92:55:e7:4b:4a:32:6a:31:d9:51:cf:06: + a5:39:ea:30:98:b8:8d:4f:24:c5:34:fd:c6:98:10:59:32:7e: + 57:f5:8f:ba:67:c9:fc:44:68:b3:7c:f1:af:3a:5f:0d:8f:a1: + fe:41:21:0e:e9:08:a3:63:49:66:34:4a:cd:ce:66:74:47:30: + f7:dc:82:99:21:56:82:ff:2d:12:90:7d:7a:64:22:a0:ed:fa: + 62:d9:5a:d3:97:96:0c:04:a7:47:88:da:53:b6:33:15:15:f9: + da:ee:ac:25:e9:07:02:89:bc:73:a2:c6:27:6f:1f:bd:73:b8: + 8e:f7:94:54:57:a7:8b:5b:9a:24:aa:86:d4:04:5c:8c:cb:28: + a2:45:f9:34:f0:01:20:bb:06:e8:41:14:d2:d7:ca:e8:bf:4e: + 16:72:22:a0:0c:86:ca:73:23:09:ae:71:f1:52:0c:db:b2:8a: + 4d:94:a5:fa:15:81:5b:a2:95:62:50:a1:d6:64:fe:4c:0c:60: + 8d:9b:0f:b8:41:ac:cb:31:c2:17:6c:7b:61:13:16:9a:db:64: + fc:5f:47:84:3d:d2:2e:db:0b:9e:b6:1e:85:04:c1:e5:c0:b2: + 6d:8f:f2:99:00:3a:1a:ab:02:cf:45:7a:26:c1:b0:1f:c6:b0: + d0:4d:f7:52 -----BEGIN CERTIFICATE----- -MIICLDCCAZWgAwIBAgIJANjT46bL48zBMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xMzA2 -MjkxNjQxMjJaFw0yMzA2MjcxNjQxMjJaMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEAvh6G5HkDwdGU1dSzsSiQdvu4ps1tHNFI9AiaZ//5plSxGSnfKRvN8W9m -Aefbec7AOSolEyaUDCx7WiyBD5TuUdB15kbbF0anFYsOVw+wVHZjEsqGGLwawxbA -cAnWa0M5uJgpRqzLaq04iDsH3IHNOvYd9i/vHdeuirbR57MVArkCAwEAAaNQME4w -HQYDVR0OBBYEFLiS3v2KGLMww59V8zNdtMgpikEUMB8GA1UdIwQYMBaAFLiS3v2K -GLMww59V8zNdtMgpikEUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA -Gs93YERDxFUOmeCJqrnTezK3XJx8yv6M1JTGXvODGV8pWWikT9wELrhxwG07rgHk -uYiZzM6CvmoowqxqlMaHkO2FPBBxxf88cGTiQWIx6oZ7EYyT6sbz80751PKBkNf0 -+qGRbtTdFT4mO6wew8If7bs0v8uyZ8bGUehRIrTzkug= +MIIDYDCCAkigAwIBAgIUQpdsMI55/Htq4++dGKR0nYtfV1MwDQYJKoZIhvcNAQEL +BQAwQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoMBXcx +LmZpMRAwDgYDVQQDDAdSb290IENBMB4XDTIwMDUwMjE5NDk0OFoXDTMwMDQzMDE5 +NDk0OFowQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoM +BXcxLmZpMRAwDgYDVQQDDAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAvPTuRGJ/Yk+hgUa6xKoe/U7Q7fFHyyVbZnqGOZHKtWGnfi88Y305 +uBqey20yMpHeSUmE2hW+K93GvB/cbsAtd/LQeyxAGQdgVbD/fFHvONHwKtqozOrW +VKTvvhdEGp4zcFek8wasPe5LLeVGJS0zCfZJqAIxpGWbMgpn9QLhO0emruT2hetd +PgJm3RGYrDRywo8lVUpq6uiCL71/eDGkWtcyu2RIRiPvyMnihABWcuhLVJViOloR +ee5AQ54WLMzmRfS7gijCgzUsVTaZWRGxFdADwaU34R+7Q8e0uTPeFNd8mUUPwQb+ +tiUQWbdydn+RS+rRuWpq7d0bqQ6nKUi3TQIDAQABo1AwTjAdBgNVHQ4EFgQUpP25 +ORuBs6rriB3Ugam1EXDMp+EwHwYDVR0jBBgwFoAUpP25ORuBs6rriB3Ugam1EXDM +p+EwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQfnDo3cRklXnS0oy +ajHZUc8GpTnqMJi4jU8kxTT9xpgQWTJ+V/WPumfJ/ERos3zxrzpfDY+h/kEhDukI +o2NJZjRKzc5mdEcw99yCmSFWgv8tEpB9emQioO36Ytla05eWDASnR4jaU7YzFRX5 +2u6sJekHAom8c6LGJ28fvXO4jveUVFeni1uaJKqG1ARcjMsookX5NPABILsG6EEU +0tfK6L9OFnIioAyGynMjCa5x8VIM27KKTZSl+hWBW6KVYlCh1mT+TAxgjZsPuEGs +yzHCF2x7YRMWmttk/F9HhD3SLtsLnrYehQTB5cCybY/ymQA6GqsCz0V6JsGwH8aw +0E33Ug== -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/dh.conf b/tests/hwsim/auth_serv/dh.conf index 7bc83251c..f8cd30fd8 100644 --- a/tests/hwsim/auth_serv/dh.conf +++ b/tests/hwsim/auth_serv/dh.conf @@ -1,5 +1,8 @@ -----BEGIN DH PARAMETERS----- -MIGHAoGBAP3V8IHq3H2DUlYywsvjYNuS17eCdt0mJo6/os6PHqdhgkMrPxF9u4Gr -qKXq9e6GqmZYdjta30N3FkXaV924BJ0xOqb2TntiKg4u50/l6hSUneWt6UFBaizd -XrqjNFIme/5RXMZ7RglXliBpCepAaFLMcKhOS4ulUyYYHSy+oqRjAgEC +MIIBCAKCAQEAn5Zfi2JHL512eWsfgD2un5TKWlIvNVIYedyWyzkG7JvccUIdaqx1 +xDVXldaAXW2VkDoRGpFSNk43fPfrYcDIZiWHydNjetQ4Cejv7GcjBPMbNm47eIO1 ++9OXrBwpYatW8npTRGF83TqQ/wJgjfr3Cl580Qp2Tv9XjGWHjqDmJI8xVmmOjn/w +sT1sSN0MryujDzxh7AtkX2NtJMTB1o1Z8MZPnRbxf1crECUNOhYTuTIkzJU1lROq +HKR72RcMUfJp6GxrYRmx8CQ69UwUwyJoedkkV39HRqvZGc8b8HLFwmlhkGy+qfaN +zNugMb5eoRAqm+6ZQjZJWAU29+OG/Ku2owIBAg== -----END DH PARAMETERS----- diff --git a/tests/hwsim/auth_serv/dsaparam.pem b/tests/hwsim/auth_serv/dsaparam.pem index 54ba66a46..890695d40 100644 --- a/tests/hwsim/auth_serv/dsaparam.pem +++ b/tests/hwsim/auth_serv/dsaparam.pem @@ -1,11 +1,14 @@ -----BEGIN DSA PARAMETERS----- -MIIBngKBwQCKGwQSQa8/VqJBvFDwpbJTEgQ2myTzbDCZqZof9EBBO5KlbUfgFZfY -szSaZAWPok0mG9BRGoJgtajJruLU6lvoZ94FgGPhRrOZWd0wT6kiySRz4nv9kEMK -Ch83zLQ+i1IdRFozP4k+9YHlAVL354zU+O5USxNMuhPVab4MPsl9I7gZmEQmisHA -fwQOLppTrILuqNtVOqpRogKhVnvQITqV3VsRYV0JVersx48olOqtPGQKKewiJFJp -n7fwGC208/sCFQD4vIUetIr4LGLwm3D/Y5HxNMyFFwKBwC7b0nT/lb1+z86vKg3v -Cyy40D03ezYgmlwV+xObadfMmciwxK98DX763dFsY9omd6csFho1xGfSFRj8Bkv6 -rbumVtoZGurdRxU4ADJf4SF5MuK2rJ9jg4Wz6F1BhHEKtoubINlk3fyZWPx0sjkm -t2IJlFY4rfbTI8ETrPrE+zb53tiaundB72cUWmZY/gRuaXh7lRzpMVr71+OedLU6 -VkIHXOG/nnb48hZfGohKvWTAp/wkb2w/dCdeGKgVZn3FzA== +MIICLQKCAQEA4Gx/0VQqdHPnUdPwtyYRYPMqJqIufW2SkWMEVCMHLo6yZx+2Y1Kn +N8Zi7TlCHshBXPS/ZF3jMpFk5lOf0M/YujayuVl1iii7B79d5NC0eehX3LnlS3WK +npGmuCIlnxPrOvrrwx9gPznruNrLNh57IERidYtolFAPjtNKuCYbCmpS1J6mh3pR +XlNkkTC6L2zkkgDwDZQzJmbQ5gSDY57uneSOgZaPGOYt+Uxsv4v/xxBRTALEcRDk +AyB0OhzNx5gsNw1qfO1Ck1IOG0Z+A8VnS6Kpeh42bCTdF3OfXwK2BgOzQLCpyEfp +MEqgRG7VUQjlsdkUy35apIvYpZbovgmbbQIhAIc7hanE2sJ1kKBMYxQx6mlxc+NI +LxoyLRqAE0iQs08HAoIBAQCFmPw/JGlVVMMdC3RYlTdH2Lu2lGJoDmuuKhrmQOo/ +/jAcShg3n2hVSKzximtZX+KNoJ3TklWG30jPsV1CSOeX0IDeiuEiH/1bGAtHmIxo +BLbF5fS94fAbL9IAXhuXaHozgnVoutbFUxGVCCopPmYnX8nDCHdy6cHQld1/S5Y4 +hYWQTTSJETUzqYUWQtdAzUCPFBwDGJA7CpYgGQ3mJRUt/Hk6QnEc8NrAFNvbnxWA +me0/rZmg4lZwtA8GfrOzsZSVXCsL56KZZ8iMElfcN/E4fxWOfBoFkNI3IOc5B+j2 +EsZcXUcbK2o57BHiZ1GMcbfnuz5STFY8/vBXpyAbBDqO -----END DSA PARAMETERS----- diff --git a/tests/hwsim/auth_serv/eap_user.conf b/tests/hwsim/auth_serv/eap_user.conf index 7343f40a3..b5c65f178 100644 --- a/tests/hwsim/auth_serv/eap_user.conf +++ b/tests/hwsim/auth_serv/eap_user.conf @@ -83,6 +83,8 @@ radius_accept_attr=27:d:3 "phase1-user" MSCHAPV2,MD5,GTC "password" +"/C=FI/O=w1.fi/CN=Test User" TLS [2] + "020000000000" MACACL "020000000000" "020000000100" MACACL "020000000100" diff --git a/tests/hwsim/auth_serv/iCA-server/ca-and-root.pem b/tests/hwsim/auth_serv/iCA-server/ca-and-root.pem index d32194454..2f10391d0 100644 --- a/tests/hwsim/auth_serv/iCA-server/ca-and-root.pem +++ b/tests/hwsim/auth_serv/iCA-server/ca-and-root.pem @@ -1,125 +1,160 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162867 (0xd8d3e3a6cbe3ccf3) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + d8:d3:e3:a6:cb:e3:cc:f7 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 22 19:37:36 2025 GMT + Not Before: May 3 15:20:10 2020 GMT + Not After : May 3 15:20:10 2030 GMT Subject: C=FI, O=w1.fi, CN=Server Intermediate CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:de:58:ac:e3:d8:7e:40:f6:84:2a:49:24:49:5a: - f7:c8:23:08:b9:6c:d9:07:01:69:8f:77:28:71:42: - a2:eb:ae:86:10:c6:31:61:9a:14:88:44:0a:68:bf: - 6e:a2:46:41:e9:6f:a2:89:fb:0b:f3:e1:b8:30:bf: - e5:80:5e:f9:61:8d:6e:ac:e2:f7:28:e7:9e:44:28: - b8:e4:6e:87:76:a9:d7:ac:ed:11:3f:de:c3:dd:41: - c3:45:82:09:c3:a7:4c:e6:df:2b:88:1e:44:ce:e2: - a7:29:53:f6:13:96:ad:6c:2e:93:00:28:42:77:bc: - 73:6e:86:e7:5b:e8:eb:e9:37:1d:63:e7:ea:05:5a: - 71:28:f0:81:0b:4c:3f:dd:73:f8:db:13:a8:f0:5f: - 6f:6f:e5:1b:c7:94:7f:57:c5:dc:66:26:0c:5a:71: - 7a:e3:d2:3e:7a:a6:59:46:03:61:78:89:84:3d:ef: - 22:9c:f8:c2:22:75:c4:0c:ef:fb:e4:fa:6f:b8:11: - db:aa:92:9b:6c:23:4e:6e:e5:55:d2:41:47:18:95: - c6:7d:17:be:6d:ab:39:a1:38:61:fd:f9:22:95:69: - f3:9e:28:fd:8a:c8:58:72:3c:91:c2:22:d9:fb:b2: - 54:0f:9a:17:27:88:df:60:f5:de:fc:95:9f:25:c6: - 64:81 + 00:a2:b0:de:7f:e6:17:69:4b:bb:8d:dc:4f:8b:95: + 33:5e:13:ee:a1:01:f5:82:de:6e:fc:83:db:e7:22: + 5f:b9:8d:2b:de:10:72:4e:da:81:c1:f7:f3:eb:0e: + db:5b:5f:90:92:bb:41:68:55:4f:84:d9:73:5b:0c: + 6d:40:e6:c5:0f:5d:5c:5e:80:1e:64:87:5a:99:44: + 8b:3d:61:20:f0:15:cc:87:95:5b:a0:46:0f:bc:5c: + 14:ee:ac:4f:c8:7c:d2:c0:ef:60:94:22:b6:74:05: + 4f:ca:97:01:0a:30:b4:50:44:89:d0:c2:6b:e5:7f: + ce:66:22:1a:d6:38:7c:ff:42:42:ca:58:a0:38:85: + ca:f1:b1:1f:33:27:db:bf:5c:49:96:36:7a:11:2f: + 62:d7:eb:7e:9f:9b:9c:0e:2b:df:cd:59:bc:ee:e8: + 6a:e3:7d:fa:06:ba:34:42:b5:7d:e7:be:e1:7b:85: + af:1b:25:a9:45:33:06:cb:cc:0d:ca:78:5c:56:52: + ac:43:7e:f6:0c:e7:fb:86:b4:ac:d7:f4:b2:54:ee: + 65:7a:5c:32:6b:33:a0:68:1b:d8:ea:c8:74:94:08: + 00:7f:9b:f0:da:80:0f:f2:45:13:11:63:4c:e6:d2: + 97:d3:ae:12:b0:7c:e8:f0:56:c0:7b:7c:82:99:6d: + 3b:5d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - 84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9 + EB:DC:8D:38:75:10:2F:E6:82:8E:FE:43:EC:9F:7E:63:22:BD:51:55 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Certificate Sign, CRL Sign Signature Algorithm: sha256WithRSAEncryption - bd:22:63:3d:a7:e5:ce:c9:f5:66:1f:77:5f:d5:24:e3:68:dc: - a4:07:80:3e:5e:b1:2c:96:88:39:ad:00:4c:aa:9d:0b:ed:f3: - 6d:df:9d:2f:97:d2:77:8b:ba:d0:9c:0f:a6:5e:60:b8:0f:e1: - 96:b1:61:25:48:69:81:64:a8:5c:82:58:0b:f3:d0:a9:4e:8b: - 90:fc:2f:67:57:da:72:dc:3c:eb:c2:20:19:05:8d:42:0d:14: - cf:00:db:59:00:ea:f0:76:3e:ca:85:b1:05:e5:b8:5f:0b:46: - c7:3c:a1:d9:5c:4d:b9:24:e7:d6:2b:3d:0d:eb:c3:88:d8:3a: - f6:60 + 86:74:75:b2:bb:b0:85:25:48:38:e1:34:54:d5:d4:3a:9f:0e: + b1:96:fd:cc:ea:15:21:72:da:9e:ef:e2:fa:ae:29:74:dc:83: + 36:87:88:7d:75:51:9a:c5:6e:a8:80:77:3f:5c:ed:9e:ac:57: + 17:ed:ab:64:4f:15:8b:47:90:0a:17:2a:7e:49:a9:01:a1:41: + 66:d4:fe:be:18:70:d6:23:f7:0b:0a:53:d7:75:a8:7f:0a:52: + 1c:1d:8c:63:6f:82:ed:ed:fd:e2:fe:86:ef:0a:4c:f8:d7:93: + 56:9a:a3:dd:74:02:8c:b3:31:83:c1:8a:66:c6:c0:1d:dc:00: + 5c:57:f4:31:31:8b:d4:84:d8:da:6d:d6:f6:e4:10:7e:bb:f2: + 41:95:dd:a6:0c:37:c7:22:80:e6:36:3e:34:c6:1c:73:ab:42: + 90:6e:f8:db:e8:b6:c0:b2:f5:17:d2:6f:d3:8c:fb:14:25:8e: + 72:81:45:76:86:f7:d1:d9:3d:ff:b1:a2:10:6f:c0:24:e7:70: + 3f:2d:cf:32:ee:06:70:d5:1b:04:84:6d:48:69:26:1e:98:5a: + ed:e3:61:f5:29:45:88:25:cf:7f:c4:fb:f3:87:a7:11:95:9e: + cf:a8:aa:88:db:12:32:66:66:c4:1d:12:b1:62:1d:fa:28:f4: + 97:ac:df:2e -----BEGIN CERTIFICATE----- -MIIC1TCCAj6gAwIBAgIJANjT46bL48zzMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy -MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMD4xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVkaWF0ZSBDQTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5YrOPYfkD2hCpJJEla98gjCLls2QcB -aY93KHFCouuuhhDGMWGaFIhECmi/bqJGQelvoon7C/PhuDC/5YBe+WGNbqzi9yjn -nkQouORuh3ap16ztET/ew91Bw0WCCcOnTObfK4geRM7ipylT9hOWrWwukwAoQne8 -c26G51vo6+k3HWPn6gVacSjwgQtMP91z+NsTqPBfb2/lG8eUf1fF3GYmDFpxeuPS -PnqmWUYDYXiJhD3vIpz4wiJ1xAzv++T6b7gR26qSm2wjTm7lVdJBRxiVxn0Xvm2r -OaE4Yf35IpVp854o/YrIWHI8kcIi2fuyVA+aFyeI32D13vyVnyXGZIECAwEAAaNm -MGQwHQYDVR0OBBYEFIQJi1UffS8PKNec7FROnxGXVdm5MB8GA1UdIwQYMBaAFLiS -3v2KGLMww59V8zNdtMgpikEUMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4GBAL0iYz2n5c7J9WYfd1/VJONo3KQHgD5e -sSyWiDmtAEyqnQvt823fnS+X0neLutCcD6ZeYLgP4ZaxYSVIaYFkqFyCWAvz0KlO -i5D8L2dX2nLcPOvCIBkFjUINFM8A21kA6vB2PsqFsQXluF8LRsc8odlcTbkk59Yr -PQ3rw4jYOvZg +MIIDaDCCAlCgAwIBAgIJANjT46bL48z3MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDMxNTIwMTBaFw0zMDA1MDMxNTIwMTBaMD4xCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVy +bWVkaWF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKw3n/m +F2lLu43cT4uVM14T7qEB9YLebvyD2+ciX7mNK94Qck7agcH38+sO21tfkJK7QWhV +T4TZc1sMbUDmxQ9dXF6AHmSHWplEiz1hIPAVzIeVW6BGD7xcFO6sT8h80sDvYJQi +tnQFT8qXAQowtFBEidDCa+V/zmYiGtY4fP9CQspYoDiFyvGxHzMn279cSZY2ehEv +Ytfrfp+bnA4r381ZvO7oauN9+ga6NEK1fee+4XuFrxslqUUzBsvMDcp4XFZSrEN+ +9gzn+4a0rNf0slTuZXpcMmszoGgb2OrIdJQIAH+b8NqAD/JFExFjTObSl9OuErB8 +6PBWwHt8gpltO10CAwEAAaNmMGQwHQYDVR0OBBYEFOvcjTh1EC/mgo7+Q+yffmMi +vVFVMB8GA1UdIwQYMBaAFKT9uTkbgbOq64gd1IGptRFwzKfhMBIGA1UdEwEB/wQI +MAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQCGdHWy +u7CFJUg44TRU1dQ6nw6xlv3M6hUhctqe7+L6ril03IM2h4h9dVGaxW6ogHc/XO2e +rFcX7atkTxWLR5AKFyp+SakBoUFm1P6+GHDWI/cLClPXdah/ClIcHYxjb4Lt7f3i +/obvCkz415NWmqPddAKMszGDwYpmxsAd3ABcV/QxMYvUhNjabdb25BB+u/JBld2m +DDfHIoDmNj40xhxzq0KQbvjb6LbAsvUX0m/TjPsUJY5ygUV2hvfR2T3/saIQb8Ak +53A/Lc8y7gZw1RsEhG1IaSYemFrt42H1KUWIJc9/xPvzh6cRlZ7PqKqI2xIyZmbE +HRKxYh36KPSXrN8u -----END CERTIFICATE----- Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162817 (0xd8d3e3a6cbe3ccc1) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + 42:97:6c:30:8e:79:fc:7b:6a:e3:ef:9d:18:a4:74:9d:8b:5f:57:53 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Validity - Not Before: Jun 29 16:41:22 2013 GMT - Not After : Jun 27 16:41:22 2023 GMT - Subject: C=FI, O=w1.fi, CN=Root CA + Not Before: May 2 19:49:48 2020 GMT + Not After : Apr 30 19:49:48 2030 GMT + Subject: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:be:1e:86:e4:79:03:c1:d1:94:d5:d4:b3:b1:28: - 90:76:fb:b8:a6:cd:6d:1c:d1:48:f4:08:9a:67:ff: - f9:a6:54:b1:19:29:df:29:1b:cd:f1:6f:66:01:e7: - db:79:ce:c0:39:2a:25:13:26:94:0c:2c:7b:5a:2c: - 81:0f:94:ee:51:d0:75:e6:46:db:17:46:a7:15:8b: - 0e:57:0f:b0:54:76:63:12:ca:86:18:bc:1a:c3:16: - c0:70:09:d6:6b:43:39:b8:98:29:46:ac:cb:6a:ad: - 38:88:3b:07:dc:81:cd:3a:f6:1d:f6:2f:ef:1d:d7: - ae:8a:b6:d1:e7:b3:15:02:b9 + 00:bc:f4:ee:44:62:7f:62:4f:a1:81:46:ba:c4:aa: + 1e:fd:4e:d0:ed:f1:47:cb:25:5b:66:7a:86:39:91: + ca:b5:61:a7:7e:2f:3c:63:7d:39:b8:1a:9e:cb:6d: + 32:32:91:de:49:49:84:da:15:be:2b:dd:c6:bc:1f: + dc:6e:c0:2d:77:f2:d0:7b:2c:40:19:07:60:55:b0: + ff:7c:51:ef:38:d1:f0:2a:da:a8:cc:ea:d6:54:a4: + ef:be:17:44:1a:9e:33:70:57:a4:f3:06:ac:3d:ee: + 4b:2d:e5:46:25:2d:33:09:f6:49:a8:02:31:a4:65: + 9b:32:0a:67:f5:02:e1:3b:47:a6:ae:e4:f6:85:eb: + 5d:3e:02:66:dd:11:98:ac:34:72:c2:8f:25:55:4a: + 6a:ea:e8:82:2f:bd:7f:78:31:a4:5a:d7:32:bb:64: + 48:46:23:ef:c8:c9:e2:84:00:56:72:e8:4b:54:95: + 62:3a:5a:11:79:ee:40:43:9e:16:2c:cc:e6:45:f4: + bb:82:28:c2:83:35:2c:55:36:99:59:11:b1:15:d0: + 03:c1:a5:37:e1:1f:bb:43:c7:b4:b9:33:de:14:d7: + 7c:99:45:0f:c1:06:fe:b6:25:10:59:b7:72:76:7f: + 91:4b:ea:d1:b9:6a:6a:ed:dd:1b:a9:0e:a7:29:48: + b7:4d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 1a:cf:77:60:44:43:c4:55:0e:99:e0:89:aa:b9:d3:7b:32:b7: - 5c:9c:7c:ca:fe:8c:d4:94:c6:5e:f3:83:19:5f:29:59:68:a4: - 4f:dc:04:2e:b8:71:c0:6d:3b:ae:01:e4:b9:88:99:cc:ce:82: - be:6a:28:c2:ac:6a:94:c6:87:90:ed:85:3c:10:71:c5:ff:3c: - 70:64:e2:41:62:31:ea:86:7b:11:8c:93:ea:c6:f3:f3:4e:f9: - d4:f2:81:90:d7:f4:fa:a1:91:6e:d4:dd:15:3e:26:3b:ac:1e: - c3:c2:1f:ed:bb:34:bf:cb:b2:67:c6:c6:51:e8:51:22:b4:f3: - 92:e8 + Signature Algorithm: sha256WithRSAEncryption + 41:f9:c3:a3:77:11:92:55:e7:4b:4a:32:6a:31:d9:51:cf:06: + a5:39:ea:30:98:b8:8d:4f:24:c5:34:fd:c6:98:10:59:32:7e: + 57:f5:8f:ba:67:c9:fc:44:68:b3:7c:f1:af:3a:5f:0d:8f:a1: + fe:41:21:0e:e9:08:a3:63:49:66:34:4a:cd:ce:66:74:47:30: + f7:dc:82:99:21:56:82:ff:2d:12:90:7d:7a:64:22:a0:ed:fa: + 62:d9:5a:d3:97:96:0c:04:a7:47:88:da:53:b6:33:15:15:f9: + da:ee:ac:25:e9:07:02:89:bc:73:a2:c6:27:6f:1f:bd:73:b8: + 8e:f7:94:54:57:a7:8b:5b:9a:24:aa:86:d4:04:5c:8c:cb:28: + a2:45:f9:34:f0:01:20:bb:06:e8:41:14:d2:d7:ca:e8:bf:4e: + 16:72:22:a0:0c:86:ca:73:23:09:ae:71:f1:52:0c:db:b2:8a: + 4d:94:a5:fa:15:81:5b:a2:95:62:50:a1:d6:64:fe:4c:0c:60: + 8d:9b:0f:b8:41:ac:cb:31:c2:17:6c:7b:61:13:16:9a:db:64: + fc:5f:47:84:3d:d2:2e:db:0b:9e:b6:1e:85:04:c1:e5:c0:b2: + 6d:8f:f2:99:00:3a:1a:ab:02:cf:45:7a:26:c1:b0:1f:c6:b0: + d0:4d:f7:52 -----BEGIN CERTIFICATE----- -MIICLDCCAZWgAwIBAgIJANjT46bL48zBMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xMzA2 -MjkxNjQxMjJaFw0yMzA2MjcxNjQxMjJaMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEAvh6G5HkDwdGU1dSzsSiQdvu4ps1tHNFI9AiaZ//5plSxGSnfKRvN8W9m -Aefbec7AOSolEyaUDCx7WiyBD5TuUdB15kbbF0anFYsOVw+wVHZjEsqGGLwawxbA -cAnWa0M5uJgpRqzLaq04iDsH3IHNOvYd9i/vHdeuirbR57MVArkCAwEAAaNQME4w -HQYDVR0OBBYEFLiS3v2KGLMww59V8zNdtMgpikEUMB8GA1UdIwQYMBaAFLiS3v2K -GLMww59V8zNdtMgpikEUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA -Gs93YERDxFUOmeCJqrnTezK3XJx8yv6M1JTGXvODGV8pWWikT9wELrhxwG07rgHk -uYiZzM6CvmoowqxqlMaHkO2FPBBxxf88cGTiQWIx6oZ7EYyT6sbz80751PKBkNf0 -+qGRbtTdFT4mO6wew8If7bs0v8uyZ8bGUehRIrTzkug= +MIIDYDCCAkigAwIBAgIUQpdsMI55/Htq4++dGKR0nYtfV1MwDQYJKoZIhvcNAQEL +BQAwQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoMBXcx +LmZpMRAwDgYDVQQDDAdSb290IENBMB4XDTIwMDUwMjE5NDk0OFoXDTMwMDQzMDE5 +NDk0OFowQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoM +BXcxLmZpMRAwDgYDVQQDDAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAvPTuRGJ/Yk+hgUa6xKoe/U7Q7fFHyyVbZnqGOZHKtWGnfi88Y305 +uBqey20yMpHeSUmE2hW+K93GvB/cbsAtd/LQeyxAGQdgVbD/fFHvONHwKtqozOrW +VKTvvhdEGp4zcFek8wasPe5LLeVGJS0zCfZJqAIxpGWbMgpn9QLhO0emruT2hetd +PgJm3RGYrDRywo8lVUpq6uiCL71/eDGkWtcyu2RIRiPvyMnihABWcuhLVJViOloR +ee5AQ54WLMzmRfS7gijCgzUsVTaZWRGxFdADwaU34R+7Q8e0uTPeFNd8mUUPwQb+ +tiUQWbdydn+RS+rRuWpq7d0bqQ6nKUi3TQIDAQABo1AwTjAdBgNVHQ4EFgQUpP25 +ORuBs6rriB3Ugam1EXDMp+EwHwYDVR0jBBgwFoAUpP25ORuBs6rriB3Ugam1EXDM +p+EwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQfnDo3cRklXnS0oy +ajHZUc8GpTnqMJi4jU8kxTT9xpgQWTJ+V/WPumfJ/ERos3zxrzpfDY+h/kEhDukI +o2NJZjRKzc5mdEcw99yCmSFWgv8tEpB9emQioO36Ytla05eWDASnR4jaU7YzFRX5 +2u6sJekHAom8c6LGJ28fvXO4jveUVFeni1uaJKqG1ARcjMsookX5NPABILsG6EEU +0tfK6L9OFnIioAyGynMjCa5x8VIM27KKTZSl+hWBW6KVYlCh1mT+TAxgjZsPuEGs +yzHCF2x7YRMWmttk/F9HhD3SLtsLnrYehQTB5cCybY/ymQA6GqsCz0V6JsGwH8aw +0E33Ug== -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/iCA-server/cacert.pem b/tests/hwsim/auth_serv/iCA-server/cacert.pem index d5532e994..1ea16ecde 100644 --- a/tests/hwsim/auth_serv/iCA-server/cacert.pem +++ b/tests/hwsim/auth_serv/iCA-server/cacert.pem @@ -1,70 +1,81 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162867 (0xd8d3e3a6cbe3ccf3) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + d8:d3:e3:a6:cb:e3:cc:f7 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 22 19:37:36 2025 GMT + Not Before: May 3 15:20:10 2020 GMT + Not After : May 3 15:20:10 2030 GMT Subject: C=FI, O=w1.fi, CN=Server Intermediate CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:de:58:ac:e3:d8:7e:40:f6:84:2a:49:24:49:5a: - f7:c8:23:08:b9:6c:d9:07:01:69:8f:77:28:71:42: - a2:eb:ae:86:10:c6:31:61:9a:14:88:44:0a:68:bf: - 6e:a2:46:41:e9:6f:a2:89:fb:0b:f3:e1:b8:30:bf: - e5:80:5e:f9:61:8d:6e:ac:e2:f7:28:e7:9e:44:28: - b8:e4:6e:87:76:a9:d7:ac:ed:11:3f:de:c3:dd:41: - c3:45:82:09:c3:a7:4c:e6:df:2b:88:1e:44:ce:e2: - a7:29:53:f6:13:96:ad:6c:2e:93:00:28:42:77:bc: - 73:6e:86:e7:5b:e8:eb:e9:37:1d:63:e7:ea:05:5a: - 71:28:f0:81:0b:4c:3f:dd:73:f8:db:13:a8:f0:5f: - 6f:6f:e5:1b:c7:94:7f:57:c5:dc:66:26:0c:5a:71: - 7a:e3:d2:3e:7a:a6:59:46:03:61:78:89:84:3d:ef: - 22:9c:f8:c2:22:75:c4:0c:ef:fb:e4:fa:6f:b8:11: - db:aa:92:9b:6c:23:4e:6e:e5:55:d2:41:47:18:95: - c6:7d:17:be:6d:ab:39:a1:38:61:fd:f9:22:95:69: - f3:9e:28:fd:8a:c8:58:72:3c:91:c2:22:d9:fb:b2: - 54:0f:9a:17:27:88:df:60:f5:de:fc:95:9f:25:c6: - 64:81 + 00:a2:b0:de:7f:e6:17:69:4b:bb:8d:dc:4f:8b:95: + 33:5e:13:ee:a1:01:f5:82:de:6e:fc:83:db:e7:22: + 5f:b9:8d:2b:de:10:72:4e:da:81:c1:f7:f3:eb:0e: + db:5b:5f:90:92:bb:41:68:55:4f:84:d9:73:5b:0c: + 6d:40:e6:c5:0f:5d:5c:5e:80:1e:64:87:5a:99:44: + 8b:3d:61:20:f0:15:cc:87:95:5b:a0:46:0f:bc:5c: + 14:ee:ac:4f:c8:7c:d2:c0:ef:60:94:22:b6:74:05: + 4f:ca:97:01:0a:30:b4:50:44:89:d0:c2:6b:e5:7f: + ce:66:22:1a:d6:38:7c:ff:42:42:ca:58:a0:38:85: + ca:f1:b1:1f:33:27:db:bf:5c:49:96:36:7a:11:2f: + 62:d7:eb:7e:9f:9b:9c:0e:2b:df:cd:59:bc:ee:e8: + 6a:e3:7d:fa:06:ba:34:42:b5:7d:e7:be:e1:7b:85: + af:1b:25:a9:45:33:06:cb:cc:0d:ca:78:5c:56:52: + ac:43:7e:f6:0c:e7:fb:86:b4:ac:d7:f4:b2:54:ee: + 65:7a:5c:32:6b:33:a0:68:1b:d8:ea:c8:74:94:08: + 00:7f:9b:f0:da:80:0f:f2:45:13:11:63:4c:e6:d2: + 97:d3:ae:12:b0:7c:e8:f0:56:c0:7b:7c:82:99:6d: + 3b:5d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - 84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9 + EB:DC:8D:38:75:10:2F:E6:82:8E:FE:43:EC:9F:7E:63:22:BD:51:55 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Certificate Sign, CRL Sign Signature Algorithm: sha256WithRSAEncryption - bd:22:63:3d:a7:e5:ce:c9:f5:66:1f:77:5f:d5:24:e3:68:dc: - a4:07:80:3e:5e:b1:2c:96:88:39:ad:00:4c:aa:9d:0b:ed:f3: - 6d:df:9d:2f:97:d2:77:8b:ba:d0:9c:0f:a6:5e:60:b8:0f:e1: - 96:b1:61:25:48:69:81:64:a8:5c:82:58:0b:f3:d0:a9:4e:8b: - 90:fc:2f:67:57:da:72:dc:3c:eb:c2:20:19:05:8d:42:0d:14: - cf:00:db:59:00:ea:f0:76:3e:ca:85:b1:05:e5:b8:5f:0b:46: - c7:3c:a1:d9:5c:4d:b9:24:e7:d6:2b:3d:0d:eb:c3:88:d8:3a: - f6:60 + 86:74:75:b2:bb:b0:85:25:48:38:e1:34:54:d5:d4:3a:9f:0e: + b1:96:fd:cc:ea:15:21:72:da:9e:ef:e2:fa:ae:29:74:dc:83: + 36:87:88:7d:75:51:9a:c5:6e:a8:80:77:3f:5c:ed:9e:ac:57: + 17:ed:ab:64:4f:15:8b:47:90:0a:17:2a:7e:49:a9:01:a1:41: + 66:d4:fe:be:18:70:d6:23:f7:0b:0a:53:d7:75:a8:7f:0a:52: + 1c:1d:8c:63:6f:82:ed:ed:fd:e2:fe:86:ef:0a:4c:f8:d7:93: + 56:9a:a3:dd:74:02:8c:b3:31:83:c1:8a:66:c6:c0:1d:dc:00: + 5c:57:f4:31:31:8b:d4:84:d8:da:6d:d6:f6:e4:10:7e:bb:f2: + 41:95:dd:a6:0c:37:c7:22:80:e6:36:3e:34:c6:1c:73:ab:42: + 90:6e:f8:db:e8:b6:c0:b2:f5:17:d2:6f:d3:8c:fb:14:25:8e: + 72:81:45:76:86:f7:d1:d9:3d:ff:b1:a2:10:6f:c0:24:e7:70: + 3f:2d:cf:32:ee:06:70:d5:1b:04:84:6d:48:69:26:1e:98:5a: + ed:e3:61:f5:29:45:88:25:cf:7f:c4:fb:f3:87:a7:11:95:9e: + cf:a8:aa:88:db:12:32:66:66:c4:1d:12:b1:62:1d:fa:28:f4: + 97:ac:df:2e -----BEGIN CERTIFICATE----- -MIIC1TCCAj6gAwIBAgIJANjT46bL48zzMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy -MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMD4xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVkaWF0ZSBDQTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5YrOPYfkD2hCpJJEla98gjCLls2QcB -aY93KHFCouuuhhDGMWGaFIhECmi/bqJGQelvoon7C/PhuDC/5YBe+WGNbqzi9yjn -nkQouORuh3ap16ztET/ew91Bw0WCCcOnTObfK4geRM7ipylT9hOWrWwukwAoQne8 -c26G51vo6+k3HWPn6gVacSjwgQtMP91z+NsTqPBfb2/lG8eUf1fF3GYmDFpxeuPS -PnqmWUYDYXiJhD3vIpz4wiJ1xAzv++T6b7gR26qSm2wjTm7lVdJBRxiVxn0Xvm2r -OaE4Yf35IpVp854o/YrIWHI8kcIi2fuyVA+aFyeI32D13vyVnyXGZIECAwEAAaNm -MGQwHQYDVR0OBBYEFIQJi1UffS8PKNec7FROnxGXVdm5MB8GA1UdIwQYMBaAFLiS -3v2KGLMww59V8zNdtMgpikEUMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4GBAL0iYz2n5c7J9WYfd1/VJONo3KQHgD5e -sSyWiDmtAEyqnQvt823fnS+X0neLutCcD6ZeYLgP4ZaxYSVIaYFkqFyCWAvz0KlO -i5D8L2dX2nLcPOvCIBkFjUINFM8A21kA6vB2PsqFsQXluF8LRsc8odlcTbkk59Yr -PQ3rw4jYOvZg +MIIDaDCCAlCgAwIBAgIJANjT46bL48z3MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDMxNTIwMTBaFw0zMDA1MDMxNTIwMTBaMD4xCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVy +bWVkaWF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKw3n/m +F2lLu43cT4uVM14T7qEB9YLebvyD2+ciX7mNK94Qck7agcH38+sO21tfkJK7QWhV +T4TZc1sMbUDmxQ9dXF6AHmSHWplEiz1hIPAVzIeVW6BGD7xcFO6sT8h80sDvYJQi +tnQFT8qXAQowtFBEidDCa+V/zmYiGtY4fP9CQspYoDiFyvGxHzMn279cSZY2ehEv +Ytfrfp+bnA4r381ZvO7oauN9+ga6NEK1fee+4XuFrxslqUUzBsvMDcp4XFZSrEN+ +9gzn+4a0rNf0slTuZXpcMmszoGgb2OrIdJQIAH+b8NqAD/JFExFjTObSl9OuErB8 +6PBWwHt8gpltO10CAwEAAaNmMGQwHQYDVR0OBBYEFOvcjTh1EC/mgo7+Q+yffmMi +vVFVMB8GA1UdIwQYMBaAFKT9uTkbgbOq64gd1IGptRFwzKfhMBIGA1UdEwEB/wQI +MAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQCGdHWy +u7CFJUg44TRU1dQ6nw6xlv3M6hUhctqe7+L6ril03IM2h4h9dVGaxW6ogHc/XO2e +rFcX7atkTxWLR5AKFyp+SakBoUFm1P6+GHDWI/cLClPXdah/ClIcHYxjb4Lt7f3i +/obvCkz415NWmqPddAKMszGDwYpmxsAd3ABcV/QxMYvUhNjabdb25BB+u/JBld2m +DDfHIoDmNj40xhxzq0KQbvjb6LbAsvUX0m/TjPsUJY5ygUV2hvfR2T3/saIQb8Ak +53A/Lc8y7gZw1RsEhG1IaSYemFrt42H1KUWIJc9/xPvzh6cRlZ7PqKqI2xIyZmbE +HRKxYh36KPSXrN8u -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/iCA-server/careq.pem b/tests/hwsim/auth_serv/iCA-server/careq.pem index 70726e8ed..31445908b 100644 --- a/tests/hwsim/auth_serv/iCA-server/careq.pem +++ b/tests/hwsim/auth_serv/iCA-server/careq.pem @@ -1,16 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- MIICljCCAX4CAQAwUTELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4w DAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVkaWF0ZSBDQTCC -ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5YrOPYfkD2hCpJJEla98gj -CLls2QcBaY93KHFCouuuhhDGMWGaFIhECmi/bqJGQelvoon7C/PhuDC/5YBe+WGN -bqzi9yjnnkQouORuh3ap16ztET/ew91Bw0WCCcOnTObfK4geRM7ipylT9hOWrWwu -kwAoQne8c26G51vo6+k3HWPn6gVacSjwgQtMP91z+NsTqPBfb2/lG8eUf1fF3GYm -DFpxeuPSPnqmWUYDYXiJhD3vIpz4wiJ1xAzv++T6b7gR26qSm2wjTm7lVdJBRxiV -xn0Xvm2rOaE4Yf35IpVp854o/YrIWHI8kcIi2fuyVA+aFyeI32D13vyVnyXGZIEC -AwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQCdd8AniQQQA4urnrqdR9hQlFY5JxUU -OtGqkRGb8pTJAfxU8hgmAhbHmPw7qhNnZNqr2i/p8A1UcwCuU7Sx2StszIjyuEQJ -SteaUpvLUWM/KrlqBH4VTcHFGsZWEJ+gMhBJwJuET6mtZFdm84HALJClIysx973p -d6i92H93ew3RuMF/erMnCPNjt0Pe8QWU/tpwsVD/SBGbqg8PCShqySNO9P+P1pAb -wIPInq3ox2E6RStFnIY8MES5sTUFWAxh3MNYY8OuVcuun2R0Yk0jy/wmmaWzcXS+ -sOj48LNyptGk8SAS1Yxu8lUfj3p77eZZqUqLorj/hdoqfnMOnCx7NOww +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKw3n/mF2lLu43cT4uVM14T +7qEB9YLebvyD2+ciX7mNK94Qck7agcH38+sO21tfkJK7QWhVT4TZc1sMbUDmxQ9d +XF6AHmSHWplEiz1hIPAVzIeVW6BGD7xcFO6sT8h80sDvYJQitnQFT8qXAQowtFBE +idDCa+V/zmYiGtY4fP9CQspYoDiFyvGxHzMn279cSZY2ehEvYtfrfp+bnA4r381Z +vO7oauN9+ga6NEK1fee+4XuFrxslqUUzBsvMDcp4XFZSrEN+9gzn+4a0rNf0slTu +ZXpcMmszoGgb2OrIdJQIAH+b8NqAD/JFExFjTObSl9OuErB86PBWwHt8gpltO10C +AwEAAaAAMA0GCSqGSIb3DQEBCwUAA4IBAQA+ruQc1HRbWOLQh+vOzw4e8WMPZ3nr +9qTDKjtpQKQUiNy7ZtCvi3kTtYVQcmyXWFf+Fq7NCHfH6GUgXfH/cCsOW0gdsPmH +YuAfZam1njO3+qZqacCpxaVmn3XExC01oIFLf0CtepXrMDh23MoPtZt7kh7bwomG +vrUtAecjLuZIIVzD2OkOIFZCEi4Dce85+CrDw7Es59xj1WySvHMWgU5prOf5Wp// +7yS26YYjHcaJ3ePO/mFnB3XH4rrQwczNAHx6W4NE0IPvbE9FRN7fIQGPCN40XsPc +XCR12oNtPBWpHExHsqCk6d6B3omfLUJe8eJiY1hPKiDI2ATdBoX5Ogbs -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/iCA-server/index.txt b/tests/hwsim/auth_serv/iCA-server/index.txt index a480a97b5..fe7d24864 100644 --- a/tests/hwsim/auth_serv/iCA-server/index.txt +++ b/tests/hwsim/auth_serv/iCA-server/index.txt @@ -1,2 +1,2 @@ -V 251220193736Z 8020A0407F798AB8 unknown /C=FI/O=w1.fi/CN=server.w1.fi -R 251220193736Z 151223193736Z 8020A0407F798AB9 unknown /C=FI/O=w1.fi/CN=server-revoked.w1.fi +V 300501152010Z 5C9DE4A6D17A49C88375E75768F77216B2AEB782 unknown /C=FI/O=w1.fi/CN=server.w1.fi +R 300501152010Z 200503152010Z 5C9DE4A6D17A49C88375E75768F77216B2AEB783 unknown /C=FI/O=w1.fi/CN=server-revoked.w1.fi diff --git a/tests/hwsim/auth_serv/iCA-server/index.txt.attr b/tests/hwsim/auth_serv/iCA-server/index.txt.attr index 8f7e63a34..3a7e39e6e 100644 --- a/tests/hwsim/auth_serv/iCA-server/index.txt.attr +++ b/tests/hwsim/auth_serv/iCA-server/index.txt.attr @@ -1 +1 @@ -unique_subject = yes +unique_subject = no diff --git a/tests/hwsim/auth_serv/iCA-server/newcerts/8020A0407F798AB8.pem b/tests/hwsim/auth_serv/iCA-server/newcerts/8020A0407F798AB8.pem deleted file mode 100644 index ebcbde353..000000000 --- a/tests/hwsim/auth_serv/iCA-server/newcerts/8020A0407F798AB8.pem +++ /dev/null @@ -1,84 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 9232555434986539704 (0x8020a0407f798ab8) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Server Intermediate CA - Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 20 19:37:36 2025 GMT - Subject: C=FI, O=w1.fi, CN=server.w1.fi - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:e4:88:a5:93:02:5b:bc:54:68:46:fa:73:7d:33: - 30:47:45:5c:49:5f:3c:51:5f:9b:fe:c5:14:10:26: - 3d:0f:e3:c2:b2:17:84:d3:3e:12:a8:b2:7b:02:1a: - 8a:8b:e9:f4:41:1e:fc:f3:49:2d:c6:d4:88:27:81: - d0:86:f3:b9:c0:0a:2a:28:45:00:32:c3:18:22:f6: - 99:37:f1:74:8d:ac:54:47:73:e5:b6:d3:e7:f8:80: - 99:75:f5:19:19:eb:19:70:df:92:53:b1:61:38:ff: - 7f:cf:8b:bd:e1:7f:50:5b:d0:95:30:a3:37:6b:8a: - 72:06:a7:e8:39:e2:a4:78:43:98:91:cd:30:88:34: - 5b:aa:9e:a2:9f:26:d5:e1:5b:86:4d:01:a4:c2:65: - cd:27:94:be:e2:f5:73:5d:c4:60:98:f1:75:11:94: - 09:0d:9d:04:7f:ef:1a:9d:5f:f0:4a:3f:88:d7:76: - 2e:9b:d6:2a:c6:94:09:37:0a:37:24:92:91:9d:18: - 0f:ea:4e:d4:e4:9d:45:38:5a:ba:d8:df:b6:15:6f: - ac:ff:6c:41:ac:d7:c0:0a:55:ec:81:ca:9a:59:40: - 55:8b:a4:77:13:df:fa:c3:b5:ee:ef:87:41:8d:94: - d0:c0:96:41:b4:3a:04:b6:6b:6a:56:93:f4:67:7e: - 27:e1 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: critical - CA:FALSE - X509v3 Subject Key Identifier: - 4B:81:85:B4:88:41:0D:D4:15:D3:48:0E:F4:A9:99:14:2D:B1:DB:93 - X509v3 Authority Key Identifier: - keyid:84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9 - - X509v3 Subject Alternative Name: critical - DNS:server.w1.fi - X509v3 Extended Key Usage: critical - TLS Web Server Authentication - X509v3 Key Usage: - Digital Signature, Key Encipherment - Signature Algorithm: sha256WithRSAEncryption - 49:2a:14:22:16:2c:12:f5:4e:06:f3:c2:1e:ac:54:07:5d:86: - 16:3e:6c:a0:73:e1:a6:d7:c3:49:1f:80:0d:b6:54:22:77:ce: - 39:dd:f6:f6:9f:62:ff:d5:27:7f:c3:92:73:b9:a7:ce:87:5a: - e3:bc:52:b3:0a:99:eb:91:56:b6:78:01:c3:0e:4b:ca:8a:04: - ee:5c:56:05:ef:7a:cb:21:f9:eb:8a:38:12:50:c7:6e:a8:1f: - 0e:81:81:a6:2d:ea:35:94:24:db:76:77:df:ea:41:4c:af:7e: - 29:9d:d5:e6:e3:12:78:19:92:ed:35:b9:99:19:a9:d6:cb:f8: - a7:21:fb:8e:a7:39:dc:e1:ab:3d:ba:12:87:ba:1c:08:e6:8a: - 21:96:44:44:8a:61:0f:70:00:d0:cb:63:93:a4:fa:cc:75:a3: - fd:e8:af:33:24:80:4a:d9:b9:2a:a1:20:0b:62:0b:17:6c:9a: - 7c:8b:fd:9e:ff:be:b2:51:5e:e9:3a:cc:28:22:63:44:69:7f: - 6d:1f:08:14:a4:32:d0:1f:f9:c3:8d:28:1a:76:12:00:3c:b3: - 38:13:ca:67:17:79:c6:de:5d:b7:9d:f8:e3:64:f7:b3:a0:5c: - e5:6e:fc:10:f3:53:d6:70:38:c2:6f:87:ab:07:1c:64:ff:30: - d8:3a:1e:75 ------BEGIN CERTIFICATE----- -MIIDiDCCAnCgAwIBAgIJAIAgoEB/eYq4MA0GCSqGSIb3DQEBCwUAMD4xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVk -aWF0ZSBDQTAeFw0xNTEyMjMxOTM3MzZaFw0yNTEyMjAxOTM3MzZaMDQxCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEVMBMGA1UEAwwMc2VydmVyLncxLmZpMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5IilkwJbvFRoRvpzfTMwR0Vc -SV88UV+b/sUUECY9D+PCsheE0z4SqLJ7AhqKi+n0QR7880ktxtSIJ4HQhvO5wAoq -KEUAMsMYIvaZN/F0jaxUR3PlttPn+ICZdfUZGesZcN+SU7FhOP9/z4u94X9QW9CV -MKM3a4pyBqfoOeKkeEOYkc0wiDRbqp6inybV4VuGTQGkwmXNJ5S+4vVzXcRgmPF1 -EZQJDZ0Ef+8anV/wSj+I13Yum9YqxpQJNwo3JJKRnRgP6k7U5J1FOFq62N+2FW+s -/2xBrNfAClXsgcqaWUBVi6R3E9/6w7Xu74dBjZTQwJZBtDoEtmtqVpP0Z34n4QID -AQABo4GSMIGPMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFEuBhbSIQQ3UFdNIDvSp -mRQtsduTMB8GA1UdIwQYMBaAFIQJi1UffS8PKNec7FROnxGXVdm5MBoGA1UdEQEB -/wQQMA6CDHNlcnZlci53MS5maTAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATALBgNV -HQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggEBAEkqFCIWLBL1Tgbzwh6sVAddhhY+ -bKBz4abXw0kfgA22VCJ3zjnd9vafYv/VJ3/DknO5p86HWuO8UrMKmeuRVrZ4AcMO -S8qKBO5cVgXvessh+euKOBJQx26oHw6BgaYt6jWUJNt2d9/qQUyvfimd1ebjEngZ -ku01uZkZqdbL+Kch+46nOdzhqz26Eoe6HAjmiiGWRESKYQ9wANDLY5Ok+sx1o/3o -rzMkgErZuSqhIAtiCxdsmnyL/Z7/vrJRXuk6zCgiY0Rpf20fCBSkMtAf+cONKBp2 -EgA8szgTymcXecbeXbed+ONk97OgXOVu/BDzU9ZwOMJvh6sHHGT/MNg6HnU= ------END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/iCA-server/newcerts/8020A0407F798AB9.pem b/tests/hwsim/auth_serv/iCA-server/newcerts/8020A0407F798AB9.pem deleted file mode 100644 index 737978502..000000000 --- a/tests/hwsim/auth_serv/iCA-server/newcerts/8020A0407F798AB9.pem +++ /dev/null @@ -1,85 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 9232555434986539705 (0x8020a0407f798ab9) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Server Intermediate CA - Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 20 19:37:36 2025 GMT - Subject: C=FI, O=w1.fi, CN=server-revoked.w1.fi - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:ac:5c:ae:06:36:4a:65:e0:db:0b:3c:28:13:08: - 8b:90:66:43:6f:c8:b2:3b:fa:41:bd:1a:10:10:fb: - e9:05:6a:ba:42:90:4d:2e:cf:b1:b9:c3:73:f5:fc: - ac:4c:18:e9:44:73:69:5e:2d:83:63:d1:29:e5:59: - 55:a8:bf:b0:1c:7a:0d:17:18:b0:38:21:af:cb:6d: - a9:6b:9d:a2:88:0e:1c:ee:1a:a5:9f:3c:27:ea:fe: - 8f:9b:94:df:12:3c:34:bb:bf:6c:d0:6c:6b:46:ad: - bc:ff:88:ae:d8:4d:8b:9f:34:50:25:c4:96:be:25: - 42:06:c8:b3:8e:21:a5:fd:a3:82:f9:74:78:46:56: - 8d:0b:f0:c4:fa:1a:0e:f5:34:22:53:fd:43:37:a3: - 47:fd:9f:a2:bc:d0:60:25:a8:db:93:f7:0c:88:fe: - 79:52:f2:07:f1:de:fc:66:6e:fe:da:10:76:6c:d0: - 87:8c:ef:dd:40:6d:82:7c:d1:39:b2:17:d6:07:cf: - 1a:5a:39:12:ed:49:4f:d9:c7:91:40:ab:73:f7:54: - 3c:a5:7d:9f:bb:0c:47:77:0e:d9:61:e5:1b:14:65: - 4e:38:c5:a7:8a:ee:32:be:05:25:94:a0:7f:96:09: - 59:1b:04:08:42:6b:50:6b:95:7a:78:f6:ec:f4:f6: - 4d:43 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: critical - CA:FALSE - X509v3 Subject Key Identifier: - 0D:49:37:45:42:77:90:25:BA:9B:67:DB:F6:DC:61:D2:53:5B:C6:BC - X509v3 Authority Key Identifier: - keyid:84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9 - - X509v3 Subject Alternative Name: critical - DNS:server-revoked.w1.fi - X509v3 Extended Key Usage: critical - TLS Web Server Authentication - X509v3 Key Usage: - Digital Signature, Key Encipherment - Signature Algorithm: sha256WithRSAEncryption - 22:c6:72:08:84:a9:e9:19:77:ea:6a:06:68:43:8b:e7:72:af: - 9c:a2:47:b9:6f:b6:cb:11:17:89:0a:42:52:14:58:9e:3c:01: - fd:e7:fc:a2:0d:85:a5:b5:8c:27:d5:5e:b2:47:05:05:f9:56: - b6:0b:e2:28:f3:1d:75:5e:13:eb:ec:a0:76:2b:d9:ed:99:84: - 08:6d:64:71:13:b6:02:81:b3:c2:7e:b8:b6:00:98:4f:26:ea: - f1:67:5b:35:2a:26:d0:ca:a8:fb:eb:21:fb:f1:d6:5a:63:42: - 01:5f:b3:59:3d:f8:e0:4d:94:3a:3a:82:46:02:9d:81:2c:ef: - e5:46:c7:99:f4:2f:43:ad:85:fc:2c:ca:0b:6b:48:01:ac:d7: - f7:da:0e:16:c4:10:18:14:83:9c:85:90:75:ef:66:9f:65:42: - e5:e7:8c:16:ac:f6:60:61:d7:5f:a0:21:cd:8a:85:d4:a0:f2: - 8e:17:0e:38:5e:31:12:ac:24:b5:67:61:9d:15:84:0b:fc:84: - 8a:d4:29:90:3d:4b:23:48:19:6b:f7:26:1f:fe:b9:b9:f1:6e: - 70:ac:ec:31:60:be:7d:6f:58:7e:c1:47:61:a7:b0:4b:b2:fd: - 62:06:c5:97:43:28:39:a5:c5:60:51:c0:46:9d:6b:e4:1a:ed: - 0c:a6:51:8a ------BEGIN CERTIFICATE----- -MIIDmDCCAoCgAwIBAgIJAIAgoEB/eYq5MA0GCSqGSIb3DQEBCwUAMD4xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVk -aWF0ZSBDQTAeFw0xNTEyMjMxOTM3MzZaFw0yNTEyMjAxOTM3MzZaMDwxCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUc2VydmVyLXJldm9rZWQu -dzEuZmkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsXK4GNkpl4NsL -PCgTCIuQZkNvyLI7+kG9GhAQ++kFarpCkE0uz7G5w3P1/KxMGOlEc2leLYNj0Snl -WVWov7Aceg0XGLA4Ia/LbalrnaKIDhzuGqWfPCfq/o+blN8SPDS7v2zQbGtGrbz/ -iK7YTYufNFAlxJa+JUIGyLOOIaX9o4L5dHhGVo0L8MT6Gg71NCJT/UM3o0f9n6K8 -0GAlqNuT9wyI/nlS8gfx3vxmbv7aEHZs0IeM791AbYJ80TmyF9YHzxpaORLtSU/Z -x5FAq3P3VDylfZ+7DEd3Dtlh5RsUZU44xaeK7jK+BSWUoH+WCVkbBAhCa1BrlXp4 -9uz09k1DAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUDUk3RUJ3 -kCW6m2fb9txh0lNbxrwwHwYDVR0jBBgwFoAUhAmLVR99Lw8o15zsVE6fEZdV2bkw -IgYDVR0RAQH/BBgwFoIUc2VydmVyLXJldm9rZWQudzEuZmkwFgYDVR0lAQH/BAww -CgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4IBAQAixnII -hKnpGXfqagZoQ4vncq+coke5b7bLEReJCkJSFFiePAH95/yiDYWltYwn1V6yRwUF -+Va2C+Io8x11XhPr7KB2K9ntmYQIbWRxE7YCgbPCfri2AJhPJurxZ1s1KibQyqj7 -6yH78dZaY0IBX7NZPfjgTZQ6OoJGAp2BLO/lRseZ9C9DrYX8LMoLa0gBrNf32g4W -xBAYFIOchZB172afZULl54wWrPZgYddfoCHNioXUoPKOFw44XjESrCS1Z2GdFYQL -/ISK1CmQPUsjSBlr9yYf/rm58W5wrOwxYL59b1h+wUdhp7BLsv1iBsWXQyg5pcVg -UcBGnWvkGu0MplGK ------END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/iCA-server/private/cakey.pem b/tests/hwsim/auth_serv/iCA-server/private/cakey.pem index 579139e72..67bad6718 100644 --- a/tests/hwsim/auth_serv/iCA-server/private/cakey.pem +++ b/tests/hwsim/auth_serv/iCA-server/private/cakey.pem @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDeWKzj2H5A9oQq -SSRJWvfIIwi5bNkHAWmPdyhxQqLrroYQxjFhmhSIRApov26iRkHpb6KJ+wvz4bgw -v+WAXvlhjW6s4vco555EKLjkbod2qdes7RE/3sPdQcNFggnDp0zm3yuIHkTO4qcp -U/YTlq1sLpMAKEJ3vHNuhudb6OvpNx1j5+oFWnEo8IELTD/dc/jbE6jwX29v5RvH -lH9XxdxmJgxacXrj0j56pllGA2F4iYQ97yKc+MIidcQM7/vk+m+4EduqkptsI05u -5VXSQUcYlcZ9F75tqzmhOGH9+SKVafOeKP2KyFhyPJHCItn7slQPmhcniN9g9d78 -lZ8lxmSBAgMBAAECggEAYEOYJtVWZB3WvtAH69J8sKOqZU1g8Q2FfF2kntSw4MUg -uiZ0vsMM3KpIr20iIxOz+bMhdgfA9wfkzQZoAJod8kRfhG6Hf6g3916CHjRUZeXG -wNGqxDJYLnUIbBGO1KycOOCqYjZoqAGtSdFWGskDsHDBqDHGBT0L5PB3Pm2rpb4u -JQV2Dcvqjf8MfDBGsyKx7+L+EtMXhcgUCQ4vRtvCvNV+Xl4wL37l1/OkfIPTWkQE -FpkBMy+/cvB8H6rmlAxp6t8EV9rbgyt9OW86+gf1q4U7VM6VUXFGjFvGwji9OkgA -UnwrdX0IryG/ruuKzIb6eBEb5hRoluGqHphptiX8IQKBgQD5/QazeInpiHkfZpm5 -obgLYtLHkQuewVIZVFhVAle07AaZ2748lRMu/UHo0YITS1mLK8AA7xVi+NjwIbg0 -WpoBQ4V6k7U/+PfLygFYbTB+vTreH6Za/zIpEXjYudemt5Xgjva+YEM5/rYNkNgH -d0Dcbuq1D5OgsEWs/S3jlPzWJQKBgQDjsXrj1wO8yYokv9kGETVN9604lYFNfTnD -HwAcEanCa+Ist6TpMZOK7QV78rmR5bxymLKI6UPCvrdqhLb+BuTl2GrSvrSeNwk4 -zAHi25MapTQxssJMtom88htbBIJ/P+0iEXKKXIRzIi0UXRNfoE5lwQZlHUdFHtlK -xUvnrgXALQKBgQCva2JcZeVAvsdfxXtxy41+T+Zgq+Nfj4CwzYL+hBpPlqA7Lvub -P3CqtISffwSrzWAUTKr6/MohHUX9m2vLMRiIcn0juqqhLW+UzTeMeXJiPR8l50ew -6wqjzuLiEebF0mWVojx68sm51IajllRBSOl2xU5lp3yMcaUy8qZU4KNbEQKBgBnu -lLhuPJa7vWgCEY2HWDLRCoFvRZK1uGZomXKY8GScNN4y7C1C4DLqW72KH2hmadgD -XBILvxPm9KzFALJdxqQGyePGpHuAeSRm17AmodJfDlq6qTZjc7x5NnRfRx2HAlLm -+cyYTN1v/wJat2Ikt8kO+tN5SiytHsJNRh/UygLhAoGAXctGrFNl7a/cg0b7zr8O -0t7UcaqXRpYHFTOaijL3WkI7Ps4us14lmkWvkM1iUjCyPtBCRNeYXu5HxENIn4p5 -RixqYvO1DO/9TYNL/fXReqtVEgYz8ygAmasRf7NSJxO1ByhCiJ+rxRXCTFic/GPU -k5WGvSSepCUM2RpqXVWsm44= +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCisN5/5hdpS7uN +3E+LlTNeE+6hAfWC3m78g9vnIl+5jSveEHJO2oHB9/PrDttbX5CSu0FoVU+E2XNb +DG1A5sUPXVxegB5kh1qZRIs9YSDwFcyHlVugRg+8XBTurE/IfNLA72CUIrZ0BU/K +lwEKMLRQRInQwmvlf85mIhrWOHz/QkLKWKA4hcrxsR8zJ9u/XEmWNnoRL2LX636f +m5wOK9/NWbzu6GrjffoGujRCtX3nvuF7ha8bJalFMwbLzA3KeFxWUqxDfvYM5/uG +tKzX9LJU7mV6XDJrM6BoG9jqyHSUCAB/m/DagA/yRRMRY0zm0pfTrhKwfOjwVsB7 +fIKZbTtdAgMBAAECggEAU2/YPMn5mcQAZYnmtdSIKqiYSrThgAOp8hGCFzE23Me9 +Br9ykGRaBeuvig7tixgg4k/tBKA0DxMiqUBfS9jOmcms1L5qV+5fFZnku070AI19 +fs+n1TP5YAXtqlZu+Iij4dUit/ZxkmEjAeid3OcLotrzvz/m7CW26gR1tQX1fUdh ++YFwUjyY1g2QRrUiPI/LJnOwJeZuxjnRaabmYjKvjHcbN/kmKWxqBrrTMU6KNq0o +4PPKragvpvePrKSPwOyQROlRXsj6qY/FMrXVrSVGfrUAk7NCmccbtJM6SY2/k3ly +Y69YWNj2laui5loTpUcuTFFPwmHkHBJC6GJCGoaHYQKBgQDNonjx7e0dzLjRzMUg +1SX4oH+IqL4oMq1Cs3l9iibFXFpG23gCh7ao54ehmYJE3088L7NGvGjoMl/4uj+T +WElFENCk0lzjxPPAEkAuHY3JApL+0ZsU4RyWjNVSOaD7eQCfN/og0ZgNW6+TUiOu +Wq6rA/KTywSUnnwdvqMTTXhDaQKBgQDKicYXLH8TmOvauRkrfWjS5XhBEplskxiQ +uqlQEXlbT3jymyIAdt+3hnydL557lbKPfTe/rs22wnH/++aUQTzQgKNs7oWSFyDt +km0LCGdLg7NuVNI4Sdi5SoIWsTcAkmkYA+KFy3YQK9vwr3eZ3ExbYI55QTyoVKON +jReguOBd1QKBgQC8LTMqiYVUoNR8wTuf6Q4/cHhk0a56UK22/VBvLq5+Kx49+3be +Md1Ywc+fdT/90LDMrgYL9Dy4R+kFT0MAjmk2d8XHHu58TO6WVN1AljD6wo1L/PpC +6CHmL2jDPxNvLPMBwRL3V3Yiu0V3tlIKqtdujkU9NCqz6jhAbAUFk/47CQKBgQCw +PRB868AsCl349iXbvQWwtfJdFVUhsCGpFnPr8ziZZt8EpE8C/m2PIdxfXqdWPJ2i +1D/lcLMae7p9F/G9QcMsXzNVv3vE8pE5iLeP6SERCanhsLc4ObH3Ecl++3ez7LK8 +Le03pSK30aJRni3BWXur66ouAsFIbFXg/0v3E8hQfQKBgQCicOnaNKD/dARZZhfR +eoX+97PRTpoloOF+jd/AOYq4ATZoNQwF2Jizs8fDbi0SUWFoFG8UmrrJ4xv4DBDq +rAeHvZle2K8od1/NjOG5/WFAF0/Aci+R5U/bX2/2vspb5AWBdwMbvnf7GKtwrAYU +TiK7X/iftZZWuApQauRR4yrCAw== -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/iCA-server/serial b/tests/hwsim/auth_serv/iCA-server/serial index 06b9bf87b..b40c84109 100644 --- a/tests/hwsim/auth_serv/iCA-server/serial +++ b/tests/hwsim/auth_serv/iCA-server/serial @@ -1 +1 @@ -8020A0407F798ABA +5C9DE4A6D17A49C88375E75768F77216B2AEB784 diff --git a/tests/hwsim/auth_serv/iCA-server/server-revoked.key b/tests/hwsim/auth_serv/iCA-server/server-revoked.key index 51f25170f..85c11d612 100644 --- a/tests/hwsim/auth_serv/iCA-server/server-revoked.key +++ b/tests/hwsim/auth_serv/iCA-server/server-revoked.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCsXK4GNkpl4NsL -PCgTCIuQZkNvyLI7+kG9GhAQ++kFarpCkE0uz7G5w3P1/KxMGOlEc2leLYNj0Snl -WVWov7Aceg0XGLA4Ia/LbalrnaKIDhzuGqWfPCfq/o+blN8SPDS7v2zQbGtGrbz/ -iK7YTYufNFAlxJa+JUIGyLOOIaX9o4L5dHhGVo0L8MT6Gg71NCJT/UM3o0f9n6K8 -0GAlqNuT9wyI/nlS8gfx3vxmbv7aEHZs0IeM791AbYJ80TmyF9YHzxpaORLtSU/Z -x5FAq3P3VDylfZ+7DEd3Dtlh5RsUZU44xaeK7jK+BSWUoH+WCVkbBAhCa1BrlXp4 -9uz09k1DAgMBAAECggEBAIodPemGaXlXg85t5uLRjxwnhdQ2KvQ6paDFGKizY1bO -3e/mt6JSFWT4hJxRWzMjJxCNtpobuFQsz/iS7DvrVlCLUJ/4TYS9IaPN/NtaFloV -jQMS4TJGvunkD+koktOG4O6tBqHArvmU0ISm3ww+nyn0fmC1NeGp802CV7cFqYAi -y5QT6FhBZYRGj8v+YH9I06Os+tr6C0tKdy5J5nMrbHa64XZulHn/McbeDImtnBfy -5aLOMIZjlat6nYjMC9dhAuDXKXodnmBW4Jq889UVbg+kgtu9r8Uga5Wx+IBKiieM -vjHOtJPCb4fHTjCl19G7D5WsXy4r/JNQyUQXlSLpO+kCgYEA4cTzLQ5D8WVsUBOp -cOZBi93AdbQvbbC7HhkMiFACmhs1cQhgvMXVgjdxt1NcX33tZ9kK8dnx41kp0/ey -/8JEJM5DI1RFqPIBkXi50RY32uazi7azoSAx0xvmkXvdpTdBUB5BjMHbqzxQZhgH -D4gtC93o2C53z1StE0Dr37b3zNcCgYEAw3EA+PN+y6Y5e13GLC9M0NSK1gFutCEK -RqhpCWG1NqJgKMcDTaqPyb74ky9JkAVlFA7WQUUOHInbY+ZCnRLRpgNzbvOgQd33 -g7e5kyHcYsdizZrn3qRKPqocmtFNIjs6xNYufdbMvEU66E752WQOq+TZI89vYkPB -E0uEyzcq6XUCgYAEIWVNirhFf1SG9oUgEqZaV7lArgY8HIKf31dyWvxhM2Q76CpU -6c2pLzh+YSEMgjJItxjTKeiZ/zSbsylsMnKqtbdWuyD3IU5UCgBkSeLFt3jLcpFA -vmUK9rS2Lqz0a9lfDN6oI5fQPy89Xu0qJJSmZe3vnpIEkgkElCh8lE1eSwKBgQC4 -Y7oeJmSfMEGVMcDRWQLpF02xYIKYcX+ncCZBEq0MUZ/VeQWV1fB4z7Ln8jo+Jcja -ZrEfvU32AN463zhDx0iCj0juCe5NlmR6IfF0bgLmMuT1xEs0k930RzxbmFJklGr6 -4HPWh7x7d/l+yVwSDMOGy49NqNyWYgQb9yjfLTpQLQKBgAM+hF/wgbDpA7GGP1ww -c9kouaXkylPHJWab28Gr2Ef9ixZjQ/RQrcc71H8e4/ZFAgTN0hclxQMdH2mo6ocC -cEyxajAci8QaX7RDKZUppsP9vbZk+7HTgyaCo2vh5xOPAeeTzOPhFSoxUhFfj+cP -Ybdr61y8Ug/YwixvsB0eZtLt +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC6httirVW8O0Hx +we89YRNtZYrRvlhBpuBd8sXzp8HCbJ6wX/AWLOS6fSa3aUNysdco0gY9bpxnMjg/ +PGOUjWPpf7N7ZwvWyQLs2n7hWyHkoeoB7Li9b17SkuUz2qUTpo4EtRl6B5roA+69 +SixlbOw6SDh+DTAw7hrZGr4C0OHylRchCDxJTY8Rx7SM5pNLSvrdrApy2IKK4WyZ +HncbiBKzcs/c+lfSY+EtwFpXNtT/NyAgAbQRGSz5m/b6k//KafKE62+vRLgY49hC +KZchAeFHofztWHSwq/l1XOhJqhZKGTHoxYxgmUif2XiS7DELIGTZVxxuaqbd+FUv +zCt2EbWbAgMBAAECggEBAIXTM5u8mQKP0WROrALxnyqh69NIKbIQtHEzOWrzNUT1 +AXWxn2OJmiFioWB+GXI0vhX/eZKhxX0Uvt4/yYJPXxusD22+JPRZC8w7h0TQSaTr +tiTjXjgrq3CRC/kEKePLX6Fo/Xpb8nv8NlGA4hFy8JlwL3fgpm60pnaVhTYn/7Q2 +oey4zIKwnRYp8oFf58iu5Otjga247AWiR3VDHTeSlvSQOMj+4RybQgpbeB6hVfrs +0IjR7hq+dBoMdY5NuEPhGIvcoQq2T6K7hYqIx2ou8OCDeBefdJOm30Y2Iu1CpEx5 +dwJWtgv+ZVHUKl7MlXYiLVZjzX2ZSOJukeNs8AoRrwECgYEA25Z2/XlT2E3C24Q3 +S6GZJtbPnvYLr8xHzQ1ljA39ltu5PQXcKRYAgaOGQtl6NhrpoE8uiiVXegbw0CP2 +yyKLlqn0JvJaZREpJcCPqdt4jDgNZ3ajXhiq1SFGsZsLxmrM0Iu43Kf2nxVQyP0R +6npuvlagOnggvCMzQWfQqsxrxDsCgYEA2XTy5BwmDhoczMbQozFFCd8MbzoDwnDR +hXVSEbG0TjNe/d9UfD8Y9xsV8tlkcDhfS3lwMFHp/poSnvjrF2vGmMNaLEcZnQEX +crqrL6gRpUs6dpv40Q/Dtkze3p2DoCD+La94RHjHrXtTJ5DZcliNZJt90zXz0Kmy +6abXvv8jniECgYEAjxSQvgLjdirdEAoruZU3ZM5NhKeP3+G820iiZUrsdPMA1VlP +JlpWxCIYJtDsR/rrRfCyQ4OnZzTEjusQMTZ2PBrLouEBs58l75p0Qdpmxv7zBPqR +4osyLSO8m5eKaaRHho+0SdsL4IaUGBKGLQHPzShGyTJjKhPJnxGVLuV6RucCgYAI +9XR8SVyYACNnnFlEH+eEPJg6jN1SyWsYYHj9GaEgB6XGN8k3RTI2G/uPgb1NkkT6 +ywoAM5+8SYSy3/ZvhJUt/f5dDKDVgxIAPAiJchcoBC1obYyWsFuTyx7zdPHTSwit +wSjnSUKQtx/55VHQEC3jEzTf2r0sv5ELZ0BEMia5gQKBgQCgOkdrjh7CHy8qZ51i +mlctafZyOnqp98i6q+R5AN5S9EDemKtUmAq7JSmBX/5cn1wgde115YiEwvt/xNmE +c0RBpcz+ZsgJnoQsCPUJmzIkwMIjZ3t9nrdHDTegcNJM1M7V7xN4jf7ycoynEmGK +k4XzV7M/nhOjiRwWCq6ba3Ddwg== -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/iCA-server/server-revoked.pem b/tests/hwsim/auth_serv/iCA-server/server-revoked.pem index 737978502..031b9d1a9 100644 --- a/tests/hwsim/auth_serv/iCA-server/server-revoked.pem +++ b/tests/hwsim/auth_serv/iCA-server/server-revoked.pem @@ -1,43 +1,44 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 9232555434986539705 (0x8020a0407f798ab9) - Signature Algorithm: sha256WithRSAEncryption + Serial Number: + 5c:9d:e4:a6:d1:7a:49:c8:83:75:e7:57:68:f7:72:16:b2:ae:b7:83 + Signature Algorithm: sha256WithRSAEncryption Issuer: C=FI, O=w1.fi, CN=Server Intermediate CA Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 20 19:37:36 2025 GMT + Not Before: May 3 15:20:10 2020 GMT + Not After : May 1 15:20:10 2030 GMT Subject: C=FI, O=w1.fi, CN=server-revoked.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:ac:5c:ae:06:36:4a:65:e0:db:0b:3c:28:13:08: - 8b:90:66:43:6f:c8:b2:3b:fa:41:bd:1a:10:10:fb: - e9:05:6a:ba:42:90:4d:2e:cf:b1:b9:c3:73:f5:fc: - ac:4c:18:e9:44:73:69:5e:2d:83:63:d1:29:e5:59: - 55:a8:bf:b0:1c:7a:0d:17:18:b0:38:21:af:cb:6d: - a9:6b:9d:a2:88:0e:1c:ee:1a:a5:9f:3c:27:ea:fe: - 8f:9b:94:df:12:3c:34:bb:bf:6c:d0:6c:6b:46:ad: - bc:ff:88:ae:d8:4d:8b:9f:34:50:25:c4:96:be:25: - 42:06:c8:b3:8e:21:a5:fd:a3:82:f9:74:78:46:56: - 8d:0b:f0:c4:fa:1a:0e:f5:34:22:53:fd:43:37:a3: - 47:fd:9f:a2:bc:d0:60:25:a8:db:93:f7:0c:88:fe: - 79:52:f2:07:f1:de:fc:66:6e:fe:da:10:76:6c:d0: - 87:8c:ef:dd:40:6d:82:7c:d1:39:b2:17:d6:07:cf: - 1a:5a:39:12:ed:49:4f:d9:c7:91:40:ab:73:f7:54: - 3c:a5:7d:9f:bb:0c:47:77:0e:d9:61:e5:1b:14:65: - 4e:38:c5:a7:8a:ee:32:be:05:25:94:a0:7f:96:09: - 59:1b:04:08:42:6b:50:6b:95:7a:78:f6:ec:f4:f6: - 4d:43 + 00:ba:86:db:62:ad:55:bc:3b:41:f1:c1:ef:3d:61: + 13:6d:65:8a:d1:be:58:41:a6:e0:5d:f2:c5:f3:a7: + c1:c2:6c:9e:b0:5f:f0:16:2c:e4:ba:7d:26:b7:69: + 43:72:b1:d7:28:d2:06:3d:6e:9c:67:32:38:3f:3c: + 63:94:8d:63:e9:7f:b3:7b:67:0b:d6:c9:02:ec:da: + 7e:e1:5b:21:e4:a1:ea:01:ec:b8:bd:6f:5e:d2:92: + e5:33:da:a5:13:a6:8e:04:b5:19:7a:07:9a:e8:03: + ee:bd:4a:2c:65:6c:ec:3a:48:38:7e:0d:30:30:ee: + 1a:d9:1a:be:02:d0:e1:f2:95:17:21:08:3c:49:4d: + 8f:11:c7:b4:8c:e6:93:4b:4a:fa:dd:ac:0a:72:d8: + 82:8a:e1:6c:99:1e:77:1b:88:12:b3:72:cf:dc:fa: + 57:d2:63:e1:2d:c0:5a:57:36:d4:ff:37:20:20:01: + b4:11:19:2c:f9:9b:f6:fa:93:ff:ca:69:f2:84:eb: + 6f:af:44:b8:18:e3:d8:42:29:97:21:01:e1:47:a1: + fc:ed:58:74:b0:ab:f9:75:5c:e8:49:aa:16:4a:19: + 31:e8:c5:8c:60:99:48:9f:d9:78:92:ec:31:0b:20: + 64:d9:57:1c:6e:6a:a6:dd:f8:55:2f:cc:2b:76:11: + b5:9b Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: critical CA:FALSE X509v3 Subject Key Identifier: - 0D:49:37:45:42:77:90:25:BA:9B:67:DB:F6:DC:61:D2:53:5B:C6:BC + FB:67:34:A4:0E:E6:BB:BF:90:0D:7C:B2:69:E8:04:D5:71:8F:76:44 X509v3 Authority Key Identifier: - keyid:84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9 + keyid:EB:DC:8D:38:75:10:2F:E6:82:8E:FE:43:EC:9F:7E:63:22:BD:51:55 X509v3 Subject Alternative Name: critical DNS:server-revoked.w1.fi @@ -46,40 +47,40 @@ Certificate: X509v3 Key Usage: Digital Signature, Key Encipherment Signature Algorithm: sha256WithRSAEncryption - 22:c6:72:08:84:a9:e9:19:77:ea:6a:06:68:43:8b:e7:72:af: - 9c:a2:47:b9:6f:b6:cb:11:17:89:0a:42:52:14:58:9e:3c:01: - fd:e7:fc:a2:0d:85:a5:b5:8c:27:d5:5e:b2:47:05:05:f9:56: - b6:0b:e2:28:f3:1d:75:5e:13:eb:ec:a0:76:2b:d9:ed:99:84: - 08:6d:64:71:13:b6:02:81:b3:c2:7e:b8:b6:00:98:4f:26:ea: - f1:67:5b:35:2a:26:d0:ca:a8:fb:eb:21:fb:f1:d6:5a:63:42: - 01:5f:b3:59:3d:f8:e0:4d:94:3a:3a:82:46:02:9d:81:2c:ef: - e5:46:c7:99:f4:2f:43:ad:85:fc:2c:ca:0b:6b:48:01:ac:d7: - f7:da:0e:16:c4:10:18:14:83:9c:85:90:75:ef:66:9f:65:42: - e5:e7:8c:16:ac:f6:60:61:d7:5f:a0:21:cd:8a:85:d4:a0:f2: - 8e:17:0e:38:5e:31:12:ac:24:b5:67:61:9d:15:84:0b:fc:84: - 8a:d4:29:90:3d:4b:23:48:19:6b:f7:26:1f:fe:b9:b9:f1:6e: - 70:ac:ec:31:60:be:7d:6f:58:7e:c1:47:61:a7:b0:4b:b2:fd: - 62:06:c5:97:43:28:39:a5:c5:60:51:c0:46:9d:6b:e4:1a:ed: - 0c:a6:51:8a + 22:c0:a0:7c:25:b4:4d:61:44:25:09:9c:14:8d:35:6e:36:7b: + 91:60:6b:35:90:48:a9:a2:ee:81:70:c4:d8:2a:9d:a3:7e:a2: + c9:0c:dc:b2:73:98:01:cf:db:d4:3a:17:8a:b6:3d:b5:97:47: + 33:e9:b6:14:ed:a6:8e:a4:6d:34:d0:03:3a:01:04:ce:28:24: + f9:c3:15:a9:b1:8c:2a:dc:8d:40:98:ac:78:8f:f5:fc:53:88: + 0e:84:28:39:86:75:59:ad:12:54:77:f2:9c:e1:d2:4e:e1:ee: + 8d:57:f3:41:ab:15:4d:ab:77:75:47:9a:c6:36:28:08:b5:8d: + c7:9f:5a:87:87:f8:a7:17:9a:44:4e:ce:84:24:12:da:7f:a8: + ab:15:fd:24:9b:cf:1c:ae:2f:8f:13:28:27:09:1e:57:2b:ca: + 1f:c8:bc:a4:95:08:27:4e:c4:21:68:a5:45:9f:5a:42:1c:7f: + 37:59:d7:ed:30:be:ed:26:12:5d:80:f5:7d:7d:94:ff:52:56: + fc:67:0f:3f:00:21:e7:b4:2f:48:7b:77:86:fb:16:28:ab:68: + e1:4d:80:eb:5e:4b:99:88:2f:ec:a3:1d:06:c5:04:2e:bb:56: + fb:6b:75:9d:5b:78:83:63:2b:70:7c:21:94:a1:58:a4:8e:8b: + 30:d3:28:88 -----BEGIN CERTIFICATE----- -MIIDmDCCAoCgAwIBAgIJAIAgoEB/eYq5MA0GCSqGSIb3DQEBCwUAMD4xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVk -aWF0ZSBDQTAeFw0xNTEyMjMxOTM3MzZaFw0yNTEyMjAxOTM3MzZaMDwxCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUc2VydmVyLXJldm9rZWQu -dzEuZmkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsXK4GNkpl4NsL -PCgTCIuQZkNvyLI7+kG9GhAQ++kFarpCkE0uz7G5w3P1/KxMGOlEc2leLYNj0Snl -WVWov7Aceg0XGLA4Ia/LbalrnaKIDhzuGqWfPCfq/o+blN8SPDS7v2zQbGtGrbz/ -iK7YTYufNFAlxJa+JUIGyLOOIaX9o4L5dHhGVo0L8MT6Gg71NCJT/UM3o0f9n6K8 -0GAlqNuT9wyI/nlS8gfx3vxmbv7aEHZs0IeM791AbYJ80TmyF9YHzxpaORLtSU/Z -x5FAq3P3VDylfZ+7DEd3Dtlh5RsUZU44xaeK7jK+BSWUoH+WCVkbBAhCa1BrlXp4 -9uz09k1DAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUDUk3RUJ3 -kCW6m2fb9txh0lNbxrwwHwYDVR0jBBgwFoAUhAmLVR99Lw8o15zsVE6fEZdV2bkw -IgYDVR0RAQH/BBgwFoIUc2VydmVyLXJldm9rZWQudzEuZmkwFgYDVR0lAQH/BAww -CgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4IBAQAixnII -hKnpGXfqagZoQ4vncq+coke5b7bLEReJCkJSFFiePAH95/yiDYWltYwn1V6yRwUF -+Va2C+Io8x11XhPr7KB2K9ntmYQIbWRxE7YCgbPCfri2AJhPJurxZ1s1KibQyqj7 -6yH78dZaY0IBX7NZPfjgTZQ6OoJGAp2BLO/lRseZ9C9DrYX8LMoLa0gBrNf32g4W -xBAYFIOchZB172afZULl54wWrPZgYddfoCHNioXUoPKOFw44XjESrCS1Z2GdFYQL -/ISK1CmQPUsjSBlr9yYf/rm58W5wrOwxYL59b1h+wUdhp7BLsv1iBsWXQyg5pcVg -UcBGnWvkGu0MplGK +MIIDozCCAougAwIBAgIUXJ3kptF6SciDdedXaPdyFrKut4MwDQYJKoZIhvcNAQEL +BQAwPjELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMR8wHQYDVQQDDBZTZXJ2 +ZXIgSW50ZXJtZWRpYXRlIENBMB4XDTIwMDUwMzE1MjAxMFoXDTMwMDUwMTE1MjAx +MFowPDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMR0wGwYDVQQDDBRzZXJ2 +ZXItcmV2b2tlZC53MS5maTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALqG22KtVbw7QfHB7z1hE21litG+WEGm4F3yxfOnwcJsnrBf8BYs5Lp9JrdpQ3Kx +1yjSBj1unGcyOD88Y5SNY+l/s3tnC9bJAuzafuFbIeSh6gHsuL1vXtKS5TPapROm +jgS1GXoHmugD7r1KLGVs7DpIOH4NMDDuGtkavgLQ4fKVFyEIPElNjxHHtIzmk0tK ++t2sCnLYgorhbJkedxuIErNyz9z6V9Jj4S3AWlc21P83ICABtBEZLPmb9vqT/8pp +8oTrb69EuBjj2EIplyEB4Ueh/O1YdLCr+XVc6EmqFkoZMejFjGCZSJ/ZeJLsMQsg +ZNlXHG5qpt34VS/MK3YRtZsCAwEAAaOBmjCBlzAMBgNVHRMBAf8EAjAAMB0GA1Ud +DgQWBBT7ZzSkDua7v5ANfLJp6ATVcY92RDAfBgNVHSMEGDAWgBTr3I04dRAv5oKO +/kPsn35jIr1RVTAiBgNVHREBAf8EGDAWghRzZXJ2ZXItcmV2b2tlZC53MS5maTAW +BgNVHSUBAf8EDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEL +BQADggEBACLAoHwltE1hRCUJnBSNNW42e5FgazWQSKmi7oFwxNgqnaN+oskM3LJz +mAHP29Q6F4q2PbWXRzPpthTtpo6kbTTQAzoBBM4oJPnDFamxjCrcjUCYrHiP9fxT +iA6EKDmGdVmtElR38pzh0k7h7o1X80GrFU2rd3VHmsY2KAi1jcefWoeH+KcXmkRO +zoQkEtp/qKsV/SSbzxyuL48TKCcJHlcryh/IvKSVCCdOxCFopUWfWkIcfzdZ1+0w +vu0mEl2A9X19lP9SVvxnDz8AIee0L0h7d4b7FiiraOFNgOteS5mIL+yjHQbFBC67 +VvtrdZ1beINjK3B8IZShWKSOizDTKIg= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/iCA-server/server-revoked.req b/tests/hwsim/auth_serv/iCA-server/server-revoked.req index 775c8a109..b4c0f2374 100644 --- a/tests/hwsim/auth_serv/iCA-server/server-revoked.req +++ b/tests/hwsim/auth_serv/iCA-server/server-revoked.req @@ -1,16 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- MIIClDCCAXwCAQAwTzELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4w DAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUc2VydmVyLXJldm9rZWQudzEuZmkwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsXK4GNkpl4NsLPCgTCIuQZkNv -yLI7+kG9GhAQ++kFarpCkE0uz7G5w3P1/KxMGOlEc2leLYNj0SnlWVWov7Aceg0X -GLA4Ia/LbalrnaKIDhzuGqWfPCfq/o+blN8SPDS7v2zQbGtGrbz/iK7YTYufNFAl -xJa+JUIGyLOOIaX9o4L5dHhGVo0L8MT6Gg71NCJT/UM3o0f9n6K80GAlqNuT9wyI -/nlS8gfx3vxmbv7aEHZs0IeM791AbYJ80TmyF9YHzxpaORLtSU/Zx5FAq3P3VDyl -fZ+7DEd3Dtlh5RsUZU44xaeK7jK+BSWUoH+WCVkbBAhCa1BrlXp49uz09k1DAgMB -AAGgADANBgkqhkiG9w0BAQsFAAOCAQEAUcB51hlCnud4M8uQMv74+6VpPykm7srA -f+kX1or6J1hRrpdUENDydBG/WavyKJmJ4FEb+SS3K+BDoLCObGwazOcFPvJWlT8S -8h8vX5BC+zqLqqjtBv6BJ6Wkb3s/3yhMpGJtrEHShxQTagkqsqSV+nRcnqR/9Ufw -/pHVZ+2sc0Q+dzY+aOmHw+XKkczeI73/j8odhf+a5yTyt6DmUgPRsCOhrBPAlakb -rHzhfnziYI2pS4/q8Ok5LyFAiBjYp5HFvHEwfjb/3o4bLFTpbDDsJoeyX0ddFFhb -fZUhqGHYHMIGR5RXJ685RXg39f7PN8/YPIq4wAjGb9qpkwCbqUJPOA== +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6httirVW8O0Hxwe89YRNtZYrR +vlhBpuBd8sXzp8HCbJ6wX/AWLOS6fSa3aUNysdco0gY9bpxnMjg/PGOUjWPpf7N7 +ZwvWyQLs2n7hWyHkoeoB7Li9b17SkuUz2qUTpo4EtRl6B5roA+69SixlbOw6SDh+ +DTAw7hrZGr4C0OHylRchCDxJTY8Rx7SM5pNLSvrdrApy2IKK4WyZHncbiBKzcs/c ++lfSY+EtwFpXNtT/NyAgAbQRGSz5m/b6k//KafKE62+vRLgY49hCKZchAeFHofzt +WHSwq/l1XOhJqhZKGTHoxYxgmUif2XiS7DELIGTZVxxuaqbd+FUvzCt2EbWbAgMB +AAGgADANBgkqhkiG9w0BAQsFAAOCAQEAo3V6gURcTGy95qxhogpMRD20D9VwiK5m +O81e8wvu6bFn0881Khzi24M4D54JG7NBiVl8FyW7zfnmzpd7lxceSyOuEF7wSIYD ++GrVQ8wgcfPTy0z9iUH/lEjiesv7BEq9AuvAUXSaBC1dPaoWdmEZ+EJRSehle2fj +Lw1OtkjAN47eXo+gXE+kW1V4oM0mI6n7EJ8lEyz6/CUf3mw3EBLXhIncVRthKbrt +S4ujuaak3AGD+KBkxLjxTOIb0IPPsX+lYUly+PayUSe2LhQI0p34wN7Tb4oSu4qH +nZZFb5RIysq0av7y8SqUoJJyaEiYtXxbbUKme/6xUqY4OMpP+01EOQ== -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/iCA-server/server-revoked_and_ica.pem b/tests/hwsim/auth_serv/iCA-server/server-revoked_and_ica.pem index fae468a78..09619be1a 100644 --- a/tests/hwsim/auth_serv/iCA-server/server-revoked_and_ica.pem +++ b/tests/hwsim/auth_serv/iCA-server/server-revoked_and_ica.pem @@ -1,113 +1,125 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162867 (0xd8d3e3a6cbe3ccf3) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + d8:d3:e3:a6:cb:e3:cc:f7 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 22 19:37:36 2025 GMT + Not Before: May 3 15:20:10 2020 GMT + Not After : May 3 15:20:10 2030 GMT Subject: C=FI, O=w1.fi, CN=Server Intermediate CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:de:58:ac:e3:d8:7e:40:f6:84:2a:49:24:49:5a: - f7:c8:23:08:b9:6c:d9:07:01:69:8f:77:28:71:42: - a2:eb:ae:86:10:c6:31:61:9a:14:88:44:0a:68:bf: - 6e:a2:46:41:e9:6f:a2:89:fb:0b:f3:e1:b8:30:bf: - e5:80:5e:f9:61:8d:6e:ac:e2:f7:28:e7:9e:44:28: - b8:e4:6e:87:76:a9:d7:ac:ed:11:3f:de:c3:dd:41: - c3:45:82:09:c3:a7:4c:e6:df:2b:88:1e:44:ce:e2: - a7:29:53:f6:13:96:ad:6c:2e:93:00:28:42:77:bc: - 73:6e:86:e7:5b:e8:eb:e9:37:1d:63:e7:ea:05:5a: - 71:28:f0:81:0b:4c:3f:dd:73:f8:db:13:a8:f0:5f: - 6f:6f:e5:1b:c7:94:7f:57:c5:dc:66:26:0c:5a:71: - 7a:e3:d2:3e:7a:a6:59:46:03:61:78:89:84:3d:ef: - 22:9c:f8:c2:22:75:c4:0c:ef:fb:e4:fa:6f:b8:11: - db:aa:92:9b:6c:23:4e:6e:e5:55:d2:41:47:18:95: - c6:7d:17:be:6d:ab:39:a1:38:61:fd:f9:22:95:69: - f3:9e:28:fd:8a:c8:58:72:3c:91:c2:22:d9:fb:b2: - 54:0f:9a:17:27:88:df:60:f5:de:fc:95:9f:25:c6: - 64:81 + 00:a2:b0:de:7f:e6:17:69:4b:bb:8d:dc:4f:8b:95: + 33:5e:13:ee:a1:01:f5:82:de:6e:fc:83:db:e7:22: + 5f:b9:8d:2b:de:10:72:4e:da:81:c1:f7:f3:eb:0e: + db:5b:5f:90:92:bb:41:68:55:4f:84:d9:73:5b:0c: + 6d:40:e6:c5:0f:5d:5c:5e:80:1e:64:87:5a:99:44: + 8b:3d:61:20:f0:15:cc:87:95:5b:a0:46:0f:bc:5c: + 14:ee:ac:4f:c8:7c:d2:c0:ef:60:94:22:b6:74:05: + 4f:ca:97:01:0a:30:b4:50:44:89:d0:c2:6b:e5:7f: + ce:66:22:1a:d6:38:7c:ff:42:42:ca:58:a0:38:85: + ca:f1:b1:1f:33:27:db:bf:5c:49:96:36:7a:11:2f: + 62:d7:eb:7e:9f:9b:9c:0e:2b:df:cd:59:bc:ee:e8: + 6a:e3:7d:fa:06:ba:34:42:b5:7d:e7:be:e1:7b:85: + af:1b:25:a9:45:33:06:cb:cc:0d:ca:78:5c:56:52: + ac:43:7e:f6:0c:e7:fb:86:b4:ac:d7:f4:b2:54:ee: + 65:7a:5c:32:6b:33:a0:68:1b:d8:ea:c8:74:94:08: + 00:7f:9b:f0:da:80:0f:f2:45:13:11:63:4c:e6:d2: + 97:d3:ae:12:b0:7c:e8:f0:56:c0:7b:7c:82:99:6d: + 3b:5d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - 84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9 + EB:DC:8D:38:75:10:2F:E6:82:8E:FE:43:EC:9F:7E:63:22:BD:51:55 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Certificate Sign, CRL Sign Signature Algorithm: sha256WithRSAEncryption - bd:22:63:3d:a7:e5:ce:c9:f5:66:1f:77:5f:d5:24:e3:68:dc: - a4:07:80:3e:5e:b1:2c:96:88:39:ad:00:4c:aa:9d:0b:ed:f3: - 6d:df:9d:2f:97:d2:77:8b:ba:d0:9c:0f:a6:5e:60:b8:0f:e1: - 96:b1:61:25:48:69:81:64:a8:5c:82:58:0b:f3:d0:a9:4e:8b: - 90:fc:2f:67:57:da:72:dc:3c:eb:c2:20:19:05:8d:42:0d:14: - cf:00:db:59:00:ea:f0:76:3e:ca:85:b1:05:e5:b8:5f:0b:46: - c7:3c:a1:d9:5c:4d:b9:24:e7:d6:2b:3d:0d:eb:c3:88:d8:3a: - f6:60 + 86:74:75:b2:bb:b0:85:25:48:38:e1:34:54:d5:d4:3a:9f:0e: + b1:96:fd:cc:ea:15:21:72:da:9e:ef:e2:fa:ae:29:74:dc:83: + 36:87:88:7d:75:51:9a:c5:6e:a8:80:77:3f:5c:ed:9e:ac:57: + 17:ed:ab:64:4f:15:8b:47:90:0a:17:2a:7e:49:a9:01:a1:41: + 66:d4:fe:be:18:70:d6:23:f7:0b:0a:53:d7:75:a8:7f:0a:52: + 1c:1d:8c:63:6f:82:ed:ed:fd:e2:fe:86:ef:0a:4c:f8:d7:93: + 56:9a:a3:dd:74:02:8c:b3:31:83:c1:8a:66:c6:c0:1d:dc:00: + 5c:57:f4:31:31:8b:d4:84:d8:da:6d:d6:f6:e4:10:7e:bb:f2: + 41:95:dd:a6:0c:37:c7:22:80:e6:36:3e:34:c6:1c:73:ab:42: + 90:6e:f8:db:e8:b6:c0:b2:f5:17:d2:6f:d3:8c:fb:14:25:8e: + 72:81:45:76:86:f7:d1:d9:3d:ff:b1:a2:10:6f:c0:24:e7:70: + 3f:2d:cf:32:ee:06:70:d5:1b:04:84:6d:48:69:26:1e:98:5a: + ed:e3:61:f5:29:45:88:25:cf:7f:c4:fb:f3:87:a7:11:95:9e: + cf:a8:aa:88:db:12:32:66:66:c4:1d:12:b1:62:1d:fa:28:f4: + 97:ac:df:2e -----BEGIN CERTIFICATE----- -MIIC1TCCAj6gAwIBAgIJANjT46bL48zzMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy -MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMD4xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVkaWF0ZSBDQTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5YrOPYfkD2hCpJJEla98gjCLls2QcB -aY93KHFCouuuhhDGMWGaFIhECmi/bqJGQelvoon7C/PhuDC/5YBe+WGNbqzi9yjn -nkQouORuh3ap16ztET/ew91Bw0WCCcOnTObfK4geRM7ipylT9hOWrWwukwAoQne8 -c26G51vo6+k3HWPn6gVacSjwgQtMP91z+NsTqPBfb2/lG8eUf1fF3GYmDFpxeuPS -PnqmWUYDYXiJhD3vIpz4wiJ1xAzv++T6b7gR26qSm2wjTm7lVdJBRxiVxn0Xvm2r -OaE4Yf35IpVp854o/YrIWHI8kcIi2fuyVA+aFyeI32D13vyVnyXGZIECAwEAAaNm -MGQwHQYDVR0OBBYEFIQJi1UffS8PKNec7FROnxGXVdm5MB8GA1UdIwQYMBaAFLiS -3v2KGLMww59V8zNdtMgpikEUMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4GBAL0iYz2n5c7J9WYfd1/VJONo3KQHgD5e -sSyWiDmtAEyqnQvt823fnS+X0neLutCcD6ZeYLgP4ZaxYSVIaYFkqFyCWAvz0KlO -i5D8L2dX2nLcPOvCIBkFjUINFM8A21kA6vB2PsqFsQXluF8LRsc8odlcTbkk59Yr -PQ3rw4jYOvZg +MIIDaDCCAlCgAwIBAgIJANjT46bL48z3MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDMxNTIwMTBaFw0zMDA1MDMxNTIwMTBaMD4xCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVy +bWVkaWF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKw3n/m +F2lLu43cT4uVM14T7qEB9YLebvyD2+ciX7mNK94Qck7agcH38+sO21tfkJK7QWhV +T4TZc1sMbUDmxQ9dXF6AHmSHWplEiz1hIPAVzIeVW6BGD7xcFO6sT8h80sDvYJQi +tnQFT8qXAQowtFBEidDCa+V/zmYiGtY4fP9CQspYoDiFyvGxHzMn279cSZY2ehEv +Ytfrfp+bnA4r381ZvO7oauN9+ga6NEK1fee+4XuFrxslqUUzBsvMDcp4XFZSrEN+ +9gzn+4a0rNf0slTuZXpcMmszoGgb2OrIdJQIAH+b8NqAD/JFExFjTObSl9OuErB8 +6PBWwHt8gpltO10CAwEAAaNmMGQwHQYDVR0OBBYEFOvcjTh1EC/mgo7+Q+yffmMi +vVFVMB8GA1UdIwQYMBaAFKT9uTkbgbOq64gd1IGptRFwzKfhMBIGA1UdEwEB/wQI +MAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQCGdHWy +u7CFJUg44TRU1dQ6nw6xlv3M6hUhctqe7+L6ril03IM2h4h9dVGaxW6ogHc/XO2e +rFcX7atkTxWLR5AKFyp+SakBoUFm1P6+GHDWI/cLClPXdah/ClIcHYxjb4Lt7f3i +/obvCkz415NWmqPddAKMszGDwYpmxsAd3ABcV/QxMYvUhNjabdb25BB+u/JBld2m +DDfHIoDmNj40xhxzq0KQbvjb6LbAsvUX0m/TjPsUJY5ygUV2hvfR2T3/saIQb8Ak +53A/Lc8y7gZw1RsEhG1IaSYemFrt42H1KUWIJc9/xPvzh6cRlZ7PqKqI2xIyZmbE +HRKxYh36KPSXrN8u -----END CERTIFICATE----- Certificate: Data: Version: 3 (0x2) - Serial Number: 9232555434986539705 (0x8020a0407f798ab9) - Signature Algorithm: sha256WithRSAEncryption + Serial Number: + 5c:9d:e4:a6:d1:7a:49:c8:83:75:e7:57:68:f7:72:16:b2:ae:b7:83 + Signature Algorithm: sha256WithRSAEncryption Issuer: C=FI, O=w1.fi, CN=Server Intermediate CA Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 20 19:37:36 2025 GMT + Not Before: May 3 15:20:10 2020 GMT + Not After : May 1 15:20:10 2030 GMT Subject: C=FI, O=w1.fi, CN=server-revoked.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:ac:5c:ae:06:36:4a:65:e0:db:0b:3c:28:13:08: - 8b:90:66:43:6f:c8:b2:3b:fa:41:bd:1a:10:10:fb: - e9:05:6a:ba:42:90:4d:2e:cf:b1:b9:c3:73:f5:fc: - ac:4c:18:e9:44:73:69:5e:2d:83:63:d1:29:e5:59: - 55:a8:bf:b0:1c:7a:0d:17:18:b0:38:21:af:cb:6d: - a9:6b:9d:a2:88:0e:1c:ee:1a:a5:9f:3c:27:ea:fe: - 8f:9b:94:df:12:3c:34:bb:bf:6c:d0:6c:6b:46:ad: - bc:ff:88:ae:d8:4d:8b:9f:34:50:25:c4:96:be:25: - 42:06:c8:b3:8e:21:a5:fd:a3:82:f9:74:78:46:56: - 8d:0b:f0:c4:fa:1a:0e:f5:34:22:53:fd:43:37:a3: - 47:fd:9f:a2:bc:d0:60:25:a8:db:93:f7:0c:88:fe: - 79:52:f2:07:f1:de:fc:66:6e:fe:da:10:76:6c:d0: - 87:8c:ef:dd:40:6d:82:7c:d1:39:b2:17:d6:07:cf: - 1a:5a:39:12:ed:49:4f:d9:c7:91:40:ab:73:f7:54: - 3c:a5:7d:9f:bb:0c:47:77:0e:d9:61:e5:1b:14:65: - 4e:38:c5:a7:8a:ee:32:be:05:25:94:a0:7f:96:09: - 59:1b:04:08:42:6b:50:6b:95:7a:78:f6:ec:f4:f6: - 4d:43 + 00:ba:86:db:62:ad:55:bc:3b:41:f1:c1:ef:3d:61: + 13:6d:65:8a:d1:be:58:41:a6:e0:5d:f2:c5:f3:a7: + c1:c2:6c:9e:b0:5f:f0:16:2c:e4:ba:7d:26:b7:69: + 43:72:b1:d7:28:d2:06:3d:6e:9c:67:32:38:3f:3c: + 63:94:8d:63:e9:7f:b3:7b:67:0b:d6:c9:02:ec:da: + 7e:e1:5b:21:e4:a1:ea:01:ec:b8:bd:6f:5e:d2:92: + e5:33:da:a5:13:a6:8e:04:b5:19:7a:07:9a:e8:03: + ee:bd:4a:2c:65:6c:ec:3a:48:38:7e:0d:30:30:ee: + 1a:d9:1a:be:02:d0:e1:f2:95:17:21:08:3c:49:4d: + 8f:11:c7:b4:8c:e6:93:4b:4a:fa:dd:ac:0a:72:d8: + 82:8a:e1:6c:99:1e:77:1b:88:12:b3:72:cf:dc:fa: + 57:d2:63:e1:2d:c0:5a:57:36:d4:ff:37:20:20:01: + b4:11:19:2c:f9:9b:f6:fa:93:ff:ca:69:f2:84:eb: + 6f:af:44:b8:18:e3:d8:42:29:97:21:01:e1:47:a1: + fc:ed:58:74:b0:ab:f9:75:5c:e8:49:aa:16:4a:19: + 31:e8:c5:8c:60:99:48:9f:d9:78:92:ec:31:0b:20: + 64:d9:57:1c:6e:6a:a6:dd:f8:55:2f:cc:2b:76:11: + b5:9b Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: critical CA:FALSE X509v3 Subject Key Identifier: - 0D:49:37:45:42:77:90:25:BA:9B:67:DB:F6:DC:61:D2:53:5B:C6:BC + FB:67:34:A4:0E:E6:BB:BF:90:0D:7C:B2:69:E8:04:D5:71:8F:76:44 X509v3 Authority Key Identifier: - keyid:84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9 + keyid:EB:DC:8D:38:75:10:2F:E6:82:8E:FE:43:EC:9F:7E:63:22:BD:51:55 X509v3 Subject Alternative Name: critical DNS:server-revoked.w1.fi @@ -116,40 +128,40 @@ Certificate: X509v3 Key Usage: Digital Signature, Key Encipherment Signature Algorithm: sha256WithRSAEncryption - 22:c6:72:08:84:a9:e9:19:77:ea:6a:06:68:43:8b:e7:72:af: - 9c:a2:47:b9:6f:b6:cb:11:17:89:0a:42:52:14:58:9e:3c:01: - fd:e7:fc:a2:0d:85:a5:b5:8c:27:d5:5e:b2:47:05:05:f9:56: - b6:0b:e2:28:f3:1d:75:5e:13:eb:ec:a0:76:2b:d9:ed:99:84: - 08:6d:64:71:13:b6:02:81:b3:c2:7e:b8:b6:00:98:4f:26:ea: - f1:67:5b:35:2a:26:d0:ca:a8:fb:eb:21:fb:f1:d6:5a:63:42: - 01:5f:b3:59:3d:f8:e0:4d:94:3a:3a:82:46:02:9d:81:2c:ef: - e5:46:c7:99:f4:2f:43:ad:85:fc:2c:ca:0b:6b:48:01:ac:d7: - f7:da:0e:16:c4:10:18:14:83:9c:85:90:75:ef:66:9f:65:42: - e5:e7:8c:16:ac:f6:60:61:d7:5f:a0:21:cd:8a:85:d4:a0:f2: - 8e:17:0e:38:5e:31:12:ac:24:b5:67:61:9d:15:84:0b:fc:84: - 8a:d4:29:90:3d:4b:23:48:19:6b:f7:26:1f:fe:b9:b9:f1:6e: - 70:ac:ec:31:60:be:7d:6f:58:7e:c1:47:61:a7:b0:4b:b2:fd: - 62:06:c5:97:43:28:39:a5:c5:60:51:c0:46:9d:6b:e4:1a:ed: - 0c:a6:51:8a + 22:c0:a0:7c:25:b4:4d:61:44:25:09:9c:14:8d:35:6e:36:7b: + 91:60:6b:35:90:48:a9:a2:ee:81:70:c4:d8:2a:9d:a3:7e:a2: + c9:0c:dc:b2:73:98:01:cf:db:d4:3a:17:8a:b6:3d:b5:97:47: + 33:e9:b6:14:ed:a6:8e:a4:6d:34:d0:03:3a:01:04:ce:28:24: + f9:c3:15:a9:b1:8c:2a:dc:8d:40:98:ac:78:8f:f5:fc:53:88: + 0e:84:28:39:86:75:59:ad:12:54:77:f2:9c:e1:d2:4e:e1:ee: + 8d:57:f3:41:ab:15:4d:ab:77:75:47:9a:c6:36:28:08:b5:8d: + c7:9f:5a:87:87:f8:a7:17:9a:44:4e:ce:84:24:12:da:7f:a8: + ab:15:fd:24:9b:cf:1c:ae:2f:8f:13:28:27:09:1e:57:2b:ca: + 1f:c8:bc:a4:95:08:27:4e:c4:21:68:a5:45:9f:5a:42:1c:7f: + 37:59:d7:ed:30:be:ed:26:12:5d:80:f5:7d:7d:94:ff:52:56: + fc:67:0f:3f:00:21:e7:b4:2f:48:7b:77:86:fb:16:28:ab:68: + e1:4d:80:eb:5e:4b:99:88:2f:ec:a3:1d:06:c5:04:2e:bb:56: + fb:6b:75:9d:5b:78:83:63:2b:70:7c:21:94:a1:58:a4:8e:8b: + 30:d3:28:88 -----BEGIN CERTIFICATE----- -MIIDmDCCAoCgAwIBAgIJAIAgoEB/eYq5MA0GCSqGSIb3DQEBCwUAMD4xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVk -aWF0ZSBDQTAeFw0xNTEyMjMxOTM3MzZaFw0yNTEyMjAxOTM3MzZaMDwxCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUc2VydmVyLXJldm9rZWQu -dzEuZmkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsXK4GNkpl4NsL -PCgTCIuQZkNvyLI7+kG9GhAQ++kFarpCkE0uz7G5w3P1/KxMGOlEc2leLYNj0Snl -WVWov7Aceg0XGLA4Ia/LbalrnaKIDhzuGqWfPCfq/o+blN8SPDS7v2zQbGtGrbz/ -iK7YTYufNFAlxJa+JUIGyLOOIaX9o4L5dHhGVo0L8MT6Gg71NCJT/UM3o0f9n6K8 -0GAlqNuT9wyI/nlS8gfx3vxmbv7aEHZs0IeM791AbYJ80TmyF9YHzxpaORLtSU/Z -x5FAq3P3VDylfZ+7DEd3Dtlh5RsUZU44xaeK7jK+BSWUoH+WCVkbBAhCa1BrlXp4 -9uz09k1DAgMBAAGjgZowgZcwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUDUk3RUJ3 -kCW6m2fb9txh0lNbxrwwHwYDVR0jBBgwFoAUhAmLVR99Lw8o15zsVE6fEZdV2bkw -IgYDVR0RAQH/BBgwFoIUc2VydmVyLXJldm9rZWQudzEuZmkwFgYDVR0lAQH/BAww -CgYIKwYBBQUHAwEwCwYDVR0PBAQDAgWgMA0GCSqGSIb3DQEBCwUAA4IBAQAixnII -hKnpGXfqagZoQ4vncq+coke5b7bLEReJCkJSFFiePAH95/yiDYWltYwn1V6yRwUF -+Va2C+Io8x11XhPr7KB2K9ntmYQIbWRxE7YCgbPCfri2AJhPJurxZ1s1KibQyqj7 -6yH78dZaY0IBX7NZPfjgTZQ6OoJGAp2BLO/lRseZ9C9DrYX8LMoLa0gBrNf32g4W -xBAYFIOchZB172afZULl54wWrPZgYddfoCHNioXUoPKOFw44XjESrCS1Z2GdFYQL -/ISK1CmQPUsjSBlr9yYf/rm58W5wrOwxYL59b1h+wUdhp7BLsv1iBsWXQyg5pcVg -UcBGnWvkGu0MplGK +MIIDozCCAougAwIBAgIUXJ3kptF6SciDdedXaPdyFrKut4MwDQYJKoZIhvcNAQEL +BQAwPjELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMR8wHQYDVQQDDBZTZXJ2 +ZXIgSW50ZXJtZWRpYXRlIENBMB4XDTIwMDUwMzE1MjAxMFoXDTMwMDUwMTE1MjAx +MFowPDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMR0wGwYDVQQDDBRzZXJ2 +ZXItcmV2b2tlZC53MS5maTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +ALqG22KtVbw7QfHB7z1hE21litG+WEGm4F3yxfOnwcJsnrBf8BYs5Lp9JrdpQ3Kx +1yjSBj1unGcyOD88Y5SNY+l/s3tnC9bJAuzafuFbIeSh6gHsuL1vXtKS5TPapROm +jgS1GXoHmugD7r1KLGVs7DpIOH4NMDDuGtkavgLQ4fKVFyEIPElNjxHHtIzmk0tK ++t2sCnLYgorhbJkedxuIErNyz9z6V9Jj4S3AWlc21P83ICABtBEZLPmb9vqT/8pp +8oTrb69EuBjj2EIplyEB4Ueh/O1YdLCr+XVc6EmqFkoZMejFjGCZSJ/ZeJLsMQsg +ZNlXHG5qpt34VS/MK3YRtZsCAwEAAaOBmjCBlzAMBgNVHRMBAf8EAjAAMB0GA1Ud +DgQWBBT7ZzSkDua7v5ANfLJp6ATVcY92RDAfBgNVHSMEGDAWgBTr3I04dRAv5oKO +/kPsn35jIr1RVTAiBgNVHREBAf8EGDAWghRzZXJ2ZXItcmV2b2tlZC53MS5maTAW +BgNVHSUBAf8EDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQEL +BQADggEBACLAoHwltE1hRCUJnBSNNW42e5FgazWQSKmi7oFwxNgqnaN+oskM3LJz +mAHP29Q6F4q2PbWXRzPpthTtpo6kbTTQAzoBBM4oJPnDFamxjCrcjUCYrHiP9fxT +iA6EKDmGdVmtElR38pzh0k7h7o1X80GrFU2rd3VHmsY2KAi1jcefWoeH+KcXmkRO +zoQkEtp/qKsV/SSbzxyuL48TKCcJHlcryh/IvKSVCCdOxCFopUWfWkIcfzdZ1+0w +vu0mEl2A9X19lP9SVvxnDz8AIee0L0h7d4b7FiiraOFNgOteS5mIL+yjHQbFBC67 +VvtrdZ1beINjK3B8IZShWKSOizDTKIg= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/iCA-server/server.key b/tests/hwsim/auth_serv/iCA-server/server.key index e817ad8a1..068c0f6d0 100644 --- a/tests/hwsim/auth_serv/iCA-server/server.key +++ b/tests/hwsim/auth_serv/iCA-server/server.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDkiKWTAlu8VGhG -+nN9MzBHRVxJXzxRX5v+xRQQJj0P48KyF4TTPhKosnsCGoqL6fRBHvzzSS3G1Ign -gdCG87nACiooRQAywxgi9pk38XSNrFRHc+W20+f4gJl19RkZ6xlw35JTsWE4/3/P -i73hf1Bb0JUwozdrinIGp+g54qR4Q5iRzTCINFuqnqKfJtXhW4ZNAaTCZc0nlL7i -9XNdxGCY8XURlAkNnQR/7xqdX/BKP4jXdi6b1irGlAk3CjckkpGdGA/qTtTknUU4 -WrrY37YVb6z/bEGs18AKVeyByppZQFWLpHcT3/rDte7vh0GNlNDAlkG0OgS2a2pW -k/RnfifhAgMBAAECggEAA+GSNknu9ubUEoiEV5b79enmpFRauOMPyibcrV2I4fEz -SET/+3ptZLILRsDeo3uoq0Z0c0lF3r+TRGB/Axu2ht1lU+PAGhyYF1fqyDlwiktn -7wK33wAAS4cblBZCg98rQnB5krRLe2VTbVnpMqAv5C9JqVbMRSZHw3csiXcg5e3v -urH5A90pwFY/1DG68JS+HCLxvorO5EIfeTSBg1F54FHBCQ6Yjr232uXAUez5hv5/ -zX6oxw2zarKMgNiosy5FCoGEUECCfvM2tiXjfZ0DBmZgF/c6Alg+J8gYFVJzSX+x -xAyL9o3LYddSdDnGBiMm4SU8oUxvnUgrZ+xhnyL69QKBgQD9717EmTLKBna4wX+d -PM03yIv2ZpFESd4VuxZMyTOO64CMD75n1V/r1V44xIQa7M5QwfD+NmTjW/QyJ0EN -F5mJYavXc56nlV4wVQJC2/NnyOScjKEIXu/QmEPwTm/NqEqCFs6XGpftigjB+FIO -Te/PmOVFSDCE+JkOF3Fls55iMwKBgQDmZGW/duaEL4qMnDO51hSz+qv9mZNXoPzg -DWzmraOikp1zSTjaLzRy6w8bbHTqTZDG68hJ/knW2boD0pDqmuUzS6ADnV7P0fVT -mOolwmKdGO3axyIsStuhPKaaHv28X0+y2qhUkK7hYJ2yeZIQ/259D75g0BNozjO5 -1sKEsW+BmwKBgBgZu9jU4WkjK+llFAOMXb3Jnt8H5QmiKR3O39Lx1Z7e4xhn9h5M -tgnf+k1Q+WjEyOAJSCIYb4LUm1yXNSlU8BGF35VXN9uX5ZSYvNoznepfurLQ9geh -WwllKi2IhDv0mP23xGu67mhxDVu7ga4x32zIihoFO/Wi0oPv3adVYNbZAoGBAOMF -VwVdYjQqrHl1ibq66teWUFeqNvgIGGWmlQKRY0bU9fUd17mW/jWmzdIWAvbFy71X -pJrUyWm+TX9qw4WJcAQlpt0o+r4Jg5YGfeMLMiTe5bHIuzGt6dFtdDU2CIzP1jbF -I02A6/IFRB8TkAzTxcnR86RuJFIHrgyXREGAngG1AoGBAOR/fBPsVAf2MsfGyX7l -JpHkHgfmAldfRammmGxV2c+NJ/cWjkN/1p8KaiqINP08FemC7Rxvu8Nhm50qOLRM -iq2KeDCaHoUp9waX7T+WzKbT+jEdcyXeu2DlN8AIyTNjDrVyZil0NbZfQFbR8nWR -0VX+Eq8Oxrl+pRza/6f62K7s +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCsIexV4pRs1Rtt ++neHf34q9SZOPCjUcFBwVeKp1atiFQECtZDoVZF8sPSf/RE8c3L3Vn1MtVYhjxfE +ZVwqPw3iIqWA7RqwqIzimvePd23FJJ8rwDommxN1ltLPGUzK7ZCzyNrnIAOmCl2t +BJ1rN51p6Wxj1RLa/8Kl1PQE3845wgY9P+yLPZ4cpy3yY1N+OqpoCrCTsmk9I9qx +rv6Q+sbq7jWUTZrYXW+57YBrG71GVqu/KYrJIOUxPRGW4MVWWOHxhG28D+WbvJ91 +KwMBGliOiCKzCnyNs00egjF1f88oOqrA9cNFcrxI95phESwx1D1bbiXKKuqI6Vj+ +7g0A1TaLAgMBAAECggEBAKBGHeaCSK1laFro4i76GSIqjXY/Mc1MnrlaXujAGQoE +gKJjKQAL3KF7qurlGg1tedivYY/xMLeiowCtWDnF6Els9SmsnDNtXXEJ1gRxsXXk ++YglPn//2QieXL+U0RoKRbgBB0I5XuxVro+RQno4mIurWs9B8IKVrkn2lReMxFql +tXaAUEkvnIbEnEuXUtb7XNzAv3LeF5XrFZ5egHggKwDlA1o0wl2Nx0JVynX9EJER +VoWWWAvJhtZLQb2EetYKA2WOIwkCwFMX/EYP4BuGRFLnrPOMMqAkS42ZdVLhwCk7 +m00J5GO1Bwf9OBy2aPVGubaU4P+BKHkCSzxs22guIWECgYEA064UlbqudqL+Jtpc +B4gYqh4d61Cf8PaOz61YVggpcXTQtf+Ov02h3M2Iq0i42fw4hewRRiQmFyOP8daA +OsqAHj0eOv4ibE23hR1KssBl3fBt6ubjCxeFf3Sl0e0j+5XFgCPYEdJPPsJhY91f +TK6IUYq9DAITdmU2+TL5RdK7KVMCgYEA0CwfEaveSzeBZTMudh0WsywF6EsplWHM +QyawOPbltZxxTQHDAillFyoPHNtFZs8KBVdmTxcITW3YyaEFbZ0rXLKFjyHiMQfG +KSCB2nzFOhT8eXsdVyXahXkKiIsoFjaKqRRsNoxyUtbj8Pu7/CRtbabDLOj/iF43 +eo8iNn3LvukCgYEA0Bq+Zg1n436OekgGXekwxl5hb6yN8WmUMRvsUngntkDvx119 +SxnZXag7CpmuEbBjKVZSDTEQuYLeyxTkb+gRWKkhhUG/OdaV66pGe8Gm5DCw/1UK +NSdkuU9GjkGjNH2j8zxJ+gtWmQ6kjHdgb5TOs8u/24RW+fi7uPaiFkD8e70CgYEA +pml+9Lt12p8me2Xs0FL0oIqitk3PkjE5/rxgx0jn3MSQ9kRgRcwdmeTva9wFoOgF +VLvHd5Yr9unHEXf9ROENlu7HQeKOVS+nw5zO8YAokgPQyLQYgmAqTeSy/PBxPUCg +nAVNdFXV1k8erLgwUKI2MB/NiotAKx1WME1XxkPNqnECgYAR6WJkK4t4uJueta3P +c4AUU585nTX6CyH7oxkud/s+Mg6ztbtC9/BSxtQNTJKWhbqdpI7xz2807Wzv3/6h +IFpCPf3aXWX9yp3FlohRfE/hCRz8IhBzQNCUaXxMta3KOVw0u88aQycEI8CGad2Z +By9hDAFwSLj4vQuD0VclFyCfZA== -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/iCA-server/server.pem b/tests/hwsim/auth_serv/iCA-server/server.pem index ebcbde353..58d76bcbe 100644 --- a/tests/hwsim/auth_serv/iCA-server/server.pem +++ b/tests/hwsim/auth_serv/iCA-server/server.pem @@ -1,43 +1,44 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 9232555434986539704 (0x8020a0407f798ab8) - Signature Algorithm: sha256WithRSAEncryption + Serial Number: + 5c:9d:e4:a6:d1:7a:49:c8:83:75:e7:57:68:f7:72:16:b2:ae:b7:82 + Signature Algorithm: sha256WithRSAEncryption Issuer: C=FI, O=w1.fi, CN=Server Intermediate CA Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 20 19:37:36 2025 GMT + Not Before: May 3 15:20:10 2020 GMT + Not After : May 1 15:20:10 2030 GMT Subject: C=FI, O=w1.fi, CN=server.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:e4:88:a5:93:02:5b:bc:54:68:46:fa:73:7d:33: - 30:47:45:5c:49:5f:3c:51:5f:9b:fe:c5:14:10:26: - 3d:0f:e3:c2:b2:17:84:d3:3e:12:a8:b2:7b:02:1a: - 8a:8b:e9:f4:41:1e:fc:f3:49:2d:c6:d4:88:27:81: - d0:86:f3:b9:c0:0a:2a:28:45:00:32:c3:18:22:f6: - 99:37:f1:74:8d:ac:54:47:73:e5:b6:d3:e7:f8:80: - 99:75:f5:19:19:eb:19:70:df:92:53:b1:61:38:ff: - 7f:cf:8b:bd:e1:7f:50:5b:d0:95:30:a3:37:6b:8a: - 72:06:a7:e8:39:e2:a4:78:43:98:91:cd:30:88:34: - 5b:aa:9e:a2:9f:26:d5:e1:5b:86:4d:01:a4:c2:65: - cd:27:94:be:e2:f5:73:5d:c4:60:98:f1:75:11:94: - 09:0d:9d:04:7f:ef:1a:9d:5f:f0:4a:3f:88:d7:76: - 2e:9b:d6:2a:c6:94:09:37:0a:37:24:92:91:9d:18: - 0f:ea:4e:d4:e4:9d:45:38:5a:ba:d8:df:b6:15:6f: - ac:ff:6c:41:ac:d7:c0:0a:55:ec:81:ca:9a:59:40: - 55:8b:a4:77:13:df:fa:c3:b5:ee:ef:87:41:8d:94: - d0:c0:96:41:b4:3a:04:b6:6b:6a:56:93:f4:67:7e: - 27:e1 + 00:ac:21:ec:55:e2:94:6c:d5:1b:6d:fa:77:87:7f: + 7e:2a:f5:26:4e:3c:28:d4:70:50:70:55:e2:a9:d5: + ab:62:15:01:02:b5:90:e8:55:91:7c:b0:f4:9f:fd: + 11:3c:73:72:f7:56:7d:4c:b5:56:21:8f:17:c4:65: + 5c:2a:3f:0d:e2:22:a5:80:ed:1a:b0:a8:8c:e2:9a: + f7:8f:77:6d:c5:24:9f:2b:c0:3a:26:9b:13:75:96: + d2:cf:19:4c:ca:ed:90:b3:c8:da:e7:20:03:a6:0a: + 5d:ad:04:9d:6b:37:9d:69:e9:6c:63:d5:12:da:ff: + c2:a5:d4:f4:04:df:ce:39:c2:06:3d:3f:ec:8b:3d: + 9e:1c:a7:2d:f2:63:53:7e:3a:aa:68:0a:b0:93:b2: + 69:3d:23:da:b1:ae:fe:90:fa:c6:ea:ee:35:94:4d: + 9a:d8:5d:6f:b9:ed:80:6b:1b:bd:46:56:ab:bf:29: + 8a:c9:20:e5:31:3d:11:96:e0:c5:56:58:e1:f1:84: + 6d:bc:0f:e5:9b:bc:9f:75:2b:03:01:1a:58:8e:88: + 22:b3:0a:7c:8d:b3:4d:1e:82:31:75:7f:cf:28:3a: + aa:c0:f5:c3:45:72:bc:48:f7:9a:61:11:2c:31:d4: + 3d:5b:6e:25:ca:2a:ea:88:e9:58:fe:ee:0d:00:d5: + 36:8b Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: critical CA:FALSE X509v3 Subject Key Identifier: - 4B:81:85:B4:88:41:0D:D4:15:D3:48:0E:F4:A9:99:14:2D:B1:DB:93 + E9:E3:CE:7A:C2:27:BF:88:CF:19:9E:5C:6C:DC:12:C0:D5:00:64:15 X509v3 Authority Key Identifier: - keyid:84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9 + keyid:EB:DC:8D:38:75:10:2F:E6:82:8E:FE:43:EC:9F:7E:63:22:BD:51:55 X509v3 Subject Alternative Name: critical DNS:server.w1.fi @@ -46,39 +47,40 @@ Certificate: X509v3 Key Usage: Digital Signature, Key Encipherment Signature Algorithm: sha256WithRSAEncryption - 49:2a:14:22:16:2c:12:f5:4e:06:f3:c2:1e:ac:54:07:5d:86: - 16:3e:6c:a0:73:e1:a6:d7:c3:49:1f:80:0d:b6:54:22:77:ce: - 39:dd:f6:f6:9f:62:ff:d5:27:7f:c3:92:73:b9:a7:ce:87:5a: - e3:bc:52:b3:0a:99:eb:91:56:b6:78:01:c3:0e:4b:ca:8a:04: - ee:5c:56:05:ef:7a:cb:21:f9:eb:8a:38:12:50:c7:6e:a8:1f: - 0e:81:81:a6:2d:ea:35:94:24:db:76:77:df:ea:41:4c:af:7e: - 29:9d:d5:e6:e3:12:78:19:92:ed:35:b9:99:19:a9:d6:cb:f8: - a7:21:fb:8e:a7:39:dc:e1:ab:3d:ba:12:87:ba:1c:08:e6:8a: - 21:96:44:44:8a:61:0f:70:00:d0:cb:63:93:a4:fa:cc:75:a3: - fd:e8:af:33:24:80:4a:d9:b9:2a:a1:20:0b:62:0b:17:6c:9a: - 7c:8b:fd:9e:ff:be:b2:51:5e:e9:3a:cc:28:22:63:44:69:7f: - 6d:1f:08:14:a4:32:d0:1f:f9:c3:8d:28:1a:76:12:00:3c:b3: - 38:13:ca:67:17:79:c6:de:5d:b7:9d:f8:e3:64:f7:b3:a0:5c: - e5:6e:fc:10:f3:53:d6:70:38:c2:6f:87:ab:07:1c:64:ff:30: - d8:3a:1e:75 + 1b:c4:4a:ea:b3:ee:c3:82:4d:98:93:49:6a:34:98:80:b6:a3: + dc:00:d5:ca:27:56:43:e2:71:4c:60:a1:ef:c2:41:9c:fa:93: + a4:61:20:f5:3f:2c:3a:91:e8:12:e1:7a:51:c0:86:2b:cf:1b: + 73:26:b3:0c:e7:03:2e:8e:48:49:3e:32:29:df:b2:9e:d5:29: + 26:bf:c3:3e:eb:7d:34:96:c7:6e:0e:ae:16:a1:a1:fa:25:dd: + a3:2e:3e:4e:3e:76:ff:d6:35:ef:d4:07:2f:d2:6f:48:08:ab: + e7:4a:09:ff:43:09:ec:32:49:19:52:cd:30:03:22:3c:f0:9c: + 9b:e3:fd:bc:e7:f9:d1:7a:da:c6:66:bf:e0:86:95:5c:45:43: + 07:26:6d:70:fc:24:66:4a:cd:86:bd:6c:d3:7a:0d:12:4b:33: + bc:a0:4b:81:08:1a:26:bc:42:a2:e7:37:36:56:ac:ef:85:34: + 52:89:33:df:b6:33:11:ac:20:67:cd:8d:ce:d7:bb:cb:bc:b5: + 16:3c:08:cf:c7:1a:68:60:16:9c:55:e6:b5:17:4f:3f:69:f9: + b4:18:70:af:60:5d:0f:c4:66:08:b9:75:a3:78:11:f7:8f:8d: + f1:2b:4e:05:b9:90:b6:f3:99:8b:0c:43:6a:8c:b4:cc:ff:2f: + 58:70:d7:8e -----BEGIN CERTIFICATE----- -MIIDiDCCAnCgAwIBAgIJAIAgoEB/eYq4MA0GCSqGSIb3DQEBCwUAMD4xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVk -aWF0ZSBDQTAeFw0xNTEyMjMxOTM3MzZaFw0yNTEyMjAxOTM3MzZaMDQxCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEVMBMGA1UEAwwMc2VydmVyLncxLmZpMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5IilkwJbvFRoRvpzfTMwR0Vc -SV88UV+b/sUUECY9D+PCsheE0z4SqLJ7AhqKi+n0QR7880ktxtSIJ4HQhvO5wAoq -KEUAMsMYIvaZN/F0jaxUR3PlttPn+ICZdfUZGesZcN+SU7FhOP9/z4u94X9QW9CV -MKM3a4pyBqfoOeKkeEOYkc0wiDRbqp6inybV4VuGTQGkwmXNJ5S+4vVzXcRgmPF1 -EZQJDZ0Ef+8anV/wSj+I13Yum9YqxpQJNwo3JJKRnRgP6k7U5J1FOFq62N+2FW+s -/2xBrNfAClXsgcqaWUBVi6R3E9/6w7Xu74dBjZTQwJZBtDoEtmtqVpP0Z34n4QID -AQABo4GSMIGPMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFEuBhbSIQQ3UFdNIDvSp -mRQtsduTMB8GA1UdIwQYMBaAFIQJi1UffS8PKNec7FROnxGXVdm5MBoGA1UdEQEB -/wQQMA6CDHNlcnZlci53MS5maTAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATALBgNV -HQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggEBAEkqFCIWLBL1Tgbzwh6sVAddhhY+ -bKBz4abXw0kfgA22VCJ3zjnd9vafYv/VJ3/DknO5p86HWuO8UrMKmeuRVrZ4AcMO -S8qKBO5cVgXvessh+euKOBJQx26oHw6BgaYt6jWUJNt2d9/qQUyvfimd1ebjEngZ -ku01uZkZqdbL+Kch+46nOdzhqz26Eoe6HAjmiiGWRESKYQ9wANDLY5Ok+sx1o/3o -rzMkgErZuSqhIAtiCxdsmnyL/Z7/vrJRXuk6zCgiY0Rpf20fCBSkMtAf+cONKBp2 -EgA8szgTymcXecbeXbed+ONk97OgXOVu/BDzU9ZwOMJvh6sHHGT/MNg6HnU= +MIIDkzCCAnugAwIBAgIUXJ3kptF6SciDdedXaPdyFrKut4IwDQYJKoZIhvcNAQEL +BQAwPjELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMR8wHQYDVQQDDBZTZXJ2 +ZXIgSW50ZXJtZWRpYXRlIENBMB4XDTIwMDUwMzE1MjAxMFoXDTMwMDUwMTE1MjAx +MFowNDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMRUwEwYDVQQDDAxzZXJ2 +ZXIudzEuZmkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsIexV4pRs +1Rtt+neHf34q9SZOPCjUcFBwVeKp1atiFQECtZDoVZF8sPSf/RE8c3L3Vn1MtVYh +jxfEZVwqPw3iIqWA7RqwqIzimvePd23FJJ8rwDommxN1ltLPGUzK7ZCzyNrnIAOm +Cl2tBJ1rN51p6Wxj1RLa/8Kl1PQE3845wgY9P+yLPZ4cpy3yY1N+OqpoCrCTsmk9 +I9qxrv6Q+sbq7jWUTZrYXW+57YBrG71GVqu/KYrJIOUxPRGW4MVWWOHxhG28D+Wb +vJ91KwMBGliOiCKzCnyNs00egjF1f88oOqrA9cNFcrxI95phESwx1D1bbiXKKuqI +6Vj+7g0A1TaLAgMBAAGjgZIwgY8wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU6ePO +esInv4jPGZ5cbNwSwNUAZBUwHwYDVR0jBBgwFoAU69yNOHUQL+aCjv5D7J9+YyK9 +UVUwGgYDVR0RAQH/BBAwDoIMc2VydmVyLncxLmZpMBYGA1UdJQEB/wQMMAoGCCsG +AQUFBwMBMAsGA1UdDwQEAwIFoDANBgkqhkiG9w0BAQsFAAOCAQEAG8RK6rPuw4JN +mJNJajSYgLaj3ADVyidWQ+JxTGCh78JBnPqTpGEg9T8sOpHoEuF6UcCGK88bcyaz +DOcDLo5IST4yKd+yntUpJr/DPut9NJbHbg6uFqGh+iXdoy4+Tj52/9Y179QHL9Jv +SAir50oJ/0MJ7DJJGVLNMAMiPPCcm+P9vOf50Xraxma/4IaVXEVDByZtcPwkZkrN +hr1s03oNEkszvKBLgQgaJrxCouc3Nlas74U0Uokz37YzEawgZ82Nzte7y7y1FjwI +z8caaGAWnFXmtRdPP2n5tBhwr2BdD8RmCLl1o3gR94+N8StOBbmQtvOZiwxDaoy0 +zP8vWHDXjg== -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/iCA-server/server.req b/tests/hwsim/auth_serv/iCA-server/server.req index 2db7cc13a..181564b93 100644 --- a/tests/hwsim/auth_serv/iCA-server/server.req +++ b/tests/hwsim/auth_serv/iCA-server/server.req @@ -1,16 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- MIICjDCCAXQCAQAwRzELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4w DAYDVQQKDAV3MS5maTEVMBMGA1UEAwwMc2VydmVyLncxLmZpMIIBIjANBgkqhkiG -9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5IilkwJbvFRoRvpzfTMwR0VcSV88UV+b/sUU -ECY9D+PCsheE0z4SqLJ7AhqKi+n0QR7880ktxtSIJ4HQhvO5wAoqKEUAMsMYIvaZ -N/F0jaxUR3PlttPn+ICZdfUZGesZcN+SU7FhOP9/z4u94X9QW9CVMKM3a4pyBqfo -OeKkeEOYkc0wiDRbqp6inybV4VuGTQGkwmXNJ5S+4vVzXcRgmPF1EZQJDZ0Ef+8a -nV/wSj+I13Yum9YqxpQJNwo3JJKRnRgP6k7U5J1FOFq62N+2FW+s/2xBrNfAClXs -gcqaWUBVi6R3E9/6w7Xu74dBjZTQwJZBtDoEtmtqVpP0Z34n4QIDAQABoAAwDQYJ -KoZIhvcNAQELBQADggEBAE+hOOVtzHJvvrjl21A/gmdj5kRHYCijOGJ53ipY9mFX -aIK9+kJ0Jrlm9cZGbxwTMwJpAyk+7yPl3K0euoToXf+vdLnYds/HGRonN66pXqmD -QRZXGp6j58mBcmfiU1OB+6XRcLsYITaOaU9AvJ0jg9wkHISrN5uxfDG9QH//YYQ6 -aWzBfjUPAa+2trlmvI4tpC+w7sDHLa5WB5yBDm7HZ6UGwU5R7aMIZn2Hpe1BZS1u -Xo86qqJpbt6RvR5QEb6+79+8fmt3onQvZ28+wheUdcUin0G/JP7Lfo9/tNzU/29v -YJopHLeK1zNc6+lBwRTJiDbLC726H5dqZgxu9NNl8zg= +9w0BAQEFAAOCAQ8AMIIBCgKCAQEArCHsVeKUbNUbbfp3h39+KvUmTjwo1HBQcFXi +qdWrYhUBArWQ6FWRfLD0n/0RPHNy91Z9TLVWIY8XxGVcKj8N4iKlgO0asKiM4pr3 +j3dtxSSfK8A6JpsTdZbSzxlMyu2Qs8ja5yADpgpdrQSdazedaelsY9US2v/CpdT0 +BN/OOcIGPT/siz2eHKct8mNTfjqqaAqwk7JpPSPasa7+kPrG6u41lE2a2F1vue2A +axu9RlarvymKySDlMT0RluDFVljh8YRtvA/lm7yfdSsDARpYjogiswp8jbNNHoIx +dX/PKDqqwPXDRXK8SPeaYREsMdQ9W24lyirqiOlY/u4NANU2iwIDAQABoAAwDQYJ +KoZIhvcNAQELBQADggEBACNfUGcccnZoS3TqbWbfYMtWhi0a80xuWb+8v//aO0D2 +NeJMFmOKVgChOqHZza8rnIGMCOEbL1DkEJIZh1Z5ovy0fkGbcdCxeJIcem8PRLK0 +oFiLgIM9MeVDTSLY6FP7hjifR3x6SnO39DahiycnG45Kek7kVq25oCuyKxJrsoEQ +pwHdPG1VWvgDy4O7u2RA6kedU2gWjgHVUCJYpeJFp953kV1qrMM/ynFYJF049etm +Vyl/wxM69LP/bibElna/iAVFPBCe4Mav/bbI371Ju0AHzcdNxdoMnHgEhHB7c7Ye +QmZKRVi2HHD+PZ1xdtvqJD3EtSKkOuY8JRy6EteGdR4= -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/iCA-server/server_and_ica.pem b/tests/hwsim/auth_serv/iCA-server/server_and_ica.pem index 2e9917909..c7798a214 100644 --- a/tests/hwsim/auth_serv/iCA-server/server_and_ica.pem +++ b/tests/hwsim/auth_serv/iCA-server/server_and_ica.pem @@ -1,43 +1,125 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 9232555434986539704 (0x8020a0407f798ab8) + Serial Number: + d8:d3:e3:a6:cb:e3:cc:f7 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA + Validity + Not Before: May 3 15:20:10 2020 GMT + Not After : May 3 15:20:10 2030 GMT + Subject: C=FI, O=w1.fi, CN=Server Intermediate CA + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public-Key: (2048 bit) + Modulus: + 00:a2:b0:de:7f:e6:17:69:4b:bb:8d:dc:4f:8b:95: + 33:5e:13:ee:a1:01:f5:82:de:6e:fc:83:db:e7:22: + 5f:b9:8d:2b:de:10:72:4e:da:81:c1:f7:f3:eb:0e: + db:5b:5f:90:92:bb:41:68:55:4f:84:d9:73:5b:0c: + 6d:40:e6:c5:0f:5d:5c:5e:80:1e:64:87:5a:99:44: + 8b:3d:61:20:f0:15:cc:87:95:5b:a0:46:0f:bc:5c: + 14:ee:ac:4f:c8:7c:d2:c0:ef:60:94:22:b6:74:05: + 4f:ca:97:01:0a:30:b4:50:44:89:d0:c2:6b:e5:7f: + ce:66:22:1a:d6:38:7c:ff:42:42:ca:58:a0:38:85: + ca:f1:b1:1f:33:27:db:bf:5c:49:96:36:7a:11:2f: + 62:d7:eb:7e:9f:9b:9c:0e:2b:df:cd:59:bc:ee:e8: + 6a:e3:7d:fa:06:ba:34:42:b5:7d:e7:be:e1:7b:85: + af:1b:25:a9:45:33:06:cb:cc:0d:ca:78:5c:56:52: + ac:43:7e:f6:0c:e7:fb:86:b4:ac:d7:f4:b2:54:ee: + 65:7a:5c:32:6b:33:a0:68:1b:d8:ea:c8:74:94:08: + 00:7f:9b:f0:da:80:0f:f2:45:13:11:63:4c:e6:d2: + 97:d3:ae:12:b0:7c:e8:f0:56:c0:7b:7c:82:99:6d: + 3b:5d + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + EB:DC:8D:38:75:10:2F:E6:82:8E:FE:43:EC:9F:7E:63:22:BD:51:55 + X509v3 Authority Key Identifier: + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 + + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 Key Usage: critical + Certificate Sign, CRL Sign Signature Algorithm: sha256WithRSAEncryption + 86:74:75:b2:bb:b0:85:25:48:38:e1:34:54:d5:d4:3a:9f:0e: + b1:96:fd:cc:ea:15:21:72:da:9e:ef:e2:fa:ae:29:74:dc:83: + 36:87:88:7d:75:51:9a:c5:6e:a8:80:77:3f:5c:ed:9e:ac:57: + 17:ed:ab:64:4f:15:8b:47:90:0a:17:2a:7e:49:a9:01:a1:41: + 66:d4:fe:be:18:70:d6:23:f7:0b:0a:53:d7:75:a8:7f:0a:52: + 1c:1d:8c:63:6f:82:ed:ed:fd:e2:fe:86:ef:0a:4c:f8:d7:93: + 56:9a:a3:dd:74:02:8c:b3:31:83:c1:8a:66:c6:c0:1d:dc:00: + 5c:57:f4:31:31:8b:d4:84:d8:da:6d:d6:f6:e4:10:7e:bb:f2: + 41:95:dd:a6:0c:37:c7:22:80:e6:36:3e:34:c6:1c:73:ab:42: + 90:6e:f8:db:e8:b6:c0:b2:f5:17:d2:6f:d3:8c:fb:14:25:8e: + 72:81:45:76:86:f7:d1:d9:3d:ff:b1:a2:10:6f:c0:24:e7:70: + 3f:2d:cf:32:ee:06:70:d5:1b:04:84:6d:48:69:26:1e:98:5a: + ed:e3:61:f5:29:45:88:25:cf:7f:c4:fb:f3:87:a7:11:95:9e: + cf:a8:aa:88:db:12:32:66:66:c4:1d:12:b1:62:1d:fa:28:f4: + 97:ac:df:2e +-----BEGIN CERTIFICATE----- +MIIDaDCCAlCgAwIBAgIJANjT46bL48z3MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDMxNTIwMTBaFw0zMDA1MDMxNTIwMTBaMD4xCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVy +bWVkaWF0ZSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKKw3n/m +F2lLu43cT4uVM14T7qEB9YLebvyD2+ciX7mNK94Qck7agcH38+sO21tfkJK7QWhV +T4TZc1sMbUDmxQ9dXF6AHmSHWplEiz1hIPAVzIeVW6BGD7xcFO6sT8h80sDvYJQi +tnQFT8qXAQowtFBEidDCa+V/zmYiGtY4fP9CQspYoDiFyvGxHzMn279cSZY2ehEv +Ytfrfp+bnA4r381ZvO7oauN9+ga6NEK1fee+4XuFrxslqUUzBsvMDcp4XFZSrEN+ +9gzn+4a0rNf0slTuZXpcMmszoGgb2OrIdJQIAH+b8NqAD/JFExFjTObSl9OuErB8 +6PBWwHt8gpltO10CAwEAAaNmMGQwHQYDVR0OBBYEFOvcjTh1EC/mgo7+Q+yffmMi +vVFVMB8GA1UdIwQYMBaAFKT9uTkbgbOq64gd1IGptRFwzKfhMBIGA1UdEwEB/wQI +MAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4IBAQCGdHWy +u7CFJUg44TRU1dQ6nw6xlv3M6hUhctqe7+L6ril03IM2h4h9dVGaxW6ogHc/XO2e +rFcX7atkTxWLR5AKFyp+SakBoUFm1P6+GHDWI/cLClPXdah/ClIcHYxjb4Lt7f3i +/obvCkz415NWmqPddAKMszGDwYpmxsAd3ABcV/QxMYvUhNjabdb25BB+u/JBld2m +DDfHIoDmNj40xhxzq0KQbvjb6LbAsvUX0m/TjPsUJY5ygUV2hvfR2T3/saIQb8Ak +53A/Lc8y7gZw1RsEhG1IaSYemFrt42H1KUWIJc9/xPvzh6cRlZ7PqKqI2xIyZmbE +HRKxYh36KPSXrN8u +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 5c:9d:e4:a6:d1:7a:49:c8:83:75:e7:57:68:f7:72:16:b2:ae:b7:82 + Signature Algorithm: sha256WithRSAEncryption Issuer: C=FI, O=w1.fi, CN=Server Intermediate CA Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 20 19:37:36 2025 GMT + Not Before: May 3 15:20:10 2020 GMT + Not After : May 1 15:20:10 2030 GMT Subject: C=FI, O=w1.fi, CN=server.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:e4:88:a5:93:02:5b:bc:54:68:46:fa:73:7d:33: - 30:47:45:5c:49:5f:3c:51:5f:9b:fe:c5:14:10:26: - 3d:0f:e3:c2:b2:17:84:d3:3e:12:a8:b2:7b:02:1a: - 8a:8b:e9:f4:41:1e:fc:f3:49:2d:c6:d4:88:27:81: - d0:86:f3:b9:c0:0a:2a:28:45:00:32:c3:18:22:f6: - 99:37:f1:74:8d:ac:54:47:73:e5:b6:d3:e7:f8:80: - 99:75:f5:19:19:eb:19:70:df:92:53:b1:61:38:ff: - 7f:cf:8b:bd:e1:7f:50:5b:d0:95:30:a3:37:6b:8a: - 72:06:a7:e8:39:e2:a4:78:43:98:91:cd:30:88:34: - 5b:aa:9e:a2:9f:26:d5:e1:5b:86:4d:01:a4:c2:65: - cd:27:94:be:e2:f5:73:5d:c4:60:98:f1:75:11:94: - 09:0d:9d:04:7f:ef:1a:9d:5f:f0:4a:3f:88:d7:76: - 2e:9b:d6:2a:c6:94:09:37:0a:37:24:92:91:9d:18: - 0f:ea:4e:d4:e4:9d:45:38:5a:ba:d8:df:b6:15:6f: - ac:ff:6c:41:ac:d7:c0:0a:55:ec:81:ca:9a:59:40: - 55:8b:a4:77:13:df:fa:c3:b5:ee:ef:87:41:8d:94: - d0:c0:96:41:b4:3a:04:b6:6b:6a:56:93:f4:67:7e: - 27:e1 + 00:ac:21:ec:55:e2:94:6c:d5:1b:6d:fa:77:87:7f: + 7e:2a:f5:26:4e:3c:28:d4:70:50:70:55:e2:a9:d5: + ab:62:15:01:02:b5:90:e8:55:91:7c:b0:f4:9f:fd: + 11:3c:73:72:f7:56:7d:4c:b5:56:21:8f:17:c4:65: + 5c:2a:3f:0d:e2:22:a5:80:ed:1a:b0:a8:8c:e2:9a: + f7:8f:77:6d:c5:24:9f:2b:c0:3a:26:9b:13:75:96: + d2:cf:19:4c:ca:ed:90:b3:c8:da:e7:20:03:a6:0a: + 5d:ad:04:9d:6b:37:9d:69:e9:6c:63:d5:12:da:ff: + c2:a5:d4:f4:04:df:ce:39:c2:06:3d:3f:ec:8b:3d: + 9e:1c:a7:2d:f2:63:53:7e:3a:aa:68:0a:b0:93:b2: + 69:3d:23:da:b1:ae:fe:90:fa:c6:ea:ee:35:94:4d: + 9a:d8:5d:6f:b9:ed:80:6b:1b:bd:46:56:ab:bf:29: + 8a:c9:20:e5:31:3d:11:96:e0:c5:56:58:e1:f1:84: + 6d:bc:0f:e5:9b:bc:9f:75:2b:03:01:1a:58:8e:88: + 22:b3:0a:7c:8d:b3:4d:1e:82:31:75:7f:cf:28:3a: + aa:c0:f5:c3:45:72:bc:48:f7:9a:61:11:2c:31:d4: + 3d:5b:6e:25:ca:2a:ea:88:e9:58:fe:ee:0d:00:d5: + 36:8b Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: critical CA:FALSE X509v3 Subject Key Identifier: - 4B:81:85:B4:88:41:0D:D4:15:D3:48:0E:F4:A9:99:14:2D:B1:DB:93 + E9:E3:CE:7A:C2:27:BF:88:CF:19:9E:5C:6C:DC:12:C0:D5:00:64:15 X509v3 Authority Key Identifier: - keyid:84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9 + keyid:EB:DC:8D:38:75:10:2F:E6:82:8E:FE:43:EC:9F:7E:63:22:BD:51:55 X509v3 Subject Alternative Name: critical DNS:server.w1.fi @@ -46,109 +128,40 @@ Certificate: X509v3 Key Usage: Digital Signature, Key Encipherment Signature Algorithm: sha256WithRSAEncryption - 49:2a:14:22:16:2c:12:f5:4e:06:f3:c2:1e:ac:54:07:5d:86: - 16:3e:6c:a0:73:e1:a6:d7:c3:49:1f:80:0d:b6:54:22:77:ce: - 39:dd:f6:f6:9f:62:ff:d5:27:7f:c3:92:73:b9:a7:ce:87:5a: - e3:bc:52:b3:0a:99:eb:91:56:b6:78:01:c3:0e:4b:ca:8a:04: - ee:5c:56:05:ef:7a:cb:21:f9:eb:8a:38:12:50:c7:6e:a8:1f: - 0e:81:81:a6:2d:ea:35:94:24:db:76:77:df:ea:41:4c:af:7e: - 29:9d:d5:e6:e3:12:78:19:92:ed:35:b9:99:19:a9:d6:cb:f8: - a7:21:fb:8e:a7:39:dc:e1:ab:3d:ba:12:87:ba:1c:08:e6:8a: - 21:96:44:44:8a:61:0f:70:00:d0:cb:63:93:a4:fa:cc:75:a3: - fd:e8:af:33:24:80:4a:d9:b9:2a:a1:20:0b:62:0b:17:6c:9a: - 7c:8b:fd:9e:ff:be:b2:51:5e:e9:3a:cc:28:22:63:44:69:7f: - 6d:1f:08:14:a4:32:d0:1f:f9:c3:8d:28:1a:76:12:00:3c:b3: - 38:13:ca:67:17:79:c6:de:5d:b7:9d:f8:e3:64:f7:b3:a0:5c: - e5:6e:fc:10:f3:53:d6:70:38:c2:6f:87:ab:07:1c:64:ff:30: - d8:3a:1e:75 + 1b:c4:4a:ea:b3:ee:c3:82:4d:98:93:49:6a:34:98:80:b6:a3: + dc:00:d5:ca:27:56:43:e2:71:4c:60:a1:ef:c2:41:9c:fa:93: + a4:61:20:f5:3f:2c:3a:91:e8:12:e1:7a:51:c0:86:2b:cf:1b: + 73:26:b3:0c:e7:03:2e:8e:48:49:3e:32:29:df:b2:9e:d5:29: + 26:bf:c3:3e:eb:7d:34:96:c7:6e:0e:ae:16:a1:a1:fa:25:dd: + a3:2e:3e:4e:3e:76:ff:d6:35:ef:d4:07:2f:d2:6f:48:08:ab: + e7:4a:09:ff:43:09:ec:32:49:19:52:cd:30:03:22:3c:f0:9c: + 9b:e3:fd:bc:e7:f9:d1:7a:da:c6:66:bf:e0:86:95:5c:45:43: + 07:26:6d:70:fc:24:66:4a:cd:86:bd:6c:d3:7a:0d:12:4b:33: + bc:a0:4b:81:08:1a:26:bc:42:a2:e7:37:36:56:ac:ef:85:34: + 52:89:33:df:b6:33:11:ac:20:67:cd:8d:ce:d7:bb:cb:bc:b5: + 16:3c:08:cf:c7:1a:68:60:16:9c:55:e6:b5:17:4f:3f:69:f9: + b4:18:70:af:60:5d:0f:c4:66:08:b9:75:a3:78:11:f7:8f:8d: + f1:2b:4e:05:b9:90:b6:f3:99:8b:0c:43:6a:8c:b4:cc:ff:2f: + 58:70:d7:8e -----BEGIN CERTIFICATE----- -MIIDiDCCAnCgAwIBAgIJAIAgoEB/eYq4MA0GCSqGSIb3DQEBCwUAMD4xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVk -aWF0ZSBDQTAeFw0xNTEyMjMxOTM3MzZaFw0yNTEyMjAxOTM3MzZaMDQxCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEVMBMGA1UEAwwMc2VydmVyLncxLmZpMIIB -IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5IilkwJbvFRoRvpzfTMwR0Vc -SV88UV+b/sUUECY9D+PCsheE0z4SqLJ7AhqKi+n0QR7880ktxtSIJ4HQhvO5wAoq -KEUAMsMYIvaZN/F0jaxUR3PlttPn+ICZdfUZGesZcN+SU7FhOP9/z4u94X9QW9CV -MKM3a4pyBqfoOeKkeEOYkc0wiDRbqp6inybV4VuGTQGkwmXNJ5S+4vVzXcRgmPF1 -EZQJDZ0Ef+8anV/wSj+I13Yum9YqxpQJNwo3JJKRnRgP6k7U5J1FOFq62N+2FW+s -/2xBrNfAClXsgcqaWUBVi6R3E9/6w7Xu74dBjZTQwJZBtDoEtmtqVpP0Z34n4QID -AQABo4GSMIGPMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFEuBhbSIQQ3UFdNIDvSp -mRQtsduTMB8GA1UdIwQYMBaAFIQJi1UffS8PKNec7FROnxGXVdm5MBoGA1UdEQEB -/wQQMA6CDHNlcnZlci53MS5maTAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATALBgNV -HQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggEBAEkqFCIWLBL1Tgbzwh6sVAddhhY+ -bKBz4abXw0kfgA22VCJ3zjnd9vafYv/VJ3/DknO5p86HWuO8UrMKmeuRVrZ4AcMO -S8qKBO5cVgXvessh+euKOBJQx26oHw6BgaYt6jWUJNt2d9/qQUyvfimd1ebjEngZ -ku01uZkZqdbL+Kch+46nOdzhqz26Eoe6HAjmiiGWRESKYQ9wANDLY5Ok+sx1o/3o -rzMkgErZuSqhIAtiCxdsmnyL/Z7/vrJRXuk6zCgiY0Rpf20fCBSkMtAf+cONKBp2 -EgA8szgTymcXecbeXbed+ONk97OgXOVu/BDzU9ZwOMJvh6sHHGT/MNg6HnU= ------END CERTIFICATE----- -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 15624081837803162867 (0xd8d3e3a6cbe3ccf3) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA - Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 22 19:37:36 2025 GMT - Subject: C=FI, O=w1.fi, CN=Server Intermediate CA - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:de:58:ac:e3:d8:7e:40:f6:84:2a:49:24:49:5a: - f7:c8:23:08:b9:6c:d9:07:01:69:8f:77:28:71:42: - a2:eb:ae:86:10:c6:31:61:9a:14:88:44:0a:68:bf: - 6e:a2:46:41:e9:6f:a2:89:fb:0b:f3:e1:b8:30:bf: - e5:80:5e:f9:61:8d:6e:ac:e2:f7:28:e7:9e:44:28: - b8:e4:6e:87:76:a9:d7:ac:ed:11:3f:de:c3:dd:41: - c3:45:82:09:c3:a7:4c:e6:df:2b:88:1e:44:ce:e2: - a7:29:53:f6:13:96:ad:6c:2e:93:00:28:42:77:bc: - 73:6e:86:e7:5b:e8:eb:e9:37:1d:63:e7:ea:05:5a: - 71:28:f0:81:0b:4c:3f:dd:73:f8:db:13:a8:f0:5f: - 6f:6f:e5:1b:c7:94:7f:57:c5:dc:66:26:0c:5a:71: - 7a:e3:d2:3e:7a:a6:59:46:03:61:78:89:84:3d:ef: - 22:9c:f8:c2:22:75:c4:0c:ef:fb:e4:fa:6f:b8:11: - db:aa:92:9b:6c:23:4e:6e:e5:55:d2:41:47:18:95: - c6:7d:17:be:6d:ab:39:a1:38:61:fd:f9:22:95:69: - f3:9e:28:fd:8a:c8:58:72:3c:91:c2:22:d9:fb:b2: - 54:0f:9a:17:27:88:df:60:f5:de:fc:95:9f:25:c6: - 64:81 - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Subject Key Identifier: - 84:09:8B:55:1F:7D:2F:0F:28:D7:9C:EC:54:4E:9F:11:97:55:D9:B9 - X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 - - X509v3 Basic Constraints: critical - CA:TRUE, pathlen:0 - X509v3 Key Usage: critical - Certificate Sign, CRL Sign - Signature Algorithm: sha256WithRSAEncryption - bd:22:63:3d:a7:e5:ce:c9:f5:66:1f:77:5f:d5:24:e3:68:dc: - a4:07:80:3e:5e:b1:2c:96:88:39:ad:00:4c:aa:9d:0b:ed:f3: - 6d:df:9d:2f:97:d2:77:8b:ba:d0:9c:0f:a6:5e:60:b8:0f:e1: - 96:b1:61:25:48:69:81:64:a8:5c:82:58:0b:f3:d0:a9:4e:8b: - 90:fc:2f:67:57:da:72:dc:3c:eb:c2:20:19:05:8d:42:0d:14: - cf:00:db:59:00:ea:f0:76:3e:ca:85:b1:05:e5:b8:5f:0b:46: - c7:3c:a1:d9:5c:4d:b9:24:e7:d6:2b:3d:0d:eb:c3:88:d8:3a: - f6:60 ------BEGIN CERTIFICATE----- -MIIC1TCCAj6gAwIBAgIJANjT46bL48zzMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy -MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMD4xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEfMB0GA1UEAwwWU2VydmVyIEludGVybWVkaWF0ZSBDQTCCASIwDQYJ -KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN5YrOPYfkD2hCpJJEla98gjCLls2QcB -aY93KHFCouuuhhDGMWGaFIhECmi/bqJGQelvoon7C/PhuDC/5YBe+WGNbqzi9yjn -nkQouORuh3ap16ztET/ew91Bw0WCCcOnTObfK4geRM7ipylT9hOWrWwukwAoQne8 -c26G51vo6+k3HWPn6gVacSjwgQtMP91z+NsTqPBfb2/lG8eUf1fF3GYmDFpxeuPS -PnqmWUYDYXiJhD3vIpz4wiJ1xAzv++T6b7gR26qSm2wjTm7lVdJBRxiVxn0Xvm2r -OaE4Yf35IpVp854o/YrIWHI8kcIi2fuyVA+aFyeI32D13vyVnyXGZIECAwEAAaNm -MGQwHQYDVR0OBBYEFIQJi1UffS8PKNec7FROnxGXVdm5MB8GA1UdIwQYMBaAFLiS -3v2KGLMww59V8zNdtMgpikEUMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/ -BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4GBAL0iYz2n5c7J9WYfd1/VJONo3KQHgD5e -sSyWiDmtAEyqnQvt823fnS+X0neLutCcD6ZeYLgP4ZaxYSVIaYFkqFyCWAvz0KlO -i5D8L2dX2nLcPOvCIBkFjUINFM8A21kA6vB2PsqFsQXluF8LRsc8odlcTbkk59Yr -PQ3rw4jYOvZg +MIIDkzCCAnugAwIBAgIUXJ3kptF6SciDdedXaPdyFrKut4IwDQYJKoZIhvcNAQEL +BQAwPjELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMR8wHQYDVQQDDBZTZXJ2 +ZXIgSW50ZXJtZWRpYXRlIENBMB4XDTIwMDUwMzE1MjAxMFoXDTMwMDUwMTE1MjAx +MFowNDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMRUwEwYDVQQDDAxzZXJ2 +ZXIudzEuZmkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsIexV4pRs +1Rtt+neHf34q9SZOPCjUcFBwVeKp1atiFQECtZDoVZF8sPSf/RE8c3L3Vn1MtVYh +jxfEZVwqPw3iIqWA7RqwqIzimvePd23FJJ8rwDommxN1ltLPGUzK7ZCzyNrnIAOm +Cl2tBJ1rN51p6Wxj1RLa/8Kl1PQE3845wgY9P+yLPZ4cpy3yY1N+OqpoCrCTsmk9 +I9qxrv6Q+sbq7jWUTZrYXW+57YBrG71GVqu/KYrJIOUxPRGW4MVWWOHxhG28D+Wb +vJ91KwMBGliOiCKzCnyNs00egjF1f88oOqrA9cNFcrxI95phESwx1D1bbiXKKuqI +6Vj+7g0A1TaLAgMBAAGjgZIwgY8wDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU6ePO +esInv4jPGZ5cbNwSwNUAZBUwHwYDVR0jBBgwFoAU69yNOHUQL+aCjv5D7J9+YyK9 +UVUwGgYDVR0RAQH/BBAwDoIMc2VydmVyLncxLmZpMBYGA1UdJQEB/wQMMAoGCCsG +AQUFBwMBMAsGA1UdDwQEAwIFoDANBgkqhkiG9w0BAQsFAAOCAQEAG8RK6rPuw4JN +mJNJajSYgLaj3ADVyidWQ+JxTGCh78JBnPqTpGEg9T8sOpHoEuF6UcCGK88bcyaz +DOcDLo5IST4yKd+yntUpJr/DPut9NJbHbg6uFqGh+iXdoy4+Tj52/9Y179QHL9Jv +SAir50oJ/0MJ7DJJGVLNMAMiPPCcm+P9vOf50Xraxma/4IaVXEVDByZtcPwkZkrN +hr1s03oNEkszvKBLgQgaJrxCouc3Nlas74U0Uokz37YzEawgZ82Nzte7y7y1FjwI +z8caaGAWnFXmtRdPP2n5tBhwr2BdD8RmCLl1o3gR94+N8StOBbmQtvOZiwxDaoy0 +zP8vWHDXjg== -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/iCA-user/ca-and-root.pem b/tests/hwsim/auth_serv/iCA-user/ca-and-root.pem index 4fa1248ac..41c8240e5 100644 --- a/tests/hwsim/auth_serv/iCA-user/ca-and-root.pem +++ b/tests/hwsim/auth_serv/iCA-user/ca-and-root.pem @@ -1,125 +1,160 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162868 (0xd8d3e3a6cbe3ccf4) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + d8:d3:e3:a6:cb:e3:cc:f8 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 22 19:37:36 2025 GMT + Not Before: May 3 15:20:10 2020 GMT + Not After : May 3 15:20:10 2030 GMT Subject: C=FI, O=w1.fi, CN=User Intermediate CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:c3:2a:0d:f4:66:23:5d:96:91:f7:a0:be:b1:b0: - f7:9e:ae:ea:a6:72:91:f5:70:65:57:91:49:55:59: - 67:bb:d7:f5:9e:bc:66:b2:bf:cf:95:31:32:ae:db: - 9a:3b:43:e8:a5:8d:1f:8b:3b:e6:e8:e3:3b:b2:9d: - f0:58:62:ea:a3:8a:6f:c8:ed:01:ca:27:74:1c:0e: - 9e:28:5c:43:98:db:14:b8:72:07:9f:6b:27:28:25: - ce:a5:91:b7:b7:23:9a:35:ef:0e:b7:fc:9f:69:4d: - 10:2e:81:ab:9d:04:ba:2f:b4:eb:61:7d:fd:68:a1: - 11:6f:f4:16:42:16:99:20:38:24:04:2d:39:7c:74: - 67:14:b9:aa:26:7a:b2:d9:1e:ce:cd:8b:bc:8d:e3: - c7:58:9c:4a:f9:3a:7e:6c:38:f8:5f:1c:ec:05:4c: - e5:56:64:d4:08:d8:fa:db:17:d9:a1:e4:cf:b4:9d: - df:99:50:ce:fa:a4:af:af:c6:f7:f2:0e:c2:c5:7b: - 6c:f9:6c:eb:17:e5:c8:6e:5a:bf:eb:a6:b8:c0:f7: - 43:81:88:c3:d8:aa:a9:60:ac:a7:45:3f:5d:cb:8d: - 6c:48:92:2b:04:5a:c4:a8:32:b3:e9:6f:fe:8d:2d: - 65:c0:ea:c5:09:b2:30:b1:a3:2e:db:22:8a:49:b1: - fe:4f + 00:b9:88:7a:fc:1a:f9:00:68:63:c7:40:ff:d5:38: + 8e:88:8c:c9:8f:66:ec:74:0a:a6:f1:18:30:30:36: + 9a:2a:98:c5:a0:46:02:e2:3c:64:86:79:43:45:19: + 83:7a:82:3d:f9:c6:af:01:11:91:2c:4f:07:f8:d7: + ef:da:80:6c:07:88:6a:1e:e6:0e:78:ca:08:50:4f: + f0:8a:2e:54:41:9f:04:63:8b:70:99:ae:6f:95:ed: + 5c:c8:34:8e:6b:36:64:bc:44:c9:fb:cb:50:ef:b1: + 5b:9b:2c:db:2a:a7:f9:e0:e2:48:57:78:cf:ba:0f: + 1a:af:5a:63:64:18:39:9c:d4:af:8d:f9:27:d9:10: + b4:67:17:a1:24:98:f1:ef:ce:ad:12:6f:e4:47:36: + b6:d2:b6:1c:04:03:76:43:63:fb:b6:3e:3f:1a:c8: + c4:8b:69:28:7c:75:dc:bb:36:7f:ad:6a:a2:c1:32: + f3:5e:64:86:57:f1:ee:20:af:64:bd:e0:7c:ba:68: + 9b:75:ed:b3:1c:0f:12:e0:52:12:ff:18:0e:8f:1d: + bf:c8:88:56:35:4d:9e:1f:74:1e:19:d7:0c:b4:e7: + 46:ee:cf:c6:63:35:ba:16:7f:05:84:8b:bf:16:72: + 05:ee:22:6e:3a:54:80:2b:0e:36:96:8d:65:5f:64: + 12:cd Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - AC:C4:F6:07:9E:B2:E5:F1:66:7C:40:05:08:AA:DC:EF:8A:60:DA:C1 + F0:F7:82:29:71:CD:AF:72:CE:F6:3C:0B:40:16:C2:FD:9F:8A:51:A7 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Certificate Sign, CRL Sign Signature Algorithm: sha256WithRSAEncryption - 0d:60:2b:fa:00:f2:5a:90:31:96:50:c8:9e:7f:60:02:99:c6: - 31:d4:93:86:9e:4c:24:15:b6:b2:31:49:21:79:ce:7f:92:86: - 1e:83:d8:a0:37:05:1b:89:2b:ef:0b:83:21:b0:37:8d:2f:7b: - 6b:7d:c6:04:1e:a2:c8:59:be:52:bf:47:ee:46:cb:45:8d:1f: - 7a:e4:d4:e5:54:60:5f:46:b0:ac:68:8a:26:57:ea:48:45:c1: - 07:7d:ee:10:9e:94:87:4c:7e:26:2e:f8:ad:03:e5:03:86:09: - 3e:48:0c:e0:04:2f:22:b4:e0:3a:b0:72:8c:e2:40:d2:cd:fb: - 8f:fa + 70:45:66:14:00:22:85:1c:f8:b9:b3:2c:e8:64:4d:01:53:b8: + cb:23:ad:fa:01:7c:27:f7:aa:8d:d8:6c:6a:f8:72:21:63:bf: + 30:7e:05:8c:84:e3:d1:1e:d1:f3:1d:80:3d:e8:75:06:ae:1b: + 48:a9:cf:0e:c6:59:6b:f8:d1:25:5a:64:b7:46:2d:29:72:da: + d6:3a:79:d3:92:41:d7:31:e4:4e:5e:1b:62:88:41:77:f6:62: + a2:3e:c1:a2:ef:79:0c:8f:39:7c:df:a0:4b:d5:ac:58:aa:3e: + fd:95:6b:f7:c0:42:29:2e:86:67:5e:d9:3e:7b:e7:a6:bd:3b: + 7e:3b:19:54:9b:89:40:0e:39:23:8a:af:f2:db:12:5b:09:b4: + 45:df:c8:3e:8f:fc:fc:55:3e:35:8d:7b:82:50:d5:a3:ea:bb: + c4:40:6d:61:ad:92:b2:66:91:0f:5b:3d:49:5e:b5:3e:98:15: + 9e:2a:23:06:35:e0:13:bc:50:84:06:e4:1b:b9:fc:32:a2:4a: + 0d:e5:86:ac:69:47:c3:17:11:07:ac:5a:09:69:ed:99:d0:52: + fd:6d:ab:0d:44:35:bb:c0:76:27:50:75:df:06:78:f6:92:54: + fc:54:76:b5:6f:a0:f6:51:20:1f:7f:8e:aa:5f:c8:48:88:e4: + 1a:83:f6:b7 -----BEGIN CERTIFICATE----- -MIIC0zCCAjygAwIBAgIJANjT46bL48z0MA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy -MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMDwxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDKg30ZiNdlpH3oL6xsPeeruqmcpH1cGVX -kUlVWWe71/WevGayv8+VMTKu25o7Q+iljR+LO+bo4zuynfBYYuqjim/I7QHKJ3Qc -Dp4oXEOY2xS4cgefaycoJc6lkbe3I5o17w63/J9pTRAugaudBLovtOthff1ooRFv -9BZCFpkgOCQELTl8dGcUuaomerLZHs7Ni7yN48dYnEr5On5sOPhfHOwFTOVWZNQI -2PrbF9mh5M+0nd+ZUM76pK+vxvfyDsLFe2z5bOsX5chuWr/rprjA90OBiMPYqqlg -rKdFP13LjWxIkisEWsSoMrPpb/6NLWXA6sUJsjCxoy7bIopJsf5PAgMBAAGjZjBk -MB0GA1UdDgQWBBSsxPYHnrLl8WZ8QAUIqtzvimDawTAfBgNVHSMEGDAWgBS4kt79 -ihizMMOfVfMzXbTIKYpBFDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQE -AwIBBjANBgkqhkiG9w0BAQsFAAOBgQANYCv6APJakDGWUMief2ACmcYx1JOGnkwk -FbayMUkhec5/koYeg9igNwUbiSvvC4MhsDeNL3trfcYEHqLIWb5Sv0fuRstFjR96 -5NTlVGBfRrCsaIomV+pIRcEHfe4QnpSHTH4mLvitA+UDhgk+SAzgBC8itOA6sHKM -4kDSzfuP+g== +MIIDZjCCAk6gAwIBAgIJANjT46bL48z4MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDMxNTIwMTBaFw0zMDA1MDMxNTIwMTBaMDwxCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1l +ZGlhdGUgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5iHr8GvkA +aGPHQP/VOI6IjMmPZux0CqbxGDAwNpoqmMWgRgLiPGSGeUNFGYN6gj35xq8BEZEs +Twf41+/agGwHiGoe5g54yghQT/CKLlRBnwRji3CZrm+V7VzINI5rNmS8RMn7y1Dv +sVubLNsqp/ng4khXeM+6DxqvWmNkGDmc1K+N+SfZELRnF6EkmPHvzq0Sb+RHNrbS +thwEA3ZDY/u2Pj8ayMSLaSh8ddy7Nn+taqLBMvNeZIZX8e4gr2S94Hy6aJt17bMc +DxLgUhL/GA6PHb/IiFY1TZ4fdB4Z1wy050buz8ZjNboWfwWEi78WcgXuIm46VIAr +DjaWjWVfZBLNAgMBAAGjZjBkMB0GA1UdDgQWBBTw94Ipcc2vcs72PAtAFsL9n4pR +pzAfBgNVHSMEGDAWgBSk/bk5G4GzquuIHdSBqbURcMyn4TASBgNVHRMBAf8ECDAG +AQH/AgEAMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAcEVmFAAi +hRz4ubMs6GRNAVO4yyOt+gF8J/eqjdhsavhyIWO/MH4FjITj0R7R8x2APeh1Bq4b +SKnPDsZZa/jRJVpkt0YtKXLa1jp505JB1zHkTl4bYohBd/Zioj7Bou95DI85fN+g +S9WsWKo+/ZVr98BCKS6GZ17ZPnvnpr07fjsZVJuJQA45I4qv8tsSWwm0Rd/IPo/8 +/FU+NY17glDVo+q7xEBtYa2SsmaRD1s9SV61PpgVniojBjXgE7xQhAbkG7n8MqJK +DeWGrGlHwxcRB6xaCWntmdBS/W2rDUQ1u8B2J1B13wZ49pJU/FR2tW+g9lEgH3+O +ql/ISIjkGoP2tw== -----END CERTIFICATE----- Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162817 (0xd8d3e3a6cbe3ccc1) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + 42:97:6c:30:8e:79:fc:7b:6a:e3:ef:9d:18:a4:74:9d:8b:5f:57:53 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Validity - Not Before: Jun 29 16:41:22 2013 GMT - Not After : Jun 27 16:41:22 2023 GMT - Subject: C=FI, O=w1.fi, CN=Root CA + Not Before: May 2 19:49:48 2020 GMT + Not After : Apr 30 19:49:48 2030 GMT + Subject: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:be:1e:86:e4:79:03:c1:d1:94:d5:d4:b3:b1:28: - 90:76:fb:b8:a6:cd:6d:1c:d1:48:f4:08:9a:67:ff: - f9:a6:54:b1:19:29:df:29:1b:cd:f1:6f:66:01:e7: - db:79:ce:c0:39:2a:25:13:26:94:0c:2c:7b:5a:2c: - 81:0f:94:ee:51:d0:75:e6:46:db:17:46:a7:15:8b: - 0e:57:0f:b0:54:76:63:12:ca:86:18:bc:1a:c3:16: - c0:70:09:d6:6b:43:39:b8:98:29:46:ac:cb:6a:ad: - 38:88:3b:07:dc:81:cd:3a:f6:1d:f6:2f:ef:1d:d7: - ae:8a:b6:d1:e7:b3:15:02:b9 + 00:bc:f4:ee:44:62:7f:62:4f:a1:81:46:ba:c4:aa: + 1e:fd:4e:d0:ed:f1:47:cb:25:5b:66:7a:86:39:91: + ca:b5:61:a7:7e:2f:3c:63:7d:39:b8:1a:9e:cb:6d: + 32:32:91:de:49:49:84:da:15:be:2b:dd:c6:bc:1f: + dc:6e:c0:2d:77:f2:d0:7b:2c:40:19:07:60:55:b0: + ff:7c:51:ef:38:d1:f0:2a:da:a8:cc:ea:d6:54:a4: + ef:be:17:44:1a:9e:33:70:57:a4:f3:06:ac:3d:ee: + 4b:2d:e5:46:25:2d:33:09:f6:49:a8:02:31:a4:65: + 9b:32:0a:67:f5:02:e1:3b:47:a6:ae:e4:f6:85:eb: + 5d:3e:02:66:dd:11:98:ac:34:72:c2:8f:25:55:4a: + 6a:ea:e8:82:2f:bd:7f:78:31:a4:5a:d7:32:bb:64: + 48:46:23:ef:c8:c9:e2:84:00:56:72:e8:4b:54:95: + 62:3a:5a:11:79:ee:40:43:9e:16:2c:cc:e6:45:f4: + bb:82:28:c2:83:35:2c:55:36:99:59:11:b1:15:d0: + 03:c1:a5:37:e1:1f:bb:43:c7:b4:b9:33:de:14:d7: + 7c:99:45:0f:c1:06:fe:b6:25:10:59:b7:72:76:7f: + 91:4b:ea:d1:b9:6a:6a:ed:dd:1b:a9:0e:a7:29:48: + b7:4d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 1a:cf:77:60:44:43:c4:55:0e:99:e0:89:aa:b9:d3:7b:32:b7: - 5c:9c:7c:ca:fe:8c:d4:94:c6:5e:f3:83:19:5f:29:59:68:a4: - 4f:dc:04:2e:b8:71:c0:6d:3b:ae:01:e4:b9:88:99:cc:ce:82: - be:6a:28:c2:ac:6a:94:c6:87:90:ed:85:3c:10:71:c5:ff:3c: - 70:64:e2:41:62:31:ea:86:7b:11:8c:93:ea:c6:f3:f3:4e:f9: - d4:f2:81:90:d7:f4:fa:a1:91:6e:d4:dd:15:3e:26:3b:ac:1e: - c3:c2:1f:ed:bb:34:bf:cb:b2:67:c6:c6:51:e8:51:22:b4:f3: - 92:e8 + Signature Algorithm: sha256WithRSAEncryption + 41:f9:c3:a3:77:11:92:55:e7:4b:4a:32:6a:31:d9:51:cf:06: + a5:39:ea:30:98:b8:8d:4f:24:c5:34:fd:c6:98:10:59:32:7e: + 57:f5:8f:ba:67:c9:fc:44:68:b3:7c:f1:af:3a:5f:0d:8f:a1: + fe:41:21:0e:e9:08:a3:63:49:66:34:4a:cd:ce:66:74:47:30: + f7:dc:82:99:21:56:82:ff:2d:12:90:7d:7a:64:22:a0:ed:fa: + 62:d9:5a:d3:97:96:0c:04:a7:47:88:da:53:b6:33:15:15:f9: + da:ee:ac:25:e9:07:02:89:bc:73:a2:c6:27:6f:1f:bd:73:b8: + 8e:f7:94:54:57:a7:8b:5b:9a:24:aa:86:d4:04:5c:8c:cb:28: + a2:45:f9:34:f0:01:20:bb:06:e8:41:14:d2:d7:ca:e8:bf:4e: + 16:72:22:a0:0c:86:ca:73:23:09:ae:71:f1:52:0c:db:b2:8a: + 4d:94:a5:fa:15:81:5b:a2:95:62:50:a1:d6:64:fe:4c:0c:60: + 8d:9b:0f:b8:41:ac:cb:31:c2:17:6c:7b:61:13:16:9a:db:64: + fc:5f:47:84:3d:d2:2e:db:0b:9e:b6:1e:85:04:c1:e5:c0:b2: + 6d:8f:f2:99:00:3a:1a:ab:02:cf:45:7a:26:c1:b0:1f:c6:b0: + d0:4d:f7:52 -----BEGIN CERTIFICATE----- -MIICLDCCAZWgAwIBAgIJANjT46bL48zBMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xMzA2 -MjkxNjQxMjJaFw0yMzA2MjcxNjQxMjJaMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEAvh6G5HkDwdGU1dSzsSiQdvu4ps1tHNFI9AiaZ//5plSxGSnfKRvN8W9m -Aefbec7AOSolEyaUDCx7WiyBD5TuUdB15kbbF0anFYsOVw+wVHZjEsqGGLwawxbA -cAnWa0M5uJgpRqzLaq04iDsH3IHNOvYd9i/vHdeuirbR57MVArkCAwEAAaNQME4w -HQYDVR0OBBYEFLiS3v2KGLMww59V8zNdtMgpikEUMB8GA1UdIwQYMBaAFLiS3v2K -GLMww59V8zNdtMgpikEUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA -Gs93YERDxFUOmeCJqrnTezK3XJx8yv6M1JTGXvODGV8pWWikT9wELrhxwG07rgHk -uYiZzM6CvmoowqxqlMaHkO2FPBBxxf88cGTiQWIx6oZ7EYyT6sbz80751PKBkNf0 -+qGRbtTdFT4mO6wew8If7bs0v8uyZ8bGUehRIrTzkug= +MIIDYDCCAkigAwIBAgIUQpdsMI55/Htq4++dGKR0nYtfV1MwDQYJKoZIhvcNAQEL +BQAwQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoMBXcx +LmZpMRAwDgYDVQQDDAdSb290IENBMB4XDTIwMDUwMjE5NDk0OFoXDTMwMDQzMDE5 +NDk0OFowQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoM +BXcxLmZpMRAwDgYDVQQDDAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAvPTuRGJ/Yk+hgUa6xKoe/U7Q7fFHyyVbZnqGOZHKtWGnfi88Y305 +uBqey20yMpHeSUmE2hW+K93GvB/cbsAtd/LQeyxAGQdgVbD/fFHvONHwKtqozOrW +VKTvvhdEGp4zcFek8wasPe5LLeVGJS0zCfZJqAIxpGWbMgpn9QLhO0emruT2hetd +PgJm3RGYrDRywo8lVUpq6uiCL71/eDGkWtcyu2RIRiPvyMnihABWcuhLVJViOloR +ee5AQ54WLMzmRfS7gijCgzUsVTaZWRGxFdADwaU34R+7Q8e0uTPeFNd8mUUPwQb+ +tiUQWbdydn+RS+rRuWpq7d0bqQ6nKUi3TQIDAQABo1AwTjAdBgNVHQ4EFgQUpP25 +ORuBs6rriB3Ugam1EXDMp+EwHwYDVR0jBBgwFoAUpP25ORuBs6rriB3Ugam1EXDM +p+EwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQfnDo3cRklXnS0oy +ajHZUc8GpTnqMJi4jU8kxTT9xpgQWTJ+V/WPumfJ/ERos3zxrzpfDY+h/kEhDukI +o2NJZjRKzc5mdEcw99yCmSFWgv8tEpB9emQioO36Ytla05eWDASnR4jaU7YzFRX5 +2u6sJekHAom8c6LGJ28fvXO4jveUVFeni1uaJKqG1ARcjMsookX5NPABILsG6EEU +0tfK6L9OFnIioAyGynMjCa5x8VIM27KKTZSl+hWBW6KVYlCh1mT+TAxgjZsPuEGs +yzHCF2x7YRMWmttk/F9HhD3SLtsLnrYehQTB5cCybY/ymQA6GqsCz0V6JsGwH8aw +0E33Ug== -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/iCA-user/cacert.pem b/tests/hwsim/auth_serv/iCA-user/cacert.pem index 9f2dd7bff..f55814817 100644 --- a/tests/hwsim/auth_serv/iCA-user/cacert.pem +++ b/tests/hwsim/auth_serv/iCA-user/cacert.pem @@ -1,70 +1,81 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162868 (0xd8d3e3a6cbe3ccf4) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + d8:d3:e3:a6:cb:e3:cc:f8 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 22 19:37:36 2025 GMT + Not Before: May 3 15:20:10 2020 GMT + Not After : May 3 15:20:10 2030 GMT Subject: C=FI, O=w1.fi, CN=User Intermediate CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:c3:2a:0d:f4:66:23:5d:96:91:f7:a0:be:b1:b0: - f7:9e:ae:ea:a6:72:91:f5:70:65:57:91:49:55:59: - 67:bb:d7:f5:9e:bc:66:b2:bf:cf:95:31:32:ae:db: - 9a:3b:43:e8:a5:8d:1f:8b:3b:e6:e8:e3:3b:b2:9d: - f0:58:62:ea:a3:8a:6f:c8:ed:01:ca:27:74:1c:0e: - 9e:28:5c:43:98:db:14:b8:72:07:9f:6b:27:28:25: - ce:a5:91:b7:b7:23:9a:35:ef:0e:b7:fc:9f:69:4d: - 10:2e:81:ab:9d:04:ba:2f:b4:eb:61:7d:fd:68:a1: - 11:6f:f4:16:42:16:99:20:38:24:04:2d:39:7c:74: - 67:14:b9:aa:26:7a:b2:d9:1e:ce:cd:8b:bc:8d:e3: - c7:58:9c:4a:f9:3a:7e:6c:38:f8:5f:1c:ec:05:4c: - e5:56:64:d4:08:d8:fa:db:17:d9:a1:e4:cf:b4:9d: - df:99:50:ce:fa:a4:af:af:c6:f7:f2:0e:c2:c5:7b: - 6c:f9:6c:eb:17:e5:c8:6e:5a:bf:eb:a6:b8:c0:f7: - 43:81:88:c3:d8:aa:a9:60:ac:a7:45:3f:5d:cb:8d: - 6c:48:92:2b:04:5a:c4:a8:32:b3:e9:6f:fe:8d:2d: - 65:c0:ea:c5:09:b2:30:b1:a3:2e:db:22:8a:49:b1: - fe:4f + 00:b9:88:7a:fc:1a:f9:00:68:63:c7:40:ff:d5:38: + 8e:88:8c:c9:8f:66:ec:74:0a:a6:f1:18:30:30:36: + 9a:2a:98:c5:a0:46:02:e2:3c:64:86:79:43:45:19: + 83:7a:82:3d:f9:c6:af:01:11:91:2c:4f:07:f8:d7: + ef:da:80:6c:07:88:6a:1e:e6:0e:78:ca:08:50:4f: + f0:8a:2e:54:41:9f:04:63:8b:70:99:ae:6f:95:ed: + 5c:c8:34:8e:6b:36:64:bc:44:c9:fb:cb:50:ef:b1: + 5b:9b:2c:db:2a:a7:f9:e0:e2:48:57:78:cf:ba:0f: + 1a:af:5a:63:64:18:39:9c:d4:af:8d:f9:27:d9:10: + b4:67:17:a1:24:98:f1:ef:ce:ad:12:6f:e4:47:36: + b6:d2:b6:1c:04:03:76:43:63:fb:b6:3e:3f:1a:c8: + c4:8b:69:28:7c:75:dc:bb:36:7f:ad:6a:a2:c1:32: + f3:5e:64:86:57:f1:ee:20:af:64:bd:e0:7c:ba:68: + 9b:75:ed:b3:1c:0f:12:e0:52:12:ff:18:0e:8f:1d: + bf:c8:88:56:35:4d:9e:1f:74:1e:19:d7:0c:b4:e7: + 46:ee:cf:c6:63:35:ba:16:7f:05:84:8b:bf:16:72: + 05:ee:22:6e:3a:54:80:2b:0e:36:96:8d:65:5f:64: + 12:cd Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - AC:C4:F6:07:9E:B2:E5:F1:66:7C:40:05:08:AA:DC:EF:8A:60:DA:C1 + F0:F7:82:29:71:CD:AF:72:CE:F6:3C:0B:40:16:C2:FD:9F:8A:51:A7 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Certificate Sign, CRL Sign Signature Algorithm: sha256WithRSAEncryption - 0d:60:2b:fa:00:f2:5a:90:31:96:50:c8:9e:7f:60:02:99:c6: - 31:d4:93:86:9e:4c:24:15:b6:b2:31:49:21:79:ce:7f:92:86: - 1e:83:d8:a0:37:05:1b:89:2b:ef:0b:83:21:b0:37:8d:2f:7b: - 6b:7d:c6:04:1e:a2:c8:59:be:52:bf:47:ee:46:cb:45:8d:1f: - 7a:e4:d4:e5:54:60:5f:46:b0:ac:68:8a:26:57:ea:48:45:c1: - 07:7d:ee:10:9e:94:87:4c:7e:26:2e:f8:ad:03:e5:03:86:09: - 3e:48:0c:e0:04:2f:22:b4:e0:3a:b0:72:8c:e2:40:d2:cd:fb: - 8f:fa + 70:45:66:14:00:22:85:1c:f8:b9:b3:2c:e8:64:4d:01:53:b8: + cb:23:ad:fa:01:7c:27:f7:aa:8d:d8:6c:6a:f8:72:21:63:bf: + 30:7e:05:8c:84:e3:d1:1e:d1:f3:1d:80:3d:e8:75:06:ae:1b: + 48:a9:cf:0e:c6:59:6b:f8:d1:25:5a:64:b7:46:2d:29:72:da: + d6:3a:79:d3:92:41:d7:31:e4:4e:5e:1b:62:88:41:77:f6:62: + a2:3e:c1:a2:ef:79:0c:8f:39:7c:df:a0:4b:d5:ac:58:aa:3e: + fd:95:6b:f7:c0:42:29:2e:86:67:5e:d9:3e:7b:e7:a6:bd:3b: + 7e:3b:19:54:9b:89:40:0e:39:23:8a:af:f2:db:12:5b:09:b4: + 45:df:c8:3e:8f:fc:fc:55:3e:35:8d:7b:82:50:d5:a3:ea:bb: + c4:40:6d:61:ad:92:b2:66:91:0f:5b:3d:49:5e:b5:3e:98:15: + 9e:2a:23:06:35:e0:13:bc:50:84:06:e4:1b:b9:fc:32:a2:4a: + 0d:e5:86:ac:69:47:c3:17:11:07:ac:5a:09:69:ed:99:d0:52: + fd:6d:ab:0d:44:35:bb:c0:76:27:50:75:df:06:78:f6:92:54: + fc:54:76:b5:6f:a0:f6:51:20:1f:7f:8e:aa:5f:c8:48:88:e4: + 1a:83:f6:b7 -----BEGIN CERTIFICATE----- -MIIC0zCCAjygAwIBAgIJANjT46bL48z0MA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy -MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMDwxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDKg30ZiNdlpH3oL6xsPeeruqmcpH1cGVX -kUlVWWe71/WevGayv8+VMTKu25o7Q+iljR+LO+bo4zuynfBYYuqjim/I7QHKJ3Qc -Dp4oXEOY2xS4cgefaycoJc6lkbe3I5o17w63/J9pTRAugaudBLovtOthff1ooRFv -9BZCFpkgOCQELTl8dGcUuaomerLZHs7Ni7yN48dYnEr5On5sOPhfHOwFTOVWZNQI -2PrbF9mh5M+0nd+ZUM76pK+vxvfyDsLFe2z5bOsX5chuWr/rprjA90OBiMPYqqlg -rKdFP13LjWxIkisEWsSoMrPpb/6NLWXA6sUJsjCxoy7bIopJsf5PAgMBAAGjZjBk -MB0GA1UdDgQWBBSsxPYHnrLl8WZ8QAUIqtzvimDawTAfBgNVHSMEGDAWgBS4kt79 -ihizMMOfVfMzXbTIKYpBFDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQE -AwIBBjANBgkqhkiG9w0BAQsFAAOBgQANYCv6APJakDGWUMief2ACmcYx1JOGnkwk -FbayMUkhec5/koYeg9igNwUbiSvvC4MhsDeNL3trfcYEHqLIWb5Sv0fuRstFjR96 -5NTlVGBfRrCsaIomV+pIRcEHfe4QnpSHTH4mLvitA+UDhgk+SAzgBC8itOA6sHKM -4kDSzfuP+g== +MIIDZjCCAk6gAwIBAgIJANjT46bL48z4MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDMxNTIwMTBaFw0zMDA1MDMxNTIwMTBaMDwxCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1l +ZGlhdGUgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5iHr8GvkA +aGPHQP/VOI6IjMmPZux0CqbxGDAwNpoqmMWgRgLiPGSGeUNFGYN6gj35xq8BEZEs +Twf41+/agGwHiGoe5g54yghQT/CKLlRBnwRji3CZrm+V7VzINI5rNmS8RMn7y1Dv +sVubLNsqp/ng4khXeM+6DxqvWmNkGDmc1K+N+SfZELRnF6EkmPHvzq0Sb+RHNrbS +thwEA3ZDY/u2Pj8ayMSLaSh8ddy7Nn+taqLBMvNeZIZX8e4gr2S94Hy6aJt17bMc +DxLgUhL/GA6PHb/IiFY1TZ4fdB4Z1wy050buz8ZjNboWfwWEi78WcgXuIm46VIAr +DjaWjWVfZBLNAgMBAAGjZjBkMB0GA1UdDgQWBBTw94Ipcc2vcs72PAtAFsL9n4pR +pzAfBgNVHSMEGDAWgBSk/bk5G4GzquuIHdSBqbURcMyn4TASBgNVHRMBAf8ECDAG +AQH/AgEAMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAcEVmFAAi +hRz4ubMs6GRNAVO4yyOt+gF8J/eqjdhsavhyIWO/MH4FjITj0R7R8x2APeh1Bq4b +SKnPDsZZa/jRJVpkt0YtKXLa1jp505JB1zHkTl4bYohBd/Zioj7Bou95DI85fN+g +S9WsWKo+/ZVr98BCKS6GZ17ZPnvnpr07fjsZVJuJQA45I4qv8tsSWwm0Rd/IPo/8 +/FU+NY17glDVo+q7xEBtYa2SsmaRD1s9SV61PpgVniojBjXgE7xQhAbkG7n8MqJK +DeWGrGlHwxcRB6xaCWntmdBS/W2rDUQ1u8B2J1B13wZ49pJU/FR2tW+g9lEgH3+O +ql/ISIjkGoP2tw== -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/iCA-user/careq.pem b/tests/hwsim/auth_serv/iCA-user/careq.pem index 887c80cc4..58a202e23 100644 --- a/tests/hwsim/auth_serv/iCA-user/careq.pem +++ b/tests/hwsim/auth_serv/iCA-user/careq.pem @@ -1,16 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- MIIClDCCAXwCAQAwTzELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4w DAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlhdGUgQ0EwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDKg30ZiNdlpH3oL6xsPeeruqm -cpH1cGVXkUlVWWe71/WevGayv8+VMTKu25o7Q+iljR+LO+bo4zuynfBYYuqjim/I -7QHKJ3QcDp4oXEOY2xS4cgefaycoJc6lkbe3I5o17w63/J9pTRAugaudBLovtOth -ff1ooRFv9BZCFpkgOCQELTl8dGcUuaomerLZHs7Ni7yN48dYnEr5On5sOPhfHOwF -TOVWZNQI2PrbF9mh5M+0nd+ZUM76pK+vxvfyDsLFe2z5bOsX5chuWr/rprjA90OB -iMPYqqlgrKdFP13LjWxIkisEWsSoMrPpb/6NLWXA6sUJsjCxoy7bIopJsf5PAgMB -AAGgADANBgkqhkiG9w0BAQsFAAOCAQEAKYOesAY0nFSXY1Ez8q5cGRUa0YZWic1l -NwF05zIFoD3loCWRiayzINJqwXvUO29X0c8W35hTIGHyGUzcc0iwtrjphlmpuimN -AzL+NG1+TwfEQi+LL+e0lJnl2PIZkIN4cQDgTSdejU40sNRPWzD8w8EYHYAOJ4oU -0TXfrIRJWBDZKFtjO2fcknf1beGN79ZOHxc6pCFdZ7pM2w3+mKbfysnVBZkDwavG -SlIdL23QcD3Uj0vOrU+oOSGQKXamZrjjpmu647bcQ5XQr8kZbXWu6A4G24bxZ2rw -S7Z7DVvLqGxJgSl8b72otGJqkszHiul2ZKHy25flrtGM0SBU+k9FEQ== +MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5iHr8GvkAaGPHQP/VOI6IjMmP +Zux0CqbxGDAwNpoqmMWgRgLiPGSGeUNFGYN6gj35xq8BEZEsTwf41+/agGwHiGoe +5g54yghQT/CKLlRBnwRji3CZrm+V7VzINI5rNmS8RMn7y1DvsVubLNsqp/ng4khX +eM+6DxqvWmNkGDmc1K+N+SfZELRnF6EkmPHvzq0Sb+RHNrbSthwEA3ZDY/u2Pj8a +yMSLaSh8ddy7Nn+taqLBMvNeZIZX8e4gr2S94Hy6aJt17bMcDxLgUhL/GA6PHb/I +iFY1TZ4fdB4Z1wy050buz8ZjNboWfwWEi78WcgXuIm46VIArDjaWjWVfZBLNAgMB +AAGgADANBgkqhkiG9w0BAQsFAAOCAQEAt/AtU5ZkTH2fksE0NkQ24G2s/3FGSPH1 +wOtQKHUaUXHWeAddimhKOCo2nStyzJ3SYkrkBaGkCf2YDVmDT2FJrEEU/8fhwWgb +VPdqMHG+tXhzAf6AoqOZ/r/5wGLEvOXuoVlF4Ey+dfYPBpfvJRjOl/xHN7B+b5Pe +1Q25yWo3ekdeRIWZnJx7b/5xkgSH1blqiSVVlhQ9uOUeBiOIS+CXGBo+kqcGRxm2 +awQRONpQb4dJ2+PEAFMTWHs/WWHpftDx878YafRfrcEx9iCWb4L4FKQo7VgcmgSs +cErQMDUfGOmRKTXJ6pJAv6O8KdWaDuTiM7o6yo5VggIcUTj2XGkRLQ== -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/iCA-user/index.txt b/tests/hwsim/auth_serv/iCA-user/index.txt index 61be730ce..df7ada787 100644 --- a/tests/hwsim/auth_serv/iCA-user/index.txt +++ b/tests/hwsim/auth_serv/iCA-user/index.txt @@ -1 +1 @@ -V 251220193736Z E153BA3A7605DA1E unknown /C=FI/O=w1.fi/CN=user.w1.fi +V 300501152011Z 5923F47610CA8942F55C075C62D2678BE42292A9 unknown /C=FI/O=w1.fi/CN=user.w1.fi diff --git a/tests/hwsim/auth_serv/iCA-user/index.txt.attr b/tests/hwsim/auth_serv/iCA-user/index.txt.attr index 8f7e63a34..3a7e39e6e 100644 --- a/tests/hwsim/auth_serv/iCA-user/index.txt.attr +++ b/tests/hwsim/auth_serv/iCA-user/index.txt.attr @@ -1 +1 @@ -unique_subject = yes +unique_subject = no diff --git a/tests/hwsim/auth_serv/iCA-user/newcerts/E153BA3A7605DA1E.pem b/tests/hwsim/auth_serv/iCA-user/newcerts/E153BA3A7605DA1E.pem deleted file mode 100644 index 296060a0b..000000000 --- a/tests/hwsim/auth_serv/iCA-user/newcerts/E153BA3A7605DA1E.pem +++ /dev/null @@ -1,84 +0,0 @@ -Certificate: - Data: - Version: 3 (0x2) - Serial Number: 16236525841851734558 (0xe153ba3a7605da1e) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=User Intermediate CA - Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 20 19:37:36 2025 GMT - Subject: C=FI, O=w1.fi, CN=user.w1.fi - Subject Public Key Info: - Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) - Modulus: - 00:c0:86:20:e5:06:5a:a8:47:2d:c9:5e:25:24:f7: - bf:a6:b6:44:50:99:8c:95:b5:6a:ad:74:b6:ba:ee: - 31:5e:b2:20:60:9a:b4:93:55:6d:15:0b:dc:5a:27: - 3f:df:c1:92:18:59:66:10:eb:47:1c:35:1f:08:dd: - eb:25:bd:21:9c:2d:48:34:5f:97:18:dc:83:28:db: - 14:8c:16:3b:5a:36:6a:50:63:e9:3b:e0:37:fd:f6: - a0:d6:40:af:ef:1e:99:1d:88:c1:4f:4b:92:25:53: - 28:cb:c4:b7:ce:ca:ca:26:af:2d:f7:e4:62:79:48: - 49:6a:82:33:b0:a6:c6:a5:17:33:88:93:77:36:b2: - 77:61:e0:55:de:2e:75:15:92:4c:e7:bf:11:ea:33: - 03:1e:4a:e6:18:38:16:34:f5:d9:ed:f8:0c:17:6f: - 78:65:ae:14:18:a3:0f:08:b6:e2:87:02:e4:eb:0f: - fb:81:d9:4b:90:ff:b3:fa:0f:d3:04:4d:b0:99:b4: - 2b:5e:fb:ad:04:2b:a7:d6:36:0d:17:e0:be:c0:43: - cf:e5:2e:f0:8e:87:88:60:b3:22:d8:03:59:53:50: - a6:69:ce:de:d0:c9:2e:f7:6d:9a:59:4d:99:dc:4b: - 3c:c2:15:8f:27:64:23:34:14:34:af:41:76:a5:6a: - 9a:0f - Exponent: 65537 (0x10001) - X509v3 extensions: - X509v3 Basic Constraints: - CA:FALSE - X509v3 Subject Key Identifier: - 3E:35:E0:F9:A3:1E:2C:FA:DD:E7:8B:CE:58:06:38:20:5D:5E:71:D2 - X509v3 Authority Key Identifier: - keyid:AC:C4:F6:07:9E:B2:E5:F1:66:7C:40:05:08:AA:DC:EF:8A:60:DA:C1 - - X509v3 Subject Alternative Name: critical - DNS:user.w1.fi - X509v3 Extended Key Usage: - TLS Web Client Authentication - X509v3 Key Usage: - Digital Signature, Key Encipherment - Signature Algorithm: sha256WithRSAEncryption - 7b:e9:eb:d7:d4:60:a8:08:62:71:61:dd:42:7d:e5:88:f4:24: - bb:3f:6b:a9:16:64:2d:fb:ce:8e:55:1c:f5:7e:b4:c3:74:de: - 96:e4:59:32:f4:aa:74:e2:ac:43:28:06:54:5d:f7:fe:87:31: - 3d:ac:45:d5:1c:51:7f:8c:f9:37:0b:66:94:a7:22:5f:d1:55: - bf:a4:82:c7:0a:50:bb:c7:18:cf:df:47:81:00:c4:d2:d7:12: - b0:83:2d:67:3f:80:b8:be:6f:c9:c5:76:9a:87:ef:3a:f6:0d: - 4f:24:d8:e7:06:6c:6e:ff:dc:5e:6e:21:a1:e7:26:f6:94:44: - 69:f4:b2:36:38:08:b1:df:07:fa:7a:53:b8:60:db:63:4b:4f: - e6:2a:42:ff:29:68:b5:99:3a:36:eb:26:05:76:d2:ab:e6:d0: - 7c:af:8c:a0:20:8b:50:6c:3b:bc:1a:53:6d:a7:c8:70:97:21: - 56:02:24:04:9b:63:2a:5d:b8:8c:e4:bf:e9:8f:58:cd:6e:99: - 47:3c:02:7b:63:67:c1:c7:32:53:cc:d5:cb:e9:a0:39:ef:f8: - 44:b7:f3:57:0c:b5:a7:23:3f:16:28:c6:02:14:b6:80:d8:33: - 42:0c:81:5c:ac:3f:13:d0:5b:4a:66:9f:33:ee:ac:56:fe:37: - 17:2b:03:40 ------BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIJAOFTujp2BdoeMA0GCSqGSIb3DQEBCwUAMDwxCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlh -dGUgQ0EwHhcNMTUxMjIzMTkzNzM2WhcNMjUxMjIwMTkzNzM2WjAyMQswCQYDVQQG -EwJGSTEOMAwGA1UECgwFdzEuZmkxEzARBgNVBAMMCnVzZXIudzEuZmkwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAhiDlBlqoRy3JXiUk97+mtkRQmYyV -tWqtdLa67jFesiBgmrSTVW0VC9xaJz/fwZIYWWYQ60ccNR8I3eslvSGcLUg0X5cY -3IMo2xSMFjtaNmpQY+k74Df99qDWQK/vHpkdiMFPS5IlUyjLxLfOysomry335GJ5 -SElqgjOwpsalFzOIk3c2sndh4FXeLnUVkkznvxHqMwMeSuYYOBY09dnt+AwXb3hl -rhQYow8ItuKHAuTrD/uB2UuQ/7P6D9METbCZtCte+60EK6fWNg0X4L7AQ8/lLvCO -h4hgsyLYA1lTUKZpzt7QyS73bZpZTZncSzzCFY8nZCM0FDSvQXalapoPAgMBAAGj -gYowgYcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUPjXg+aMeLPrd54vOWAY4IF1ecdIw -HwYDVR0jBBgwFoAUrMT2B56y5fFmfEAFCKrc74pg2sEwGAYDVR0RAQH/BA4wDIIK -dXNlci53MS5maTATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMCBaAwDQYJ -KoZIhvcNAQELBQADggEBAHvp69fUYKgIYnFh3UJ95Yj0JLs/a6kWZC37zo5VHPV+ -tMN03pbkWTL0qnTirEMoBlRd9/6HMT2sRdUcUX+M+TcLZpSnIl/RVb+kgscKULvH -GM/fR4EAxNLXErCDLWc/gLi+b8nFdpqH7zr2DU8k2OcGbG7/3F5uIaHnJvaURGn0 -sjY4CLHfB/p6U7hg22NLT+YqQv8paLWZOjbrJgV20qvm0HyvjKAgi1BsO7waU22n -yHCXIVYCJASbYypduIzkv+mPWM1umUc8AntjZ8HHMlPM1cvpoDnv+ES381cMtacj -PxYoxgIUtoDYM0IMgVysPxPQW0pmnzPurFb+NxcrA0A= ------END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/iCA-user/private/cakey.pem b/tests/hwsim/auth_serv/iCA-user/private/cakey.pem index 97ead18a7..fb51ae7ea 100644 --- a/tests/hwsim/auth_serv/iCA-user/private/cakey.pem +++ b/tests/hwsim/auth_serv/iCA-user/private/cakey.pem @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDDKg30ZiNdlpH3 -oL6xsPeeruqmcpH1cGVXkUlVWWe71/WevGayv8+VMTKu25o7Q+iljR+LO+bo4zuy -nfBYYuqjim/I7QHKJ3QcDp4oXEOY2xS4cgefaycoJc6lkbe3I5o17w63/J9pTRAu -gaudBLovtOthff1ooRFv9BZCFpkgOCQELTl8dGcUuaomerLZHs7Ni7yN48dYnEr5 -On5sOPhfHOwFTOVWZNQI2PrbF9mh5M+0nd+ZUM76pK+vxvfyDsLFe2z5bOsX5chu -Wr/rprjA90OBiMPYqqlgrKdFP13LjWxIkisEWsSoMrPpb/6NLWXA6sUJsjCxoy7b -IopJsf5PAgMBAAECggEAMQpcP1F7CYVQYH0P7e6eCk3BwNmBO79md76WQtAYdOcr -XRvSYpA4RTD7n1ynQMUrrI3tozsGJvcShSuSvWL9uuKKfF6x2G5ZisNRkqq8gahr -aH2e1LxENp5pcslO9MIJegv8Etdz5y3qJwWGbgpGDr7TdsgF6Uiv7QXUof6zs5h3 -dri5y4tIbv+/OrEL9pz0x0wR1wFZ24huLLd+I4qHW+nSVynzRsb7dH76vvJRcj+o -UUIXx0QASoiFyhTPL3kSIcLcwRW1WEkqQXSENj3765CewhpOVcbzUZQiHjPVdOmg -6+CRptOGJMh5SGHzAbeABwkgeQ4LGWnPdL9B0ZClYQKBgQDk6tGncCWYELelrt9q -D/bzTvTZADzxYKuOUmyiu9Wr6Lx3nbfJupf0kZSGZuTBOjOd8iQkI1edIWTZLgyY -48oW2EggJTo5xmAaAdz82ItXpI0/Rt71QQqhcxsaT2uLIinBdox8wP6/DbnG57DJ -6FcHOsVfAFAVk2sM8ZCK1XRjiwKBgQDaQPbUNGXg04D08jk+15FDlPYh/2TJNSc+ -SBOE1j7wlTNGr6Vcg7N34U+I8Zo/ci8CXQVAMlLd7UJR9UhPsU2ptMldziDPEn5d -28CkoAmfw/vrcE8j12cuKUViJK6E/Fpvmbmb/cKrACj9qHd1QV7kXFemDKPEUlAe -8zp4EqPYzQKBgB4NphCxbH4WU8Xwu2wVRHqU9xg2K8oUwvEgaRrERj0XhQa/Mg3N -7X0yT6mFgKrNlVE7JPuJmEsMw0yv+v9niHSPWIi/2nETVjKT5Atd8o1DETgpecQB -EgA4OGqv2pKdnZXElpUaUVeL2cP/TvpzAln0oUzjoZ/zhq5gWHWhqHIZAoGBANjt -pyfGKNitAEj2FKX8dvrYLUgfY5qFhUrnMtdeZ1KSyVNhs5dfo9rsjDQOB4U2Rbkw -oc5r9md0se1qQYRMM2gRM/BTt9J5jDZX/ILkOoycrGEX0OFL8Nc12CuzT+8IMA8q -mQyNzZZPY26zqoBWCC4sBkYZ3BB+y/nnQV8lD8ulAoGAB0cwM8SWfP+u4M7qWGFV -Dk448ODrEfwnbSABc6EavEJ0BL5h60AsXhV9FW6nxfB66Yt84DZm6YXS+9MElLVy -jlql+Gbaj1Wawtwyzwk7Sl/vqtDwCRta+TP98kAm93Y9CVizlRH93kpNCoYAoDrA -qN+IRKm0VOAaYV4NXrTTMWE= +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC5iHr8GvkAaGPH +QP/VOI6IjMmPZux0CqbxGDAwNpoqmMWgRgLiPGSGeUNFGYN6gj35xq8BEZEsTwf4 +1+/agGwHiGoe5g54yghQT/CKLlRBnwRji3CZrm+V7VzINI5rNmS8RMn7y1DvsVub +LNsqp/ng4khXeM+6DxqvWmNkGDmc1K+N+SfZELRnF6EkmPHvzq0Sb+RHNrbSthwE +A3ZDY/u2Pj8ayMSLaSh8ddy7Nn+taqLBMvNeZIZX8e4gr2S94Hy6aJt17bMcDxLg +UhL/GA6PHb/IiFY1TZ4fdB4Z1wy050buz8ZjNboWfwWEi78WcgXuIm46VIArDjaW +jWVfZBLNAgMBAAECggEAJ3Ghm+lsGK8Yz2q9OSp9+v/bdjZOfNkq5sTasdVZ70Zt +dYaM5GYshP5Q0+b5sdjwriKUYCjI8V+X9UqLPqvgy7UvwoPsfbeODuz/2ZDB7vWM +rFEfzjxskrZU7GdoA9kbj38cZgCyo1LUg+gEbEwr7qiM8rPHjenaJX+U89nGndWo +xbjy+PtpSkcNV38H690w2elxTIz4XBHRFumQ4rmlGaa9rMTKRkeVaV42cAdScwmh +OR/Cy0XW+x2xyQolBIBRSp7Sn5xtulA1g4iaifVtY8qNQhQ9++TxkId3+VB/7HGJ +kYmfucUPeTD1SR6yVhhXtmrpTfas0rvzAR2RAxjsbQKBgQDspqiXOGSXJS0XupVR +Zzpb44306Zr9kobLZoIjLa4igEoJvB3IZTLNMK6UAvbDiQJYAP4Mx0x8hWhyWcb+ +PiXDfWFshlQvLKikt4hLtxBGCoGf4TcR5y2qkOlRjAC+LwgGMQ1q34E5JI1sOo/2 +frB1dYApow9IpC4Svy2QIFkicwKBgQDIs9+laNPoFwHljEF7xRA3QYt2+03ps4gF +GsO/vb73C0sStS5M9I0MlY44Fk7dtEo6WQCORHlusc0Zr1qli6EdUh5wnR6SMqYZ +IX3gJiGzu8AQBGTL/fZAzy4YQeiVicJCUeu2MxXhKcqstWC4UUyQgys67by0YvpF +qn7TtYRlvwKBgQC2YN4u5IQJQ9pTnjTzLlX4eQ9u/xW2dFUzrkV+7PZ1ml70z6g4 +R112ax0v7nTUTuOihOlFWdblZD8RWYUVbTnXRepuI7v/OzCg+NyuVV/SSsiJOZ0i +TAKSn+lgMkBkUYSimO0ZPzSsoDHphdxrAEnny+1AqWze88CaLAHmQDfRZwKBgHgy +iWEVm7smdENWMS1/wotlHLIgJPQuSerMsajWaVSolchZa6Y423RK6QacDZVnUQEK +pnONfLAXmb6lLwNv0QivUn2dC18BKEpqrWkdTRfH/GlbSEaHDQCZU4DBkBpmi0mO +qDzQ8WyMy82NPqSEQ/dUJwK+uEHL+RjZ1+TQk78fAoGBAJcRCj4OBMHBSKazW/T2 +b8WXps3bEwdDBg8lBj2yv10AN6DtJqhPd4DaEdriRSMaufrPuNEdkMbOHkXGqPM6 +Fayi/ayFGGO20XrfuUHRbLCiF1f8/OZSTOEXFpungFLk2awpTkcsbwQ0GK/BU2H1 +hW28/pW9mlvPCm3HQFE8rMxS -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/iCA-user/serial b/tests/hwsim/auth_serv/iCA-user/serial index f692ea90b..24ff150cb 100644 --- a/tests/hwsim/auth_serv/iCA-user/serial +++ b/tests/hwsim/auth_serv/iCA-user/serial @@ -1 +1 @@ -E153BA3A7605DA1F +5923F47610CA8942F55C075C62D2678BE42292AA diff --git a/tests/hwsim/auth_serv/iCA-user/user.key b/tests/hwsim/auth_serv/iCA-user/user.key index a6d31a545..1ede4cd19 100644 --- a/tests/hwsim/auth_serv/iCA-user/user.key +++ b/tests/hwsim/auth_serv/iCA-user/user.key @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDAhiDlBlqoRy3J -XiUk97+mtkRQmYyVtWqtdLa67jFesiBgmrSTVW0VC9xaJz/fwZIYWWYQ60ccNR8I -3eslvSGcLUg0X5cY3IMo2xSMFjtaNmpQY+k74Df99qDWQK/vHpkdiMFPS5IlUyjL -xLfOysomry335GJ5SElqgjOwpsalFzOIk3c2sndh4FXeLnUVkkznvxHqMwMeSuYY -OBY09dnt+AwXb3hlrhQYow8ItuKHAuTrD/uB2UuQ/7P6D9METbCZtCte+60EK6fW -Ng0X4L7AQ8/lLvCOh4hgsyLYA1lTUKZpzt7QyS73bZpZTZncSzzCFY8nZCM0FDSv -QXalapoPAgMBAAECggEBAItIPkISv8GghTJ6htrg1elRUckR3VBtyDinCI/iRRti -OORK6DrzAZDJXOhoHuDNVNmCy8GPxYlVsRckHbvWwZsQc31YbqLQ3Z7QKGRUrSnN -1kpEjfcAduGn7KI0eFPBSjrAtkGcxaV1LT2GGwhjU6567AG8W7Wso1iHy8eQUIQc -LKRJ6KYpDc019Ly01XRH8mNhmxo3hxpBzMxudiHua/9qXmsRGevsshxQ911wkPdO -7Yr9bH1YJ7OvwOxxxAkNyRFAhWa7KPzvhsYX6KHEPTfTSv+3GCz5WLI//5NJ6NFB -3E2ofJOrmxT6EG6hKzyoNzoUwqpbA2BiHhlSVvOjHhECgYEA4pfICLLh40DMdBc9 -LMnPsp7Sv6H1Lcv/SJr0sjI8ESa2WK+XQOKgfB7jxyBHoMYhlr4UxwtgFA2M0cIs -4tfqv6zNKWmwB8VpUS+1kwaITtny8U4Kb7hQadpE0dXG84kb1aG3dsvK07aSTS6w -cW/NPZ9mNQhQ1sYsqF0HzuNysvkCgYEA2YJ0qKvLEkzTGcU0y5CLvzb4ZEuhAc7X -zzHRCNW61mmhNKR3QVEo3vzpKlxF3PbWJUwt0OOUkdyjbRE3yV0d4JCsNH6vRUmD -CxafENHZgkuCDD9TrDWhSefhWc7ip3unGG8KdnkGYDe1lw7zIJW5g7GS41GORqDV -gZngtyxJb0cCgYBQL5ZCPctiOFQh4PdtGh2+ACZkWlQBWOeGMg/V36ESELkGuVy1 -QX25btT8apfudS79wVZo+cWOUx06PZTU0cPpAKW5ugTpOxsB9/gxh2ZFQSuP6SYY -Uwlh7DPebeBx3ltTRl8+Uu/76+fqGFOoUQA4hmgM7FxvJMI48nMI68RzQQKBgQCW -BgAW8t9PUQPt63Kd0aZCDlVHQE7eY1/A/nhSorCLATJ6j9HdkHAjVcgxOpHJdcuA -0EltofswnEFwkgarcfmQkdjlIFgd7zVeqYyvWj6vOwuJDQjWZ+tGgZSSkDsPEB/R -n41U5+b46JPsjBgv6nWZmxpYhkEfAAIjsRIo5XgFMwKBgD6fAKGFelZuJ/W3uUYl -swb0ks/L3CMmisMmPwafp4C9QB89xV8jtyDNhiIG1nCI54it9mKrPCASoPDrdJR5 -r2/yovQFWk1LIRqcfCjqV/2qVZo5Hdp7Ux/aI8N7/M1eEIgbq+RcZlFTclQ6fppt -gBDXmqE8gFdegAGqv+OiifB5 +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDUXyPsAcY+0lnu +381yjUHOQK+GvsKZaTuRo3wt5PWhcjwOuaalofWlv19TmDPCwBgkR0yES57R8kkF +hS2HVq5DvKGJ10qpZhPHrjVKzC9ztlB+Y7qwpryV8fGaw6mymD7/J5dks1QJB/xu +xM9/keCXwmMQodrmqX1AuQO+txxGkBBfmgrljAlW076lwUJd9Ezlvv3ZZkP56Tg2 +GmbTO3wRRnkWebjPgRQKTLe+e/KD9IcqHrH/eBwVUyF/dtFVDwi+EQ8Z60Zhrak2 +vLuBvzdtDF/RZ3Gp2iduL5DoO9Brl8Mb582BQA3WLv4kQGeE7eq38ybFIzX5fLVc ++d8fn6CFAgMBAAECggEAHiVvPPY3hP1pJL6CNGuW1sdZ4z+68fn9KbxSSVWCBKvp +mJGD9WkbLK8QwhYN6uxHwQaZ9wGhBt5kvTLddqO4Uwc4yw9Tmt5RmnvBNt/rMHrF +zFstyhuxE3vntvdlZGO2NZQSKopGOI34qGSpq8syXXiLhXXkU+/lRsW8oVru2Zkh +dZMgdOmd9aTNNXA1f4uufOBnlgv0g+VeXAH/k1juybQYj2BilLZFUSkWtRxffm98 +hyMKHkcr4XEdZSyuhAM/yHn0REG//XMrKCoe5snzV9R3BKuJpMVctrePAKlKdIbk +OJz6EJfT4whDuI9nO0aCIJCKx88Qsgka0JOHVuL0tQKBgQDsi66IONWzR2/K4K+r +9G38T5bzg3qB5YbXHyqRgU77W13Z2CaEjzB1QfX8pFaPARMJxg+WXupbSq632iTH +wPMjnSMYc4PeucyvEAudUeP8yc8hx5vVRCIyIyz3QhAB2bo48EKq9dSwsCJ1HrIO +xtjEU9x+BLl6cgesdVZgl75oBwKBgQDl1n2TPUoxpYkF5cavbs2c7wPXajbd54h8 +EwwF71AWMsngjuY02pzKDniU5tKgHHWXvGdZ5ER+7JJyqenyAQgdfjkKJ4ujqsOL +MHsLEH1qopWGNtrDxGFfibBNMrKPM2n/oYbYsrfSvKadhwZbwDVq4ZtzmszWqLtf ++weGR4jYEwKBgQCKGN5TLwMsAFe21MgalsAjXn/dOPQro8m+C7b5bcmjm2rGRJfw +Kfx7aH/o+DSElnb77MKq4kzl8UrhkRyJ9g68yv9zRfVF8akaxz5QoT9+FH+10+gZ +cQaZyMl2rP3VZrx+g14Ymx6J7LqhL8N6NwLUU7VVaQK0BqCOQY6lI9IIvwKBgHyn +EARDQXIbrW0dadzL44gxuYujd45yfHuOeP7fBDiF4yd/WSthRZfwsUVQyvs7dCuP +ax49x0hvVh4KOW+fT59vTdBMElf5zYQ4DwO5NcwX0bCxH4T9hTIjoxK7ZEx2Pg7+ +s/vjMf+BgXv+N1ybql0FbyIL2vyxFq6/nx0cvwMxAoGAMTuKJfxbN8UfQzGWWZ9g +Q3YQhEwOytLYs3yiymSlUfNlyFGC41zM1Jn/wsx7koWyTdzVYoOR7Dm/yKMwcRrc +Oqd+04Vn5BF81HgM8rmEUxD5x5WXWALg8pN2r8gb7QUlcjkxMEbfyKSo515JbnYc +84mcq6qC9A8ksJ/KdFv7dTY= -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/iCA-user/user.pem b/tests/hwsim/auth_serv/iCA-user/user.pem index 296060a0b..4ed6c06e2 100644 --- a/tests/hwsim/auth_serv/iCA-user/user.pem +++ b/tests/hwsim/auth_serv/iCA-user/user.pem @@ -1,43 +1,44 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 16236525841851734558 (0xe153ba3a7605da1e) - Signature Algorithm: sha256WithRSAEncryption + Serial Number: + 59:23:f4:76:10:ca:89:42:f5:5c:07:5c:62:d2:67:8b:e4:22:92:a9 + Signature Algorithm: sha256WithRSAEncryption Issuer: C=FI, O=w1.fi, CN=User Intermediate CA Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 20 19:37:36 2025 GMT + Not Before: May 3 15:20:11 2020 GMT + Not After : May 1 15:20:11 2030 GMT Subject: C=FI, O=w1.fi, CN=user.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:c0:86:20:e5:06:5a:a8:47:2d:c9:5e:25:24:f7: - bf:a6:b6:44:50:99:8c:95:b5:6a:ad:74:b6:ba:ee: - 31:5e:b2:20:60:9a:b4:93:55:6d:15:0b:dc:5a:27: - 3f:df:c1:92:18:59:66:10:eb:47:1c:35:1f:08:dd: - eb:25:bd:21:9c:2d:48:34:5f:97:18:dc:83:28:db: - 14:8c:16:3b:5a:36:6a:50:63:e9:3b:e0:37:fd:f6: - a0:d6:40:af:ef:1e:99:1d:88:c1:4f:4b:92:25:53: - 28:cb:c4:b7:ce:ca:ca:26:af:2d:f7:e4:62:79:48: - 49:6a:82:33:b0:a6:c6:a5:17:33:88:93:77:36:b2: - 77:61:e0:55:de:2e:75:15:92:4c:e7:bf:11:ea:33: - 03:1e:4a:e6:18:38:16:34:f5:d9:ed:f8:0c:17:6f: - 78:65:ae:14:18:a3:0f:08:b6:e2:87:02:e4:eb:0f: - fb:81:d9:4b:90:ff:b3:fa:0f:d3:04:4d:b0:99:b4: - 2b:5e:fb:ad:04:2b:a7:d6:36:0d:17:e0:be:c0:43: - cf:e5:2e:f0:8e:87:88:60:b3:22:d8:03:59:53:50: - a6:69:ce:de:d0:c9:2e:f7:6d:9a:59:4d:99:dc:4b: - 3c:c2:15:8f:27:64:23:34:14:34:af:41:76:a5:6a: - 9a:0f + 00:d4:5f:23:ec:01:c6:3e:d2:59:ee:df:cd:72:8d: + 41:ce:40:af:86:be:c2:99:69:3b:91:a3:7c:2d:e4: + f5:a1:72:3c:0e:b9:a6:a5:a1:f5:a5:bf:5f:53:98: + 33:c2:c0:18:24:47:4c:84:4b:9e:d1:f2:49:05:85: + 2d:87:56:ae:43:bc:a1:89:d7:4a:a9:66:13:c7:ae: + 35:4a:cc:2f:73:b6:50:7e:63:ba:b0:a6:bc:95:f1: + f1:9a:c3:a9:b2:98:3e:ff:27:97:64:b3:54:09:07: + fc:6e:c4:cf:7f:91:e0:97:c2:63:10:a1:da:e6:a9: + 7d:40:b9:03:be:b7:1c:46:90:10:5f:9a:0a:e5:8c: + 09:56:d3:be:a5:c1:42:5d:f4:4c:e5:be:fd:d9:66: + 43:f9:e9:38:36:1a:66:d3:3b:7c:11:46:79:16:79: + b8:cf:81:14:0a:4c:b7:be:7b:f2:83:f4:87:2a:1e: + b1:ff:78:1c:15:53:21:7f:76:d1:55:0f:08:be:11: + 0f:19:eb:46:61:ad:a9:36:bc:bb:81:bf:37:6d:0c: + 5f:d1:67:71:a9:da:27:6e:2f:90:e8:3b:d0:6b:97: + c3:1b:e7:cd:81:40:0d:d6:2e:fe:24:40:67:84:ed: + ea:b7:f3:26:c5:23:35:f9:7c:b5:5c:f9:df:1f:9f: + a0:85 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - 3E:35:E0:F9:A3:1E:2C:FA:DD:E7:8B:CE:58:06:38:20:5D:5E:71:D2 + 4F:DA:AA:81:CB:4A:79:E4:8B:4A:92:FC:38:41:92:BA:D9:F9:4C:32 X509v3 Authority Key Identifier: - keyid:AC:C4:F6:07:9E:B2:E5:F1:66:7C:40:05:08:AA:DC:EF:8A:60:DA:C1 + keyid:F0:F7:82:29:71:CD:AF:72:CE:F6:3C:0B:40:16:C2:FD:9F:8A:51:A7 X509v3 Subject Alternative Name: critical DNS:user.w1.fi @@ -46,39 +47,39 @@ Certificate: X509v3 Key Usage: Digital Signature, Key Encipherment Signature Algorithm: sha256WithRSAEncryption - 7b:e9:eb:d7:d4:60:a8:08:62:71:61:dd:42:7d:e5:88:f4:24: - bb:3f:6b:a9:16:64:2d:fb:ce:8e:55:1c:f5:7e:b4:c3:74:de: - 96:e4:59:32:f4:aa:74:e2:ac:43:28:06:54:5d:f7:fe:87:31: - 3d:ac:45:d5:1c:51:7f:8c:f9:37:0b:66:94:a7:22:5f:d1:55: - bf:a4:82:c7:0a:50:bb:c7:18:cf:df:47:81:00:c4:d2:d7:12: - b0:83:2d:67:3f:80:b8:be:6f:c9:c5:76:9a:87:ef:3a:f6:0d: - 4f:24:d8:e7:06:6c:6e:ff:dc:5e:6e:21:a1:e7:26:f6:94:44: - 69:f4:b2:36:38:08:b1:df:07:fa:7a:53:b8:60:db:63:4b:4f: - e6:2a:42:ff:29:68:b5:99:3a:36:eb:26:05:76:d2:ab:e6:d0: - 7c:af:8c:a0:20:8b:50:6c:3b:bc:1a:53:6d:a7:c8:70:97:21: - 56:02:24:04:9b:63:2a:5d:b8:8c:e4:bf:e9:8f:58:cd:6e:99: - 47:3c:02:7b:63:67:c1:c7:32:53:cc:d5:cb:e9:a0:39:ef:f8: - 44:b7:f3:57:0c:b5:a7:23:3f:16:28:c6:02:14:b6:80:d8:33: - 42:0c:81:5c:ac:3f:13:d0:5b:4a:66:9f:33:ee:ac:56:fe:37: - 17:2b:03:40 + 86:b3:8b:79:3b:32:a2:34:bb:9b:12:9d:ad:d2:c7:c6:58:cd: + 24:14:70:7b:4f:7c:52:9a:36:c1:72:aa:bb:a7:a8:a0:ae:82: + ff:ea:9e:14:29:5f:04:82:8f:0a:46:ee:6b:b8:c8:f9:4f:8d: + 1a:af:e6:d2:b0:87:4c:f4:a0:f9:c3:1c:cf:16:2e:28:c7:95: + 5c:86:a8:15:52:e8:9b:4d:40:6c:b0:82:f9:e5:8e:10:1f:f8: + d9:7a:4a:a6:e6:fb:00:ab:13:09:ee:4a:2b:6f:aa:a0:5d:90: + e9:89:40:68:fd:1e:99:f1:cf:5d:fb:d4:76:16:6b:76:52:66: + 17:77:68:e3:d1:7a:35:17:e3:81:9a:46:bd:c9:44:37:10:c4: + a4:13:dd:f6:c9:b8:08:f4:e1:92:18:7f:8c:c5:c9:14:4b:34: + 5b:d4:db:46:a3:6b:61:1c:5b:52:b4:24:73:98:ce:b2:5a:f3: + 51:72:68:bc:d0:8f:36:5d:16:58:b9:91:2e:e2:6f:09:33:40: + 13:f7:ba:8f:b7:36:02:36:1c:0e:c4:db:a2:dc:17:31:dd:6b: + 4c:e3:5e:04:ab:d5:30:fd:f6:ba:1a:00:04:ea:4b:88:34:d8: + 5e:f2:0a:44:61:05:1c:7b:42:86:7e:42:e8:42:f1:19:a2:48: + 28:44:97:3e -----BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIJAOFTujp2BdoeMA0GCSqGSIb3DQEBCwUAMDwxCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlh -dGUgQ0EwHhcNMTUxMjIzMTkzNzM2WhcNMjUxMjIwMTkzNzM2WjAyMQswCQYDVQQG -EwJGSTEOMAwGA1UECgwFdzEuZmkxEzARBgNVBAMMCnVzZXIudzEuZmkwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAhiDlBlqoRy3JXiUk97+mtkRQmYyV -tWqtdLa67jFesiBgmrSTVW0VC9xaJz/fwZIYWWYQ60ccNR8I3eslvSGcLUg0X5cY -3IMo2xSMFjtaNmpQY+k74Df99qDWQK/vHpkdiMFPS5IlUyjLxLfOysomry335GJ5 -SElqgjOwpsalFzOIk3c2sndh4FXeLnUVkkznvxHqMwMeSuYYOBY09dnt+AwXb3hl -rhQYow8ItuKHAuTrD/uB2UuQ/7P6D9METbCZtCte+60EK6fWNg0X4L7AQ8/lLvCO -h4hgsyLYA1lTUKZpzt7QyS73bZpZTZncSzzCFY8nZCM0FDSvQXalapoPAgMBAAGj -gYowgYcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUPjXg+aMeLPrd54vOWAY4IF1ecdIw -HwYDVR0jBBgwFoAUrMT2B56y5fFmfEAFCKrc74pg2sEwGAYDVR0RAQH/BA4wDIIK -dXNlci53MS5maTATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMCBaAwDQYJ -KoZIhvcNAQELBQADggEBAHvp69fUYKgIYnFh3UJ95Yj0JLs/a6kWZC37zo5VHPV+ -tMN03pbkWTL0qnTirEMoBlRd9/6HMT2sRdUcUX+M+TcLZpSnIl/RVb+kgscKULvH -GM/fR4EAxNLXErCDLWc/gLi+b8nFdpqH7zr2DU8k2OcGbG7/3F5uIaHnJvaURGn0 -sjY4CLHfB/p6U7hg22NLT+YqQv8paLWZOjbrJgV20qvm0HyvjKAgi1BsO7waU22n -yHCXIVYCJASbYypduIzkv+mPWM1umUc8AntjZ8HHMlPM1cvpoDnv+ES381cMtacj -PxYoxgIUtoDYM0IMgVysPxPQW0pmnzPurFb+NxcrA0A= +MIIDhzCCAm+gAwIBAgIUWSP0dhDKiUL1XAdcYtJni+QikqkwDQYJKoZIhvcNAQEL +BQAwPDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMR0wGwYDVQQDDBRVc2Vy +IEludGVybWVkaWF0ZSBDQTAeFw0yMDA1MDMxNTIwMTFaFw0zMDA1MDExNTIwMTFa +MDIxCzAJBgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTETMBEGA1UEAwwKdXNlci53 +MS5maTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANRfI+wBxj7SWe7f +zXKNQc5Ar4a+wplpO5GjfC3k9aFyPA65pqWh9aW/X1OYM8LAGCRHTIRLntHySQWF +LYdWrkO8oYnXSqlmE8euNUrML3O2UH5jurCmvJXx8ZrDqbKYPv8nl2SzVAkH/G7E +z3+R4JfCYxCh2uapfUC5A763HEaQEF+aCuWMCVbTvqXBQl30TOW+/dlmQ/npODYa +ZtM7fBFGeRZ5uM+BFApMt7578oP0hyoesf94HBVTIX920VUPCL4RDxnrRmGtqTa8 +u4G/N20MX9FncanaJ24vkOg70GuXwxvnzYFADdYu/iRAZ4Tt6rfzJsUjNfl8tVz5 +3x+foIUCAwEAAaOBijCBhzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRP2qqBy0p55ItK +kvw4QZK62flMMjAfBgNVHSMEGDAWgBTw94Ipcc2vcs72PAtAFsL9n4pRpzAYBgNV +HREBAf8EDjAMggp1c2VyLncxLmZpMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAsGA1Ud +DwQEAwIFoDANBgkqhkiG9w0BAQsFAAOCAQEAhrOLeTsyojS7mxKdrdLHxljNJBRw +e098Upo2wXKqu6eooK6C/+qeFClfBIKPCkbua7jI+U+NGq/m0rCHTPSg+cMczxYu +KMeVXIaoFVLom01AbLCC+eWOEB/42XpKpub7AKsTCe5KK2+qoF2Q6YlAaP0emfHP +XfvUdhZrdlJmF3do49F6NRfjgZpGvclENxDEpBPd9sm4CPThkhh/jMXJFEs0W9Tb +RqNrYRxbUrQkc5jOslrzUXJovNCPNl0WWLmRLuJvCTNAE/e6j7c2AjYcDsTbotwX +Md1rTONeBKvVMP32uhoABOpLiDTYXvIKRGEFHHtChn5C6ELxGaJIKESXPg== -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/iCA-user/user.req b/tests/hwsim/auth_serv/iCA-user/user.req index 21314b714..5b5256655 100644 --- a/tests/hwsim/auth_serv/iCA-user/user.req +++ b/tests/hwsim/auth_serv/iCA-user/user.req @@ -1,16 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- MIICijCCAXICAQAwRTELMAkGA1UEBhMCRkkxETAPBgNVBAcMCEhlbHNpbmtpMQ4w DAYDVQQKDAV3MS5maTETMBEGA1UEAwwKdXNlci53MS5maTCCASIwDQYJKoZIhvcN -AQEBBQADggEPADCCAQoCggEBAMCGIOUGWqhHLcleJST3v6a2RFCZjJW1aq10trru -MV6yIGCatJNVbRUL3FonP9/BkhhZZhDrRxw1Hwjd6yW9IZwtSDRflxjcgyjbFIwW -O1o2alBj6TvgN/32oNZAr+8emR2IwU9LkiVTKMvEt87KyiavLffkYnlISWqCM7Cm -xqUXM4iTdzayd2HgVd4udRWSTOe/EeozAx5K5hg4FjT12e34DBdveGWuFBijDwi2 -4ocC5OsP+4HZS5D/s/oP0wRNsJm0K177rQQrp9Y2DRfgvsBDz+Uu8I6HiGCzItgD -WVNQpmnO3tDJLvdtmllNmdxLPMIVjydkIzQUNK9BdqVqmg8CAwEAAaAAMA0GCSqG -SIb3DQEBCwUAA4IBAQCUmkpNMn0zJiThP+5G+GvjE4bf1zBPWCQ2jNu9ve5dAd6+ -og47aR2PAJWUmFYMfFBzAFxAVkXVwAMAzN7npwtSjTW9kVPxYHItrncopEzPjIOQ -WHSH8nuYxNNYbbkq1/dvivcJVFk8gNCIFvnW8EKgtDfvDlYcyleWnYA343N7eeBc -ujRiiRrZuADk7VFqWM0TdwUEytP/6FJIhB50Y3yDkGNx1KkAJuCU8eSx/aBg/2Si -XPxDKAcVsESrCfFnHuaqN1+BXP5QXuuvR5N6EPt+C/Mv1VnV28uSkLzFO4PCN2pD -ArGZjVzFM6Qegag10DPk8BmDuh3s+NydD29xUfbA +AQEBBQADggEPADCCAQoCggEBANRfI+wBxj7SWe7fzXKNQc5Ar4a+wplpO5GjfC3k +9aFyPA65pqWh9aW/X1OYM8LAGCRHTIRLntHySQWFLYdWrkO8oYnXSqlmE8euNUrM +L3O2UH5jurCmvJXx8ZrDqbKYPv8nl2SzVAkH/G7Ez3+R4JfCYxCh2uapfUC5A763 +HEaQEF+aCuWMCVbTvqXBQl30TOW+/dlmQ/npODYaZtM7fBFGeRZ5uM+BFApMt757 +8oP0hyoesf94HBVTIX920VUPCL4RDxnrRmGtqTa8u4G/N20MX9FncanaJ24vkOg7 +0GuXwxvnzYFADdYu/iRAZ4Tt6rfzJsUjNfl8tVz53x+foIUCAwEAAaAAMA0GCSqG +SIb3DQEBCwUAA4IBAQBXDSMg3STy5dxee9/+DnPa859cH3b3xawbT7RY4j3n/ZCL +RiB6EqH8L0wSEwTZpF1YqNdjx1weDwxA1eM4esLslcyyCdMTRXVS7QogwuHj+Qo4 +3qqiSFOpJBh7zxdz3Eph/4rr0SdeUefHUyFvKvu7gcS1LwHY0vCGQ3FO6eVLDZl4 +eEMdz6MynkBBj1kjYWnn8jaUraNBqOFKg9ll3S5K9RH3yJZhdhcodiun2S2IaL4E +evgt2u2Fr9Eka2wXRBlf1F+raSyVsdFY4a3aMzYQes0whGwWpmkMOo/4Ax8TL+co +SMc3B4yezaS4iypgI9EZThe4/KaidGEqCkyAPOem -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/iCA-user/user_and_ica.pem b/tests/hwsim/auth_serv/iCA-user/user_and_ica.pem index 0a5c955b9..50df34d62 100644 --- a/tests/hwsim/auth_serv/iCA-user/user_and_ica.pem +++ b/tests/hwsim/auth_serv/iCA-user/user_and_ica.pem @@ -1,43 +1,44 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 16236525841851734558 (0xe153ba3a7605da1e) - Signature Algorithm: sha256WithRSAEncryption + Serial Number: + 59:23:f4:76:10:ca:89:42:f5:5c:07:5c:62:d2:67:8b:e4:22:92:a9 + Signature Algorithm: sha256WithRSAEncryption Issuer: C=FI, O=w1.fi, CN=User Intermediate CA Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 20 19:37:36 2025 GMT + Not Before: May 3 15:20:11 2020 GMT + Not After : May 1 15:20:11 2030 GMT Subject: C=FI, O=w1.fi, CN=user.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:c0:86:20:e5:06:5a:a8:47:2d:c9:5e:25:24:f7: - bf:a6:b6:44:50:99:8c:95:b5:6a:ad:74:b6:ba:ee: - 31:5e:b2:20:60:9a:b4:93:55:6d:15:0b:dc:5a:27: - 3f:df:c1:92:18:59:66:10:eb:47:1c:35:1f:08:dd: - eb:25:bd:21:9c:2d:48:34:5f:97:18:dc:83:28:db: - 14:8c:16:3b:5a:36:6a:50:63:e9:3b:e0:37:fd:f6: - a0:d6:40:af:ef:1e:99:1d:88:c1:4f:4b:92:25:53: - 28:cb:c4:b7:ce:ca:ca:26:af:2d:f7:e4:62:79:48: - 49:6a:82:33:b0:a6:c6:a5:17:33:88:93:77:36:b2: - 77:61:e0:55:de:2e:75:15:92:4c:e7:bf:11:ea:33: - 03:1e:4a:e6:18:38:16:34:f5:d9:ed:f8:0c:17:6f: - 78:65:ae:14:18:a3:0f:08:b6:e2:87:02:e4:eb:0f: - fb:81:d9:4b:90:ff:b3:fa:0f:d3:04:4d:b0:99:b4: - 2b:5e:fb:ad:04:2b:a7:d6:36:0d:17:e0:be:c0:43: - cf:e5:2e:f0:8e:87:88:60:b3:22:d8:03:59:53:50: - a6:69:ce:de:d0:c9:2e:f7:6d:9a:59:4d:99:dc:4b: - 3c:c2:15:8f:27:64:23:34:14:34:af:41:76:a5:6a: - 9a:0f + 00:d4:5f:23:ec:01:c6:3e:d2:59:ee:df:cd:72:8d: + 41:ce:40:af:86:be:c2:99:69:3b:91:a3:7c:2d:e4: + f5:a1:72:3c:0e:b9:a6:a5:a1:f5:a5:bf:5f:53:98: + 33:c2:c0:18:24:47:4c:84:4b:9e:d1:f2:49:05:85: + 2d:87:56:ae:43:bc:a1:89:d7:4a:a9:66:13:c7:ae: + 35:4a:cc:2f:73:b6:50:7e:63:ba:b0:a6:bc:95:f1: + f1:9a:c3:a9:b2:98:3e:ff:27:97:64:b3:54:09:07: + fc:6e:c4:cf:7f:91:e0:97:c2:63:10:a1:da:e6:a9: + 7d:40:b9:03:be:b7:1c:46:90:10:5f:9a:0a:e5:8c: + 09:56:d3:be:a5:c1:42:5d:f4:4c:e5:be:fd:d9:66: + 43:f9:e9:38:36:1a:66:d3:3b:7c:11:46:79:16:79: + b8:cf:81:14:0a:4c:b7:be:7b:f2:83:f4:87:2a:1e: + b1:ff:78:1c:15:53:21:7f:76:d1:55:0f:08:be:11: + 0f:19:eb:46:61:ad:a9:36:bc:bb:81:bf:37:6d:0c: + 5f:d1:67:71:a9:da:27:6e:2f:90:e8:3b:d0:6b:97: + c3:1b:e7:cd:81:40:0d:d6:2e:fe:24:40:67:84:ed: + ea:b7:f3:26:c5:23:35:f9:7c:b5:5c:f9:df:1f:9f: + a0:85 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - 3E:35:E0:F9:A3:1E:2C:FA:DD:E7:8B:CE:58:06:38:20:5D:5E:71:D2 + 4F:DA:AA:81:CB:4A:79:E4:8B:4A:92:FC:38:41:92:BA:D9:F9:4C:32 X509v3 Authority Key Identifier: - keyid:AC:C4:F6:07:9E:B2:E5:F1:66:7C:40:05:08:AA:DC:EF:8A:60:DA:C1 + keyid:F0:F7:82:29:71:CD:AF:72:CE:F6:3C:0B:40:16:C2:FD:9F:8A:51:A7 X509v3 Subject Alternative Name: critical DNS:user.w1.fi @@ -46,109 +47,120 @@ Certificate: X509v3 Key Usage: Digital Signature, Key Encipherment Signature Algorithm: sha256WithRSAEncryption - 7b:e9:eb:d7:d4:60:a8:08:62:71:61:dd:42:7d:e5:88:f4:24: - bb:3f:6b:a9:16:64:2d:fb:ce:8e:55:1c:f5:7e:b4:c3:74:de: - 96:e4:59:32:f4:aa:74:e2:ac:43:28:06:54:5d:f7:fe:87:31: - 3d:ac:45:d5:1c:51:7f:8c:f9:37:0b:66:94:a7:22:5f:d1:55: - bf:a4:82:c7:0a:50:bb:c7:18:cf:df:47:81:00:c4:d2:d7:12: - b0:83:2d:67:3f:80:b8:be:6f:c9:c5:76:9a:87:ef:3a:f6:0d: - 4f:24:d8:e7:06:6c:6e:ff:dc:5e:6e:21:a1:e7:26:f6:94:44: - 69:f4:b2:36:38:08:b1:df:07:fa:7a:53:b8:60:db:63:4b:4f: - e6:2a:42:ff:29:68:b5:99:3a:36:eb:26:05:76:d2:ab:e6:d0: - 7c:af:8c:a0:20:8b:50:6c:3b:bc:1a:53:6d:a7:c8:70:97:21: - 56:02:24:04:9b:63:2a:5d:b8:8c:e4:bf:e9:8f:58:cd:6e:99: - 47:3c:02:7b:63:67:c1:c7:32:53:cc:d5:cb:e9:a0:39:ef:f8: - 44:b7:f3:57:0c:b5:a7:23:3f:16:28:c6:02:14:b6:80:d8:33: - 42:0c:81:5c:ac:3f:13:d0:5b:4a:66:9f:33:ee:ac:56:fe:37: - 17:2b:03:40 + 86:b3:8b:79:3b:32:a2:34:bb:9b:12:9d:ad:d2:c7:c6:58:cd: + 24:14:70:7b:4f:7c:52:9a:36:c1:72:aa:bb:a7:a8:a0:ae:82: + ff:ea:9e:14:29:5f:04:82:8f:0a:46:ee:6b:b8:c8:f9:4f:8d: + 1a:af:e6:d2:b0:87:4c:f4:a0:f9:c3:1c:cf:16:2e:28:c7:95: + 5c:86:a8:15:52:e8:9b:4d:40:6c:b0:82:f9:e5:8e:10:1f:f8: + d9:7a:4a:a6:e6:fb:00:ab:13:09:ee:4a:2b:6f:aa:a0:5d:90: + e9:89:40:68:fd:1e:99:f1:cf:5d:fb:d4:76:16:6b:76:52:66: + 17:77:68:e3:d1:7a:35:17:e3:81:9a:46:bd:c9:44:37:10:c4: + a4:13:dd:f6:c9:b8:08:f4:e1:92:18:7f:8c:c5:c9:14:4b:34: + 5b:d4:db:46:a3:6b:61:1c:5b:52:b4:24:73:98:ce:b2:5a:f3: + 51:72:68:bc:d0:8f:36:5d:16:58:b9:91:2e:e2:6f:09:33:40: + 13:f7:ba:8f:b7:36:02:36:1c:0e:c4:db:a2:dc:17:31:dd:6b: + 4c:e3:5e:04:ab:d5:30:fd:f6:ba:1a:00:04:ea:4b:88:34:d8: + 5e:f2:0a:44:61:05:1c:7b:42:86:7e:42:e8:42:f1:19:a2:48: + 28:44:97:3e -----BEGIN CERTIFICATE----- -MIIDfDCCAmSgAwIBAgIJAOFTujp2BdoeMA0GCSqGSIb3DQEBCwUAMDwxCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlh -dGUgQ0EwHhcNMTUxMjIzMTkzNzM2WhcNMjUxMjIwMTkzNzM2WjAyMQswCQYDVQQG -EwJGSTEOMAwGA1UECgwFdzEuZmkxEzARBgNVBAMMCnVzZXIudzEuZmkwggEiMA0G -CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAhiDlBlqoRy3JXiUk97+mtkRQmYyV -tWqtdLa67jFesiBgmrSTVW0VC9xaJz/fwZIYWWYQ60ccNR8I3eslvSGcLUg0X5cY -3IMo2xSMFjtaNmpQY+k74Df99qDWQK/vHpkdiMFPS5IlUyjLxLfOysomry335GJ5 -SElqgjOwpsalFzOIk3c2sndh4FXeLnUVkkznvxHqMwMeSuYYOBY09dnt+AwXb3hl -rhQYow8ItuKHAuTrD/uB2UuQ/7P6D9METbCZtCte+60EK6fWNg0X4L7AQ8/lLvCO -h4hgsyLYA1lTUKZpzt7QyS73bZpZTZncSzzCFY8nZCM0FDSvQXalapoPAgMBAAGj -gYowgYcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUPjXg+aMeLPrd54vOWAY4IF1ecdIw -HwYDVR0jBBgwFoAUrMT2B56y5fFmfEAFCKrc74pg2sEwGAYDVR0RAQH/BA4wDIIK -dXNlci53MS5maTATBgNVHSUEDDAKBggrBgEFBQcDAjALBgNVHQ8EBAMCBaAwDQYJ -KoZIhvcNAQELBQADggEBAHvp69fUYKgIYnFh3UJ95Yj0JLs/a6kWZC37zo5VHPV+ -tMN03pbkWTL0qnTirEMoBlRd9/6HMT2sRdUcUX+M+TcLZpSnIl/RVb+kgscKULvH -GM/fR4EAxNLXErCDLWc/gLi+b8nFdpqH7zr2DU8k2OcGbG7/3F5uIaHnJvaURGn0 -sjY4CLHfB/p6U7hg22NLT+YqQv8paLWZOjbrJgV20qvm0HyvjKAgi1BsO7waU22n -yHCXIVYCJASbYypduIzkv+mPWM1umUc8AntjZ8HHMlPM1cvpoDnv+ES381cMtacj -PxYoxgIUtoDYM0IMgVysPxPQW0pmnzPurFb+NxcrA0A= +MIIDhzCCAm+gAwIBAgIUWSP0dhDKiUL1XAdcYtJni+QikqkwDQYJKoZIhvcNAQEL +BQAwPDELMAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMR0wGwYDVQQDDBRVc2Vy +IEludGVybWVkaWF0ZSBDQTAeFw0yMDA1MDMxNTIwMTFaFw0zMDA1MDExNTIwMTFa +MDIxCzAJBgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTETMBEGA1UEAwwKdXNlci53 +MS5maTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANRfI+wBxj7SWe7f +zXKNQc5Ar4a+wplpO5GjfC3k9aFyPA65pqWh9aW/X1OYM8LAGCRHTIRLntHySQWF +LYdWrkO8oYnXSqlmE8euNUrML3O2UH5jurCmvJXx8ZrDqbKYPv8nl2SzVAkH/G7E +z3+R4JfCYxCh2uapfUC5A763HEaQEF+aCuWMCVbTvqXBQl30TOW+/dlmQ/npODYa +ZtM7fBFGeRZ5uM+BFApMt7578oP0hyoesf94HBVTIX920VUPCL4RDxnrRmGtqTa8 +u4G/N20MX9FncanaJ24vkOg70GuXwxvnzYFADdYu/iRAZ4Tt6rfzJsUjNfl8tVz5 +3x+foIUCAwEAAaOBijCBhzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRP2qqBy0p55ItK +kvw4QZK62flMMjAfBgNVHSMEGDAWgBTw94Ipcc2vcs72PAtAFsL9n4pRpzAYBgNV +HREBAf8EDjAMggp1c2VyLncxLmZpMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAsGA1Ud +DwQEAwIFoDANBgkqhkiG9w0BAQsFAAOCAQEAhrOLeTsyojS7mxKdrdLHxljNJBRw +e098Upo2wXKqu6eooK6C/+qeFClfBIKPCkbua7jI+U+NGq/m0rCHTPSg+cMczxYu +KMeVXIaoFVLom01AbLCC+eWOEB/42XpKpub7AKsTCe5KK2+qoF2Q6YlAaP0emfHP +XfvUdhZrdlJmF3do49F6NRfjgZpGvclENxDEpBPd9sm4CPThkhh/jMXJFEs0W9Tb +RqNrYRxbUrQkc5jOslrzUXJovNCPNl0WWLmRLuJvCTNAE/e6j7c2AjYcDsTbotwX +Md1rTONeBKvVMP32uhoABOpLiDTYXvIKRGEFHHtChn5C6ELxGaJIKESXPg== -----END CERTIFICATE----- Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162868 (0xd8d3e3a6cbe3ccf4) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + d8:d3:e3:a6:cb:e3:cc:f8 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Dec 23 19:37:36 2015 GMT - Not After : Dec 22 19:37:36 2025 GMT + Not Before: May 3 15:20:10 2020 GMT + Not After : May 3 15:20:10 2030 GMT Subject: C=FI, O=w1.fi, CN=User Intermediate CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (2048 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:c3:2a:0d:f4:66:23:5d:96:91:f7:a0:be:b1:b0: - f7:9e:ae:ea:a6:72:91:f5:70:65:57:91:49:55:59: - 67:bb:d7:f5:9e:bc:66:b2:bf:cf:95:31:32:ae:db: - 9a:3b:43:e8:a5:8d:1f:8b:3b:e6:e8:e3:3b:b2:9d: - f0:58:62:ea:a3:8a:6f:c8:ed:01:ca:27:74:1c:0e: - 9e:28:5c:43:98:db:14:b8:72:07:9f:6b:27:28:25: - ce:a5:91:b7:b7:23:9a:35:ef:0e:b7:fc:9f:69:4d: - 10:2e:81:ab:9d:04:ba:2f:b4:eb:61:7d:fd:68:a1: - 11:6f:f4:16:42:16:99:20:38:24:04:2d:39:7c:74: - 67:14:b9:aa:26:7a:b2:d9:1e:ce:cd:8b:bc:8d:e3: - c7:58:9c:4a:f9:3a:7e:6c:38:f8:5f:1c:ec:05:4c: - e5:56:64:d4:08:d8:fa:db:17:d9:a1:e4:cf:b4:9d: - df:99:50:ce:fa:a4:af:af:c6:f7:f2:0e:c2:c5:7b: - 6c:f9:6c:eb:17:e5:c8:6e:5a:bf:eb:a6:b8:c0:f7: - 43:81:88:c3:d8:aa:a9:60:ac:a7:45:3f:5d:cb:8d: - 6c:48:92:2b:04:5a:c4:a8:32:b3:e9:6f:fe:8d:2d: - 65:c0:ea:c5:09:b2:30:b1:a3:2e:db:22:8a:49:b1: - fe:4f + 00:b9:88:7a:fc:1a:f9:00:68:63:c7:40:ff:d5:38: + 8e:88:8c:c9:8f:66:ec:74:0a:a6:f1:18:30:30:36: + 9a:2a:98:c5:a0:46:02:e2:3c:64:86:79:43:45:19: + 83:7a:82:3d:f9:c6:af:01:11:91:2c:4f:07:f8:d7: + ef:da:80:6c:07:88:6a:1e:e6:0e:78:ca:08:50:4f: + f0:8a:2e:54:41:9f:04:63:8b:70:99:ae:6f:95:ed: + 5c:c8:34:8e:6b:36:64:bc:44:c9:fb:cb:50:ef:b1: + 5b:9b:2c:db:2a:a7:f9:e0:e2:48:57:78:cf:ba:0f: + 1a:af:5a:63:64:18:39:9c:d4:af:8d:f9:27:d9:10: + b4:67:17:a1:24:98:f1:ef:ce:ad:12:6f:e4:47:36: + b6:d2:b6:1c:04:03:76:43:63:fb:b6:3e:3f:1a:c8: + c4:8b:69:28:7c:75:dc:bb:36:7f:ad:6a:a2:c1:32: + f3:5e:64:86:57:f1:ee:20:af:64:bd:e0:7c:ba:68: + 9b:75:ed:b3:1c:0f:12:e0:52:12:ff:18:0e:8f:1d: + bf:c8:88:56:35:4d:9e:1f:74:1e:19:d7:0c:b4:e7: + 46:ee:cf:c6:63:35:ba:16:7f:05:84:8b:bf:16:72: + 05:ee:22:6e:3a:54:80:2b:0e:36:96:8d:65:5f:64: + 12:cd Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - AC:C4:F6:07:9E:B2:E5:F1:66:7C:40:05:08:AA:DC:EF:8A:60:DA:C1 + F0:F7:82:29:71:CD:AF:72:CE:F6:3C:0B:40:16:C2:FD:9F:8A:51:A7 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: critical CA:TRUE, pathlen:0 X509v3 Key Usage: critical Certificate Sign, CRL Sign Signature Algorithm: sha256WithRSAEncryption - 0d:60:2b:fa:00:f2:5a:90:31:96:50:c8:9e:7f:60:02:99:c6: - 31:d4:93:86:9e:4c:24:15:b6:b2:31:49:21:79:ce:7f:92:86: - 1e:83:d8:a0:37:05:1b:89:2b:ef:0b:83:21:b0:37:8d:2f:7b: - 6b:7d:c6:04:1e:a2:c8:59:be:52:bf:47:ee:46:cb:45:8d:1f: - 7a:e4:d4:e5:54:60:5f:46:b0:ac:68:8a:26:57:ea:48:45:c1: - 07:7d:ee:10:9e:94:87:4c:7e:26:2e:f8:ad:03:e5:03:86:09: - 3e:48:0c:e0:04:2f:22:b4:e0:3a:b0:72:8c:e2:40:d2:cd:fb: - 8f:fa + 70:45:66:14:00:22:85:1c:f8:b9:b3:2c:e8:64:4d:01:53:b8: + cb:23:ad:fa:01:7c:27:f7:aa:8d:d8:6c:6a:f8:72:21:63:bf: + 30:7e:05:8c:84:e3:d1:1e:d1:f3:1d:80:3d:e8:75:06:ae:1b: + 48:a9:cf:0e:c6:59:6b:f8:d1:25:5a:64:b7:46:2d:29:72:da: + d6:3a:79:d3:92:41:d7:31:e4:4e:5e:1b:62:88:41:77:f6:62: + a2:3e:c1:a2:ef:79:0c:8f:39:7c:df:a0:4b:d5:ac:58:aa:3e: + fd:95:6b:f7:c0:42:29:2e:86:67:5e:d9:3e:7b:e7:a6:bd:3b: + 7e:3b:19:54:9b:89:40:0e:39:23:8a:af:f2:db:12:5b:09:b4: + 45:df:c8:3e:8f:fc:fc:55:3e:35:8d:7b:82:50:d5:a3:ea:bb: + c4:40:6d:61:ad:92:b2:66:91:0f:5b:3d:49:5e:b5:3e:98:15: + 9e:2a:23:06:35:e0:13:bc:50:84:06:e4:1b:b9:fc:32:a2:4a: + 0d:e5:86:ac:69:47:c3:17:11:07:ac:5a:09:69:ed:99:d0:52: + fd:6d:ab:0d:44:35:bb:c0:76:27:50:75:df:06:78:f6:92:54: + fc:54:76:b5:6f:a0:f6:51:20:1f:7f:8e:aa:5f:c8:48:88:e4: + 1a:83:f6:b7 -----BEGIN CERTIFICATE----- -MIIC0zCCAjygAwIBAgIJANjT46bL48z0MA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNTEy -MjMxOTM3MzZaFw0yNTEyMjIxOTM3MzZaMDwxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqG -SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDKg30ZiNdlpH3oL6xsPeeruqmcpH1cGVX -kUlVWWe71/WevGayv8+VMTKu25o7Q+iljR+LO+bo4zuynfBYYuqjim/I7QHKJ3Qc -Dp4oXEOY2xS4cgefaycoJc6lkbe3I5o17w63/J9pTRAugaudBLovtOthff1ooRFv -9BZCFpkgOCQELTl8dGcUuaomerLZHs7Ni7yN48dYnEr5On5sOPhfHOwFTOVWZNQI -2PrbF9mh5M+0nd+ZUM76pK+vxvfyDsLFe2z5bOsX5chuWr/rprjA90OBiMPYqqlg -rKdFP13LjWxIkisEWsSoMrPpb/6NLWXA6sUJsjCxoy7bIopJsf5PAgMBAAGjZjBk -MB0GA1UdDgQWBBSsxPYHnrLl8WZ8QAUIqtzvimDawTAfBgNVHSMEGDAWgBS4kt79 -ihizMMOfVfMzXbTIKYpBFDASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQE -AwIBBjANBgkqhkiG9w0BAQsFAAOBgQANYCv6APJakDGWUMief2ACmcYx1JOGnkwk -FbayMUkhec5/koYeg9igNwUbiSvvC4MhsDeNL3trfcYEHqLIWb5Sv0fuRstFjR96 -5NTlVGBfRrCsaIomV+pIRcEHfe4QnpSHTH4mLvitA+UDhgk+SAzgBC8itOA6sHKM -4kDSzfuP+g== +MIIDZjCCAk6gAwIBAgIJANjT46bL48z4MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDMxNTIwMTBaFw0zMDA1MDMxNTIwMTBaMDwxCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEdMBsGA1UEAwwUVXNlciBJbnRlcm1l +ZGlhdGUgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC5iHr8GvkA +aGPHQP/VOI6IjMmPZux0CqbxGDAwNpoqmMWgRgLiPGSGeUNFGYN6gj35xq8BEZEs +Twf41+/agGwHiGoe5g54yghQT/CKLlRBnwRji3CZrm+V7VzINI5rNmS8RMn7y1Dv +sVubLNsqp/ng4khXeM+6DxqvWmNkGDmc1K+N+SfZELRnF6EkmPHvzq0Sb+RHNrbS +thwEA3ZDY/u2Pj8ayMSLaSh8ddy7Nn+taqLBMvNeZIZX8e4gr2S94Hy6aJt17bMc +DxLgUhL/GA6PHb/IiFY1TZ4fdB4Z1wy050buz8ZjNboWfwWEi78WcgXuIm46VIAr +DjaWjWVfZBLNAgMBAAGjZjBkMB0GA1UdDgQWBBTw94Ipcc2vcs72PAtAFsL9n4pR +pzAfBgNVHSMEGDAWgBSk/bk5G4GzquuIHdSBqbURcMyn4TASBgNVHRMBAf8ECDAG +AQH/AgEAMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAcEVmFAAi +hRz4ubMs6GRNAVO4yyOt+gF8J/eqjdhsavhyIWO/MH4FjITj0R7R8x2APeh1Bq4b +SKnPDsZZa/jRJVpkt0YtKXLa1jp505JB1zHkTl4bYohBd/Zioj7Bou95DI85fN+g +S9WsWKo+/ZVr98BCKS6GZ17ZPnvnpr07fjsZVJuJQA45I4qv8tsSWwm0Rd/IPo/8 +/FU+NY17glDVo+q7xEBtYa2SsmaRD1s9SV61PpgVniojBjXgE7xQhAbkG7n8MqJK +DeWGrGlHwxcRB6xaCWntmdBS/W2rDUQ1u8B2J1B13wZ49pJU/FR2tW+g9lEgH3+O +ql/ISIjkGoP2tw== -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/index.txt b/tests/hwsim/auth_serv/index.txt index 7e48c3f81..090cb9235 100644 --- a/tests/hwsim/auth_serv/index.txt +++ b/tests/hwsim/auth_serv/index.txt @@ -5,4 +5,4 @@ V 150215083008Z D8D3E3A6CBE3CCCB unknown /C=FI/O=w1.fi/CN=server5.w1.fi V 150228224144Z D8D3E3A6CBE3CCCC unknown /C=FI/O=w1.fi/CN=server6.w1.fi V 160111185024Z D8D3E3A6CBE3CCCD unknown /C=FI/O=w1.fi/CN=ocsp.w1.fi V 150929211300Z D8D3E3A6CBE3CCD1 unknown /C=FI/O=w1.fi/CN=Test User -V 201003130223Z D8D3E3A6CBE3CD1F unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502195538Z D8D3E3A6CBE3CD5F unknown /C=FI/O=w1.fi/CN=server.w1.fi diff --git a/tests/hwsim/auth_serv/ocsp-multi-server-cache.der b/tests/hwsim/auth_serv/ocsp-multi-server-cache.der index 2e0e88b3b..15ea6647d 100644 Binary files a/tests/hwsim/auth_serv/ocsp-multi-server-cache.der and b/tests/hwsim/auth_serv/ocsp-multi-server-cache.der differ diff --git a/tests/hwsim/auth_serv/ocsp-req.der b/tests/hwsim/auth_serv/ocsp-req.der index 92ae09930..ebab4a025 100644 Binary files a/tests/hwsim/auth_serv/ocsp-req.der and b/tests/hwsim/auth_serv/ocsp-req.der differ diff --git a/tests/hwsim/auth_serv/ocsp-responder.csr b/tests/hwsim/auth_serv/ocsp-responder.csr new file mode 100644 index 000000000..d00550cdd --- /dev/null +++ b/tests/hwsim/auth_serv/ocsp-responder.csr @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICiTCCAXECAQAwRDELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAM +BgNVBAoMBXcxLmZpMRMwEQYDVQQDDApvY3NwLncxLmZpMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEApyKFXbs7HAKaAXOqiGNuoUMztf0C/h/IIwSLjFFS +W+DMYmAqqrqIT0E5a/s0wKJ6dy7hVp7vyq5n1fmLX6uuh+GwFCMDrWlL3yuRcHXN +v2VAEtDrL4nwQRUb7UwNOpKWkfjNVDgV62tFn1KFfk4Vq05L6yLCXb7/Nm9CJ9hL +xuG++AjPrP1RMKLogBMABbYFVUIL+h5AhFAJjCU1VCVFOZ9OfArZxEoMFk4+aH8b +rclTCFy4BNTWk2L9r/m0HfSWPpudFG0cbCOuPce0zzGQIGqAmWJ+XOnV1b1ZTaPZ +3On76Htlh9X5SZ6+DvOpId6U6FT8gM/a44+axkx2GA7+qwIDAQABoAAwDQYJKoZI +hvcNAQELBQADggEBAE/iM0/mhspobneVqSBhCrM2n0KUozbLRBZXfc8hCMW85XPI +kD7bJdTwndj6wGAd2G4IQr4jeR4tGUU6XAYEsyIVfFlHlBQaUjF9EJmnqqwDAlN3 +v6em8QEv49EL2HO0Q1MFsly2CUk07WYpy0ll5wTjEXIEQ/2J9jNJfgPDs06IQAQi +9WkFCfBogTn23ZRxomYqukqbirHxGJ2XFRM/LkssyIkMi0jEWzljXYiuzhuD/KtP +hXXYXcJdL3WdZU9FZw/na4pBrtCTscluwaTDEaW4k60ge/ne51pB32RfsF4aEfsx +/Xrxva+5dZexgMxK078QL2q7o43HprVa1U/wBfg= +-----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/ocsp-responder.key b/tests/hwsim/auth_serv/ocsp-responder.key index fb866fbf5..f5dc4e822 100644 --- a/tests/hwsim/auth_serv/ocsp-responder.key +++ b/tests/hwsim/auth_serv/ocsp-responder.key @@ -1,16 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALJeLx3nLPZsq7AW -nvoSL7JMyCN7aAh2OIOX9T8FrF3ZganOdZKhvJbGyADuHtfw2orY58DXQsMlYufH -YPqogkwbznOaq42z/j22fwH+WWRCdagEGActImQnufGvAbTtv6bqkXjRnDD1YTf/ -+Rv4Fl9rdzL51+OdDNXDuUMW8DrDAgMBAAECgYAja1yD3aIqFQ5K21MaaX4bM/AS -S7Eu7Prv9r72ktPVlxmOdLcYNRHUBwk0VhS94NAk/kmXG6fgRI5NZGQ3ojqtOXLV -VhlcitYAfJvNpyKmFKgdGZQIxaaQr/F2X8tH5yFdIt+6mDOGptTb/S3ljQwNsg59 -7t/jYzSe5mK/Gbw4MQJBAN3sZqGz6ABygLTuTiXhE9sCXDSGy4d8ZWMaajuD7N6k -sAGKsaiVozeIvg0JNiCMm02A8M/cWjGedDWFxrnvvF8CQQDNwagUpozfXMboibHI -BNwpUzyri/5bqJ/dU7/sAOA1AZ9yoO5s2WlNutXkG3mDoQCzseG/pNxU403dU0jQ -wpwdAkEAk5lbWUkSkNmXCL9GcqMUVaFoOfc8/suZkyRKa3L+48Wc2imop3t+przn -yjvKKDPcRtvvThA8XKwKll53Ict0+QJBAKj7o09Sed/4EmRosdnUI/zMn8dD8mLU -2narkbQCBCGEc69w/F/pLtLn30K4TdQNJsZuETmT7GDLTee3vtW0/wECQCtyVgw/ -aZ0QTac8ut1oG072qOA2cFGhEuDELlX8JcNy28ygmzn0KS8uiTsq6YVu8V7WCj4X -EkAZMm19nY5ZE+A= +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCnIoVduzscApoB +c6qIY26hQzO1/QL+H8gjBIuMUVJb4MxiYCqquohPQTlr+zTAonp3LuFWnu/KrmfV ++Ytfq66H4bAUIwOtaUvfK5Fwdc2/ZUAS0OsvifBBFRvtTA06kpaR+M1UOBXra0Wf +UoV+ThWrTkvrIsJdvv82b0In2EvG4b74CM+s/VEwouiAEwAFtgVVQgv6HkCEUAmM +JTVUJUU5n058CtnESgwWTj5ofxutyVMIXLgE1NaTYv2v+bQd9JY+m50UbRxsI649 +x7TPMZAgaoCZYn5c6dXVvVlNo9nc6fvoe2WH1flJnr4O86kh3pToVPyAz9rjj5rG +THYYDv6rAgMBAAECggEAEyuNeoPIMt1Fhtcaf0xQWyTXII+lsTo5/XI/A1gshydQ +qhP3sN92VQjZKj6E/Xdlbpgs9n+CZ4/7jvpxdwa9HQ7Q4G5ntJM4RZ+8rdaFQ+e8 +Iqxd3XUH3p8qNdycQ9Seep28B2XrdbY3JSAU+bjBGYYAhTbWbmRC5555SxKvFl+M +xtSbujwAEgDYpvBYpiqBf2lfglQ/UgY8xmGrAwxhEAuNTYZj8MCsMFM6s0iwq0oo +UhpXKIVtcrlujXrQJpEfZjsqOLTPe/Jw85CW3upJuSewAPC4zX8adSv62ZMHOQXZ +StPh1vOuA9dcC2dJCf4LCuyPDjhTnS+s/fc10kV9qQKBgQDXp99f7YPB3dEdZC5S +Lf5dDn+7r2QrxIiky+iLgsC4SrvEGr997TRmUrBYj+HnLKjgB5qLVZwtWYhWYW04 +ly/J08croMU2C6q5iqYUvMmW65T2zsNkII4ztvKp7zYX9UnIqS3AsuvqUmFFPb1B +o/VWvBJ+xYcb1zFyqDr2lxV4bQKBgQDGZuXzyfkxH8WuX3XxSlhYfFVwWU+q5LX2 +scg2Rm4vQ6rtaaYIznKN/jaSFanXbf48b6glkkmn9fNERktyqK3p90rOkM6MEXb7 +61+pJdAPs9DD1fi2gw/KtLEkZqPymnO/BlJJbkBbm8Co+w5oRANLa/4J+3eLibf0 +6MN7kimUdwKBgQDTqF2iRvkkE1MkZ6jW23FlX8+aI8BK/K+oHsFz+7auqhqzlBUR +wPfG3a1anoz3WWu9xXi2/CU2lUMslJ6gBjLPAd3fQgGM09KSHDR48flg+ILR4YkA +ArvOoeZ1RuRuiz4JhZH0KSdGaegyDzBq9kLbB+eXKMM8Xe6YO+jzEMHv2QKBgFzu +0gOxtcHm6gfVuz883ckE5Fht3T1lSD6349pYf0AwaB4xAI7bdRlB3HntH9NDOHVC +r/Z5YXsFX9+5NZoNnPkc1rOPbNB7VcqG5BYtGhpg1gcFcSy8k2cV4Gv2kBERe+oc +oeq3c/n1KPd+Ma9xPEHV4fb3DXYVGk/jv71gJ43dAoGAcV2MV2vaH657r6cK+Ddh +8GUw6eSBDfK80Q0BQ2vRsAunE4pKPwYDo60eIKAhhQAol3OVDNf67ItGLX9Mc+yQ +pXoadPaEkFWgYR5xaUzsVJomtrb9xa3VBhOsVvCZZtNhP8PNcnAA+sfZCNysbWlX +yIWM7r1ekF8uEPTM5XLtZY4= -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/ocsp-responder.pem b/tests/hwsim/auth_serv/ocsp-responder.pem index 240cec1d1..778f1b8f6 100644 --- a/tests/hwsim/auth_serv/ocsp-responder.pem +++ b/tests/hwsim/auth_serv/ocsp-responder.pem @@ -1,26 +1,36 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162831 (0xd8d3e3a6cbe3cccf) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + d8:d3:e3:a6:cb:e3:cd:67 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Jan 12 22:37:50 2016 GMT - Not After : Jan 11 22:37:50 2021 GMT + Not Before: May 3 14:01:18 2020 GMT + Not After : May 3 14:01:18 2021 GMT Subject: C=FI, O=w1.fi, CN=ocsp.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:b2:5e:2f:1d:e7:2c:f6:6c:ab:b0:16:9e:fa:12: - 2f:b2:4c:c8:23:7b:68:08:76:38:83:97:f5:3f:05: - ac:5d:d9:81:a9:ce:75:92:a1:bc:96:c6:c8:00:ee: - 1e:d7:f0:da:8a:d8:e7:c0:d7:42:c3:25:62:e7:c7: - 60:fa:a8:82:4c:1b:ce:73:9a:ab:8d:b3:fe:3d:b6: - 7f:01:fe:59:64:42:75:a8:04:18:07:2d:22:64:27: - b9:f1:af:01:b4:ed:bf:a6:ea:91:78:d1:9c:30:f5: - 61:37:ff:f9:1b:f8:16:5f:6b:77:32:f9:d7:e3:9d: - 0c:d5:c3:b9:43:16:f0:3a:c3 + 00:a7:22:85:5d:bb:3b:1c:02:9a:01:73:aa:88:63: + 6e:a1:43:33:b5:fd:02:fe:1f:c8:23:04:8b:8c:51: + 52:5b:e0:cc:62:60:2a:aa:ba:88:4f:41:39:6b:fb: + 34:c0:a2:7a:77:2e:e1:56:9e:ef:ca:ae:67:d5:f9: + 8b:5f:ab:ae:87:e1:b0:14:23:03:ad:69:4b:df:2b: + 91:70:75:cd:bf:65:40:12:d0:eb:2f:89:f0:41:15: + 1b:ed:4c:0d:3a:92:96:91:f8:cd:54:38:15:eb:6b: + 45:9f:52:85:7e:4e:15:ab:4e:4b:eb:22:c2:5d:be: + ff:36:6f:42:27:d8:4b:c6:e1:be:f8:08:cf:ac:fd: + 51:30:a2:e8:80:13:00:05:b6:05:55:42:0b:fa:1e: + 40:84:50:09:8c:25:35:54:25:45:39:9f:4e:7c:0a: + d9:c4:4a:0c:16:4e:3e:68:7f:1b:ad:c9:53:08:5c: + b8:04:d4:d6:93:62:fd:af:f9:b4:1d:f4:96:3e:9b: + 9d:14:6d:1c:6c:23:ae:3d:c7:b4:cf:31:90:20:6a: + 80:99:62:7e:5c:e9:d5:d5:bd:59:4d:a3:d9:dc:e9: + fb:e8:7b:65:87:d5:f9:49:9e:be:0e:f3:a9:21:de: + 94:e8:54:fc:80:cf:da:e3:8f:9a:c6:4c:76:18:0e: + fe:ab Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: @@ -30,25 +40,37 @@ Certificate: X509v3 Extended Key Usage: OCSP Signing Signature Algorithm: sha256WithRSAEncryption - ae:47:b6:23:18:58:9a:d4:26:63:ad:41:c1:5d:3e:34:78:c3: - 80:29:f6:10:2b:95:3b:dc:ef:f2:b3:b8:4b:23:07:a0:11:e5: - 5c:b6:4e:7c:6d:d4:62:a2:ae:0f:fd:25:ef:bf:9a:1a:4a:d5: - 21:c1:9a:0f:57:e6:da:96:b5:e6:d9:02:1e:5b:98:e3:35:8b: - b6:0d:24:22:d3:35:a4:20:e7:42:ea:ba:11:72:a0:64:84:73: - 3c:ce:28:5b:b0:24:53:e9:47:a4:ee:07:85:b2:7a:ec:95:8f: - 5b:4b:02:b7:c9:3b:2f:e3:30:57:f9:0c:df:f8:a9:7c:4d:b5: - 0f:01 + 5d:f3:28:20:86:b7:cd:da:e2:e8:15:7a:97:52:79:63:69:0b: + 92:96:53:89:69:a5:79:19:d1:7e:75:71:9c:e4:33:26:99:cc: + b9:fe:28:1a:40:a7:5f:83:ee:51:cd:fc:e4:cf:71:45:90:ba: + 36:25:51:37:4c:19:9f:0e:fc:36:d5:64:05:8e:10:20:aa:53: + 1e:e5:49:64:ae:54:7d:f3:51:a1:31:af:5f:30:46:5c:d0:db: + 6d:fc:07:68:7e:63:26:24:82:52:cd:e0:3e:d1:fd:9b:e8:00: + 93:e7:94:8c:d6:14:51:23:82:3b:51:ac:39:3d:6f:81:c7:ff: + fb:7a:92:eb:ec:c4:7e:0b:e6:16:5c:31:5f:a1:84:28:b3:ad: + 75:8c:c3:c6:0c:b2:1a:23:4d:6c:a5:c7:e4:47:aa:5c:0d:ab: + 75:40:a2:bd:9a:76:cb:50:ff:18:8c:c1:c0:bd:02:dd:51:1d: + d3:64:43:2c:a6:a8:40:42:c5:90:59:4c:76:56:a8:28:4d:df: + 2d:8f:99:c3:2a:a9:f2:cc:5a:90:fc:29:6b:8e:f0:8e:89:79: + c1:b1:70:8b:2e:cb:98:d6:cf:46:ed:1a:c4:f7:32:78:5d:ca: + b1:0c:5a:05:99:45:f1:1a:80:48:1d:4f:83:7f:30:e9:ca:8f: + 83:ff:f3:0b -----BEGIN CERTIFICATE----- -MIICDjCCAXegAwIBAgIJANjT46bL48zPMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNjAx -MTIyMjM3NTBaFw0yMTAxMTEyMjM3NTBaMDIxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTETMBEGA1UEAwwKb2NzcC53MS5maTCBnzANBgkqhkiG9w0BAQEFAAOB -jQAwgYkCgYEAsl4vHecs9myrsBae+hIvskzII3toCHY4g5f1PwWsXdmBqc51kqG8 -lsbIAO4e1/DaitjnwNdCwyVi58dg+qiCTBvOc5qrjbP+PbZ/Af5ZZEJ1qAQYBy0i -ZCe58a8BtO2/puqReNGcMPVhN//5G/gWX2t3MvnX450M1cO5QxbwOsMCAwEAAaMv -MC0wCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwEwYDVR0lBAwwCgYIKwYBBQUHAwkw -DQYJKoZIhvcNAQELBQADgYEArke2IxhYmtQmY61BwV0+NHjDgCn2ECuVO9zv8rO4 -SyMHoBHlXLZOfG3UYqKuD/0l77+aGkrVIcGaD1fm2pa15tkCHluY4zWLtg0kItM1 -pCDnQuq6EXKgZIRzPM4oW7AkU+lHpO4HhbJ67JWPW0sCt8k7L+MwV/kM3/ipfE21 -DwE= +MIIDJTCCAg2gAwIBAgIJANjT46bL481nMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDMxNDAxMThaFw0yMTA1MDMxNDAxMThaMDIxCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTETMBEGA1UEAwwKb2NzcC53MS5maTCC +ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKcihV27OxwCmgFzqohjbqFD +M7X9Av4fyCMEi4xRUlvgzGJgKqq6iE9BOWv7NMCiencu4Vae78quZ9X5i1+rrofh +sBQjA61pS98rkXB1zb9lQBLQ6y+J8EEVG+1MDTqSlpH4zVQ4FetrRZ9ShX5OFatO +S+siwl2+/zZvQifYS8bhvvgIz6z9UTCi6IATAAW2BVVCC/oeQIRQCYwlNVQlRTmf +TnwK2cRKDBZOPmh/G63JUwhcuATU1pNi/a/5tB30lj6bnRRtHGwjrj3HtM8xkCBq +gJliflzp1dW9WU2j2dzp++h7ZYfV+Umevg7zqSHelOhU/IDP2uOPmsZMdhgO/qsC +AwEAAaMvMC0wCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAwEwYDVR0lBAwwCgYIKwYB +BQUHAwkwDQYJKoZIhvcNAQELBQADggEBAF3zKCCGt83a4ugVepdSeWNpC5KWU4lp +pXkZ0X51cZzkMyaZzLn+KBpAp1+D7lHN/OTPcUWQujYlUTdMGZ8O/DbVZAWOECCq +Ux7lSWSuVH3zUaExr18wRlzQ2238B2h+YyYkglLN4D7R/ZvoAJPnlIzWFFEjgjtR +rDk9b4HH//t6kuvsxH4L5hZcMV+hhCizrXWMw8YMshojTWylx+RHqlwNq3VAor2a +dstQ/xiMwcC9At1RHdNkQyymqEBCxZBZTHZWqChN3y2PmcMqqfLMWpD8KWuO8I6J +ecGxcIsuy5jWz0btGsT3MnhdyrEMWgWZRfEagEgdT4N/MOnKj4P/8ws= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/ocsp-server-cache.der b/tests/hwsim/auth_serv/ocsp-server-cache.der index 97696b7a4..a1661ef66 100644 Binary files a/tests/hwsim/auth_serv/ocsp-server-cache.der and b/tests/hwsim/auth_serv/ocsp-server-cache.der differ diff --git a/tests/hwsim/auth_serv/openssl2.cnf b/tests/hwsim/auth_serv/openssl2.cnf index 121982bea..5c67c4f04 100644 --- a/tests/hwsim/auth_serv/openssl2.cnf +++ b/tests/hwsim/auth_serv/openssl2.cnf @@ -52,7 +52,7 @@ commonName = supplied emailAddress = optional [ req ] -default_bits = 1024 +default_bits = 2048 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes diff --git a/tests/hwsim/auth_serv/rootCA/index.txt b/tests/hwsim/auth_serv/rootCA/index.txt index 8575df948..7f364381b 100644 --- a/tests/hwsim/auth_serv/rootCA/index.txt +++ b/tests/hwsim/auth_serv/rootCA/index.txt @@ -1,2 +1,6 @@ V 251222193736Z D8D3E3A6CBE3CCF3 unknown /C=FI/O=w1.fi/CN=Server Intermediate CA V 251222193736Z D8D3E3A6CBE3CCF4 unknown /C=FI/O=w1.fi/CN=User Intermediate CA +V 300503151922Z D8D3E3A6CBE3CCF5 unknown /C=FI/O=w1.fi/CN=Server Intermediate CA +V 300503151922Z D8D3E3A6CBE3CCF6 unknown /C=FI/O=w1.fi/CN=User Intermediate CA +V 300503152010Z D8D3E3A6CBE3CCF7 unknown /C=FI/O=w1.fi/CN=Server Intermediate CA +V 300503152010Z D8D3E3A6CBE3CCF8 unknown /C=FI/O=w1.fi/CN=User Intermediate CA diff --git a/tests/hwsim/auth_serv/rootCA/serial b/tests/hwsim/auth_serv/rootCA/serial index b0de706e5..4c71e29e2 100644 --- a/tests/hwsim/auth_serv/rootCA/serial +++ b/tests/hwsim/auth_serv/rootCA/serial @@ -1 +1 @@ -D8D3E3A6CBE3CCF5 +D8D3E3A6CBE3CCF9 diff --git a/tests/hwsim/auth_serv/server-certpol.pem b/tests/hwsim/auth_serv/server-certpol.pem index 2c8111388..d01454264 100644 --- a/tests/hwsim/auth_serv/server-certpol.pem +++ b/tests/hwsim/auth_serv/server-certpol.pem @@ -2,12 +2,12 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:d3:e3:a6:cb:e3:cd:23 + d8:d3:e3:a6:cb:e3:cd:63 Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Oct 4 13:02:23 2019 GMT - Not After : Oct 3 13:02:23 2020 GMT + Not Before: May 2 19:55:38 2020 GMT + Not After : May 2 19:55:38 2021 GMT Subject: C=FI, O=w1.fi, CN=server-policies.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -46,7 +46,7 @@ Certificate: X509v3 Subject Key Identifier: 3E:AD:0D:4D:7E:FA:A2:4A:D5:F5:31:EA:B6:B4:BF:83:B1:55:7E:C7 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -59,34 +59,44 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication Signature Algorithm: sha256WithRSAEncryption - 6d:bc:df:42:16:4b:a1:22:ba:a6:06:f3:70:ce:f7:37:7b:4d: - cf:e5:37:cc:5d:e4:b0:6c:09:09:b1:eb:32:3b:54:ab:95:41: - ef:6a:0b:d9:ab:0d:23:8f:39:cf:1e:93:a2:f4:65:a6:ae:e2: - 75:35:63:7b:8f:45:08:e3:00:5a:28:a1:26:e3:19:0f:bf:08: - 12:2d:c0:7b:72:2a:48:af:a6:a6:82:1d:b5:7a:f3:ac:6e:0b: - 85:47:7a:54:2c:25:a6:38:68:4d:5c:80:6b:79:0a:70:db:aa: - 8a:ee:10:61:2c:e5:14:26:e5:52:bc:a9:fc:88:a9:6e:f9:ab: - 09:cf + b8:ef:8e:09:f5:67:a3:d6:5c:92:d2:55:f8:f2:52:e4:cd:ea: + 87:a6:aa:42:73:b2:b4:30:d8:80:3f:aa:d5:f2:65:32:b9:88: + 7d:f1:b2:c2:c1:fe:17:c7:76:7e:d9:7b:4b:1a:87:dc:1f:f6: + 57:0d:8b:5f:2a:5d:e2:7f:f4:8d:39:3a:a4:9e:9d:f3:c1:58: + cf:04:fd:72:40:c2:9a:ef:98:b2:6a:67:86:27:2c:f6:e6:dd: + b1:a0:20:b1:c0:cf:fb:00:43:1f:6f:ac:b2:3f:02:a6:87:80: + 18:74:6b:0b:26:07:d3:7a:72:1c:c7:1d:a7:dc:13:cb:70:ac: + 24:2e:45:9c:bf:53:de:ea:eb:50:4a:60:87:26:8a:28:4e:16: + 76:91:b1:b3:e2:4d:66:fd:12:60:ed:24:59:f4:f9:47:59:d1: + 4c:6e:d1:9d:55:d4:72:d8:c4:da:2f:b4:73:20:d3:7e:f7:9f: + 6e:99:b8:06:1d:5f:8c:18:ab:a3:a8:fa:50:52:50:e5:2b:c9: + fa:1d:fe:f0:ce:33:19:d5:38:e6:ba:90:c9:5e:e6:67:60:e0: + 50:16:7c:4c:08:89:d2:e2:fe:bc:57:0f:ef:83:75:ec:1d:f3: + 10:07:ce:c2:d6:30:44:f2:ec:b9:78:71:c2:41:8d:78:e4:d6: + 67:42:d7:f5 -----BEGIN CERTIFICATE----- -MIIDxTCCAy6gAwIBAgIJANjT46bL480jMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xOTEw -MDQxMzAyMjNaFw0yMDEwMDMxMzAyMjNaMD0xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEeMBwGA1UEAwwVc2VydmVyLXBvbGljaWVzLncxLmZpMIIBojANBgkq -hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA0qbvm71gY6F1rUvTb1lehPpkoGQkC3hI -/I1miy9uHUQrrsNtlLrLozS+C05HjVvZmaaoBwmHVbI3fkdnXHRfLIN5sghHtOxP -73VYZ8ZYTE9owRgahE14I0iaFDhuW0oS64bE90w4rGOnYfqzZHyJDin3n/h1w++Q -wnGWoatp08J0E8/o9wmY7Tp51sRGSZN4Oxalqd3w671Ep9xOzvenyT94CIsFxhcu -7t8RoPf1WIB2wjTvuXi+xFy+X17Xt82jEsTjdvxkhWRla9pcyThQOYly5SDvuQvM -MiY8eV5KjXiNat1zOshCJ0MN3QUfvITfVi1+mFCei3iw5/2oOQdXBRL8AO+J8D8D -9pNbsERXYWFHBWzEFphhuJMyRTn7u447hxhfOgdX0ZiJHYW3XuobUXmUXNj6vbp1 -AAPj9APNXNsWoay39JN+7Jqw5pxOXTy6ATLMcMpJPJL+0oiBndv0u4D+74lQ6oCV -vcT6KNjAhmE315krjrkGeJoIRBfaGTWXAgMBAAGjgdYwgdMwCQYDVR0TBAIwADAd -BgNVHQ4EFgQUPq0NTX76okrV9THqtrS/g7FVfscwHwYDVR0jBBgwFoAUuJLe/YoY -szDDn1XzM120yCmKQRQwNQYIKwYBBQUHAQEEKTAnMCUGCCsGAQUFBzABhhlodHRw -Oi8vc2VydmVyLncxLmZpOjg4ODgvMCAGA1UdEQQZMBeCFXNlcnZlci1wb2xpY2ll -cy53MS5maTAYBgNVHSAEETAPMA0GCysGAQQBgr5oAQMBMBMGA1UdJQQMMAoGCCsG -AQUFBwMBMA0GCSqGSIb3DQEBCwUAA4GBAG2830IWS6EiuqYG83DO9zd7Tc/lN8xd -5LBsCQmx6zI7VKuVQe9qC9mrDSOPOc8ek6L0Zaau4nU1Y3uPRQjjAFoooSbjGQ+/ -CBItwHtyKkivpqaCHbV686xuC4VHelQsJaY4aE1cgGt5CnDbqoruEGEs5RQm5VK8 -qfyIqW75qwnP +MIIEWDCCA0CgAwIBAgIJANjT46bL481jMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDIxOTU1MzhaFw0yMTA1MDIxOTU1MzhaMD0xCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEeMBwGA1UEAwwVc2VydmVyLXBvbGlj +aWVzLncxLmZpMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA0qbvm71g +Y6F1rUvTb1lehPpkoGQkC3hI/I1miy9uHUQrrsNtlLrLozS+C05HjVvZmaaoBwmH +VbI3fkdnXHRfLIN5sghHtOxP73VYZ8ZYTE9owRgahE14I0iaFDhuW0oS64bE90w4 +rGOnYfqzZHyJDin3n/h1w++QwnGWoatp08J0E8/o9wmY7Tp51sRGSZN4Oxalqd3w +671Ep9xOzvenyT94CIsFxhcu7t8RoPf1WIB2wjTvuXi+xFy+X17Xt82jEsTjdvxk +hWRla9pcyThQOYly5SDvuQvMMiY8eV5KjXiNat1zOshCJ0MN3QUfvITfVi1+mFCe +i3iw5/2oOQdXBRL8AO+J8D8D9pNbsERXYWFHBWzEFphhuJMyRTn7u447hxhfOgdX +0ZiJHYW3XuobUXmUXNj6vbp1AAPj9APNXNsWoay39JN+7Jqw5pxOXTy6ATLMcMpJ +PJL+0oiBndv0u4D+74lQ6oCVvcT6KNjAhmE315krjrkGeJoIRBfaGTWXAgMBAAGj +gdYwgdMwCQYDVR0TBAIwADAdBgNVHQ4EFgQUPq0NTX76okrV9THqtrS/g7FVfscw +HwYDVR0jBBgwFoAUpP25ORuBs6rriB3Ugam1EXDMp+EwNQYIKwYBBQUHAQEEKTAn +MCUGCCsGAQUFBzABhhlodHRwOi8vc2VydmVyLncxLmZpOjg4ODgvMCAGA1UdEQQZ +MBeCFXNlcnZlci1wb2xpY2llcy53MS5maTAYBgNVHSAEETAPMA0GCysGAQQBgr5o +AQMBMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IBAQC4744J +9Wej1lyS0lX48lLkzeqHpqpCc7K0MNiAP6rV8mUyuYh98bLCwf4Xx3Z+2XtLGofc +H/ZXDYtfKl3if/SNOTqknp3zwVjPBP1yQMKa75iyameGJyz25t2xoCCxwM/7AEMf +b6yyPwKmh4AYdGsLJgfTenIcxx2n3BPLcKwkLkWcv1Pe6utQSmCHJoooThZ2kbGz +4k1m/RJg7SRZ9PlHWdFMbtGdVdRy2MTaL7RzINN+959umbgGHV+MGKujqPpQUlDl +K8n6Hf7wzjMZ1TjmupDJXuZnYOBQFnxMCInS4v68Vw/vg3XsHfMQB87C1jBE8uy5 +eHHCQY145NZnQtf1 -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server-certpol2.pem b/tests/hwsim/auth_serv/server-certpol2.pem index d96af29e1..92c853da2 100644 --- a/tests/hwsim/auth_serv/server-certpol2.pem +++ b/tests/hwsim/auth_serv/server-certpol2.pem @@ -2,12 +2,12 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:d3:e3:a6:cb:e3:cd:24 + d8:d3:e3:a6:cb:e3:cd:64 Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Oct 4 13:02:23 2019 GMT - Not After : Oct 3 13:02:23 2020 GMT + Not Before: May 2 19:55:38 2020 GMT + Not After : May 2 19:55:38 2021 GMT Subject: C=FI, O=w1.fi, CN=server-policies2.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -46,7 +46,7 @@ Certificate: X509v3 Subject Key Identifier: 4E:01:8B:7E:C2:77:94:E1:68:B3:C4:29:35:24:05:0B:DE:84:4A:89 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -59,34 +59,44 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication Signature Algorithm: sha256WithRSAEncryption - 2c:96:45:a3:b5:47:2d:b8:0e:f9:e2:d8:5d:a5:0c:99:cb:3f: - 82:e8:81:2a:ec:c8:82:e2:c4:0a:16:b8:19:87:7d:b8:bb:e8: - e6:3c:bc:24:63:f0:82:98:23:1b:eb:39:89:01:b6:d0:e2:e0: - 53:67:14:a3:34:76:af:ef:4a:7e:50:bb:be:9b:64:14:dc:04: - 27:08:d2:9e:ef:16:2e:33:c1:fa:8a:29:0b:78:9e:e4:4f:c4: - 14:8b:cd:fb:cd:98:2c:d9:f9:66:e1:1a:25:80:b9:c7:53:84: - 80:b6:40:88:09:6a:1f:04:1c:fa:b7:c2:7c:90:8e:bc:da:84: - b3:e1 + 7d:38:98:e6:21:03:e4:1a:44:08:91:ca:21:31:5c:97:66:74: + 4c:0a:84:21:83:92:22:63:53:8d:06:1f:48:62:c1:e3:ce:e9: + 74:2a:63:0b:2b:f9:b5:d0:63:37:39:4c:b4:29:9e:98:49:48: + 1f:cd:bc:28:5f:81:56:ee:d9:d9:f7:51:6b:31:62:3a:a4:59: + 98:f3:18:3d:f9:c1:d8:71:6d:85:e1:67:0e:d6:cc:ab:61:22: + 46:f1:38:11:53:74:41:44:22:63:ac:e7:6b:12:b6:39:20:7f: + fe:e2:c7:aa:e6:80:64:d7:24:92:4e:79:fa:9d:41:75:45:30: + 4b:2b:ce:d9:b0:38:25:79:81:b3:c4:4b:60:a1:24:9f:ad:c7: + 37:b9:44:d5:02:7c:2a:05:7f:d3:f1:76:21:6a:67:d7:a9:ab: + e0:3e:4c:90:30:28:8a:75:58:ae:6a:98:39:b6:6c:f6:eb:9f: + c8:24:11:a3:33:0f:aa:30:05:23:ab:1f:4f:f4:55:f3:b8:6b: + c5:dc:dc:32:15:58:fd:cc:cf:ba:f5:9a:1b:4e:58:68:85:b7: + eb:b0:db:e9:a9:87:f9:b0:4e:c9:43:79:26:97:75:ff:d4:55: + 01:f7:c6:f5:21:56:8b:f7:f3:80:a2:f4:3f:50:2a:e3:60:52: + b6:5c:83:14 -----BEGIN CERTIFICATE----- -MIIDxzCCAzCgAwIBAgIJANjT46bL480kMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xOTEw -MDQxMzAyMjNaFw0yMDEwMDMxMzAyMjNaMD4xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEfMB0GA1UEAwwWc2VydmVyLXBvbGljaWVzMi53MS5maTCCAaIwDQYJ -KoZIhvcNAQEBBQADggGPADCCAYoCggGBAOZQ0SgFJ2zUQtNCx8xTqWvCo6sgbxc0 -neQdMdDEaGVC1ei9qrjk6fbuLnXNaoz2jqqvbHzrNVBVscKz+KfQHqMzJmhAIBN0 -CIfvtjrxfz71f5NEdDeLw4mnul9COUoiIEBmxm93z1Q/BWHeq3H6n3htl0roYKAR -qmy6nURlGOjgj9Hf2pWrQSxjZfZCQuYfQqQcdCBJ9NSSDuO+O1X9OGh0OuTfmiuV -v+nROIsWJCA127jQFTAuL2okueHp57a1veYPWd3flZyrA7TFQoFIYcw8BheFY24o -y9eI0c5Ax/9hUay7uiPJQqd9Jw0eU5DPIj9X9f8aBQycehv74kdfRcvuiKWgVHGD -99PTxbyyfoWnsRrPkcuLObp8LJ2yxXnD4IBzBjBPXYFS4r9DVYVdZMSXrOktfjC1 -4VJQUwysJI57oleN/7EFuiMzpgijtDhC9lzZvF11lYL/TZrbVi8bONJRBSyQYvGO -TO7qG66qU3SFusbDwkswveAuyKx+JcwyXwIDAQABo4HXMIHUMAkGA1UdEwQCMAAw -HQYDVR0OBBYEFE4Bi37Cd5ThaLPEKTUkBQvehEqJMB8GA1UdIwQYMBaAFLiS3v2K -GLMww59V8zNdtMgpikEUMDUGCCsGAQUFBwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0 -cDovL3NlcnZlci53MS5maTo4ODg4LzAhBgNVHREEGjAYghZzZXJ2ZXItcG9saWNp -ZXMyLncxLmZpMBgGA1UdIAQRMA8wDQYLKwYBBAGCvmgBAwIwEwYDVR0lBAwwCgYI -KwYBBQUHAwEwDQYJKoZIhvcNAQELBQADgYEALJZFo7VHLbgO+eLYXaUMmcs/guiB -KuzIguLECha4GYd9uLvo5jy8JGPwgpgjG+s5iQG20OLgU2cUozR2r+9KflC7vptk -FNwEJwjSnu8WLjPB+oopC3ie5E/EFIvN+82YLNn5ZuEaJYC5x1OEgLZAiAlqHwQc -+rfCfJCOvNqEs+E= +MIIEWjCCA0KgAwIBAgIJANjT46bL481kMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDIxOTU1MzhaFw0yMTA1MDIxOTU1MzhaMD4xCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEfMB0GA1UEAwwWc2VydmVyLXBvbGlj +aWVzMi53MS5maTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAOZQ0SgF +J2zUQtNCx8xTqWvCo6sgbxc0neQdMdDEaGVC1ei9qrjk6fbuLnXNaoz2jqqvbHzr +NVBVscKz+KfQHqMzJmhAIBN0CIfvtjrxfz71f5NEdDeLw4mnul9COUoiIEBmxm93 +z1Q/BWHeq3H6n3htl0roYKARqmy6nURlGOjgj9Hf2pWrQSxjZfZCQuYfQqQcdCBJ +9NSSDuO+O1X9OGh0OuTfmiuVv+nROIsWJCA127jQFTAuL2okueHp57a1veYPWd3f +lZyrA7TFQoFIYcw8BheFY24oy9eI0c5Ax/9hUay7uiPJQqd9Jw0eU5DPIj9X9f8a +BQycehv74kdfRcvuiKWgVHGD99PTxbyyfoWnsRrPkcuLObp8LJ2yxXnD4IBzBjBP +XYFS4r9DVYVdZMSXrOktfjC14VJQUwysJI57oleN/7EFuiMzpgijtDhC9lzZvF11 +lYL/TZrbVi8bONJRBSyQYvGOTO7qG66qU3SFusbDwkswveAuyKx+JcwyXwIDAQAB +o4HXMIHUMAkGA1UdEwQCMAAwHQYDVR0OBBYEFE4Bi37Cd5ThaLPEKTUkBQvehEqJ +MB8GA1UdIwQYMBaAFKT9uTkbgbOq64gd1IGptRFwzKfhMDUGCCsGAQUFBwEBBCkw +JzAlBggrBgEFBQcwAYYZaHR0cDovL3NlcnZlci53MS5maTo4ODg4LzAhBgNVHREE +GjAYghZzZXJ2ZXItcG9saWNpZXMyLncxLmZpMBgGA1UdIAQRMA8wDQYLKwYBBAGC +vmgBAwIwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAH04 +mOYhA+QaRAiRyiExXJdmdEwKhCGDkiJjU40GH0hiwePO6XQqYwsr+bXQYzc5TLQp +nphJSB/NvChfgVbu2dn3UWsxYjqkWZjzGD35wdhxbYXhZw7WzKthIkbxOBFTdEFE +ImOs52sStjkgf/7ix6rmgGTXJJJOefqdQXVFMEsrztmwOCV5gbPES2ChJJ+txze5 +RNUCfCoFf9PxdiFqZ9epq+A+TJAwKIp1WK5qmDm2bPbrn8gkEaMzD6owBSOrH0/0 +VfO4a8Xc3DIVWP3Mz7r1mhtOWGiFt+uw2+mph/mwTslDeSaXdf/UVQH3xvUhVov3 +84Ci9D9QKuNgUrZcgxQ= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server-eku-client-server.csr b/tests/hwsim/auth_serv/server-eku-client-server.csr index e4a7a856e..5546903e5 100644 --- a/tests/hwsim/auth_serv/server-eku-client-server.csr +++ b/tests/hwsim/auth_serv/server-eku-client-server.csr @@ -1,11 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIBhjCB8AIBADBHMQswCQYDVQQGEwJGSTEQMA4GA1UEBwwHVHV1c3VsYTEOMAwG -A1UECgwFdzEuZmkxFjAUBgNVBAMMDXNlcnZlcjYudzEuZmkwgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBAMowHv0TagIoUZoOqR5yfudayMsMfoqZgY0FswmwqYbn -rkT64Mfu8xi0MWXjBW9mTuPkhYGbR39ftRYrsFmRnMVV09PKLIHO8CeoVN4OT9jw -Eb0LEFY4Jt+pOpUVk6YW7dIetLXAqGGOrhAE/eYmykoNkEu5rMmU8rFrl2tgJOq9 -AgMBAAGgADANBgkqhkiG9w0BAQUFAAOBgQA9gLu0fMZobrP6pkMTQFB/e8iDxeEl -LlTqNoZ1hMJ5CQHHB/CLK5D0D+oGrheb/7WA9kT9aMnk1KVFHFmNb0rGMHMLHIWb -PBb7d1xEFskl/iB1VshJX0DhYhkgwxuQzPF3fQCJV+pUf7hOI0tzY4yXgLykO5Us -qzQNeSKKXD3XbQ== +MIICjDCCAXQCAQAwRzELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAM +BgNVBAoMBXcxLmZpMRYwFAYDVQQDDA1zZXJ2ZXI2LncxLmZpMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0CP0gBK+SmRNr5mvUu+N9XOaGigrkujUkCU+ +hUefycS5ejUkhC8eURZm06wx6vFjpEzqJvD6Ycef8nRpangJxcmJdNttuse2sfBh +H+86HNXG/JVdmzfWW8s3k1ntUPJqogFcniKvOjHZ7uszSZNORu6de4aG2isd+fOi +AX0NVRw7Z+nJ+7ypUkxKIYVoUC/kBcE/4LOjJdRsLmF8ndXak7sZ/uq/8sj53N5I +VOH+1LWUWj8sK4yxbO86sNIMLBN1YduXa/pr+Z33FKo1cthMC6FcCMWH1OSHHWsK +UB+1Dj+7NovG4L0eGuEc8zekkWVMQ7SezBthaAm9HqthvcGRcQIDAQABoAAwDQYJ +KoZIhvcNAQELBQADggEBABgknYle2ID7r8gu0VCYupOKsdU0CIfxqozbW2REuWnO +W5EYv/oma1ONr3DPr/pLfeCVxtqRLNBC4UAi6Pxsn4A8kxm93voZ2/9b+fvwfrqo +yKgo2X2+fn/k3IeRvKdq8o3frVzdBZmVv1irbrXeel7IRyjvG6nqwoT5jhCI4F8m +iAht0otWVPdyuIXmHsofB6wgkmFw8AqHIuKS2gl8zeByGkfO/bCFrv1G2rEacyjt +/pLaeI2VYZW5i+JvoAXSqAzV6xpc13Tts4MlQhSw8diE/NVsw7uBuJQaiE+vpgvm +1jmcmIttnkZmvkhvdW3P62OttNVGiyBfq/GVPhOfeKE= -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/server-eku-client-server.key b/tests/hwsim/auth_serv/server-eku-client-server.key index ce2e5f237..42103e4ae 100644 --- a/tests/hwsim/auth_serv/server-eku-client-server.key +++ b/tests/hwsim/auth_serv/server-eku-client-server.key @@ -1,16 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMowHv0TagIoUZoO -qR5yfudayMsMfoqZgY0FswmwqYbnrkT64Mfu8xi0MWXjBW9mTuPkhYGbR39ftRYr -sFmRnMVV09PKLIHO8CeoVN4OT9jwEb0LEFY4Jt+pOpUVk6YW7dIetLXAqGGOrhAE -/eYmykoNkEu5rMmU8rFrl2tgJOq9AgMBAAECgYAdONdBvIyVwz4IBhZrUCEHTxe2 -QRgI8CbJOwmlXOMjnFiTn67dNqvr5h89mpIuh5rfVSf2k3rB7hM+IRJb36/Ik7qg -GdktPSEIK/ktUcfofVLaLn+ehG7vXhkkB6juBR7jaXDZRBPvFM+TCtirlaZ5sQ0u -TbSw7m9NcFD2APxgAQJBAPIoCxZCJGpMvh+5ta8EJQVQKhJeMWmDlUQvscKTauWb -aTz0z+OMBGpZH7DWCTww4+/3fjqZt/TURuPSh0ZcACUCQQDVvyPTO3h3R5fig/zV -NV8E0/dCYH6kwsFk0AUIRbMHdaN3sEHWszKG9nTNyPyHhDo8i9jguSjkb9MwdgR7 -BJC5AkBB6/bAs3bYXVXwqwyzvWwamy0o3O2UrNaIvnck4h7arMkkZ/zkFCzriqGe -8VWIRkL3A6ggadJzWwqFYL2kwMzlAkEAhfEdFgUyXCy09PEYwtKLFI9vZlzpf327 -it0ACksDAS2qnhoJZ+0rQH+4eiv0c0dc5wwLf+cHxP5+LOQHsr8NoQJAcsRe+KyX -G0TLKZg/J5E+zJMH6M19BZ4BC32UIMTJWe1xzp+9XrCWflagRJMJ+DOWtHzu/Opo -Ty4OiT0uZUxcMw== +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDQI/SAEr5KZE2v +ma9S7431c5oaKCuS6NSQJT6FR5/JxLl6NSSELx5RFmbTrDHq8WOkTOom8Pphx5/y +dGlqeAnFyYl02226x7ax8GEf7zoc1cb8lV2bN9ZbyzeTWe1Q8mqiAVyeIq86Mdnu +6zNJk05G7p17hobaKx3586IBfQ1VHDtn6cn7vKlSTEohhWhQL+QFwT/gs6Ml1Gwu +YXyd1dqTuxn+6r/yyPnc3khU4f7UtZRaPywrjLFs7zqw0gwsE3Vh25dr+mv5nfcU +qjVy2EwLoVwIxYfU5IcdawpQH7UOP7s2i8bgvR4a4RzzN6SRZUxDtJ7MG2FoCb0e +q2G9wZFxAgMBAAECggEAL7pO8p9Zq01c0wt2vJnZ/5LGn4DenQ1u0K75qy5FYcsO +jQtqmDUFyqpMYfV2bN11b9ODTfKsN4fDEaHIGnX0J7qTHozCmLX7Gsp4Ow5sUPhk +bL8De/hN2za6Q7u3Q3yTHxsY1do2PC36P2MHm7N/m5xT2GN8wMJqWUqYt6apS/6H +c2UkjhopRH17WhIEIvWLhZ6IYahRpaDk6zlYTwbVJ/0T/mmK/Wmpmr/aeSVkG980 +MQUHugdOrrkV8+WFxlzzpIRa+3XFmxXNOuhXemz23tS4JEBsD0gdesvoWuszqysd +1n+W5j+OpksiF1DFWSuMKFFqurd91yjOhAsM5ex1kQKBgQDnjTpvSBTMDGNGm8qo +9POjIqa/8zS0yzwYLB4/pzym5eaIEOAq+H0W+EU8h5zes3E1lGLKO/2iT3lWTxzo +E7Fq9I2AbzMSgyZiEJq6IfiLMRhh51sPTGX+KIjC44fdfofdTc2GNePsf/IP+JGy +DPv/8mU+j0heSwyLZJCSvoNdCwKBgQDmHe2z6MIb2Rze3vgJERIrTRfxyRjwKRUd +xI7QEe/fRjhlCNyzP9sQZzJFXNean4qNg0SOGy8+KjTgI+n9HxUTvLADxnVtey3I +G78JVu5QJ4onJ3iAlCSlY6exiY9ZQjI6akCC748t03WNLQXO6lUsopLZqOx8oP+M +84UFoNjA8wKBgERiTj6tQA8fHXat7gVGCmpEgpCv6AH4/6934BsWbfAwd4v5x+qI +5pCRFAmTV33h6u5S+3YUj4yPAhu+U6AqqLwYq22h6ahu+Tf/BWMxQzEAd936MMds +3bZZDELaZbbBdqiiIK+hXMXs53VWCNlXwljNop7+O/Y1HehQ8+2SvEMPAoGBAJhn +5//Iv46MHBfr2qC+oqb1F0+2nYKp4udlQCTETHc23bDkzq8VMrRJdL0FwXISCkSx +VN09Weu1LnHot1dCl8YLqRPHBAzvkSHAZqT74zhJB7Ho7WFTPHYha3YlIkC+m9+e +cX2GxfBW5bsLv5YMEz9NqS7pNz9PrhEfU9GndwdLAoGAJ4f7qIUTweLL+295Q/dx +lGlBzkTkfw0kiEEOgWwjXbox1NJnsfrneGvPgccTeMtimtkGk/vTUtIuo4EDwjJ7 +mcUnhXIgHGngx8bOzt4G3RGOLAaf1l+IcBhxqLJFhArDZYSVYMQ6vwwRuyXfO+I9 +4It3NqEusGrCV/ydOmKtXEg= -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/server-eku-client-server.pem b/tests/hwsim/auth_serv/server-eku-client-server.pem index 2d299aed4..b44f82c54 100644 --- a/tests/hwsim/auth_serv/server-eku-client-server.pem +++ b/tests/hwsim/auth_serv/server-eku-client-server.pem @@ -2,34 +2,43 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:d3:e3:a6:cb:e3:cd:22 + d8:d3:e3:a6:cb:e3:cd:62 Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Oct 4 13:02:23 2019 GMT - Not After : Oct 3 13:02:23 2020 GMT + Not Before: May 2 19:55:38 2020 GMT + Not After : May 2 19:55:38 2021 GMT Subject: C=FI, O=w1.fi, CN=server6.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:ca:30:1e:fd:13:6a:02:28:51:9a:0e:a9:1e:72: - 7e:e7:5a:c8:cb:0c:7e:8a:99:81:8d:05:b3:09:b0: - a9:86:e7:ae:44:fa:e0:c7:ee:f3:18:b4:31:65:e3: - 05:6f:66:4e:e3:e4:85:81:9b:47:7f:5f:b5:16:2b: - b0:59:91:9c:c5:55:d3:d3:ca:2c:81:ce:f0:27:a8: - 54:de:0e:4f:d8:f0:11:bd:0b:10:56:38:26:df:a9: - 3a:95:15:93:a6:16:ed:d2:1e:b4:b5:c0:a8:61:8e: - ae:10:04:fd:e6:26:ca:4a:0d:90:4b:b9:ac:c9:94: - f2:b1:6b:97:6b:60:24:ea:bd + 00:d0:23:f4:80:12:be:4a:64:4d:af:99:af:52:ef: + 8d:f5:73:9a:1a:28:2b:92:e8:d4:90:25:3e:85:47: + 9f:c9:c4:b9:7a:35:24:84:2f:1e:51:16:66:d3:ac: + 31:ea:f1:63:a4:4c:ea:26:f0:fa:61:c7:9f:f2:74: + 69:6a:78:09:c5:c9:89:74:db:6d:ba:c7:b6:b1:f0: + 61:1f:ef:3a:1c:d5:c6:fc:95:5d:9b:37:d6:5b:cb: + 37:93:59:ed:50:f2:6a:a2:01:5c:9e:22:af:3a:31: + d9:ee:eb:33:49:93:4e:46:ee:9d:7b:86:86:da:2b: + 1d:f9:f3:a2:01:7d:0d:55:1c:3b:67:e9:c9:fb:bc: + a9:52:4c:4a:21:85:68:50:2f:e4:05:c1:3f:e0:b3: + a3:25:d4:6c:2e:61:7c:9d:d5:da:93:bb:19:fe:ea: + bf:f2:c8:f9:dc:de:48:54:e1:fe:d4:b5:94:5a:3f: + 2c:2b:8c:b1:6c:ef:3a:b0:d2:0c:2c:13:75:61:db: + 97:6b:fa:6b:f9:9d:f7:14:aa:35:72:d8:4c:0b:a1: + 5c:08:c5:87:d4:e4:87:1d:6b:0a:50:1f:b5:0e:3f: + bb:36:8b:c6:e0:bd:1e:1a:e1:1c:f3:37:a4:91:65: + 4c:43:b4:9e:cc:1b:61:68:09:bd:1e:ab:61:bd:c1: + 91:71 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - C7:C6:EF:F5:61:D2:A0:08:81:6A:6B:44:2C:F5:72:F7:DA:DE:5B:B9 + AB:D2:88:CA:9C:44:26:89:2E:C0:B9:8D:46:DD:5C:69:02:9E:01:CB X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -37,27 +46,40 @@ Certificate: X509v3 Extended Key Usage: TLS Web Client Authentication, TLS Web Server Authentication Signature Algorithm: sha256WithRSAEncryption - 1c:47:3b:a1:09:82:7d:f8:84:e2:b4:0c:26:5b:bb:f2:9a:62: - 80:ae:8e:fa:c6:4d:4b:83:73:b9:b1:d4:f8:61:5b:bb:ff:00: - e4:86:a1:c9:9d:a2:99:e8:70:6b:41:81:4c:12:22:74:60:54: - 8c:34:e8:01:a3:d5:4d:47:11:ec:39:71:2b:dc:b4:dc:2b:5d: - 49:df:49:bf:ad:de:e6:e6:6a:76:06:74:a5:50:9c:bc:46:ce: - a4:4f:5c:f3:0c:bc:08:c5:f7:a8:aa:bf:4a:60:d6:a1:30:82: - 6f:94:f1:68:09:0d:d5:94:64:e5:3f:ee:be:5d:ce:5d:91:99: - 60:c2 + 5f:6e:13:f9:af:c4:47:4d:78:19:5e:d2:bb:21:55:c3:4b:64: + 42:94:fe:37:7b:3a:4a:fc:42:f1:fc:b3:c3:05:93:46:39:cd: + a3:40:c9:90:47:a2:6b:af:d8:21:a9:1e:11:02:c8:84:e2:b2: + 8b:52:ad:30:49:e7:80:16:98:d2:0c:01:56:c2:f5:6c:a4:98: + b0:a2:af:6c:e8:6e:6d:9b:31:21:22:91:51:81:e1:f0:0d:eb: + 97:96:98:58:84:b3:29:a6:8f:d2:b5:ce:37:a7:64:b8:7f:fb: + f7:15:3c:c0:c7:2a:7f:bb:50:67:a0:5b:55:65:5d:1f:0a:90: + 10:16:c1:93:cd:a3:ab:8b:4b:9a:f0:e2:e7:ac:e6:5a:fd:bf: + 46:37:92:3e:f7:f5:d8:57:87:c2:88:cc:b1:40:06:92:d5:f0: + f2:3d:c5:d0:fd:48:5c:bf:bf:5b:da:82:11:55:6d:95:17:f2: + 43:be:8e:e7:f5:0e:d3:b3:de:65:ea:8c:85:4b:bd:4d:93:f0: + 6f:8b:2f:0e:fb:9f:cb:65:e8:72:68:92:43:08:1d:3e:1f:5a: + e5:1c:5d:7e:16:06:04:23:9e:c0:82:8a:a6:33:66:c3:3f:2a: + ad:1a:5a:90:02:56:3a:e6:45:d9:f1:02:a5:cd:16:63:03:04: + 42:85:1c:49 -----BEGIN CERTIFICATE----- -MIIChzCCAfCgAwIBAgIJANjT46bL480iMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xOTEw -MDQxMzAyMjNaFw0yMDEwMDMxMzAyMjNaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNi53MS5maTCBnzANBgkqhkiG9w0BAQEF -AAOBjQAwgYkCgYEAyjAe/RNqAihRmg6pHnJ+51rIywx+ipmBjQWzCbCphueuRPrg -x+7zGLQxZeMFb2ZO4+SFgZtHf1+1FiuwWZGcxVXT08osgc7wJ6hU3g5P2PARvQsQ -Vjgm36k6lRWTphbt0h60tcCoYY6uEAT95ibKSg2QS7msyZTysWuXa2Ak6r0CAwEA -AaOBpDCBoTAJBgNVHRMEAjAAMB0GA1UdDgQWBBTHxu/1YdKgCIFqa0Qs9XL32t5b -uTAfBgNVHSMEGDAWgBS4kt79ihizMMOfVfMzXbTIKYpBFDA1BggrBgEFBQcBAQQp -MCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8wHQYDVR0l -BBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4GBABxHO6EJ -gn34hOK0DCZbu/KaYoCujvrGTUuDc7mx1PhhW7v/AOSGocmdopnocGtBgUwSInRg -VIw06AGj1U1HEew5cSvctNwrXUnfSb+t3ubmanYGdKVQnLxGzqRPXPMMvAjF96iq -v0pg1qEwgm+U8WgJDdWUZOU/7r5dzl2RmWDC +MIIDnjCCAoagAwIBAgIJANjT46bL481iMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDIxOTU1MzhaFw0yMTA1MDIxOTU1MzhaMDUxCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNi53MS5m +aTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAj9IASvkpkTa+Zr1Lv +jfVzmhooK5Lo1JAlPoVHn8nEuXo1JIQvHlEWZtOsMerxY6RM6ibw+mHHn/J0aWp4 +CcXJiXTbbbrHtrHwYR/vOhzVxvyVXZs31lvLN5NZ7VDyaqIBXJ4irzox2e7rM0mT +TkbunXuGhtorHfnzogF9DVUcO2fpyfu8qVJMSiGFaFAv5AXBP+CzoyXUbC5hfJ3V +2pO7Gf7qv/LI+dzeSFTh/tS1lFo/LCuMsWzvOrDSDCwTdWHbl2v6a/md9xSqNXLY +TAuhXAjFh9Tkhx1rClAftQ4/uzaLxuC9HhrhHPM3pJFlTEO0nswbYWgJvR6rYb3B +kXECAwEAAaOBpDCBoTAJBgNVHRMEAjAAMB0GA1UdDgQWBBSr0ojKnEQmiS7AuY1G +3VxpAp4ByzAfBgNVHSMEGDAWgBSk/bk5G4GzquuIHdSBqbURcMyn4TA1BggrBgEF +BQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8w +HQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4IB +AQBfbhP5r8RHTXgZXtK7IVXDS2RClP43ezpK/ELx/LPDBZNGOc2jQMmQR6Jrr9gh +qR4RAsiE4rKLUq0wSeeAFpjSDAFWwvVspJiwoq9s6G5tmzEhIpFRgeHwDeuXlphY +hLMppo/Stc43p2S4f/v3FTzAxyp/u1BnoFtVZV0fCpAQFsGTzaOri0ua8OLnrOZa +/b9GN5I+9/XYV4fCiMyxQAaS1fDyPcXQ/Uhcv79b2oIRVW2VF/JDvo7n9Q7Ts95l +6oyFS71Nk/Bviy8O+5/LZehyaJJDCB0+H1rlHF1+FgYEI57AgoqmM2bDPyqtGlqQ +AlY65kXZ8QKlzRZjAwRChRxJ -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server-eku-client.csr b/tests/hwsim/auth_serv/server-eku-client.csr index 72ab7903c..8fe7071e1 100644 --- a/tests/hwsim/auth_serv/server-eku-client.csr +++ b/tests/hwsim/auth_serv/server-eku-client.csr @@ -1,11 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIBhjCB8AIBADBHMQswCQYDVQQGEwJGSTEQMA4GA1UEBwwHVHV1c3VsYTEOMAwG -A1UECgwFdzEuZmkxFjAUBgNVBAMMDXNlcnZlcjUudzEuZmkwgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBAKOZ6eLhF2A7cDQadFxG47i9u6rJ8+77EjCgacN0OIA6 -uiNSx8Fqz7rdQePSaTWkpmBsMR+FvVZsewljzadRa4RAkHd+l2h7OLXEFTt0NzQo -unri14RTeHZNFre43wly54cmdCwEysXOKfW0ztso60VHQo/tiFqjI0mbe7w54QFT -AgMBAAGgADANBgkqhkiG9w0BAQUFAAOBgQBtsWMoDQr3miJluL8rnbsu7t7HhGn8 -BBJ393C6P8UHYJTlfMPfg+H2zfyrP68EV76lym5jmNOltZUv14joZjpYX9VOT+5r -e4wq697O7BDG7aBt2BR2BgYCMQiiAXisL0bOs6crYxapqCh3tyzkhxwOyqdqRO7R -+1BujmtweBGlBQ== +MIICjDCCAXQCAQAwRzELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAM +BgNVBAoMBXcxLmZpMRYwFAYDVQQDDA1zZXJ2ZXI1LncxLmZpMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEApZRggLjIYRiMAp3czMR00Re1O0ecOA87knT7 +6idFRIqaKk0QJY53zhoJyXMZ/txwNl6M+o9MhLv3cuSUT/xHKn2JkqMrWmmcyFoQ +OTJhfQp4GbQ266xM1q91ABROFS9fg+5i9ax7DIG6ogg2e/DvYzFi+4amz9o2g0SN +dSi25BDzMt2KbFvuT/EeUwsTfMe8954ygB5jPpJ1L8UhXvAqrOI05BeyNPfoKhKK +IbgD57bY+DK1/nFFUpjeuT1B9ZCldoPBGMpQXSxSi25Pp1u72OMUJXDe0cedWc8k +Rsf1bm+DZu0bHT5RBJRnZN9RIjzA4SQKN2rcaov9RVuWLQOsYwIDAQABoAAwDQYJ +KoZIhvcNAQELBQADggEBAGDFw8louhTAswtYHa+aFvsSEB209lYFdHxn3wohbK1r +q3IPcuTiQdZR2jEllGVaXZC6eAkYO8iD+NL/iCteUivY6Jqrd5cM0IAzPLuNe89O +SSnPqUep59LObZUAsW/KaOB75xsLbm68fG2NmwOBB+8ZCRvQowcbY6nEAgaFM46V +UxOHr3ZdluhAyVIikmZLmXEbv5OaXZfc3PiifJIDgAmMf9ePjm6QZEQJ5RdBxlWT +IhU0rz9haagA13hXWurUCo8gWZoQqqCinjxLu0dV62kVCgq5Bk8HE4gvswJvCqME +TKEpPJBjmKGTeU1BbFWy6nrirsCVPybj841pMQkSWHY= -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/server-eku-client.key b/tests/hwsim/auth_serv/server-eku-client.key index f2a99cd1b..a43976ccd 100644 --- a/tests/hwsim/auth_serv/server-eku-client.key +++ b/tests/hwsim/auth_serv/server-eku-client.key @@ -1,16 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKOZ6eLhF2A7cDQa -dFxG47i9u6rJ8+77EjCgacN0OIA6uiNSx8Fqz7rdQePSaTWkpmBsMR+FvVZsewlj -zadRa4RAkHd+l2h7OLXEFTt0NzQounri14RTeHZNFre43wly54cmdCwEysXOKfW0 -ztso60VHQo/tiFqjI0mbe7w54QFTAgMBAAECgYAngwCtvtc6cqCCtPDtaGGPOKOe -d+/mA9U80UE551POBGD4LwH3gKhy5QUI1MR8JCvalca3akF0IfcFKYl9o3hnsZ73 -3wGzxM8BEf9wEVtVC2CTRVoIupleaEk3j8dgaUs/O54WkmAoHF1avXAMSGOUDxCO -Ggpn2tei78Csdj78IQJBANF7a7RaJsXh6xMI7hlrVrUsIbBvsBo1wbbGCwNRvgzL -I1mq1O+Go7Aao0pDK7sOUa86j6ECZ5pzqcdPaF22tJ8CQQDH7kTy6ERBbLFxs/Wd -YLDEh1GIGyGW10tuJTOl2R1TKSBXRzPAeI+jcC+AC00238p4MO899WOVeLvaERZa -IuLNAkAtlxXGp4Qett9JQj1HbPPu9A7U7km+OorRM2K8MzMQZ7lmz2YORxgiwHlf -NSU0TZZ7c1xE51gS5i9CAEcvdg7zAkAKIZfa20xCKHjhcyYaIIE0pErMY9uS4jwP -S9FPMS5cPXRHF/OWaEWXGaM+kNQL2NFQv+IPuLSgKWsThNQmIyhtAkEAiQq1HdN7 -3l8YhUuJtxg7nrh2s0V4UcSNOZxVf/85AKrTu1IfjdwmXFeoRB/y9Ef4h1bcXgzj -clIVhie7r0JNLw== +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCllGCAuMhhGIwC +ndzMxHTRF7U7R5w4DzuSdPvqJ0VEipoqTRAljnfOGgnJcxn+3HA2Xoz6j0yEu/dy +5JRP/EcqfYmSoytaaZzIWhA5MmF9CngZtDbrrEzWr3UAFE4VL1+D7mL1rHsMgbqi +CDZ78O9jMWL7hqbP2jaDRI11KLbkEPMy3YpsW+5P8R5TCxN8x7z3njKAHmM+knUv +xSFe8Cqs4jTkF7I09+gqEoohuAPnttj4MrX+cUVSmN65PUH1kKV2g8EYylBdLFKL +bk+nW7vY4xQlcN7Rx51ZzyRGx/Vub4Nm7RsdPlEElGdk31EiPMDhJAo3atxqi/1F +W5YtA6xjAgMBAAECggEAJ+QYX8qk0+ejC5pWsKp/7kQE8JQvCb55vq4aZu4xHPM7 +cwd/5VxudqQFSZhGYgVfr2mWE2NkrvHOCssRBDgmORFnjIFtF2osUISKNg1yOTrF +doPZW2v2Ux6QVIWPzkDMhS9wffmg54F1okXSQofoVIB4dVqaY6cRzQw9/ETj0wvz +JwSstS76VbTZSzXl/IMMiIlGLq2o4SVmTDgK5Uz8ouOIIzoVG4tQCjtAPCfu1pG9 +VYTCfE1gnGFx1bl3p1yoh468h1PqyYqDgo9heyU+aYk21v/Rm0ARj2TSkJcSF5Cv +Y3JUg1oaIMw7HxXEnkw+L3sqy9alGkJ33pbOAzva6QKBgQDO9H7ToPJysx2cO2/a +Jk7OvoyQ0AMNG7lNS4crG9SvL0SbxfDdif9yaDlasT3T18uTMuRJRo6vF8v820LY +HIdmBT6FxC+zwBRKnXMFtSrZIsl4zpOeHW2pOTM4So92K9NlSGOogQulzQyE8yeL +kHAJmnAevUMyxgQ/S8xpTJrzfQKBgQDM0blWZ91B4VvqP7MzdjPHI1yXt5miEY9P +ltTtTnmjFjvLweheoyYPW64tvxyRueEPNQB39BbYax3Zweg7TPng/lOMEwMG40dT +a4LBMK74r0OLvPfds6jSGnENmyNkUZhTCf+hgXOMeiXGqjFAIPQoA+23tNNaDPRG +emIjx69lXwKBgE4QmfqYPnwXpna1UObYBmgkJn/FhzEdoRNQByeystJ2IQola0sV +796nA+N68hiD0Q2wZ75gOBhCALdbueYtNMG9/qyUqW3DaaQPqkCf6w7G+Xpxaet9 +rEzl/7UfIuhvdalB2h3It60OIMfRtLwHesuUjvB5ceyoFxgNLokV1Wk9AoGANMRD +L1OK2RIqD+thS3zEUiV2EVAnsG09so91Q73X8IAl35SRPPBjOcmw0fBOd+yfYr+Q +41ZrHE5cXmFqZvyp06Ex/QBY40licsdb5FGagk8E49dHNEK414ggYBT7xTiQObR1 +uzIShrphSRFHpvHWdQiuEYnweV6lABM/fWBQe5kCgYBJWEJSAkyp8L4TIlt41ctK +MSjXuSwO1ktUYxQwIRZn/qcTxAAZLeE4Ow50Eoz7qtdMpn9/UdogpVpeZ9ZbSFSh +2OD15rQJWVWs9ftgV8Ny3LzCdchmIw4/pRFMkK1ECog6F2WecwYUspEWgfGTy50V +JyZlR6lQlgsLo0xLZJYyYA== -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/server-eku-client.pem b/tests/hwsim/auth_serv/server-eku-client.pem index 5e39ec0c9..2e6afa287 100644 --- a/tests/hwsim/auth_serv/server-eku-client.pem +++ b/tests/hwsim/auth_serv/server-eku-client.pem @@ -2,34 +2,43 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:d3:e3:a6:cb:e3:cd:21 + d8:d3:e3:a6:cb:e3:cd:61 Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Oct 4 13:02:23 2019 GMT - Not After : Oct 3 13:02:23 2020 GMT + Not Before: May 2 19:55:38 2020 GMT + Not After : May 2 19:55:38 2021 GMT Subject: C=FI, O=w1.fi, CN=server5.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:a3:99:e9:e2:e1:17:60:3b:70:34:1a:74:5c:46: - e3:b8:bd:bb:aa:c9:f3:ee:fb:12:30:a0:69:c3:74: - 38:80:3a:ba:23:52:c7:c1:6a:cf:ba:dd:41:e3:d2: - 69:35:a4:a6:60:6c:31:1f:85:bd:56:6c:7b:09:63: - cd:a7:51:6b:84:40:90:77:7e:97:68:7b:38:b5:c4: - 15:3b:74:37:34:28:ba:7a:e2:d7:84:53:78:76:4d: - 16:b7:b8:df:09:72:e7:87:26:74:2c:04:ca:c5:ce: - 29:f5:b4:ce:db:28:eb:45:47:42:8f:ed:88:5a:a3: - 23:49:9b:7b:bc:39:e1:01:53 + 00:a5:94:60:80:b8:c8:61:18:8c:02:9d:dc:cc:c4: + 74:d1:17:b5:3b:47:9c:38:0f:3b:92:74:fb:ea:27: + 45:44:8a:9a:2a:4d:10:25:8e:77:ce:1a:09:c9:73: + 19:fe:dc:70:36:5e:8c:fa:8f:4c:84:bb:f7:72:e4: + 94:4f:fc:47:2a:7d:89:92:a3:2b:5a:69:9c:c8:5a: + 10:39:32:61:7d:0a:78:19:b4:36:eb:ac:4c:d6:af: + 75:00:14:4e:15:2f:5f:83:ee:62:f5:ac:7b:0c:81: + ba:a2:08:36:7b:f0:ef:63:31:62:fb:86:a6:cf:da: + 36:83:44:8d:75:28:b6:e4:10:f3:32:dd:8a:6c:5b: + ee:4f:f1:1e:53:0b:13:7c:c7:bc:f7:9e:32:80:1e: + 63:3e:92:75:2f:c5:21:5e:f0:2a:ac:e2:34:e4:17: + b2:34:f7:e8:2a:12:8a:21:b8:03:e7:b6:d8:f8:32: + b5:fe:71:45:52:98:de:b9:3d:41:f5:90:a5:76:83: + c1:18:ca:50:5d:2c:52:8b:6e:4f:a7:5b:bb:d8:e3: + 14:25:70:de:d1:c7:9d:59:cf:24:46:c7:f5:6e:6f: + 83:66:ed:1b:1d:3e:51:04:94:67:64:df:51:22:3c: + c0:e1:24:0a:37:6a:dc:6a:8b:fd:45:5b:96:2d:03: + ac:63 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - 33:16:9D:3B:17:15:82:2B:34:6E:38:E8:CC:22:BF:49:A7:5E:2A:2B + 32:9F:9F:30:24:73:73:CB:8D:53:3A:80:23:EB:5B:5D:4C:DD:06:01 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -37,27 +46,40 @@ Certificate: X509v3 Extended Key Usage: TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption - 96:f9:cb:e1:73:60:40:d6:85:d1:ed:a5:14:fc:c1:98:15:2a: - bd:02:dd:54:bf:69:ac:9d:b7:af:5c:62:b0:85:32:a2:04:27: - d4:98:98:d0:99:53:a9:03:88:33:fa:41:7f:a2:e8:ca:7f:6d: - f0:ad:7a:b2:49:1c:be:43:5a:dd:58:1b:bc:32:ae:86:10:00: - 30:44:f8:44:85:34:dc:fb:05:a3:8a:ab:f4:48:6e:f3:c4:6e: - c7:a0:39:82:bd:15:3b:0b:ea:78:10:2d:43:6c:73:c0:60:f8: - 1c:ad:c1:bf:df:6e:05:b9:db:3f:0c:3e:72:23:bd:56:f6:2a: - a5:e6 + 22:02:38:3d:90:2f:5d:54:b9:36:61:fd:29:40:c0:88:5d:eb: + 63:ec:b3:6d:9b:55:8f:10:6b:b7:4b:8a:3f:89:79:fa:52:87: + 8d:91:3b:2e:ee:84:ae:f8:2d:8e:1d:35:72:cd:b8:7d:9d:98: + d3:88:9d:05:c7:85:e7:1a:29:4d:cb:00:da:a3:21:a0:f5:f3: + 52:f5:80:88:cb:2a:4f:d9:9b:56:c0:37:13:61:74:64:61:fb: + 8c:25:18:9c:96:e2:f8:bb:e2:48:60:e3:12:d8:a9:d9:9e:93: + e8:cd:46:f5:eb:b3:17:62:66:d1:5d:ea:c2:09:d1:7a:34:d2: + e0:88:1d:7f:6f:71:25:70:50:d8:51:93:61:8e:70:da:c2:ba: + f0:44:81:be:81:54:d6:3c:da:a6:54:62:40:bd:d1:2e:ce:1c: + dd:29:49:ba:b5:12:7e:42:64:54:b2:99:93:60:67:6e:1a:63: + 4b:da:b4:96:28:90:81:c4:28:05:28:64:ff:c6:7a:b3:8c:68: + 12:e3:28:64:00:82:88:bc:75:46:d2:e7:f9:0a:93:4c:5d:c8: + 99:27:4c:40:65:0d:ec:b2:86:ea:76:e2:28:c5:77:6b:3d:fc: + 91:30:89:0a:0b:e0:d4:59:cf:30:de:5f:f6:50:15:5a:40:01: + e2:a5:39:cf -----BEGIN CERTIFICATE----- -MIICfTCCAeagAwIBAgIJANjT46bL480hMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xOTEw -MDQxMzAyMjNaFw0yMDEwMDMxMzAyMjNaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNS53MS5maTCBnzANBgkqhkiG9w0BAQEF -AAOBjQAwgYkCgYEAo5np4uEXYDtwNBp0XEbjuL27qsnz7vsSMKBpw3Q4gDq6I1LH -wWrPut1B49JpNaSmYGwxH4W9Vmx7CWPNp1FrhECQd36XaHs4tcQVO3Q3NCi6euLX -hFN4dk0Wt7jfCXLnhyZ0LATKxc4p9bTO2yjrRUdCj+2IWqMjSZt7vDnhAVMCAwEA -AaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQzFp07FxWCKzRuOOjMIr9Jp14q -KzAfBgNVHSMEGDAWgBS4kt79ihizMMOfVfMzXbTIKYpBFDA1BggrBgEFBQcBAQQp -MCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8wEwYDVR0l -BAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADgYEAlvnL4XNgQNaF0e2lFPzB -mBUqvQLdVL9prJ23r1xisIUyogQn1JiY0JlTqQOIM/pBf6Loyn9t8K16skkcvkNa -3VgbvDKuhhAAMET4RIU03PsFo4qr9Ehu88Rux6A5gr0VOwvqeBAtQ2xzwGD4HK3B -v99uBbnbPww+ciO9VvYqpeY= +MIIDlDCCAnygAwIBAgIJANjT46bL481hMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDIxOTU1MzhaFw0yMTA1MDIxOTU1MzhaMDUxCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNS53MS5m +aTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKWUYIC4yGEYjAKd3MzE +dNEXtTtHnDgPO5J0++onRUSKmipNECWOd84aCclzGf7ccDZejPqPTIS793LklE/8 +Ryp9iZKjK1ppnMhaEDkyYX0KeBm0NuusTNavdQAUThUvX4PuYvWsewyBuqIINnvw +72MxYvuGps/aNoNEjXUotuQQ8zLdimxb7k/xHlMLE3zHvPeeMoAeYz6SdS/FIV7w +KqziNOQXsjT36CoSiiG4A+e22Pgytf5xRVKY3rk9QfWQpXaDwRjKUF0sUotuT6db +u9jjFCVw3tHHnVnPJEbH9W5vg2btGx0+UQSUZ2TfUSI8wOEkCjdq3GqL/UVbli0D +rGMCAwEAAaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQyn58wJHNzy41TOoAj +61tdTN0GATAfBgNVHSMEGDAWgBSk/bk5G4GzquuIHdSBqbURcMyn4TA1BggrBgEF +BQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8w +EwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBACICOD2QL11U +uTZh/SlAwIhd62Pss22bVY8Qa7dLij+JefpSh42ROy7uhK74LY4dNXLNuH2dmNOI +nQXHhecaKU3LANqjIaD181L1gIjLKk/Zm1bANxNhdGRh+4wlGJyW4vi74khg4xLY +qdmek+jNRvXrsxdiZtFd6sIJ0Xo00uCIHX9vcSVwUNhRk2GOcNrCuvBEgb6BVNY8 +2qZUYkC90S7OHN0pSbq1En5CZFSymZNgZ24aY0vatJYokIHEKAUoZP/GerOMaBLj +KGQAgoi8dUbS5/kKk0xdyJknTEBlDeyyhup24ijFd2s9/JEwiQoL4NRZzzDeX/ZQ +FVpAAeKlOc8= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server-expired.csr b/tests/hwsim/auth_serv/server-expired.csr new file mode 100644 index 000000000..f06a33da1 --- /dev/null +++ b/tests/hwsim/auth_serv/server-expired.csr @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIICjDCCAXQCAQAwRzELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAM +BgNVBAoMBXcxLmZpMRYwFAYDVQQDDA1zZXJ2ZXI0LncxLmZpMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsHfxPmbn/AtR+dijri/2SnU4PtRHe9YkMrTI +2eDQpRL0iaeJAdlUQ86BSr3tFvN8wWc2i3NNIZHnS350xTsVuMZGfqmikcP1kLPP ++Qzrum/uuat3PQOenXcHv5dq1E222v02VCXjCSaJf6ERwfbcvlxXqOZFVz2YFAZy +rOnIgQY4nM/NCg54Tp57EMJhpUPvNBbfPOCjRHdIzb7kecsxOZ9T3aMOdlpsJF5W +NZuifbOeQvFhnOieHLiaEB4yKSHLMBbgAxH5iPKPBKXmp5xz4ZPYUS27RYOPtpNB +OUGEX0utACWRPRYK6/C4kuBcdWWFF9KA5l5moqTfxwh2M0nPHQIDAQABoAAwDQYJ +KoZIhvcNAQELBQADggEBAIeunczvT7br/9Jk6zARkS7gZpAeRckiMMPFHD1HLiFM +ngU/PL4RD0TRF0cHGn+qJex7Ch97ZMHsGl0ECjXEL84UYnAdWGPddLv72XpeNX+d +f/QTWg9jVrZGspI1he6jN9JghZatKDEPYrXhFv0JbxrA4LoUzV2qGgh2ALpmP0LV +Xqje+tAoZbf8J7mba/Z2yqjJuJMxkOC+2cCUvN07+ndCGbixtzT2wZfPlVkp/af2 +HJyduA6qkLJWcrAER6jHaI3Cxq92u/H7D6Z++7v0vN8fV6inyZNadurUGY/VsIUn +jorEWeP7v1UKgLXXqBTdP5YA0Gi3O0dx7iLGalbHV9s= +-----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/server-expired.key b/tests/hwsim/auth_serv/server-expired.key index 882d645f1..545beab67 100644 --- a/tests/hwsim/auth_serv/server-expired.key +++ b/tests/hwsim/auth_serv/server-expired.key @@ -1,16 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANA7a4aeP7QOYEhU -Tcbci7lrddDkYPChQwuv+cR3aRGEUr6efXG0qoAf6+bAN95J9IVDrk1S8+swc67m -GAQUj8JjMKQM6/XWy/SvHU/WOkN4FDLe5YilNL6rmqSj3muE43iTHBwpx/xrzGjX -7sBd1z2RiIFWulQRnk7ogIPgbMrxAgMBAAECgYEArWSNSO+FRD2kVxY8HZeQkbm1 -xVgmkLj3x0elx79XMkrpS+lVs9UpFL+ABAmTe/pBLqcJAUJN8k3KRp066krk2QyQ -uilRkugON0vBJzLse9HryXilx0aWEVl3xZBKu1E3G4mcCl2LoPaASCZtjQXd/XCd -zdBR24qe123ofMpIo0ECQQDooUnHsruInBX9bRP11xXs7bI5298ZLCWHFAhGa/Tb -KvVXkXnzPVYhRi2w0Leqb0lht/4GX9MB06xcHs5TLvltAkEA5SasURCjxXc7svGJ -yP1s779DxYWoEBvGiRPygtyO40cnkOuupXKLaSkSuNUGag+6UxNzxGSUx9aiadse -oxOJFQJAL6y2SSXZBxMt8oUDPTO6O5cvGmp0G12Px1IUrBH92VjBdRPMUUw1tZYD -USRFL7mk6VDiz32d6dbukOaDVErhNQJASwnoAb/WMXLDHO0VtriudLAIbGVBTM0b -rYXXs1yweeKyJTXYghtJZc1qcRZpPFAcLto+3cAmLG6vzsRPew2JpQJBAN8krD5c -RYAGuXtslPkH7BWypJXI+K3brZkKBiyXVB/fbwnpXI1KTbzeBSly60JrjuymY9+X -NKs5A4HSiCtQjSk= +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCwd/E+Zuf8C1H5 +2KOuL/ZKdTg+1Ed71iQytMjZ4NClEvSJp4kB2VRDzoFKve0W83zBZzaLc00hkedL +fnTFOxW4xkZ+qaKRw/WQs8/5DOu6b+65q3c9A56ddwe/l2rUTbba/TZUJeMJJol/ +oRHB9ty+XFeo5kVXPZgUBnKs6ciBBjicz80KDnhOnnsQwmGlQ+80Ft884KNEd0jN +vuR5yzE5n1Pdow52WmwkXlY1m6J9s55C8WGc6J4cuJoQHjIpIcswFuADEfmI8o8E +peannHPhk9hRLbtFg4+2k0E5QYRfS60AJZE9Fgrr8LiS4Fx1ZYUX0oDmXmaipN/H +CHYzSc8dAgMBAAECggEBAJjiMQUJDm6UOB8nCxd7wfrb9zCnpI6rBY1QhroMRXbe +JzGjDdWmPZTJMcZZKTC7HhhInT7PU8GDsEj9c5j0CWudi7FsscVrajJFNibkhM1u +7/m3jYQ0wJRXbUUVn53y/jpXKVxZvopM8s658rKCdtgNFHzlkql0WW7v7yXTHLx6 +AM+559Y+LZZ3jAndrHdEpM1vCAG0VE85Ycv+1lBqlFEOthrWDL16UX6BBK5mjUsZ +QtSUzn8q5OfX8DVKOlZNA85+kdJAK2ysx13DApmFr9unvH0kKfp06sFMOLbV09dF +kJSNmzWGthVU5oo9rln7L2ctLzjwYfYCC2x36WREI5kCgYEA29J6FYwptBCWBiep +UnRmGD/9UWr77jyNfYSZpYq5WZZ5swHTdkIeBu6f/u43adLjqcggsWtDZKEMbaZG +pE3K+8NRUvw2NOt0oBVtYvSyAuDLlOroA3CcEu8089dnojSnENQe6vSsUh54qe5i +LS7VdJGv2LyT7828Df0JhLL93CcCgYEAzYLk9DTZ5rIQ7AIhyW+IoduQUWhnfS/j +usueMnvkpuYf+mVtbl1Xn8HiJPaiLrjwu/VSE5zim1tHEXRRhw4euG6p5s1V28S+ +mSOHr+jgLFZQ2hRKZKaV/8ayWJYYtLQ6E7n61mwvoeXUfOnRrP2/drWjJ9MUYt+/ +oTfS7eATERsCgYBfIYVoEdJydMMYQs3KO0l7sSWluJDylw38hgggVhrEpJRiXaXw +BckM4vQm1Vzx1Sxla5CKd4sg33mLcmwb6vavYeWt7ixfVo6QQPWn35GyISq5dbeW +1YMVxqO56zyUPAkZBVOkBuMUXs+Fav7d4ujJm8roFyRGoViDDUCzRusJ/QKBgQDF +z0zjRg/K/vBMyoyM4D8qVDVoNk8Ob08KmDzwKNJgVzbGhGQ9i7jwu+UZYQ+gW0DU +GgBjgmmX0dbpFQX4Mf4d1d7RmikfPROcQVe0WTmVU4vFLSyiDrpolG9L10V2gdc4 +75ViWIXMlnTduw2oLiHheFnP1ltUBDvmSN5NOpX/qwKBgQCmAR9C6xL68ZFO6HR1 +wswgZEDks4Da1ibWm8uw54YmdT5nG8CakhGwzLcS0Np3xvQ1WgUA1ic2XnHXHwuI +piU5MbI8+O0hdPQLG4meuZeWINt3QDH5OzuwPCwhZCZkrpG9IfrIAaaaltKHaLMC +bBd+f4vilJMr+V+VPOKFoUBibg== -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/server-expired.pem b/tests/hwsim/auth_serv/server-expired.pem index f279aae62..308d57fad 100644 --- a/tests/hwsim/auth_serv/server-expired.pem +++ b/tests/hwsim/auth_serv/server-expired.pem @@ -1,62 +1,85 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162826 (0xd8d3e3a6cbe3ccca) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + d8:d3:e3:a6:cb:e3:cd:66 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Jan 1 00:00:00 2014 GMT - Not After : Jan 2 00:00:00 2014 GMT + Not Before: Jan 1 00:00:00 2020 GMT + Not After : Jan 2 00:00:00 2020 GMT Subject: C=FI, O=w1.fi, CN=server4.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:d0:3b:6b:86:9e:3f:b4:0e:60:48:54:4d:c6:dc: - 8b:b9:6b:75:d0:e4:60:f0:a1:43:0b:af:f9:c4:77: - 69:11:84:52:be:9e:7d:71:b4:aa:80:1f:eb:e6:c0: - 37:de:49:f4:85:43:ae:4d:52:f3:eb:30:73:ae:e6: - 18:04:14:8f:c2:63:30:a4:0c:eb:f5:d6:cb:f4:af: - 1d:4f:d6:3a:43:78:14:32:de:e5:88:a5:34:be:ab: - 9a:a4:a3:de:6b:84:e3:78:93:1c:1c:29:c7:fc:6b: - cc:68:d7:ee:c0:5d:d7:3d:91:88:81:56:ba:54:11: - 9e:4e:e8:80:83:e0:6c:ca:f1 + 00:b0:77:f1:3e:66:e7:fc:0b:51:f9:d8:a3:ae:2f: + f6:4a:75:38:3e:d4:47:7b:d6:24:32:b4:c8:d9:e0: + d0:a5:12:f4:89:a7:89:01:d9:54:43:ce:81:4a:bd: + ed:16:f3:7c:c1:67:36:8b:73:4d:21:91:e7:4b:7e: + 74:c5:3b:15:b8:c6:46:7e:a9:a2:91:c3:f5:90:b3: + cf:f9:0c:eb:ba:6f:ee:b9:ab:77:3d:03:9e:9d:77: + 07:bf:97:6a:d4:4d:b6:da:fd:36:54:25:e3:09:26: + 89:7f:a1:11:c1:f6:dc:be:5c:57:a8:e6:45:57:3d: + 98:14:06:72:ac:e9:c8:81:06:38:9c:cf:cd:0a:0e: + 78:4e:9e:7b:10:c2:61:a5:43:ef:34:16:df:3c:e0: + a3:44:77:48:cd:be:e4:79:cb:31:39:9f:53:dd:a3: + 0e:76:5a:6c:24:5e:56:35:9b:a2:7d:b3:9e:42:f1: + 61:9c:e8:9e:1c:b8:9a:10:1e:32:29:21:cb:30:16: + e0:03:11:f9:88:f2:8f:04:a5:e6:a7:9c:73:e1:93: + d8:51:2d:bb:45:83:8f:b6:93:41:39:41:84:5f:4b: + ad:00:25:91:3d:16:0a:eb:f0:b8:92:e0:5c:75:65: + 85:17:d2:80:e6:5e:66:a2:a4:df:c7:08:76:33:49: + cf:1d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - 75:B0:65:1F:2F:A9:BE:D7:D0:EE:9D:42:8F:8B:13:5F:D0:AD:13:7B + 21:B0:31:C6:14:D4:BD:5C:DF:70:24:51:34:9E:93:F5:18:B3:1C:A1 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ X509v3 Extended Key Usage: TLS Web Server Authentication - Signature Algorithm: sha1WithRSAEncryption - 12:e7:8a:e1:3d:d9:fd:36:ce:71:66:b3:74:48:c1:f0:38:75: - 30:56:c7:2c:9c:0d:da:d0:68:19:47:a2:37:38:0d:db:4f:f9: - b9:cc:0d:25:b1:35:ed:df:19:8c:4b:bd:f0:08:11:13:4b:e9: - a7:d7:50:2e:fa:7a:16:e1:4f:0f:5a:b4:42:34:ff:43:08:5c: - 3c:04:6a:f8:44:8d:f6:e5:a7:82:38:60:d0:5c:d1:59:f9:02: - 84:7f:da:ae:6c:e9:55:c8:f5:0e:da:55:70:f3:77:48:30:1f: - ab:60:39:a1:77:49:29:e3:51:54:62:72:c7:78:ae:17:14:c5: - dd:2c + Signature Algorithm: sha256WithRSAEncryption + 89:4d:ee:04:3e:50:fc:a2:6e:4c:3e:4a:9e:3b:9c:2e:74:29: + 06:86:1b:bb:96:01:70:f7:46:21:b4:ef:6f:73:93:31:bd:58: + f5:2f:40:61:f1:53:86:20:75:cf:0e:75:70:2c:94:b8:c5:4e: + ec:24:0f:42:d6:8b:80:b9:fa:b5:48:83:d6:cf:c8:47:3d:09: + 50:11:4a:5d:83:c5:41:8b:4b:4e:1e:ff:96:95:f0:14:7a:7e: + cd:a6:4f:ce:0b:37:e8:f2:27:a2:72:e2:6b:18:d7:f8:86:f0: + 14:db:4c:c5:8a:76:9b:fc:55:15:49:3f:eb:df:5c:c7:7a:64: + 86:70:44:97:7e:ba:83:39:25:3b:23:8e:dc:b3:9e:59:cb:e0: + a2:ac:7e:9f:d2:60:91:a7:de:a9:a9:30:e1:97:81:e3:13:91: + 75:68:08:11:e0:ca:f9:eb:39:28:72:ab:8c:18:d2:3c:2c:cc: + 38:e5:73:1a:4e:7f:e6:74:25:8b:a2:40:45:59:28:b4:ec:ec: + 5f:c9:f5:6f:ab:02:03:70:0d:11:9b:62:df:73:7b:e0:c6:c1: + c1:ee:da:69:9a:91:a3:6b:2b:15:d6:fb:e4:35:38:86:fe:ac: + ad:77:a5:a3:03:a5:9f:f4:e7:34:91:83:9e:5b:1e:88:e1:48: + 5f:15:d8:de -----BEGIN CERTIFICATE----- -MIICfTCCAeagAwIBAgIJANjT46bL48zKMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xNDAx -MDEwMDAwMDBaFw0xNDAxMDIwMDAwMDBaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNC53MS5maTCBnzANBgkqhkiG9w0BAQEF -AAOBjQAwgYkCgYEA0Dtrhp4/tA5gSFRNxtyLuWt10ORg8KFDC6/5xHdpEYRSvp59 -cbSqgB/r5sA33kn0hUOuTVLz6zBzruYYBBSPwmMwpAzr9dbL9K8dT9Y6Q3gUMt7l -iKU0vquapKPea4TjeJMcHCnH/GvMaNfuwF3XPZGIgVa6VBGeTuiAg+BsyvECAwEA -AaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBR1sGUfL6m+19DunUKPixNf0K0T -ezAfBgNVHSMEGDAWgBS4kt79ihizMMOfVfMzXbTIKYpBFDA1BggrBgEFBQcBAQQp -MCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8wEwYDVR0l -BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQEFBQADgYEAEueK4T3Z/TbOcWazdEjB -8Dh1MFbHLJwN2tBoGUeiNzgN20/5ucwNJbE17d8ZjEu98AgRE0vpp9dQLvp6FuFP -D1q0QjT/QwhcPARq+ESN9uWngjhg0FzRWfkChH/armzpVcj1DtpVcPN3SDAfq2A5 -oXdJKeNRVGJyx3iuFxTF3Sw= +MIIDlDCCAnygAwIBAgIJANjT46bL481mMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDAxMDEwMDAwMDBaFw0yMDAxMDIwMDAwMDBaMDUxCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEWMBQGA1UEAwwNc2VydmVyNC53MS5m +aTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALB38T5m5/wLUfnYo64v +9kp1OD7UR3vWJDK0yNng0KUS9ImniQHZVEPOgUq97RbzfMFnNotzTSGR50t+dMU7 +FbjGRn6popHD9ZCzz/kM67pv7rmrdz0Dnp13B7+XatRNttr9NlQl4wkmiX+hEcH2 +3L5cV6jmRVc9mBQGcqzpyIEGOJzPzQoOeE6eexDCYaVD7zQW3zzgo0R3SM2+5HnL +MTmfU92jDnZabCReVjWbon2znkLxYZzonhy4mhAeMikhyzAW4AMR+YjyjwSl5qec +c+GT2FEtu0WDj7aTQTlBhF9LrQAlkT0WCuvwuJLgXHVlhRfSgOZeZqKk38cIdjNJ +zx0CAwEAAaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQhsDHGFNS9XN9wJFE0 +npP1GLMcoTAfBgNVHSMEGDAWgBSk/bk5G4GzquuIHdSBqbURcMyn4TA1BggrBgEF +BQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8w +EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAIlN7gQ+UPyi +bkw+Sp47nC50KQaGG7uWAXD3RiG0729zkzG9WPUvQGHxU4Ygdc8OdXAslLjFTuwk +D0LWi4C5+rVIg9bPyEc9CVARSl2DxUGLS04e/5aV8BR6fs2mT84LN+jyJ6Jy4msY +1/iG8BTbTMWKdpv8VRVJP+vfXMd6ZIZwRJd+uoM5JTsjjtyznlnL4KKsfp/SYJGn +3qmpMOGXgeMTkXVoCBHgyvnrOShyq4wY0jwszDjlcxpOf+Z0JYuiQEVZKLTs7F/J +9W+rAgNwDRGbYt9ze+DGwcHu2mmakaNrKxXW++Q1OIb+rK13paMDpZ/05zSRg55b +HojhSF8V2N4= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server-extra.pkcs12 b/tests/hwsim/auth_serv/server-extra.pkcs12 index 7c963a642..472310396 100644 Binary files a/tests/hwsim/auth_serv/server-extra.pkcs12 and b/tests/hwsim/auth_serv/server-extra.pkcs12 differ diff --git a/tests/hwsim/auth_serv/server-long-duration.csr b/tests/hwsim/auth_serv/server-long-duration.csr new file mode 100644 index 000000000..6324b778f --- /dev/null +++ b/tests/hwsim/auth_serv/server-long-duration.csr @@ -0,0 +1,27 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEjDCCAnQCAQAwRzELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAM +BgNVBAoMBXcxLmZpMRYwFAYDVQQDDA1zZXJ2ZXI3LncxLmZpMIICIjANBgkqhkiG +9w0BAQEFAAOCAg8AMIICCgKCAgEAvxDC67+9DyFoRCZ41pAP3pxneAdvLjThUaY0 +bh1P8R8at5N6GgE2BNTjNfCbUo3MLYCTaDcACV/hDYo1dPXuHhZpkxZHqpPKaKc5 +bbXbVz1FY4k4nj5XOdi9TLKgqyefSTjGxfTojYs3up8PGqADdNh3lKTdNomrGl7W +elrLv0AEkWqchPOBN6amSZH+aeyAoluyBBFXtuRoIurZG0zB+dOiKLG16bROCCU3 +ZIIUG9Lcdfj0SN658zWULWmxPESx9wgacUFMdMlwwXsJWP3hc206cMg6ue600Od9 +70j6+4Hv5P45h03cScAV7JDiDeqdqcAZQNbHc0NulROyDQ6Qwr8r2S2chUgqxUCe +N2fP5xuVwiav4GGiplEHMxU1NnQz/HT4RoA2bTnfJLGoCwWFvmIc0I4JWikMSJ2B +vMX39Mmcq+kTbhFZkMqWr8aQGPc+WFHkv9EeIFyXBtHPYRtn9WEAhwKQWs4tyzWx +lmrZ/keQA7ddxz1IwF4quWbsNrjs3Q90MmVQLLfcGkdrSTMo9jc91Q17MHmG3dXX +w4tV+oysWMivlBwDhosGngW5tfgUGBS2PiSV+JvEQGT3ooMR7LegH0yUrjMPvtTo +4mtUu3Hypu8HXxM1Zja2MGQV0mDwxM6LfSuxiKI/WLdQfbuUpDl734zsZMjFjYZU +b/GHk1ECAwEAAaAAMA0GCSqGSIb3DQEBCwUAA4ICAQCFXmnZDE5Nyumifcrtxblr +PyO2zktJmwwpJZJfzz0iCdtdx2fbrjbg18wLrfCAQA1VAFFv9rvq5Z9gx4FdBitR +NLH6xWK2nFDJl8OqPW4cFmiuO90OVGayp3ZdYaJMLQOMN2V7TSvap/RBqXtfznRL +7Ftqyn1Fryhtt6OcDf4JSSN60MwLH141bR2M0cMm0fU/A+S5XCGh+7s9m+wOjbRO +h4AGxrIcB4vV76ljt2jVTRukTECndxtwPqtmZIP6+h4Ichh/zapwoXPxXOfo0afi +dRnu7CXlN36rHk6rr8PhIp+kjArRDBDHJ9Agk1zudzTbK1yOEr6bX7MBtyEvvcfO +NRO8VDKGJSeHjmeDP0LdJeyl3bOpwaS4aj+iKykN4SlA6S/3rZptJczsYtKQP46w +HAWEZ2N+HBtClP4KJYn9lcQdsqVmBBAbrET2ttbtu+PnBD7FeQZmjxPBVXu0K8FC +BwWMFWdAZTjOOz+AP41KBw2/kKSYlx/WBH2Ort1pKIuUr+kLEuYHnXU5+EMDJOnY +Z4L+1zQbVz92mhOL9CbdCqgbxJ0eZjKV+LInLjgQhqD8mIV6pq/lbNlVs2om2JQS +byRGe6baceitwjfMi/kO58JkYoZS2nvcBb4XZ3foogN+I8PIL5oGOpXGcSmuZHfL +5fjSUaTpPgNeNHSUWxgKng== +-----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/server-long-duration.key b/tests/hwsim/auth_serv/server-long-duration.key index 857851550..3ae384507 100644 --- a/tests/hwsim/auth_serv/server-long-duration.key +++ b/tests/hwsim/auth_serv/server-long-duration.key @@ -1,52 +1,52 @@ -----BEGIN PRIVATE KEY----- -MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQDA+hcn645Hf2Vx -DuNGR2791hnx4L0bfpzsiEDZ3ssv6WTfzMgvc8k30TkenlA4Zxs9Mg/i3CmnAItV -6XqlGf3e1TtSmolOk0fPVoQ+NiPoVeQJ9buycFYHaj+l44o80s7+i66q6GrBc/MQ -qulNJPdpyzGE0MtwPTVJ6R8tNoEV3gt1dEPCIDmpJ4XVYhWVvNcicLL2CWpH37gj -LNS3Bf/ApeB6skdzsESmaCaSk5JuNm6zdpZnVQU+ipPNlrvq7y1k0j5kFZsJ57As -CwJPkppLigUL3TUnT8LGvoGw42+gZFhYENqoeSdXop2k0+Ct0i3Tmy+60fuYu6UL -66dVPcJGOCel05gHJD3D8xCCC+9Cr60kZgjsJwtN7aqybAjI4dSqiMwbswLvxDco -kMfW8kDpbfU0yRdtkRr33y5iQ7FIB2qygH6waRsfmLKtsyfFCCNo/B208xs6geyb -TvAGnpy8v2L+5/1dos87rdGFZiiXmG1zEhGcPe9Cjlj22e/ULqo3HP7FhfvCOTzE -fZg1hPGwFff0U3r8tnfWiwXcEDse5EULCPBhzsv7XkmV5jDd/kc5U1j9WsbUZSVN -xKVmEEAiHePt/ONQDi18ERjUxotFu7LF+/G94Q4Sd6rQtFTDnctlPj5y8MhgEqr+ -+4pLwptKxVktypPimbMeEBOMwKUxZQIDAQABAoICAFAo0muTrmNGqQWgkInF7HXm -dJqDpyn/mwGpy350zGQXh/5q2xDTANd9wkNUsa/sLGVsISs0Ft03HanPNVHVjR39 -5wl2Beksxpx6rK4G4T2GSBZXC+OgRCwKV2v6K5b+Xltf/Gsj5gx7tJDM3eJco6U/ -cU9hR9BUrIkKHBg01sQVmx7r76V4q1r3fuFXP+4WJis5My1+VbaLWLrLyYRJKqaE -gM2WtpV4t9uD0dn7EM1VMQC9FtbPe0EyYRj6Lw700R9bMe1zCBbCNezlmc0h8ZPF -PjliZszwldDmm4q1vs2aQRQ71Ag9YzlE5ETuehrZ/o0ynk31IZSdBX8BIV4ILGUy -10obeXFpgSjIGBnR1wl30l9DbEF3CciSJMWA323A7l81ztLf2dS6fB8vUU4rlaeY -vcJi1Qcbjt21GFxX1biMvGvYVFmnWR4LvUkVoNdhyBHHacCrupD5y/M7xycIK3Uo -6JPaMZKxFTbe1bWW4GVI4KbFKKrqxaZkj2gxa8r+M3zd5C/g2McvhqGAtqkGb/Sk -QmuBZhFaPYNUvYS62AYo9VRmJ8beZ+SsACJYBu4CJk+vievRPtRLAy3+fmkqXUIg -n3VhM30B5VmngO3Zh/RJqCsHXmf90uNNHNbS0usDnUhNnUqsKHM3DHqyWUit72ie -tIczuD5bnAghqGH8ZTyVAoIBAQD5YmjjxdyU5wllRH7BlqktN34D6BKOSkkqfBFk -aZ1K+sz8m7QmD/fbtWH3Ej/5CD4V9a31YohoUMjkQ5sL5UHAtK3BjEvFaz744DHf -yTgzkso/Tt1qp6oykXoMnj/VQQBIh0sEQ+FbJap2AmjiVOkY1krzPUuoLTDm+B3N -WS0zO9uXTdwZ6u/XlTcFwGK2YOJ8qvogQ7MDLa50S7KCgNA9F0foyS5wQbFLMwub -tWgRrRcB//spuR25k4zJVd3Lp7hbEftj0sxH1TvB0UPlIQODOipi8w4ByXOmGwoQ -jqdAWm1ApgJOf0VRzmILuviOQxbi6WmhtoWoa1+3nrKaw0FrAoIBAQDGGJzboDRx -ngtnzn8LjuT1LZ2tZD0ftxUbYJXcg+vppBo89i3XqkfnS5Wv42jxYVbPJCAHQSKB -Gep7rtC7lz8n1EPgQ0G1AtC7s45jvMROlaVVn9TbmQMxZWhyz6+aZodWtYQcZbem -QZb5AUIH2N77XTHm9QoSMYMSPFg1is8ZT9dsXbfrjnJw3yD97jT9vqfGUPBFdp/6 -OVGCm/GFtWhmnfJDKXBERKdEcOrA9VVu7TCo9RIl+ESOcPjaUXtqQO8qJMkq/BZz -rCWYRp9K0JohjyRtbqxybfCHQFoYPhYPN7NEvTcw8xzO4Fbe3UeuyAcQm6Bim/yt -UxsUVv0t5HxvAoIBABH8xiH/qHxY+bWDLj1aV5N6WC2B9KyssQBOeJasg3rgAh8K -QAEqz67aM1m1yEV3EbtVwBld5QbZJNRKCAngnFCA97NpIiH4LU+YJCDHC7W0lb/h -OVkzBLSnB42XcHU6PgH9OCzzlHKVkej3HYeNpk5zTm6i8i0MLWXLaaLhFsCGRb1x -EToRVwFOsuxIRxZugIeLcYUYPPYyuk2LFDIThnGRl080C5RvOJF6+hBeEkaMHIe5 -Ze1Je9phyRrQhbHlxAdVkbNOhgt8VtYQ+Puy2OUDMgF3FICOfjfx5VTyZR/gJdcu -4iW1SlOvNiUwdDMWpbTyLvtKBfPy4rGE0c8V3EcCggEADkXjt2dZn/4VMEuOl9SZ -5ph8zet1A/37BVf2NEdFDjaGtXG/Z9SbDa1CgcPO4eVzjcU6kYs94zNs07CK1ZlW -MZZ3tYbjCxnC1GNhlQoa0taxbPPxMElcE4kM94jDTEqq4bJ+bFVf4BjFufc/PLWB -i3bxi4SITztGCGBUsrbnqRk5mlM+VziSQlOxWtp48vdzuzRFu5uKd0r99n0p78pc -VVh4BiLMNf8EVkgUggarOyzX3rSZtCapOeIl7AUG8WbwVIcF/5TeQUNcCha8j3Vs -RZK8uy3IOw500Cnw0+JVUI9g2UkQ2vQJVVaQq8ohyhQbfjTYX4KBuDNOti52W4Ik -/QKCAQAStLzR2L2AWb4pw7azKxPBoyf3r8B31xOT2Q4LhcIzuS5VzE8vOOEprsQ3 -lP9shiaEgn6D2ifkfdUC3qEekamKFiXoPuaLdopP7u9C3Qzyu8fF9sFA5xD0vR1m -U6Cf6KOuwoEI4woaOm6+I6WDLwo6oQeMtUijycJp/FZmpz0am2z5YeynBL9mvPij -oh1zgP7q8EzF/LGvaLZASMeoEktvHodzSqEBvi+FrVjr2Rox0l8F34xZpNVzJxrm -aehPzOWdaWbhR8cC5BFf7xvpFVBwy0Weg1qua+1FPaKw/Vuohqn97N3wRgALC9Pv -Wn3OoMMoOXVSeqpHuMye16F61vko +MIIJQgIBADANBgkqhkiG9w0BAQEFAASCCSwwggkoAgEAAoICAQC/EMLrv70PIWhE +JnjWkA/enGd4B28uNOFRpjRuHU/xHxq3k3oaATYE1OM18JtSjcwtgJNoNwAJX+EN +ijV09e4eFmmTFkeqk8popzlttdtXPUVjiTiePlc52L1MsqCrJ59JOMbF9OiNize6 +nw8aoAN02HeUpN02iasaXtZ6Wsu/QASRapyE84E3pqZJkf5p7ICiW7IEEVe25Ggi +6tkbTMH506IosbXptE4IJTdkghQb0tx1+PRI3rnzNZQtabE8RLH3CBpxQUx0yXDB +ewlY/eFzbTpwyDq57rTQ533vSPr7ge/k/jmHTdxJwBXskOIN6p2pwBlA1sdzQ26V +E7INDpDCvyvZLZyFSCrFQJ43Z8/nG5XCJq/gYaKmUQczFTU2dDP8dPhGgDZtOd8k +sagLBYW+YhzQjglaKQxInYG8xff0yZyr6RNuEVmQypavxpAY9z5YUeS/0R4gXJcG +0c9hG2f1YQCHApBazi3LNbGWatn+R5ADt13HPUjAXiq5Zuw2uOzdD3QyZVAst9wa +R2tJMyj2Nz3VDXsweYbd1dfDi1X6jKxYyK+UHAOGiwaeBbm1+BQYFLY+JJX4m8RA +ZPeigxHst6AfTJSuMw++1Ojia1S7cfKm7wdfEzVmNrYwZBXSYPDEzot9K7GIoj9Y +t1B9u5SkOXvfjOxkyMWNhlRv8YeTUQIDAQABAoICAEJ/OefExq7yaJB3d0ztvKg0 +dQpgRACn5Nd+6fZ8+yqnMaw8hp1wWHWcBivqvpQfx7T6b9MweTHKDdChjnNTeHk+ +QaYwdebXIvYDZUhap6kYKQM4ad0hQ0hdt5xu+t42nwhj20JgN2Oz1UR9QUt571oG +ULAKJPdrOIKoCStyWEEKrcxSd4EKIqnUtUEbr5j799UJ5s3ln0qG+ftVExSeRVCG +qIRTPUXGO/Y3xayUXR1F6PaiG5sU8VDFD/oyM74PBoU8a7+JA2wOA9FC2gD/8ywy +EsnX1iCKBKJEPx89niRUl8Jx/GGr5oRAdyDrV9GSGydONTvMxIPILz9xKGHE9PpH +mxYAY2h5691PeLB9zr58puhVsMVaCZkgfhWuodE1aFuSxaAqxIT/5cvDKkW/LQ3L +kLiV3yb4BANys5P0WCGxBndGUoyHlSRFfr70ujPk/GQi/YgD/FWy/VkIY9x0WQR0 +Br9NS3bQhlqQEkF51xdJEOc2nUD5f2siZpSm4+vJ6gdCtO+eFA87smIxV1jCORFq +lSCSKN5ACJqfjIIAvnyTO/JIpOo3FGjJT8LZh3kj8+lQn5b8EH3nCtPETp/lzJWd +B302qq8U3V7OR0SH2j0qyZ7xC9CWXI6nAsbVuYRDxi2x7EEYIndfxi+9bIttBtlo +oul2knJ9zGKjGcC+5joFAoIBAQD3JlTm+Bvw54xv6VqDw0/Dy7CzYAMST14oT4D+ +wqpTvWFFS4YmFj5z37qZMeSVrIs23cXBzanGtMux2qeSChTBsgAhOV9N9vFNVm4V +1M23NWdx0jTXGUZuEhGJ7viF2ENYyOsiSdSeSDZRk10xp/ya+YzMfytC8z35zaaH +I4XYSxIeWAKcvlPeMf66+azB5D6hmw5hCI9Is1ZyQYUDHHZLEuGxyMJ76Vas/+5C +6WoYe+QhMN7mn7drDtrSudauACZQNjEQ9O9RV1c2Vv0Lv6MESQnsVtIGpg6yerB+ +Oj8wgo4tSJ1sW1qESH2o4LrBPFLKCJBYeQuyinZyNCoDAYL/AoIBAQDF6Et04Qgp +s7bAf+M/wUE7EEiNQoTkZfTHEcwNF7GcemlF85Wehq36PB2ePFaR79aZwngkn0zz +uMTvQVJq3jH+0uJ/j/MbUJ82dpuNf7NeplnhHrWQhiayoSbTKcSawKe6ckVrfwLy +/tV0ttkAiDPjEK/TpIJVqucmEHjHjpE6iRCqgt47eyB+VK+L7sPJQKLB4nIwqEYo +KcwwLl/f7pKjCYnkxk44Fffoy29mwPUWY0TtNuDYZNSP19sAsFem0pevLTU+PYII +Pvra5WnJ3JQc0jCYCL09y+HL73jvAEPhMqfO10uUbCC8W3KI9jvWwHI20tUqMXQL +E26g95bV6/mvAoIBADT4NC4kcuiY19KMcufWjlvqZf6rzzy3YfjFwWHYmuTDq/tM +Cn5TOiNfigCXXuRtTJD/ywiUaZS63wVJVazJGFXDLp/wSerNyD3JDmMDbuubOIZ+ +hPCs7BlfKf8kBoO5LAX1Wd/JbxZVZ77oFIs187/LSE/z2XPJ6jiFyPEhvefzfvid +6EFr0VHH6U5tgIc1we6k6toFGaB9P0PRow5dpUTF0TVnT7d69Say23/fwutociZi +8QMArDD3yBJt3gMA6TU7yBxYQopua7SrxCQmeGvMs6HBodXm9TNvdDA5j513/bza +2VKF6cp8NuJg9+W+ZggC+dzcZJNpdaVYZMCsLEUCggEAPLyi07bwO2QlFQTqqDlW +HJtNuNSOVk4YBjQnDGmWH7DNuCMeau1oXWCvsk1QQC98C+pL1ulww2eUQN0qPxP8 +AfmUe5OhB2QByMQzzwQ+9zBUaytyi20wWSft82ZhKSExGJ5TQb9UF2Ev/0bSaEBk +tC392BUnzsTJdbweZRgS6AUCsWHCdDzAZyT0Txyyx4Pnr1sgsmAiT9csDClfUSk1 +pYWa5TQa80mCsNYmVUGotfs3PxnVfXPMbGzRkG+OJuuAk8lrCrPzwTYa5Kz9f28L +oaC8OxyLf3ifzmerFKZfLrDOIUOftWhNz6C9EN2I1cpwAvVHaFCPDYskK5BwoSxv +jwKCAQEAkb5RnSaRQENeHSqnU5tNyZj5Grcsd6dPlqWRe+tZfPxfNs45n9Qsuu/+ +N1W5ZoqfNKoL9Rn9FWK98/VN47CxshtIVVYLDF+1+bdi5PgBCvG7W+77mLoaRiur +49XrQ7e5+mlKpjV1809fZGZ6UX1b7oeoBwEXAKU/vqOA/9T65SaBLo2pcxGFK+LL +H2gynD0uB3eS8SVTQLZ1nt2siPcbfqbTJnKhgwmm0bJxwAFzC54uvtoOjlZcsqvB +AuBc6reTuBQTn9+mJC0oDAjuyiDLuByU9BvTSjPwqMTt9SoKEAwsYo0t16LfxSZh +7i4QyQhhpHEPAMqvU0qdRdiWQ1QFhA== -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/server-long-duration.pem b/tests/hwsim/auth_serv/server-long-duration.pem index 442a054ea..88bd6afc9 100644 --- a/tests/hwsim/auth_serv/server-long-duration.pem +++ b/tests/hwsim/auth_serv/server-long-duration.pem @@ -1,60 +1,61 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162842 (0xd8d3e3a6cbe3ccda) - Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + d8:d3:e3:a6:cb:e3:cd:68 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: May 24 08:13:55 2015 GMT - Not After : May 11 08:13:55 2065 GMT + Not Before: May 3 14:07:41 2020 GMT + Not After : Apr 21 14:07:41 2070 GMT Subject: C=FI, O=w1.fi, CN=server7.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (4096 bit) + RSA Public-Key: (4096 bit) Modulus: - 00:c0:fa:17:27:eb:8e:47:7f:65:71:0e:e3:46:47: - 6e:fd:d6:19:f1:e0:bd:1b:7e:9c:ec:88:40:d9:de: - cb:2f:e9:64:df:cc:c8:2f:73:c9:37:d1:39:1e:9e: - 50:38:67:1b:3d:32:0f:e2:dc:29:a7:00:8b:55:e9: - 7a:a5:19:fd:de:d5:3b:52:9a:89:4e:93:47:cf:56: - 84:3e:36:23:e8:55:e4:09:f5:bb:b2:70:56:07:6a: - 3f:a5:e3:8a:3c:d2:ce:fe:8b:ae:aa:e8:6a:c1:73: - f3:10:aa:e9:4d:24:f7:69:cb:31:84:d0:cb:70:3d: - 35:49:e9:1f:2d:36:81:15:de:0b:75:74:43:c2:20: - 39:a9:27:85:d5:62:15:95:bc:d7:22:70:b2:f6:09: - 6a:47:df:b8:23:2c:d4:b7:05:ff:c0:a5:e0:7a:b2: - 47:73:b0:44:a6:68:26:92:93:92:6e:36:6e:b3:76: - 96:67:55:05:3e:8a:93:cd:96:bb:ea:ef:2d:64:d2: - 3e:64:15:9b:09:e7:b0:2c:0b:02:4f:92:9a:4b:8a: - 05:0b:dd:35:27:4f:c2:c6:be:81:b0:e3:6f:a0:64: - 58:58:10:da:a8:79:27:57:a2:9d:a4:d3:e0:ad:d2: - 2d:d3:9b:2f:ba:d1:fb:98:bb:a5:0b:eb:a7:55:3d: - c2:46:38:27:a5:d3:98:07:24:3d:c3:f3:10:82:0b: - ef:42:af:ad:24:66:08:ec:27:0b:4d:ed:aa:b2:6c: - 08:c8:e1:d4:aa:88:cc:1b:b3:02:ef:c4:37:28:90: - c7:d6:f2:40:e9:6d:f5:34:c9:17:6d:91:1a:f7:df: - 2e:62:43:b1:48:07:6a:b2:80:7e:b0:69:1b:1f:98: - b2:ad:b3:27:c5:08:23:68:fc:1d:b4:f3:1b:3a:81: - ec:9b:4e:f0:06:9e:9c:bc:bf:62:fe:e7:fd:5d:a2: - cf:3b:ad:d1:85:66:28:97:98:6d:73:12:11:9c:3d: - ef:42:8e:58:f6:d9:ef:d4:2e:aa:37:1c:fe:c5:85: - fb:c2:39:3c:c4:7d:98:35:84:f1:b0:15:f7:f4:53: - 7a:fc:b6:77:d6:8b:05:dc:10:3b:1e:e4:45:0b:08: - f0:61:ce:cb:fb:5e:49:95:e6:30:dd:fe:47:39:53: - 58:fd:5a:c6:d4:65:25:4d:c4:a5:66:10:40:22:1d: - e3:ed:fc:e3:50:0e:2d:7c:11:18:d4:c6:8b:45:bb: - b2:c5:fb:f1:bd:e1:0e:12:77:aa:d0:b4:54:c3:9d: - cb:65:3e:3e:72:f0:c8:60:12:aa:fe:fb:8a:4b:c2: - 9b:4a:c5:59:2d:ca:93:e2:99:b3:1e:10:13:8c:c0: - a5:31:65 + 00:bf:10:c2:eb:bf:bd:0f:21:68:44:26:78:d6:90: + 0f:de:9c:67:78:07:6f:2e:34:e1:51:a6:34:6e:1d: + 4f:f1:1f:1a:b7:93:7a:1a:01:36:04:d4:e3:35:f0: + 9b:52:8d:cc:2d:80:93:68:37:00:09:5f:e1:0d:8a: + 35:74:f5:ee:1e:16:69:93:16:47:aa:93:ca:68:a7: + 39:6d:b5:db:57:3d:45:63:89:38:9e:3e:57:39:d8: + bd:4c:b2:a0:ab:27:9f:49:38:c6:c5:f4:e8:8d:8b: + 37:ba:9f:0f:1a:a0:03:74:d8:77:94:a4:dd:36:89: + ab:1a:5e:d6:7a:5a:cb:bf:40:04:91:6a:9c:84:f3: + 81:37:a6:a6:49:91:fe:69:ec:80:a2:5b:b2:04:11: + 57:b6:e4:68:22:ea:d9:1b:4c:c1:f9:d3:a2:28:b1: + b5:e9:b4:4e:08:25:37:64:82:14:1b:d2:dc:75:f8: + f4:48:de:b9:f3:35:94:2d:69:b1:3c:44:b1:f7:08: + 1a:71:41:4c:74:c9:70:c1:7b:09:58:fd:e1:73:6d: + 3a:70:c8:3a:b9:ee:b4:d0:e7:7d:ef:48:fa:fb:81: + ef:e4:fe:39:87:4d:dc:49:c0:15:ec:90:e2:0d:ea: + 9d:a9:c0:19:40:d6:c7:73:43:6e:95:13:b2:0d:0e: + 90:c2:bf:2b:d9:2d:9c:85:48:2a:c5:40:9e:37:67: + cf:e7:1b:95:c2:26:af:e0:61:a2:a6:51:07:33:15: + 35:36:74:33:fc:74:f8:46:80:36:6d:39:df:24:b1: + a8:0b:05:85:be:62:1c:d0:8e:09:5a:29:0c:48:9d: + 81:bc:c5:f7:f4:c9:9c:ab:e9:13:6e:11:59:90:ca: + 96:af:c6:90:18:f7:3e:58:51:e4:bf:d1:1e:20:5c: + 97:06:d1:cf:61:1b:67:f5:61:00:87:02:90:5a:ce: + 2d:cb:35:b1:96:6a:d9:fe:47:90:03:b7:5d:c7:3d: + 48:c0:5e:2a:b9:66:ec:36:b8:ec:dd:0f:74:32:65: + 50:2c:b7:dc:1a:47:6b:49:33:28:f6:37:3d:d5:0d: + 7b:30:79:86:dd:d5:d7:c3:8b:55:fa:8c:ac:58:c8: + af:94:1c:03:86:8b:06:9e:05:b9:b5:f8:14:18:14: + b6:3e:24:95:f8:9b:c4:40:64:f7:a2:83:11:ec:b7: + a0:1f:4c:94:ae:33:0f:be:d4:e8:e2:6b:54:bb:71: + f2:a6:ef:07:5f:13:35:66:36:b6:30:64:15:d2:60: + f0:c4:ce:8b:7d:2b:b1:88:a2:3f:58:b7:50:7d:bb: + 94:a4:39:7b:df:8c:ec:64:c8:c5:8d:86:54:6f:f1: + 87:93:51 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - B9:82:B8:B0:E0:95:0E:21:A8:12:1B:41:EE:FA:DC:2E:3E:17:D2:57 + 30:C9:45:D8:D3:C8:8E:E6:41:B8:29:BD:48:DE:BF:CD:9A:A5:81:CE X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -62,35 +63,45 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication Signature Algorithm: sha256WithRSAEncryption - 8a:09:20:6d:71:d0:16:13:6d:0e:19:30:5d:70:8f:8a:0c:ab: - 67:da:8f:40:51:f7:2b:d8:01:2b:9e:b4:ee:cf:95:79:e1:4f: - 05:87:27:8f:cf:84:93:28:60:3c:1c:6e:c6:3e:62:4f:d4:de: - 78:74:d2:da:f4:8d:a7:63:40:a3:21:bb:78:28:02:53:41:ac: - 40:f1:3c:77:69:c6:81:51:49:90:41:80:3a:03:f2:8c:d5:bc: - 4c:c1:70:4b:a1:c4:66:26:0b:cb:d2:43:69:89:64:c2:69:af: - 5d:3d:4b:51:d5:51:40:3d:2d:c5:a5:ef:a0:5a:42:53:2d:e1: - 11:1b + 01:87:4b:93:49:c5:28:8b:2f:8a:45:f3:ed:a2:1e:2f:b0:d0: + 0b:d3:cc:dc:a5:bd:ff:f5:df:86:45:f3:3e:94:ff:32:16:de: + f4:08:4a:2d:24:f3:5b:da:a8:ea:21:6d:06:c9:9c:08:1c:0e: + dc:a1:82:b9:5f:67:e4:e1:1c:29:b3:b1:58:af:ce:6c:2f:e1: + 9b:dd:98:53:45:aa:d2:02:81:fd:a1:74:e4:75:69:07:9c:cc: + 5d:b7:1a:25:ba:52:3b:8e:5c:62:12:0c:0e:a2:38:2f:b5:d3: + 33:97:fe:d1:ec:6a:5d:15:93:67:98:d9:d0:93:03:bd:78:90: + df:bd:4f:50:af:79:83:70:02:9e:eb:bc:6d:d7:0f:9b:65:8d: + 4e:79:79:d1:03:18:3d:47:3e:78:05:1d:f5:23:d2:f8:8f:fb: + 56:a1:ce:ee:e0:40:25:57:cc:4d:4c:f2:ca:65:90:e0:f8:7f: + ed:4f:12:5f:1d:9c:5e:15:3c:5e:fa:a4:5f:85:3c:a1:47:a3: + 3a:db:3f:93:3a:21:f4:55:be:fb:7c:3a:3d:58:ec:91:a0:83: + d5:b0:b9:79:08:12:1d:3b:3c:31:8d:f5:f6:da:20:d3:ca:76: + fb:83:c9:20:36:32:e5:4a:44:25:c6:d5:4d:04:59:06:71:9a: + cc:b9:47:e7 -----BEGIN CERTIFICATE----- -MIIEAzCCA2ygAwIBAgIJANjT46bL48zaMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAgFw0xNTA1 -MjQwODEzNTVaGA8yMDY1MDUxMTA4MTM1NVowNTELMAkGA1UEBhMCRkkxDjAMBgNV -BAoMBXcxLmZpMRYwFAYDVQQDDA1zZXJ2ZXI3LncxLmZpMIICIjANBgkqhkiG9w0B -AQEFAAOCAg8AMIICCgKCAgEAwPoXJ+uOR39lcQ7jRkdu/dYZ8eC9G36c7IhA2d7L -L+lk38zIL3PJN9E5Hp5QOGcbPTIP4twppwCLVel6pRn93tU7UpqJTpNHz1aEPjYj -6FXkCfW7snBWB2o/peOKPNLO/ouuquhqwXPzEKrpTST3acsxhNDLcD01SekfLTaB -Fd4LdXRDwiA5qSeF1WIVlbzXInCy9glqR9+4IyzUtwX/wKXgerJHc7BEpmgmkpOS -bjZus3aWZ1UFPoqTzZa76u8tZNI+ZBWbCeewLAsCT5KaS4oFC901J0/Cxr6BsONv -oGRYWBDaqHknV6KdpNPgrdIt05svutH7mLulC+unVT3CRjgnpdOYByQ9w/MQggvv -Qq+tJGYI7CcLTe2qsmwIyOHUqojMG7MC78Q3KJDH1vJA6W31NMkXbZEa998uYkOx -SAdqsoB+sGkbH5iyrbMnxQgjaPwdtPMbOoHsm07wBp6cvL9i/uf9XaLPO63RhWYo -l5htcxIRnD3vQo5Y9tnv1C6qNxz+xYX7wjk8xH2YNYTxsBX39FN6/LZ31osF3BA7 -HuRFCwjwYc7L+15JleYw3f5HOVNY/VrG1GUlTcSlZhBAIh3j7fzjUA4tfBEY1MaL -RbuyxfvxveEOEneq0LRUw53LZT4+cvDIYBKq/vuKS8KbSsVZLcqT4pmzHhATjMCl -MWUCAwEAAaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBS5griw4JUOIagSG0Hu -+twuPhfSVzAfBgNVHSMEGDAWgBS4kt79ihizMMOfVfMzXbTIKYpBFDA1BggrBgEF -BQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8w -EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADgYEAigkgbXHQFhNt -DhkwXXCPigyrZ9qPQFH3K9gBK5607s+VeeFPBYcnj8+EkyhgPBxuxj5iT9TeeHTS -2vSNp2NAoyG7eCgCU0GsQPE8d2nGgVFJkEGAOgPyjNW8TMFwS6HEZiYLy9JDaYlk -wmmvXT1LUdVRQD0txaXvoFpCUy3hERs= +MIIEljCCA36gAwIBAgIJANjT46bL481oMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAgFw0yMDA1MDMxNDA3NDFaGA8yMDcwMDQyMTE0MDc0MVowNTEL +MAkGA1UEBhMCRkkxDjAMBgNVBAoMBXcxLmZpMRYwFAYDVQQDDA1zZXJ2ZXI3Lncx +LmZpMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvxDC67+9DyFoRCZ4 +1pAP3pxneAdvLjThUaY0bh1P8R8at5N6GgE2BNTjNfCbUo3MLYCTaDcACV/hDYo1 +dPXuHhZpkxZHqpPKaKc5bbXbVz1FY4k4nj5XOdi9TLKgqyefSTjGxfTojYs3up8P +GqADdNh3lKTdNomrGl7WelrLv0AEkWqchPOBN6amSZH+aeyAoluyBBFXtuRoIurZ +G0zB+dOiKLG16bROCCU3ZIIUG9Lcdfj0SN658zWULWmxPESx9wgacUFMdMlwwXsJ +WP3hc206cMg6ue600Od970j6+4Hv5P45h03cScAV7JDiDeqdqcAZQNbHc0NulROy +DQ6Qwr8r2S2chUgqxUCeN2fP5xuVwiav4GGiplEHMxU1NnQz/HT4RoA2bTnfJLGo +CwWFvmIc0I4JWikMSJ2BvMX39Mmcq+kTbhFZkMqWr8aQGPc+WFHkv9EeIFyXBtHP +YRtn9WEAhwKQWs4tyzWxlmrZ/keQA7ddxz1IwF4quWbsNrjs3Q90MmVQLLfcGkdr +STMo9jc91Q17MHmG3dXXw4tV+oysWMivlBwDhosGngW5tfgUGBS2PiSV+JvEQGT3 +ooMR7LegH0yUrjMPvtTo4mtUu3Hypu8HXxM1Zja2MGQV0mDwxM6LfSuxiKI/WLdQ +fbuUpDl734zsZMjFjYZUb/GHk1ECAwEAAaOBmjCBlzAJBgNVHRMEAjAAMB0GA1Ud +DgQWBBQwyUXY08iO5kG4Kb1I3r/NmqWBzjAfBgNVHSMEGDAWgBSk/bk5G4GzquuI +HdSBqbURcMyn4TA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9z +ZXJ2ZXIudzEuZmk6ODg4OC8wEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcN +AQELBQADggEBAAGHS5NJxSiLL4pF8+2iHi+w0AvTzNylvf/134ZF8z6U/zIW3vQI +Si0k81vaqOohbQbJnAgcDtyhgrlfZ+ThHCmzsVivzmwv4ZvdmFNFqtICgf2hdOR1 +aQeczF23GiW6UjuOXGISDA6iOC+10zOX/tHsal0Vk2eY2dCTA714kN+9T1CveYNw +Ap7rvG3XD5tljU55edEDGD1HPngFHfUj0viP+1ahzu7gQCVXzE1M8splkOD4f+1P +El8dnF4VPF76pF+FPKFHozrbP5M6IfRVvvt8Oj1Y7JGgg9WwuXkIEh07PDGN9fba +INPKdvuDySA2MuVKRCXG1U0EWQZxmsy5R+c= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server-no-dnsname.csr b/tests/hwsim/auth_serv/server-no-dnsname.csr index a4e044001..6f59b705c 100644 --- a/tests/hwsim/auth_serv/server-no-dnsname.csr +++ b/tests/hwsim/auth_serv/server-no-dnsname.csr @@ -1,11 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIBhjCB8AIBADBHMQswCQYDVQQGEwJGSTEQMA4GA1UEBwwHVHV1c3VsYTEOMAwG -A1UECgwFdzEuZmkxFjAUBgNVBAMMDXNlcnZlcjMudzEuZmkwgZ8wDQYJKoZIhvcN -AQEBBQADgY0AMIGJAoGBANv8D6FIh2iGxJ56+Bgod22jWA/bvmvUQ0PEuhc3m6j/ -lqJzFBMcrhkPgVQ1EGSU42RlvpsLFtKekph3h+KamfwdVwyKDUwhL65n12Nh65Fb -WC+tZ2Zl5IMHymo2peYg9lyZJ9tj5YbYK3wdkESBIiF3CgMFw+tjYbNMMsCHhzpH -AgMBAAGgADANBgkqhkiG9w0BAQUFAAOBgQCIMaSR51fy0AWM/sbq3xYrdq682feE -rbsL03Cj89+oa0UAhE5A96Xd+wE5S2M6YhRStzOG3dV+JHcK22Toc8forosURcR4 -iiIHtNxShQ716L2nf3hfb+flO5oiZGxaqFUKRxxPSdPaqwp0OedfhMl/KJhEHPH9 -wpobDyIzqeqcPw== +MIICjDCCAXQCAQAwRzELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAM +BgNVBAoMBXcxLmZpMRYwFAYDVQQDDA1zZXJ2ZXIzLncxLmZpMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwuutBG9M6yO4kk513ADQDdmtCSH4Ekotzdt9 +Y6EyEo64473flTk6F2VU+CDWcTd9t7RyMXp6Pbp0cvOsnRY4NRt9UDutll2nwHYL +u0wGqND3LT2UpRQmGhHYQhstTm5gnWrPIts2ZeIXNbxpLqsw5c38muRPD9EBw+Yz +cTHNb9qMIZ33G9Htfjl6/WmjiBzm9tM7Gh7TcMOtNSoipN5gkDdd5+DOm31MtctB +G5yWUd9YTbdn2pUlYIr/bGKE2tYkuWXZeln4yL0DvvYX2A6GrppMfVP2sQ6CzQZh +d91GXP1FavLoIspji9Mc9k8Q7OoaCB44PYBso0hH8hYqB1v3iQIDAQABoAAwDQYJ +KoZIhvcNAQELBQADggEBAFOyTkNJyRKkPGdTpgnqiapijSufwkt3uETE+4SgVwSu +ctfu4IKhwgecJl4HiyVj8vwEoB5tJLdK4EG/wSBVdqd5nN2OEm4FClqfqgiuftrU +O+pvl+HSU3X9CrW4Is0Vmb2x5SMRPwvW3lA+fcKMpjUfbUA0E5kii18qir/UsVuH +EHCJ18BRoqUS+x4r+nxjS+ErSkdTtQtrZVOH2z9IEVGtc7tSxd9Dy4+L8TX0UNEP +PEZlvuLAR5py3/zeFjkekQKx2AhJqpPC+/NMmkbm+n81NgcBG02rCL2vLALtm9cf +6VbDKAi/K0tm3s9HHm6euogDB6q4TioPLxUpIR34W4c= -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/server-no-dnsname.key b/tests/hwsim/auth_serv/server-no-dnsname.key index fd0ad39b1..f1e96e5b6 100644 --- a/tests/hwsim/auth_serv/server-no-dnsname.key +++ b/tests/hwsim/auth_serv/server-no-dnsname.key @@ -1,16 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBANv8D6FIh2iGxJ56 -+Bgod22jWA/bvmvUQ0PEuhc3m6j/lqJzFBMcrhkPgVQ1EGSU42RlvpsLFtKekph3 -h+KamfwdVwyKDUwhL65n12Nh65FbWC+tZ2Zl5IMHymo2peYg9lyZJ9tj5YbYK3wd -kESBIiF3CgMFw+tjYbNMMsCHhzpHAgMBAAECgYEAu0p2MDWk+4xKGDfPxBmn3JOG -ZTIMhJeakTcLzLqOb6rzn+lkPQVdAH8f+AaZp1jP5OlvB2fAjZ9uZhrWeUpxMA3a -TTEJqvttF1R+PjQ7hxWByPf+cFtPfJnXmJg8DuCBpc4TbPd0MMqtu37K9m41iO7K -H5Lj6J+wp4lhv1Y4oaECQQDv0bvCgrGpSMLHigsdVcsFyjZr25+9y1J2Gnm1Hm/Z -dbUtS9cOihYh8qh3YyGAKS5psCVzdeMXGKDN05pOhEGxAkEA6tO8Bhh+YA/oG+pl -Ps9W9XjWwBCByVI+Hub6/Y9NcWckmBP+41DN1Oi7cKsSyMJ74WD5r+QYqS258tC6 -YDsBdwJBAJ8OEWN+XuqRsW26Joj8P7zFUrbSYO32Dej6wkHXwAMQSGuUYzvnZap6 -UDVub+eaaIf8JbqgM088LFqWvz7YBOECQHBlN7GTN6my812pKxyNEQoc9GypefVq -L+GKnMeQN3j37UP9DhqvKlWlr1GWED+XFsQhLmFJw6P2BvJ5hTtaArECQHBSy14H -6K7lnk1UNaz4By9MOJPbHkKUl1FCrwtQ1UhJsur1pUCbud2thz4YXQh3NyJ3X0m0 -G3R+tt7p2kJzdlU= +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDC660Eb0zrI7iS +TnXcANAN2a0JIfgSSi3N231joTISjrjjvd+VOToXZVT4INZxN323tHIxeno9unRy +86ydFjg1G31QO62WXafAdgu7TAao0PctPZSlFCYaEdhCGy1ObmCdas8i2zZl4hc1 +vGkuqzDlzfya5E8P0QHD5jNxMc1v2owhnfcb0e1+OXr9aaOIHOb20zsaHtNww601 +KiKk3mCQN13n4M6bfUy1y0EbnJZR31hNt2falSVgiv9sYoTa1iS5Zdl6WfjIvQO+ +9hfYDoaumkx9U/axDoLNBmF33UZc/UVq8ugiymOL0xz2TxDs6hoIHjg9gGyjSEfy +FioHW/eJAgMBAAECggEAD8yKeZGL6oM6sqEpbGukcXrzS4o1UUYx8D2aLDkkldx7 +n/oD5VR+IOdVu8btmr+ksP8vQlNrFRXH2olltFXYuHVB8v7jUwzETBVFXikLYSOO +5VvYcIjxjatkm/cX9QN9UUUXBPw/rIJm3zQmUmIN1JKdpvBaeC24tugxwzsGK8qm +kefz6Rc+UTC0tLz62ti6fWeR6TipRFdExtXLRZlwYCDy33GBj1VRRSI5ZFxjPHqI +tChrK2OUkZrkWUsUZiPq3hFytNyfVbSzqBHJPwhufuUZw5SsSrluqJbrtoi+kOKY +lJ/gE7BBL7ZOEj9chHG5WXwN0hsyEzkm582Ls/CDAQKBgQD9L8WFL5UQitnVsEZB ++rv6WQwYsS5H2nsjRasiGp155eSGnFlkqZbUBkFCAU0FjHotTFl3ZPd+w2JP6mda +zKnAj9SfgX7UF4M8Vx3KbW2qMamycFhW3YUOyk7b3oCMKLHhwC0tcOWDqxNOgR5y +syulT8aDse9Ey/c8yIefY37VuwKBgQDFFihbgtUuR3gJR6jMWxXfNlpxyyEA77QN +HHsLjqcq1Kte/KrV2zUXy+aZAJYjnvLMOZodxRkGv+I6309S3TG9gzDNt1iguYNa +ETif4hDJoQHrXgWnkPKjuGyE811ArhHfdrPEjBhNX538T4fPZD0FJM4ZpVlvoMyz +NnNieN2RiwKBgQCnir1CbUJPOBL+fS+A6dMKz3JZxKXDlqh1ptygLMyYpbCcA0qE +elT86Ua1zvaQ/Wy8HRH3GDFPCSw9hffu9hA/BO7GvoKXBxgpDd0A33j6bvLEyeMr +WFt8dhPJG2wlU6iiovFCaLr4bnTQNlFXxYjUU/4hl9WlyPNKnchhiQ2dkQKBgQC9 +akA7QxCzu8hn0tEuJlRtBIYEW59KkRXQjBDN2Lpc9awGTHu7sUPjrPnhDqk9buQW +1z2BYw5caEp7HmfUUfYeF1nuPEoXnnPZOjfboZ9UyUNY/DIfC7XHF9ZkKKj1ItbW +l/TJ74LjygPCnIUAE2x55xeVmk7MdBSIIMrgVx1LZQKBgDFj79Q2LNKZ9OpCs/X6 +fcu30wHRTraQ4mntoQYycjn3IuGfPJ+bFYaz9oyjarMbGeVftdpwWSMQBm/a7nCU +aWPBq+INWls8NE2WtX7jzWj00AzT8TEGbJirQfOJbNXCGrVW7GrGH6JlZYpsC/lb ++CynJQUivjDzYCz1sGjNScGs -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/server-no-dnsname.pem b/tests/hwsim/auth_serv/server-no-dnsname.pem index 432f9b6ea..a09e5116c 100644 --- a/tests/hwsim/auth_serv/server-no-dnsname.pem +++ b/tests/hwsim/auth_serv/server-no-dnsname.pem @@ -2,34 +2,43 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:d3:e3:a6:cb:e3:cd:20 + d8:d3:e3:a6:cb:e3:cd:60 Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Oct 4 13:02:23 2019 GMT - Not After : Oct 3 13:02:23 2020 GMT + Not Before: May 2 19:55:38 2020 GMT + Not After : May 2 19:55:38 2021 GMT Subject: C=FI, O=w1.fi, CN=server3.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:db:fc:0f:a1:48:87:68:86:c4:9e:7a:f8:18:28: - 77:6d:a3:58:0f:db:be:6b:d4:43:43:c4:ba:17:37: - 9b:a8:ff:96:a2:73:14:13:1c:ae:19:0f:81:54:35: - 10:64:94:e3:64:65:be:9b:0b:16:d2:9e:92:98:77: - 87:e2:9a:99:fc:1d:57:0c:8a:0d:4c:21:2f:ae:67: - d7:63:61:eb:91:5b:58:2f:ad:67:66:65:e4:83:07: - ca:6a:36:a5:e6:20:f6:5c:99:27:db:63:e5:86:d8: - 2b:7c:1d:90:44:81:22:21:77:0a:03:05:c3:eb:63: - 61:b3:4c:32:c0:87:87:3a:47 + 00:c2:eb:ad:04:6f:4c:eb:23:b8:92:4e:75:dc:00: + d0:0d:d9:ad:09:21:f8:12:4a:2d:cd:db:7d:63:a1: + 32:12:8e:b8:e3:bd:df:95:39:3a:17:65:54:f8:20: + d6:71:37:7d:b7:b4:72:31:7a:7a:3d:ba:74:72:f3: + ac:9d:16:38:35:1b:7d:50:3b:ad:96:5d:a7:c0:76: + 0b:bb:4c:06:a8:d0:f7:2d:3d:94:a5:14:26:1a:11: + d8:42:1b:2d:4e:6e:60:9d:6a:cf:22:db:36:65:e2: + 17:35:bc:69:2e:ab:30:e5:cd:fc:9a:e4:4f:0f:d1: + 01:c3:e6:33:71:31:cd:6f:da:8c:21:9d:f7:1b:d1: + ed:7e:39:7a:fd:69:a3:88:1c:e6:f6:d3:3b:1a:1e: + d3:70:c3:ad:35:2a:22:a4:de:60:90:37:5d:e7:e0: + ce:9b:7d:4c:b5:cb:41:1b:9c:96:51:df:58:4d:b7: + 67:da:95:25:60:8a:ff:6c:62:84:da:d6:24:b9:65: + d9:7a:59:f8:c8:bd:03:be:f6:17:d8:0e:86:ae:9a: + 4c:7d:53:f6:b1:0e:82:cd:06:61:77:dd:46:5c:fd: + 45:6a:f2:e8:22:ca:63:8b:d3:1c:f6:4f:10:ec:ea: + 1a:08:1e:38:3d:80:6c:a3:48:47:f2:16:2a:07:5b: + f7:89 Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - 8E:9A:4F:4D:46:AD:59:AC:7F:4C:9C:BE:6D:5B:D7:99:63:8D:C7:70 + 5E:84:D6:31:98:17:71:F8:63:5C:32:5B:7D:33:C0:D4:FA:36:A7:6A X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -37,27 +46,40 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication Signature Algorithm: sha256WithRSAEncryption - 17:8a:95:bc:a7:76:e0:b7:b6:b6:47:5a:41:44:0f:43:76:1f: - 50:87:f6:64:fe:e9:3a:fb:73:04:df:7b:57:7a:34:ba:ab:bc: - ab:d1:18:59:bf:6e:9b:4d:8c:3f:15:65:dd:e9:3c:86:01:69: - d5:2b:c3:23:65:9c:07:ef:4a:52:09:c7:3a:68:8e:14:4d:4a: - 78:23:0c:ec:8d:37:13:2d:ac:ac:6e:d1:f8:5c:a1:1f:50:50: - 00:fd:ab:e9:f6:ae:f2:c4:78:3c:44:e3:5e:b0:c6:6d:a0:06: - 98:c9:e2:d1:9a:d7:8b:09:af:f4:10:06:e1:9f:1e:de:d0:c3: - b9:1c + 47:5a:18:97:c2:3a:a5:4a:6c:f6:11:53:ac:d3:3f:d7:0c:7f: + e5:cb:9c:7d:02:f3:b7:ab:0c:a6:8d:d9:77:6c:bd:2a:41:47: + fb:70:7f:0d:09:53:fc:e4:a4:5e:0b:1c:4d:84:05:71:ab:f9: + 68:9a:df:4f:b6:73:20:fd:05:cc:e2:f1:8a:9d:20:7a:27:8a: + 60:a6:ed:0e:eb:cf:5f:13:32:1b:89:ec:f6:dc:eb:5f:42:f0: + a8:f9:42:dd:e5:e6:19:28:82:61:df:07:24:7b:c6:c9:ce:a5: + 44:f0:d7:ba:4b:2b:9d:d7:97:1c:13:e9:da:0a:58:26:97:48: + 6e:33:ec:d5:d3:32:96:23:b6:40:01:a8:e0:88:ea:2a:73:82: + d7:41:58:9b:b3:dc:6b:41:2f:ae:33:38:43:05:ed:04:ff:b9: + 63:b7:7e:9b:fa:85:ab:df:12:36:24:cf:ec:8d:f8:d5:1c:95: + 4e:a8:9c:e4:8a:90:ac:db:a0:4b:d8:14:e0:84:97:f7:cb:da: + 95:cd:02:11:65:23:8b:ad:f1:c3:46:2d:2d:20:4d:cb:63:ef: + ae:be:ea:19:1d:2d:c5:35:c8:aa:b9:d3:8c:4f:cd:44:9c:fc: + a4:37:f5:b8:80:06:af:5e:ce:bc:81:23:cd:6b:de:31:c2:4c: + e8:e6:68:71 -----BEGIN CERTIFICATE----- -MIICfTCCAeagAwIBAgIJANjT46bL480gMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xOTEw -MDQxMzAyMjNaFw0yMDEwMDMxMzAyMjNaMDUxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEWMBQGA1UEAwwNc2VydmVyMy53MS5maTCBnzANBgkqhkiG9w0BAQEF -AAOBjQAwgYkCgYEA2/wPoUiHaIbEnnr4GCh3baNYD9u+a9RDQ8S6FzebqP+WonMU -ExyuGQ+BVDUQZJTjZGW+mwsW0p6SmHeH4pqZ/B1XDIoNTCEvrmfXY2HrkVtYL61n -ZmXkgwfKajal5iD2XJkn22PlhtgrfB2QRIEiIXcKAwXD62Nhs0wywIeHOkcCAwEA -AaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBSOmk9NRq1ZrH9MnL5tW9eZY43H -cDAfBgNVHSMEGDAWgBS4kt79ihizMMOfVfMzXbTIKYpBFDA1BggrBgEFBQcBAQQp -MCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8wEwYDVR0l -BAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADgYEAF4qVvKd24Le2tkdaQUQP -Q3YfUIf2ZP7pOvtzBN97V3o0uqu8q9EYWb9um02MPxVl3ek8hgFp1SvDI2WcB+9K -UgnHOmiOFE1KeCMM7I03Ey2srG7R+FyhH1BQAP2r6fau8sR4PETjXrDGbaAGmMni -0ZrXiwmv9BAG4Z8e3tDDuRw= +MIIDlDCCAnygAwIBAgIJANjT46bL481gMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDIxOTU1MzhaFw0yMTA1MDIxOTU1MzhaMDUxCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEWMBQGA1UEAwwNc2VydmVyMy53MS5m +aTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMLrrQRvTOsjuJJOddwA +0A3ZrQkh+BJKLc3bfWOhMhKOuOO935U5OhdlVPgg1nE3fbe0cjF6ej26dHLzrJ0W +ODUbfVA7rZZdp8B2C7tMBqjQ9y09lKUUJhoR2EIbLU5uYJ1qzyLbNmXiFzW8aS6r +MOXN/JrkTw/RAcPmM3ExzW/ajCGd9xvR7X45ev1po4gc5vbTOxoe03DDrTUqIqTe +YJA3Xefgzpt9TLXLQRucllHfWE23Z9qVJWCK/2xihNrWJLll2XpZ+Mi9A772F9gO +hq6aTH1T9rEOgs0GYXfdRlz9RWry6CLKY4vTHPZPEOzqGggeOD2AbKNIR/IWKgdb +94kCAwEAAaOBmjCBlzAJBgNVHRMEAjAAMB0GA1UdDgQWBBRehNYxmBdx+GNcMlt9 +M8DU+janajAfBgNVHSMEGDAWgBSk/bk5G4GzquuIHdSBqbURcMyn4TA1BggrBgEF +BQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6Ly9zZXJ2ZXIudzEuZmk6ODg4OC8w +EwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQELBQADggEBAEdaGJfCOqVK +bPYRU6zTP9cMf+XLnH0C87erDKaN2XdsvSpBR/twfw0JU/zkpF4LHE2EBXGr+Wia +30+2cyD9Bczi8YqdIHonimCm7Q7rz18TMhuJ7Pbc619C8Kj5Qt3l5hkogmHfByR7 +xsnOpUTw17pLK53XlxwT6doKWCaXSG4z7NXTMpYjtkABqOCI6ipzgtdBWJuz3GtB +L64zOEMF7QT/uWO3fpv6havfEjYkz+yN+NUclU6onOSKkKzboEvYFOCEl/fL2pXN +AhFlI4ut8cNGLS0gTctj766+6hkdLcU1yKq504xPzUSc/KQ39biABq9ezryBI81r +3jHCTOjmaHE= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server.csr b/tests/hwsim/auth_serv/server.csr index a0543aa21..3e8f7d965 100644 --- a/tests/hwsim/auth_serv/server.csr +++ b/tests/hwsim/auth_serv/server.csr @@ -1,11 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIBhTCB7wIBADBGMQswCQYDVQQGEwJGSTEQMA4GA1UEBwwHVHV1c3VsYTEOMAwG -A1UECgwFdzEuZmkxFTATBgNVBAMMDHNlcnZlci53MS5maTCBnzANBgkqhkiG9w0B -AQEFAAOBjQAwgYkCgYEAuqB3VSIUhVVlm2Qsre2b3WUxydpgUM441jTc6LwbnjDn -EuNTbMntSAN5gWmYzoq4d0c2Rc/G4PF7HnGJVPcBzCKtoEKxqDWeYKo6mFHQ/x/u -vo0KY/uiORfyZGH2ZQIyeXThn9GJZVWpwyCev2lWs/dPP6lUwtqPPK/ydVT6foEC -AwEAAaAAMA0GCSqGSIb3DQEBBQUAA4GBAHa+iMFm3en/hRmhLfMCE7n4l9nczk/P -sLlxcBIeu3pnEXQsI8SZjG8T5kehyFva7mmqcbpFfDxddXxNsqckBfKDjwLEhH49 -gpUg6ggYQ1R82IgMEmTdHKyIeTCIvyzPV2Vz1LrGpdCiRMg713zumghsCsn781mN -q7p5YSQL5DdY +MIICizCCAXMCAQAwRjELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAM +BgNVBAoMBXcxLmZpMRUwEwYDVQQDDAxzZXJ2ZXIudzEuZmkwggEiMA0GCSqGSIb3 +DQEBAQUAA4IBDwAwggEKAoIBAQD9Dl7NGSxqQYPZLA42zQmwj7LJjMjSAzhuVLxD +7s74WbHpP23UXuPFcxk9C7wp19BudQA1/PdlsbYPywZJz6lOPcJkSxgkCnC4blTc +kD9sGP22iKs33ItLteH/7btFBaPwqlEr8XkGfy/NXfzmiq8buXvKQ3UBHY4t2RET +hvs8S2CkKUnj0iAgy1wNnNKcMCERvLN032Swt2fuat+vPRgCt9zlVHW1bEDEsIob +xv2rHrnv0YMJDVW6F4hO0L3PczZ8KEv2qkjU6Psl2B2vyWhzrEauy+t5Nletw3AC +FW3wpUNzq3IEsRZgdA5KwY9SKBqVfqvQBPb6Edob0ZmkT57tAgMBAAGgADANBgkq +hkiG9w0BAQsFAAOCAQEAUQqUbXEUfPwdJoYL1jPZFCXDMFLjQgro6uWQ+yK8NEOX +MekF9AmJkBNHfOXfhtpuSutn+4TGLGShS+ocvR9oGJkSULZYOzbsntP6ZEcwaxo5 +rvSSmm1cx1GNQQ/dzoefeWlRnaUVcOTljMutCae1X9KTXuLW2DreEwo4aqPsu+EK +iSL/GcdYozU+p+ZE0BP26kDeQYKYD/1XOXvGclCAG11U3M03cazqiLr+auNhAL0T +y4PYJnrNhTZdIXLXsPTKcG2VhbGSC7NTia10XRl2Jr+yFTRvR2S0F1vZczbXc7gj +JBMk6kojPpMvqe2WmaXWEH+tzeBvTELnJDHdDl+w9A== -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/server.key b/tests/hwsim/auth_serv/server.key index 1416327be..7dd02ae13 100644 --- a/tests/hwsim/auth_serv/server.key +++ b/tests/hwsim/auth_serv/server.key @@ -1,16 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALqgd1UiFIVVZZtk -LK3tm91lMcnaYFDOONY03Oi8G54w5xLjU2zJ7UgDeYFpmM6KuHdHNkXPxuDxex5x -iVT3AcwiraBCsag1nmCqOphR0P8f7r6NCmP7ojkX8mRh9mUCMnl04Z/RiWVVqcMg -nr9pVrP3Tz+pVMLajzyv8nVU+n6BAgMBAAECgYBH8LlvcM62QyAC0Y/DkBeINY0G -wY5lN8mDESei83g196XriwPKqOA15Vj+QOVtoN3Q5PuP17NTXOLX7m5A+WKQVK/O -Cl0uBCEqS9YvPN6Fp9va5VonhWxGpLdZcrxETTpxjHhVBGS9C8wBday65r2nDfo6 -uWlCebceUBuuSzwybQJBAOAwS7ZY8xY/bCNDzvfnNuPsPQDEQWVx6A9mv9BnepT/ -8bQcvfkUbXyWy5NsPN6yt/tqmjdbUEFAuNJlI23I2wsCQQDVG7poTL8KPa7UZge7 -W79FyyEoL5but1VPTAN6JJNTMpp9k2LBWFjUSmTiTkeccHfbvKxMjUuI7NQwya41 -hSQjAkApSRuYUBcsIK/kaqdhxeW44Zd2Xa4BZZGrzGtEkNnlOKElXympBhcHm6mP -053+EQGKvl36FcnYynd+33s/y35zAkAZ5ZC1c/4TJIPGU8/EuNV5icGxvHa+85Bu -XnJduWwdxBx5/hsWG8JPqeqwhYq2PASUs0zM0K7JKN5wP1HoNxG5AkEAlaumCfLv -vA/b3HVZD/b0nxkl/F7g3nACPVJ48FU2BneB+bU75zqeI3B7xGd9CKamkuutH6or -fe17ZI8ZeLCLqA== +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQD9Dl7NGSxqQYPZ +LA42zQmwj7LJjMjSAzhuVLxD7s74WbHpP23UXuPFcxk9C7wp19BudQA1/PdlsbYP +ywZJz6lOPcJkSxgkCnC4blTckD9sGP22iKs33ItLteH/7btFBaPwqlEr8XkGfy/N +Xfzmiq8buXvKQ3UBHY4t2REThvs8S2CkKUnj0iAgy1wNnNKcMCERvLN032Swt2fu +at+vPRgCt9zlVHW1bEDEsIobxv2rHrnv0YMJDVW6F4hO0L3PczZ8KEv2qkjU6Psl +2B2vyWhzrEauy+t5Nletw3ACFW3wpUNzq3IEsRZgdA5KwY9SKBqVfqvQBPb6Edob +0ZmkT57tAgMBAAECggEARr4KsIl2CipQgpi3TIibSdmSIJgT1+oAj49upgsPnwvs +GYma2YDBagRYLOGn84aahRZ+PZl/S9WXUOjv1BiSewX23vTDRegJRPXLEXHd2QlP +fATO4Knt4vdwu4wpCw2dm/zw/jjeHXvW0DGTLpvcggKjYZLkFbC+e4CwLmZQu7TE +e5QnNDqzNjiHEYJ7P70/o5otgVCo2Kn/on+/dsVf5/x0zPktoKO/aWZPkC8ef+aY +rClhFRQZtrys6/dQ5r3ZTtublCRB3hq3tx/THJKROFvkSDiI0fJJkn2PxjKaA4ot +8Gm3598Dj5sjlluanEg72n0jreSS6WYnHfCp2/7HgQKBgQD/ZNvLsoNABNQFXhin +6e6PBG+VU1GY5yWXsdNA1NcOaq7PhdNnpQ2SkIZIwfdNmypMtY/y7yxAlv7jgqzQ +UEo4ZXQirq6ehKddy0olpu0gN8SOwKJ8VCSnGaZXp8E0ueRTLLD4JAvg4mQY+mJ5 +AYTa4Y75JTFOTe/x9+DbFLOSzQKBgQD9qBdywd/eEf45KPnoLnvDTxpS/4b5liMS +q+j8bFz5NmL/6TkAZp7Clp95wMh0Qeg0yznDNUOKG48yHJuUp8TuUTXE39u5CTki +s1wRYEtUKwKbjKyurGkR49BhJEo+aO2ai14D+pEDCoYDhICNk5IaHolmIvMPG+4I +HAG9B1l8oQKBgAVVvQWnR/iZYThve8JeL56LMC2FXQn9ohpmG4yaJZfmgJpTKFRc +7Uinfjac3qafXCXYERa5CkqbHN3xx9xeIP7Gl8N1tK4ZBUn/SiA5OXDX2WJGAd7o +/w8CiSgBmBaa33shTt0QG7Np5z9iU5ZFgtnzpkHsFfiVxjJexDKvXwTtAoGBAIqK +y7vXHoH5S+RGeDCTau+i/drFTCB4G1HwaUGtoh5P0US7SnHomt/nStVCMXomIUDs +mvD+35PIN68EJwnLlGkiG/8a0bS/z+AfHLM06A/hqfvxmsOQ0ZZ+2mqkWpS51MTr +R/9eVOPXVJkJPvmU12DCuwL5Jc5jz9/IBD8Ni5fhAoGBANsZyLEn9Rm2/kL6xe1k +jqe0gtGEctd71NdurFXSDGG1CZFeUGFGshGalRu6RqcCP6r/LpZHZc6vFDDep/1G +1fSLR3ula5rBAIrMUQPXq3LXpvC3BCZFvn3A2LRjNYB9LG5WtL/lfkeTzrx9L8hL +6mC0BwuQ5yNIyfXv1/0dQD0+ -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/server.pem b/tests/hwsim/auth_serv/server.pem index a8baa17ed..98fc032a4 100644 --- a/tests/hwsim/auth_serv/server.pem +++ b/tests/hwsim/auth_serv/server.pem @@ -2,34 +2,43 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:d3:e3:a6:cb:e3:cd:1f + d8:d3:e3:a6:cb:e3:cd:5f Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Oct 4 13:02:23 2019 GMT - Not After : Oct 3 13:02:23 2020 GMT + Not Before: May 2 19:55:38 2020 GMT + Not After : May 2 19:55:38 2021 GMT Subject: C=FI, O=w1.fi, CN=server.w1.fi Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:ba:a0:77:55:22:14:85:55:65:9b:64:2c:ad:ed: - 9b:dd:65:31:c9:da:60:50:ce:38:d6:34:dc:e8:bc: - 1b:9e:30:e7:12:e3:53:6c:c9:ed:48:03:79:81:69: - 98:ce:8a:b8:77:47:36:45:cf:c6:e0:f1:7b:1e:71: - 89:54:f7:01:cc:22:ad:a0:42:b1:a8:35:9e:60:aa: - 3a:98:51:d0:ff:1f:ee:be:8d:0a:63:fb:a2:39:17: - f2:64:61:f6:65:02:32:79:74:e1:9f:d1:89:65:55: - a9:c3:20:9e:bf:69:56:b3:f7:4f:3f:a9:54:c2:da: - 8f:3c:af:f2:75:54:fa:7e:81 + 00:fd:0e:5e:cd:19:2c:6a:41:83:d9:2c:0e:36:cd: + 09:b0:8f:b2:c9:8c:c8:d2:03:38:6e:54:bc:43:ee: + ce:f8:59:b1:e9:3f:6d:d4:5e:e3:c5:73:19:3d:0b: + bc:29:d7:d0:6e:75:00:35:fc:f7:65:b1:b6:0f:cb: + 06:49:cf:a9:4e:3d:c2:64:4b:18:24:0a:70:b8:6e: + 54:dc:90:3f:6c:18:fd:b6:88:ab:37:dc:8b:4b:b5: + e1:ff:ed:bb:45:05:a3:f0:aa:51:2b:f1:79:06:7f: + 2f:cd:5d:fc:e6:8a:af:1b:b9:7b:ca:43:75:01:1d: + 8e:2d:d9:11:13:86:fb:3c:4b:60:a4:29:49:e3:d2: + 20:20:cb:5c:0d:9c:d2:9c:30:21:11:bc:b3:74:df: + 64:b0:b7:67:ee:6a:df:af:3d:18:02:b7:dc:e5:54: + 75:b5:6c:40:c4:b0:8a:1b:c6:fd:ab:1e:b9:ef:d1: + 83:09:0d:55:ba:17:88:4e:d0:bd:cf:73:36:7c:28: + 4b:f6:aa:48:d4:e8:fb:25:d8:1d:af:c9:68:73:ac: + 46:ae:cb:eb:79:36:57:ad:c3:70:02:15:6d:f0:a5: + 43:73:ab:72:04:b1:16:60:74:0e:4a:c1:8f:52:28: + 1a:95:7e:ab:d0:04:f6:fa:11:da:1b:d1:99:a4:4f: + 9e:ed Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - 31:4F:10:5C:67:9F:BE:4E:88:D6:DC:C5:AB:9E:12:88:86:69:02:4F + 71:26:7A:1F:72:81:97:24:11:AA:C0:75:FA:BF:31:10:69:49:D0:E7 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -39,27 +48,40 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication Signature Algorithm: sha256WithRSAEncryption - 0b:dc:4c:f7:63:b6:7b:db:79:a9:6b:d3:70:cb:c1:51:30:2d: - 76:d3:20:6a:95:3a:fe:93:4b:6a:28:86:2f:1c:1c:ea:25:92: - b5:86:a8:08:ea:c4:0e:15:e1:b9:fd:b3:f0:d8:5a:bf:58:f7: - 57:a3:2d:fa:0e:ca:17:e4:42:bc:1d:40:f4:c6:01:76:ea:f3: - d3:44:d6:5b:19:1a:24:ba:c2:6e:d9:7b:10:00:f2:2c:37:9a: - fb:3e:74:2e:aa:92:b0:db:e0:92:d4:3e:66:89:37:08:71:dd: - 53:3f:83:6b:74:0e:3e:e5:1e:2f:f1:0f:b0:fb:ed:90:82:b4: - d7:ce + 62:10:9c:ed:50:98:34:2e:7c:ef:1a:11:93:a5:f0:ad:8d:03: + 71:9a:a1:be:c0:24:9a:4d:28:cd:28:ea:55:7e:7b:b3:9c:f4: + ad:94:44:7b:9c:e2:0a:c0:35:7e:80:a6:aa:9c:ae:36:22:fd: + 4e:25:b3:1f:66:1d:2e:66:4b:d4:8c:ad:3e:0d:92:7d:3a:93: + 05:c6:51:e4:75:fc:b4:6c:24:cb:c4:79:06:2f:d1:b3:6c:0c: + d8:82:76:08:cc:9a:c4:61:14:1b:3d:38:f4:a2:2c:49:0e:d5: + 82:58:46:52:3c:cd:12:d9:57:dd:58:25:34:0b:d7:7b:2a:2f: + 60:ce:da:9f:f2:98:e2:8e:0b:6c:69:42:1c:27:75:3a:7c:ae: + a5:9a:19:bc:6c:67:fc:04:a9:f4:fd:2c:17:79:56:52:a3:3b: + 01:60:ae:ea:9b:ed:a4:30:53:fc:ef:57:bb:f1:fc:04:2a:5c: + 2b:74:d0:1f:0b:30:ec:0a:b2:8b:4d:4a:b4:33:0d:cd:dc:28: + 29:0a:d1:eb:36:09:bc:15:a7:c7:f0:f0:9c:7e:48:75:14:75: + 2d:ed:fb:7a:14:e4:69:4a:54:b9:ad:25:ba:bb:d9:c0:eb:a0: + 81:53:c7:07:ea:34:73:1f:9d:43:63:8e:f9:06:c9:4d:15:bf: + 68:f9:91:de -----BEGIN CERTIFICATE----- -MIIClTCCAf6gAwIBAgIJANjT46bL480fMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xOTEw -MDQxMzAyMjNaFw0yMDEwMDMxMzAyMjNaMDQxCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEVMBMGA1UEAwwMc2VydmVyLncxLmZpMIGfMA0GCSqGSIb3DQEBAQUA -A4GNADCBiQKBgQC6oHdVIhSFVWWbZCyt7ZvdZTHJ2mBQzjjWNNzovBueMOcS41Ns -ye1IA3mBaZjOirh3RzZFz8bg8XsecYlU9wHMIq2gQrGoNZ5gqjqYUdD/H+6+jQpj -+6I5F/JkYfZlAjJ5dOGf0YllVanDIJ6/aVaz908/qVTC2o88r/J1VPp+gQIDAQAB -o4GzMIGwMAkGA1UdEwQCMAAwHQYDVR0OBBYEFDFPEFxnn75OiNbcxaueEoiGaQJP -MB8GA1UdIwQYMBaAFLiS3v2KGLMww59V8zNdtMgpikEUMDUGCCsGAQUFBwEBBCkw -JzAlBggrBgEFBQcwAYYZaHR0cDovL3NlcnZlci53MS5maTo4ODg4LzAXBgNVHREE -EDAOggxzZXJ2ZXIudzEuZmkwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcN -AQELBQADgYEAC9xM92O2e9t5qWvTcMvBUTAtdtMgapU6/pNLaiiGLxwc6iWStYao -COrEDhXhuf2z8Nhav1j3V6Mt+g7KF+RCvB1A9MYBdurz00TWWxkaJLrCbtl7EADy -LDea+z50LqqSsNvgktQ+Zok3CHHdUz+Da3QOPuUeL/EPsPvtkIK0184= +MIIDrDCCApSgAwIBAgIJANjT46bL481fMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDIxOTU1MzhaFw0yMTA1MDIxOTU1MzhaMDQxCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEVMBMGA1UEAwwMc2VydmVyLncxLmZp +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/Q5ezRksakGD2SwONs0J +sI+yyYzI0gM4blS8Q+7O+Fmx6T9t1F7jxXMZPQu8KdfQbnUANfz3ZbG2D8sGSc+p +Tj3CZEsYJApwuG5U3JA/bBj9toirN9yLS7Xh/+27RQWj8KpRK/F5Bn8vzV385oqv +G7l7ykN1AR2OLdkRE4b7PEtgpClJ49IgIMtcDZzSnDAhEbyzdN9ksLdn7mrfrz0Y +Arfc5VR1tWxAxLCKG8b9qx6579GDCQ1VuheITtC9z3M2fChL9qpI1Oj7Jdgdr8lo +c6xGrsvreTZXrcNwAhVt8KVDc6tyBLEWYHQOSsGPUigalX6r0AT2+hHaG9GZpE+e +7QIDAQABo4GzMIGwMAkGA1UdEwQCMAAwHQYDVR0OBBYEFHEmeh9ygZckEarAdfq/ +MRBpSdDnMB8GA1UdIwQYMBaAFKT9uTkbgbOq64gd1IGptRFwzKfhMDUGCCsGAQUF +BwEBBCkwJzAlBggrBgEFBQcwAYYZaHR0cDovL3NlcnZlci53MS5maTo4ODg4LzAX +BgNVHREEEDAOggxzZXJ2ZXIudzEuZmkwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJ +KoZIhvcNAQELBQADggEBAGIQnO1QmDQufO8aEZOl8K2NA3Gaob7AJJpNKM0o6lV+ +e7Oc9K2URHuc4grANX6ApqqcrjYi/U4lsx9mHS5mS9SMrT4Nkn06kwXGUeR1/LRs +JMvEeQYv0bNsDNiCdgjMmsRhFBs9OPSiLEkO1YJYRlI8zRLZV91YJTQL13sqL2DO +2p/ymOKOC2xpQhwndTp8rqWaGbxsZ/wEqfT9LBd5VlKjOwFgruqb7aQwU/zvV7vx +/AQqXCt00B8LMOwKsotNSrQzDc3cKCkK0es2CbwVp8fw8Jx+SHUUdS3t+3oU5GlK +VLmtJbq72cDroIFTxwfqNHMfnUNjjvkGyU0Vv2j5kd4= -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/server.pkcs12 b/tests/hwsim/auth_serv/server.pkcs12 index a5b698efa..a72b1644a 100644 Binary files a/tests/hwsim/auth_serv/server.pkcs12 and b/tests/hwsim/auth_serv/server.pkcs12 differ diff --git a/tests/hwsim/auth_serv/test-ca/cacert.pem b/tests/hwsim/auth_serv/test-ca/cacert.pem index b128893a1..7fcbdf767 100644 --- a/tests/hwsim/auth_serv/test-ca/cacert.pem +++ b/tests/hwsim/auth_serv/test-ca/cacert.pem @@ -1,55 +1,79 @@ Certificate: Data: Version: 3 (0x2) - Serial Number: 15624081837803162817 (0xd8d3e3a6cbe3ccc1) - Signature Algorithm: sha1WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Serial Number: + 42:97:6c:30:8e:79:fc:7b:6a:e3:ef:9d:18:a4:74:9d:8b:5f:57:53 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Validity - Not Before: Jun 29 16:41:22 2013 GMT - Not After : Jun 27 16:41:22 2023 GMT - Subject: C=FI, O=w1.fi, CN=Root CA + Not Before: May 2 19:49:48 2020 GMT + Not After : Apr 30 19:49:48 2030 GMT + Subject: C = FI, L = Tuusula, O = w1.fi, CN = Root CA Subject Public Key Info: Public Key Algorithm: rsaEncryption - Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:be:1e:86:e4:79:03:c1:d1:94:d5:d4:b3:b1:28: - 90:76:fb:b8:a6:cd:6d:1c:d1:48:f4:08:9a:67:ff: - f9:a6:54:b1:19:29:df:29:1b:cd:f1:6f:66:01:e7: - db:79:ce:c0:39:2a:25:13:26:94:0c:2c:7b:5a:2c: - 81:0f:94:ee:51:d0:75:e6:46:db:17:46:a7:15:8b: - 0e:57:0f:b0:54:76:63:12:ca:86:18:bc:1a:c3:16: - c0:70:09:d6:6b:43:39:b8:98:29:46:ac:cb:6a:ad: - 38:88:3b:07:dc:81:cd:3a:f6:1d:f6:2f:ef:1d:d7: - ae:8a:b6:d1:e7:b3:15:02:b9 + 00:bc:f4:ee:44:62:7f:62:4f:a1:81:46:ba:c4:aa: + 1e:fd:4e:d0:ed:f1:47:cb:25:5b:66:7a:86:39:91: + ca:b5:61:a7:7e:2f:3c:63:7d:39:b8:1a:9e:cb:6d: + 32:32:91:de:49:49:84:da:15:be:2b:dd:c6:bc:1f: + dc:6e:c0:2d:77:f2:d0:7b:2c:40:19:07:60:55:b0: + ff:7c:51:ef:38:d1:f0:2a:da:a8:cc:ea:d6:54:a4: + ef:be:17:44:1a:9e:33:70:57:a4:f3:06:ac:3d:ee: + 4b:2d:e5:46:25:2d:33:09:f6:49:a8:02:31:a4:65: + 9b:32:0a:67:f5:02:e1:3b:47:a6:ae:e4:f6:85:eb: + 5d:3e:02:66:dd:11:98:ac:34:72:c2:8f:25:55:4a: + 6a:ea:e8:82:2f:bd:7f:78:31:a4:5a:d7:32:bb:64: + 48:46:23:ef:c8:c9:e2:84:00:56:72:e8:4b:54:95: + 62:3a:5a:11:79:ee:40:43:9e:16:2c:cc:e6:45:f4: + bb:82:28:c2:83:35:2c:55:36:99:59:11:b1:15:d0: + 03:c1:a5:37:e1:1f:bb:43:c7:b4:b9:33:de:14:d7: + 7c:99:45:0f:c1:06:fe:b6:25:10:59:b7:72:76:7f: + 91:4b:ea:d1:b9:6a:6a:ed:dd:1b:a9:0e:a7:29:48: + b7:4d Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Subject Key Identifier: - B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 X509v3 Basic Constraints: CA:TRUE - Signature Algorithm: sha1WithRSAEncryption - 1a:cf:77:60:44:43:c4:55:0e:99:e0:89:aa:b9:d3:7b:32:b7: - 5c:9c:7c:ca:fe:8c:d4:94:c6:5e:f3:83:19:5f:29:59:68:a4: - 4f:dc:04:2e:b8:71:c0:6d:3b:ae:01:e4:b9:88:99:cc:ce:82: - be:6a:28:c2:ac:6a:94:c6:87:90:ed:85:3c:10:71:c5:ff:3c: - 70:64:e2:41:62:31:ea:86:7b:11:8c:93:ea:c6:f3:f3:4e:f9: - d4:f2:81:90:d7:f4:fa:a1:91:6e:d4:dd:15:3e:26:3b:ac:1e: - c3:c2:1f:ed:bb:34:bf:cb:b2:67:c6:c6:51:e8:51:22:b4:f3: - 92:e8 + Signature Algorithm: sha256WithRSAEncryption + 41:f9:c3:a3:77:11:92:55:e7:4b:4a:32:6a:31:d9:51:cf:06: + a5:39:ea:30:98:b8:8d:4f:24:c5:34:fd:c6:98:10:59:32:7e: + 57:f5:8f:ba:67:c9:fc:44:68:b3:7c:f1:af:3a:5f:0d:8f:a1: + fe:41:21:0e:e9:08:a3:63:49:66:34:4a:cd:ce:66:74:47:30: + f7:dc:82:99:21:56:82:ff:2d:12:90:7d:7a:64:22:a0:ed:fa: + 62:d9:5a:d3:97:96:0c:04:a7:47:88:da:53:b6:33:15:15:f9: + da:ee:ac:25:e9:07:02:89:bc:73:a2:c6:27:6f:1f:bd:73:b8: + 8e:f7:94:54:57:a7:8b:5b:9a:24:aa:86:d4:04:5c:8c:cb:28: + a2:45:f9:34:f0:01:20:bb:06:e8:41:14:d2:d7:ca:e8:bf:4e: + 16:72:22:a0:0c:86:ca:73:23:09:ae:71:f1:52:0c:db:b2:8a: + 4d:94:a5:fa:15:81:5b:a2:95:62:50:a1:d6:64:fe:4c:0c:60: + 8d:9b:0f:b8:41:ac:cb:31:c2:17:6c:7b:61:13:16:9a:db:64: + fc:5f:47:84:3d:d2:2e:db:0b:9e:b6:1e:85:04:c1:e5:c0:b2: + 6d:8f:f2:99:00:3a:1a:ab:02:cf:45:7a:26:c1:b0:1f:c6:b0: + d0:4d:f7:52 -----BEGIN CERTIFICATE----- -MIICLDCCAZWgAwIBAgIJANjT46bL48zBMA0GCSqGSIb3DQEBBQUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xMzA2 -MjkxNjQxMjJaFw0yMzA2MjcxNjQxMjJaMC8xCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw -gYkCgYEAvh6G5HkDwdGU1dSzsSiQdvu4ps1tHNFI9AiaZ//5plSxGSnfKRvN8W9m -Aefbec7AOSolEyaUDCx7WiyBD5TuUdB15kbbF0anFYsOVw+wVHZjEsqGGLwawxbA -cAnWa0M5uJgpRqzLaq04iDsH3IHNOvYd9i/vHdeuirbR57MVArkCAwEAAaNQME4w -HQYDVR0OBBYEFLiS3v2KGLMww59V8zNdtMgpikEUMB8GA1UdIwQYMBaAFLiS3v2K -GLMww59V8zNdtMgpikEUMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEA -Gs93YERDxFUOmeCJqrnTezK3XJx8yv6M1JTGXvODGV8pWWikT9wELrhxwG07rgHk -uYiZzM6CvmoowqxqlMaHkO2FPBBxxf88cGTiQWIx6oZ7EYyT6sbz80751PKBkNf0 -+qGRbtTdFT4mO6wew8If7bs0v8uyZ8bGUehRIrTzkug= +MIIDYDCCAkigAwIBAgIUQpdsMI55/Htq4++dGKR0nYtfV1MwDQYJKoZIhvcNAQEL +BQAwQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoMBXcx +LmZpMRAwDgYDVQQDDAdSb290IENBMB4XDTIwMDUwMjE5NDk0OFoXDTMwMDQzMDE5 +NDk0OFowQTELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAMBgNVBAoM +BXcxLmZpMRAwDgYDVQQDDAdSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEAvPTuRGJ/Yk+hgUa6xKoe/U7Q7fFHyyVbZnqGOZHKtWGnfi88Y305 +uBqey20yMpHeSUmE2hW+K93GvB/cbsAtd/LQeyxAGQdgVbD/fFHvONHwKtqozOrW +VKTvvhdEGp4zcFek8wasPe5LLeVGJS0zCfZJqAIxpGWbMgpn9QLhO0emruT2hetd +PgJm3RGYrDRywo8lVUpq6uiCL71/eDGkWtcyu2RIRiPvyMnihABWcuhLVJViOloR +ee5AQ54WLMzmRfS7gijCgzUsVTaZWRGxFdADwaU34R+7Q8e0uTPeFNd8mUUPwQb+ +tiUQWbdydn+RS+rRuWpq7d0bqQ6nKUi3TQIDAQABo1AwTjAdBgNVHQ4EFgQUpP25 +ORuBs6rriB3Ugam1EXDMp+EwHwYDVR0jBBgwFoAUpP25ORuBs6rriB3Ugam1EXDM +p+EwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAQfnDo3cRklXnS0oy +ajHZUc8GpTnqMJi4jU8kxTT9xpgQWTJ+V/WPumfJ/ERos3zxrzpfDY+h/kEhDukI +o2NJZjRKzc5mdEcw99yCmSFWgv8tEpB9emQioO36Ytla05eWDASnR4jaU7YzFRX5 +2u6sJekHAom8c6LGJ28fvXO4jveUVFeni1uaJKqG1ARcjMsookX5NPABILsG6EEU +0tfK6L9OFnIioAyGynMjCa5x8VIM27KKTZSl+hWBW6KVYlCh1mT+TAxgjZsPuEGs +yzHCF2x7YRMWmttk/F9HhD3SLtsLnrYehQTB5cCybY/ymQA6GqsCz0V6JsGwH8aw +0E33Ug== -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/test-ca/crlnumber b/tests/hwsim/auth_serv/test-ca/crlnumber new file mode 100644 index 000000000..adb9de8ee --- /dev/null +++ b/tests/hwsim/auth_serv/test-ca/crlnumber @@ -0,0 +1 @@ +08 diff --git a/tests/hwsim/auth_serv/test-ca/index.txt b/tests/hwsim/auth_serv/test-ca/index.txt index 6c94cb66d..b53182613 100644 --- a/tests/hwsim/auth_serv/test-ca/index.txt +++ b/tests/hwsim/auth_serv/test-ca/index.txt @@ -51,3 +51,70 @@ V 201003130223Z D8D3E3A6CBE3CD22 unknown /C=FI/O=w1.fi/CN=server6.w1.fi V 201003130223Z D8D3E3A6CBE3CD23 unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi V 201003130223Z D8D3E3A6CBE3CD24 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi V 201003130223Z D8D3E3A6CBE3CD25 unknown /C=FI/O=w1.fi/CN=Test User +V 210502173804Z D8D3E3A6CBE3CD26 unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502173804Z D8D3E3A6CBE3CD27 unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502173804Z D8D3E3A6CBE3CD28 unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502173804Z D8D3E3A6CBE3CD29 unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502173804Z D8D3E3A6CBE3CD2A unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502173804Z D8D3E3A6CBE3CD2B unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502173804Z D8D3E3A6CBE3CD2C unknown /C=FI/O=w1.fi/CN=Test User +V 210502174431Z D8D3E3A6CBE3CD2D unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502174431Z D8D3E3A6CBE3CD2E unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502174431Z D8D3E3A6CBE3CD2F unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502174431Z D8D3E3A6CBE3CD30 unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502174431Z D8D3E3A6CBE3CD31 unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502174431Z D8D3E3A6CBE3CD32 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502174431Z D8D3E3A6CBE3CD33 unknown /C=FI/O=w1.fi/CN=Test User +V 210502175131Z D8D3E3A6CBE3CD34 unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502175131Z D8D3E3A6CBE3CD35 unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502175131Z D8D3E3A6CBE3CD36 unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502175131Z D8D3E3A6CBE3CD37 unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502175131Z D8D3E3A6CBE3CD38 unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502175131Z D8D3E3A6CBE3CD39 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502175131Z D8D3E3A6CBE3CD3A unknown /C=FI/O=w1.fi/CN=Test User +V 210502175312Z D8D3E3A6CBE3CD3B unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502175312Z D8D3E3A6CBE3CD3C unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502175312Z D8D3E3A6CBE3CD3D unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502175312Z D8D3E3A6CBE3CD3E unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502175312Z D8D3E3A6CBE3CD3F unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502175312Z D8D3E3A6CBE3CD40 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502175312Z D8D3E3A6CBE3CD41 unknown /C=FI/O=w1.fi/CN=Test User +V 210502175515Z D8D3E3A6CBE3CD42 unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502175515Z D8D3E3A6CBE3CD43 unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502175515Z D8D3E3A6CBE3CD44 unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502175515Z D8D3E3A6CBE3CD45 unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502175515Z D8D3E3A6CBE3CD46 unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502175515Z D8D3E3A6CBE3CD47 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502175515Z D8D3E3A6CBE3CD48 unknown /C=FI/O=w1.fi/CN=User +V 210502175516Z D8D3E3A6CBE3CD49 unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502175516Z D8D3E3A6CBE3CD4A unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502175516Z D8D3E3A6CBE3CD4B unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502175516Z D8D3E3A6CBE3CD4C unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502175516Z D8D3E3A6CBE3CD4D unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502175516Z D8D3E3A6CBE3CD4E unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502175516Z D8D3E3A6CBE3CD4F unknown /C=FI/O=w1.fi/CN=User +V 210502190331Z D8D3E3A6CBE3CD50 unknown /C=FI/O=w1.fi/CN=User +V 210502190432Z D8D3E3A6CBE3CD51 unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502190432Z D8D3E3A6CBE3CD52 unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502190432Z D8D3E3A6CBE3CD53 unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502190432Z D8D3E3A6CBE3CD54 unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502190432Z D8D3E3A6CBE3CD55 unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502190432Z D8D3E3A6CBE3CD56 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502190432Z D8D3E3A6CBE3CD57 unknown /C=FI/O=w1.fi/CN=Test User +V 210502195156Z D8D3E3A6CBE3CD58 unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502195156Z D8D3E3A6CBE3CD59 unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502195156Z D8D3E3A6CBE3CD5A unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502195156Z D8D3E3A6CBE3CD5B unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502195156Z D8D3E3A6CBE3CD5C unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502195156Z D8D3E3A6CBE3CD5D unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502195156Z D8D3E3A6CBE3CD5E unknown /C=FI/O=w1.fi/CN=Test User +V 210502195538Z D8D3E3A6CBE3CD5F unknown /C=FI/O=w1.fi/CN=server.w1.fi +V 210502195538Z D8D3E3A6CBE3CD60 unknown /C=FI/O=w1.fi/CN=server3.w1.fi +V 210502195538Z D8D3E3A6CBE3CD61 unknown /C=FI/O=w1.fi/CN=server5.w1.fi +V 210502195538Z D8D3E3A6CBE3CD62 unknown /C=FI/O=w1.fi/CN=server6.w1.fi +V 210502195538Z D8D3E3A6CBE3CD63 unknown /C=FI/O=w1.fi/CN=server-policies.w1.fi +V 210502195538Z D8D3E3A6CBE3CD64 unknown /C=FI/O=w1.fi/CN=server-policies2.w1.fi +V 210502195538Z D8D3E3A6CBE3CD65 unknown /C=FI/O=w1.fi/CN=Test User +V 200102000000Z D8D3E3A6CBE3CD66 unknown /C=FI/O=w1.fi/CN=server4.w1.fi +V 210503140118Z D8D3E3A6CBE3CD67 unknown /C=FI/O=w1.fi/CN=ocsp.w1.fi +V 20700421140741Z D8D3E3A6CBE3CD68 unknown /C=FI/O=w1.fi/CN=server7.w1.fi diff --git a/tests/hwsim/auth_serv/test-ca/private/cakey.pem b/tests/hwsim/auth_serv/test-ca/private/cakey.pem index cddf6b1cf..b66e03802 100644 --- a/tests/hwsim/auth_serv/test-ca/private/cakey.pem +++ b/tests/hwsim/auth_serv/test-ca/private/cakey.pem @@ -1,15 +1,28 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQC+HobkeQPB0ZTV1LOxKJB2+7imzW0c0Uj0CJpn//mmVLEZKd8p -G83xb2YB59t5zsA5KiUTJpQMLHtaLIEPlO5R0HXmRtsXRqcViw5XD7BUdmMSyoYY -vBrDFsBwCdZrQzm4mClGrMtqrTiIOwfcgc069h32L+8d166KttHnsxUCuQIDAQAB -AoGAEPKDr8Yh0ZsvG0iUpAwrpI+XzDavrUvypt5FdVPaGzudddLHs9BosUbu3uie -JeOKOw5Is8ZSmCs267jf4FW0UKtgpnHGK2H0ba0iramzz07oK48V4y7C7nS3eJr/ -Oen6H9BW4DNXreFZ5yTRFOiQ4eD1pHqR/M/bBieDfRjakgECQQDfgiYYInio4TmM -9q/h1q5T1bGgajz5U4GInd0K2diNqVoGhSTAyRRGauH+68tPQuX7WCM1VE/lZfZL -4/dlOaRhAkEA2cHNkrFh4CAlXgtCub+psmT032AIFDEpNNT0K22XIE8savYNqs8w -aGPurrwGQflxCB19boiaKEcW5FQDkff9WQJAbUznNiw9V1D05OOKNWXX0HWTLMBn -WwIkOVwByZmo1fX4aXHY/FIZESqZpCFJRlSPxS9f4Gd/vs3y+T/dLupWYQJAJDGX -RrOfDg6px1jdzVvzC8jF/r7KePi23aYrs3Ayt1cRjfG50dNAO4moqXhtHdglFnE4 -YP/ph5pRTsA8G635eQJBAKbh0zB4HqFI2PmnKsShFBPNkK5x17nAZlYNJf2Ip4Ii -2Gjxyx4H0iBVgFYLsLB6hRBkOPpx6Jl8mJXOtFXb8lE= ------END RSA PRIVATE KEY----- +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC89O5EYn9iT6GB +RrrEqh79TtDt8UfLJVtmeoY5kcq1Yad+LzxjfTm4Gp7LbTIykd5JSYTaFb4r3ca8 +H9xuwC138tB7LEAZB2BVsP98Ue840fAq2qjM6tZUpO++F0QanjNwV6TzBqw97kst +5UYlLTMJ9kmoAjGkZZsyCmf1AuE7R6au5PaF610+AmbdEZisNHLCjyVVSmrq6IIv +vX94MaRa1zK7ZEhGI+/IyeKEAFZy6EtUlWI6WhF57kBDnhYszOZF9LuCKMKDNSxV +NplZEbEV0APBpTfhH7tDx7S5M94U13yZRQ/BBv62JRBZt3J2f5FL6tG5amrt3Rup +DqcpSLdNAgMBAAECggEBAJ9YofITaj8aziT545jjqfyN0c1G0vdyinCSVM0JsHtj +Xd8gsHlp6hnigRUmAdX5gw4krJ9JBLVzchvFdpwC/pUPtFabC3bP7KJ3AAzz/5vY +FwPcn8snIxYAfZi9gBY+YTyU/KphbzFO2iFbHttNEaSOCLFhIEH12XnKor5Q7mWQ +5HHlTdCzvRlGQwSdrmYctQmekdSgffF56ebZzlkwrJAF+o8NX44mcNWSausnEuds +S7Cah4dxT3Hm8luXfd1u3fCiT/p0ubMT66OVjo2cB0CIQxSpGWoIMuVrVrlzQbNt +gtQ2cred2HKizlYpCjNd2zrRHauIc2koqQTP0+yNE5UCgYEA6Fuc4Wrq/maMQiOT +QI46K5PktWArxFO152chdLpjy9qKmm0o7MjBZubRRW0kYHvtUwu15wcCH8Ctwucn +JGrvtS3lMbNy14kQG7OrT87u2J5VyXNbGxOIhoeDRxEKCbDfyA+4c7sGHMxczxPc +q6tWJ8cZeXLl8TMLacyG5aWF1WMCgYEA0C7RtPZh6J4XfsgZjO/7FoVgBp5yoche +Hc6gwHiT7qYAbDQgOq7g41jEtYoO/e8qRsxsJHJlVzYIe3WlK5IC78sk6ZS7hZ6M +LjfhnBPV1Ddtdq4w2VKY7fDYPvZK3DOc0FOIlaPicxWXUUDt0Tfud2qgYbebz+R6 +wmxqqcYM948CgYEAq6C/yGFJIpBsmY3dfpmPrhCXpsFakrGic0JiG+5xOGo8ZsSq +rfu7n15uxXFQpVPkgKrtubAbiYiw0H4dE3FJjfJQkN2TvlCnbU7RAyo+khKiGyLx +8JYFChmehie32mCjawrxm8pRQYRSKULqhIMSKF+QGX0dC4RAse041vfkWzECgYAr +tAh2EtsO+FE6Xktu2No/KhS0jwLFj8iiPURl42o6yUKBdJfnedrgHzx8V9U53cFk +R3nUVOeNXVx+fn4EHYzcRisjlgOf017ePQDxwQA8or4qEftTRBGyscLTxOSGQZeD +7GVZ9KOPQVMYzaafKzy2eP3eRatCA1b6BcSGi3shZQKBgQDA1h0rSoFoXsel8MAV +MPkGt6gzUdzKb/Qt3BOolnsIcd4Vn19uLCcLdhxRkD37MW/9/mgV+Q57DYyvS9OC +xi6q7ukgDE3YTK5WChmqJ4p0aEP4bEt6N1VIo55HCFoJy01NIJLs4VAW4y88CzDp +otex1UmIWQdfnDbIVW9NNFVTiQ== +-----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/test-ca/serial b/tests/hwsim/auth_serv/test-ca/serial index 1394bbfd8..0cf1e4210 100644 --- a/tests/hwsim/auth_serv/test-ca/serial +++ b/tests/hwsim/auth_serv/test-ca/serial @@ -1 +1 @@ -D8D3E3A6CBE3CD26 +D8D3E3A6CBE3CD69 diff --git a/tests/hwsim/auth_serv/update.sh b/tests/hwsim/auth_serv/update.sh index 585bca632..b2296b2fb 100755 --- a/tests/hwsim/auth_serv/update.sh +++ b/tests/hwsim/auth_serv/update.sh @@ -4,6 +4,47 @@ OPENSSL=openssl mkdir -p test-ca/newcerts +echo +echo "---[ DH parameters ]----------------------------------------------------" +echo + +if [ -r dh.conf ]; then + echo "Use already generated dh.conf" +else + openssl dhparam -out dh.conf 2048 +fi + +echo +echo "---[ Root CA ]----------------------------------------------------------" +echo + +if [ -r ca-key.pem ]; then + echo "Use already generated Root CA" +else + cat openssl2.cnf | + sed "s/#@CN@/commonName_default = TEST - Incorrect Root CA/" \ + > ca-openssl.cnf.tmp + $OPENSSL req -config ca-openssl.cnf.tmp -batch -x509 -new -newkey rsa:2048 -nodes -keyout ca-incorrect-key.pem -out ca-incorrect.der -outform DER -days 3650 -sha256 + $OPENSSL x509 -in ca-incorrect.der -inform DER -out ca-incorrect.pem -outform PEM -text + + cat openssl2.cnf | + sed "s/#@CN@/commonName_default = Root CA/" \ + > ca-openssl.cnf.tmp + $OPENSSL req -config ca-openssl.cnf.tmp -batch -x509 -new -newkey rsa:2048 -nodes -keyout ca-key.pem -out ca.der -outform DER -days 3650 -sha256 + $OPENSSL x509 -in ca.der -inform DER -out ca.pem -outform PEM -text + mkdir -p test-ca/certs test-ca/crl test-ca/newcerts test-ca/private + touch test-ca/index.txt + echo 01 > test-ca/crlnumber + cp ca.pem test-ca/cacert.pem + cp ca-key.pem test-ca/private/cakey.pem + $OPENSSL ca -config ca-openssl.cnf.tmp -gencrl -crldays 2922 -out crl.pem + cat ca.pem crl.pem > ca-and-crl.pem + faketime yesterday $OPENSSL ca -config ca-openssl.cnf.tmp -gencrl -crlhours 1 -out crl.pem + cat ca.pem crl.pem > ca-and-crl-expired.pem + rm crl.pem + rm ca-openssl.cnf.tmp +fi + echo echo "---[ Update server certificates ]---------------------------------------" echo @@ -12,6 +53,9 @@ cat openssl2.cnf | sed "s/#@CN@/commonName_default = server.w1.fi/" | sed "s/#@ALTNAME@/subjectAltName=DNS:server.w1.fi/" \ > openssl.cnf.tmp +if [ ! -r server.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout server.key -out server.csr -outform PEM -sha256 +fi $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server.csr -out server.pem -extensions ext_server $OPENSSL pkcs12 -export -out server.pkcs12 -in server.pem -inkey server.key -passout pass: @@ -20,24 +64,51 @@ $OPENSSL pkcs12 -export -out server-extra.pkcs12 -in server.pem -inkey server.ke cat openssl2.cnf | sed "s/#@CN@/commonName_default = server3.w1.fi/" \ > openssl.cnf.tmp +if [ ! -r server-no-dnsname.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout server-no-dnsname.key -out server-no-dnsname.csr -outform PEM -sha256 +fi $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-no-dnsname.csr -out server-no-dnsname.pem -extensions ext_server +cat openssl2.cnf | + sed "s/#@CN@/commonName_default = server4.w1.fi/" \ + > openssl.cnf.tmp +if [ ! -r server-expired.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout server-expired.key -out server-expired.csr -outform PEM -sha256 +fi +$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-expired.csr -out server-expired.pem -extensions ext_server -startdate 200101000000Z -enddate 200102000000Z + cat openssl2.cnf | sed "s/#@CN@/commonName_default = server5.w1.fi/" \ > openssl.cnf.tmp +if [ ! -r server-eku-client.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout server-eku-client.key -out server-eku-client.csr -outform PEM -sha256 +fi $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-eku-client.csr -out server-eku-client.pem -extensions ext_client cat openssl2.cnf | sed "s/#@CN@/commonName_default = server6.w1.fi/" \ > openssl.cnf.tmp +if [ ! -r server-eku-client-server.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout server-eku-client-server.key -out server-eku-client-server.csr -outform PEM -sha256 +fi $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-eku-client-server.csr -out server-eku-client-server.pem -extensions ext_client_server +cat openssl2.cnf | + sed "s/#@CN@/commonName_default = server7.w1.fi/" \ + > openssl.cnf.tmp +if [ ! -r server-long-duration.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:4096 -nodes -keyout server-long-duration.key -out server-long-duration.csr -outform PEM -sha256 +fi +$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-long-duration.csr -out server-long-duration.pem -extensions ext_server -days 18250 + cat openssl2.cnf | sed "s/#@CN@/commonName_default = server-policies.w1.fi/" | sed "s/#@ALTNAME@/subjectAltName=DNS:server-policies.w1.fi/" | sed "s/#@CERTPOL@/certificatePolicies = 1.3.6.1.4.1.40808.1.3.1/" \ > openssl.cnf.tmp -#$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:3072 -nodes -keyout server-certpol.key -out server-certpol.csr -outform PEM -sha256 +if [ ! -r server-certpol.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:3072 -nodes -keyout server-certpol.key -out server-certpol.csr -outform PEM -sha256 +fi $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-certpol.csr -out server-certpol.pem -extensions ext_server cat openssl2.cnf | @@ -45,14 +116,23 @@ cat openssl2.cnf | sed "s/#@ALTNAME@/subjectAltName=DNS:server-policies2.w1.fi/" | sed "s/#@CERTPOL@/certificatePolicies = 1.3.6.1.4.1.40808.1.3.2/" \ > openssl.cnf.tmp -#$OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:3072 -nodes -keyout server-certpol2.key -out server-certpol2.csr -outform PEM -sha256 +if [ ! -r server-certpol2.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:3072 -nodes -keyout server-certpol2.key -out server-certpol2.csr -outform PEM -sha256 +fi $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in server-certpol2.csr -out server-certpol2.pem -extensions ext_server echo echo "---[ Update user certificates ]-----------------------------------------" echo -cat openssl2.cnf | sed "s/#@CN@/commonName_default = User/" > openssl.cnf.tmp +cat openssl2.cnf | sed "s/#@CN@/commonName_default = Test User/" > openssl.cnf.tmp +if [ ! -r user.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout user.key -out user.csr -outform PEM -sha256 + $OPENSSL rsa -in user.key -out user.rsa-key + $OPENSSL pkcs8 -topk8 -in user.key -out user.key.pkcs8 -inform PEM -v2 des-ede3-cbc -v2prf hmacWithSHA1 -passout pass:whatever + $OPENSSL pkcs8 -topk8 -in user.key -out user.key.pkcs8.pkcs5v15 -inform PEM -v1 pbeWithMD5AndDES-CBC -passout pass:whatever +fi + $OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in user.csr -out user.pem -extensions ext_client rm openssl.cnf.tmp @@ -64,6 +144,14 @@ echo echo "---[ Update OCSP ]------------------------------------------------------" echo +cat openssl2.cnf | + sed "s/#@CN@/commonName_default = ocsp.w1.fi/" \ + > openssl.cnf.tmp +if [ ! -r ocsp-responder.csr ]; then + $OPENSSL req -config openssl.cnf.tmp -batch -new -newkey rsa:2048 -nodes -keyout ocsp-responder.key -out ocsp-responder.csr -outform PEM -sha256 +fi +$OPENSSL ca -config $PWD/openssl.cnf.tmp -batch -in ocsp-responder.csr -out ocsp-responder.pem -extensions v3_OCSP + $OPENSSL ocsp -CAfile test-ca/cacert.pem -issuer test-ca/cacert.pem -cert server.pem -reqout ocsp-req.der -no_nonce $OPENSSL ocsp -index test-ca/index.txt -rsigner test-ca/cacert.pem -rkey test-ca/private/cakey.pem -CA test-ca/cacert.pem -resp_no_certs -reqin ocsp-req.der -respout ocsp-server-cache.der SIZ=`ls -l ocsp-server-cache.der | cut -f5 -d' '` @@ -90,4 +178,4 @@ mv index.txt.new index.txt echo "start.sh: openssl ocsp -reqout serial" SERIAL=`grep CN=server.w1.fi test-ca/index.txt | tail -1 | cut -f4` -sed -i "s/serial 0x[^ ]* -no_nonce/serial 0x$SERIAL -no_nonce/" ../start.sh +sed -i "s/'-serial', '0x[^']*'/'-serial', '0x$SERIAL'/" ../test_ap_eap.py diff --git a/tests/hwsim/auth_serv/user.csr b/tests/hwsim/auth_serv/user.csr index 921eb68a1..49c179f26 100644 --- a/tests/hwsim/auth_serv/user.csr +++ b/tests/hwsim/auth_serv/user.csr @@ -1,11 +1,16 @@ -----BEGIN CERTIFICATE REQUEST----- -MIIBgjCB7AIBADBDMQswCQYDVQQGEwJGSTEQMA4GA1UEBwwHVHV1c3VsYTEOMAwG -A1UECgwFdzEuZmkxEjAQBgNVBAMMCVRlc3QgVXNlcjCBnzANBgkqhkiG9w0BAQEF -AAOBjQAwgYkCgYEAppYumyKM35S+i4lJ9nh2omB+FJXzlv6rGSUDNGR0AT6on3zx -R2FgTIKSKHwroA7Lh79Z69fzYSI7FPOrMfZalR+4ergsPKlhU3ib6D5Q7MLWROdD -zbw+TudG/pKew5gPKVjIy4kBdUfplVcPdsUvBV7HHg3yPBJjXblUGa9/QGsCAwEA -AaAAMA0GCSqGSIb3DQEBCwUAA4GBACZXujbQL1Y5fOWK2pRyckyk92NAwgPXWqo7 -8d9FF2bIDBfautK2GYd74SDdUOzjNjGLoEO9tIhB3jWQp8qaC/HiWwbDGd6Ugo8g -WnuLTf2vfL67IdVzG26IAdflrEF4XX3HjuHJO1NxtXKw/u5hm6qiJAu9tkA+2zEM -bbG4Bg/+ +MIICiDCCAXACAQAwQzELMAkGA1UEBhMCRkkxEDAOBgNVBAcMB1R1dXN1bGExDjAM +BgNVBAoMBXcxLmZpMRIwEAYDVQQDDAlUZXN0IFVzZXIwggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQC8JAjZB20ZDpRca9mKhBsDIuIaBkLTC2CNXzEEBvqi +QGoMJClYzYO/Op1/Nw1NJ13VV1cc8751PzpMRG8CL1uLLLBcRykZMQjRKPUenFuc +t+drQDUQPn9mZxahTmiKccwyWOMIh6IqBy1/c/ZD5X/09nSuJ+jSXK6bgtmlKnJ2 +hC/jYqpBHt4zt2T4eW/6CbW8sIzNNIItxBBViepsOJL+YdZkhATUCjcyN43DVdH8 +q7hVBqkATzHiQvHntC6cRQ3cqfmtsnfB8LHDolomkL0ZL0YdpSE98DVilMjPMz/Y +ol3fzFgACI3tsQTFKz8aFfaSCNTxQs1s2/L/4G5phNiLAgMBAAGgADANBgkqhkiG +9w0BAQsFAAOCAQEAJB2hPF8r/cPO7+4fPf3oXwEwf0YsXHzVwUnawgtMNyU10rJX +qqQIi2elEJfgYqmUhmXBrBIm06bRXlcR+QoWwX4sHk3rmHQYPy190bNpTaHVN9bZ +kZndOcdaog1a3Lbui+e/brpzo0kGskW9TsDsOkYjzgIzQHGQtfcPfLhnLj4+sRyq +tnV0vvHl3SyPmsVxrazRO4LgMBmwGx6QC4Yf3w25Us3aLzJqsZHDBRsVRdoHyLYd +Jwt2fE2dLzGNkGFUP3BeJMHze1CqRybfoVlBU1IZRYlRQ8yOO/IpO7pa363Xx5Ar +DsD2xcG7WvAjQ08vVgW2ShQRIIeX0Luhd6fqQg== -----END CERTIFICATE REQUEST----- diff --git a/tests/hwsim/auth_serv/user.key b/tests/hwsim/auth_serv/user.key index b9fd702d5..1e114958a 100644 --- a/tests/hwsim/auth_serv/user.key +++ b/tests/hwsim/auth_serv/user.key @@ -1,16 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKaWLpsijN+UvouJ -SfZ4dqJgfhSV85b+qxklAzRkdAE+qJ988UdhYEyCkih8K6AOy4e/WevX82EiOxTz -qzH2WpUfuHq4LDypYVN4m+g+UOzC1kTnQ828Pk7nRv6SnsOYDylYyMuJAXVH6ZVX -D3bFLwVexx4N8jwSY125VBmvf0BrAgMBAAECgYEAkEoS0kKJ3Hqc1IW0r6xFrX2A -l1oOpCGvl1bswKuloxJfwczZu+cHHx4VdMWgj8Fg3xKJ03K4FtEsdYhdJyhn6c6G -YsKF7HHGo2WA61VHxgqRB/CZzALy2JR/3rzElvrVQ5ZVh15DipNpwfwP9bW6P99A -omPQVnZ3p1HgU5WK68kCQQDXHbFUYX3I9SYlR4JhPy5ov2Q8WHu4p9rWXGBO75uS -7f3FZCbGULKZEOsiVFbloyUdpvLId7wvb343a1EAOnC9AkEAxj9UqsKMAdlXTDrT -9NcQmJKWt568gEV4/45fjpTzbdndEOtCMwWBWEv/SyiWgWdwPeBViRGEyPrkLV/S -teesRwJBAIfN6QuaWKyrh591W6xFFOlwGrm2KrVS0ucNfoeW4SKLOPCK36fHflj/ -w1Hy6MEkk+P6Z7+DR7yyqH4YNBTu0AkCQA7uZioWTQU2oWSUabJfIFjdcYyS4A+p -K9vTlU7f2RXE+ulzTqEZIQzNbIT0oaFNcR637rlMIHwiqVzhgrVApbECQQDK5QqX -E6Z2VHTNEnCki9YvkgjPhLxSihQMDSaR0ENkre0OctFUufbwzH7DEhzV6CQ1Uw+9 -Au5AOFzcb1tfGczP +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC8JAjZB20ZDpRc +a9mKhBsDIuIaBkLTC2CNXzEEBvqiQGoMJClYzYO/Op1/Nw1NJ13VV1cc8751PzpM +RG8CL1uLLLBcRykZMQjRKPUenFuct+drQDUQPn9mZxahTmiKccwyWOMIh6IqBy1/ +c/ZD5X/09nSuJ+jSXK6bgtmlKnJ2hC/jYqpBHt4zt2T4eW/6CbW8sIzNNIItxBBV +iepsOJL+YdZkhATUCjcyN43DVdH8q7hVBqkATzHiQvHntC6cRQ3cqfmtsnfB8LHD +olomkL0ZL0YdpSE98DVilMjPMz/Yol3fzFgACI3tsQTFKz8aFfaSCNTxQs1s2/L/ +4G5phNiLAgMBAAECggEAAVFTSonVxsYmXdtXg7PXKJd28+21TBsZSwQuqLOPz9EZ +rQoXzApscMttTPXKvw6Whqb88jP20oVl2CDmkiJYxsnCVnMdI5MHV8esp9E6hwd2 +tHaXqIx3gfUY4HpXGxke7/9VX7rrdNXmCK18PQ9/bOzI9mtLIyYJBwfMlG6OrKvP +QoeLwoZiMDvA3nS8a/TeTPNXI1md7GHfPXqOumAngV0E4FuT7XfkaeBVzataUStY +D9WEhjtiEahCJWqtN7U/Zq4qKB6XrrVye8BixDNRf/Qnz5SPrhWk3rWPEAqPBcqO +EirQapQAI+e974irowq1WOUV4xDYWq8QoXrMWFwFEQKBgQDjwxs+i+P33efaeTXG +AjK/qieLn7JvnHIxAOPK+qzPY75b01U0JH9qRKs1J2dxUQQFWu2rWtbLAVDf8et/ +URL8ZAqCy2U8HOUJuu+x9kNoLRxREuY9EhMeQ6P6clTGx1fgIc9BXsT+UjMK6I+R +3JwZEwLYf3E81KU9CmKpCfUZwwKBgQDTd2TRu9fIbmIrAf6StvsSD2OWQ/RBavNE +pISLH5/orvt3kXy9I6bAyW+FyHZ4620CE24fzstWH8l3F1jIvCf32wa8cTi1EA7l +Rh8gVRC0s2CdETse7lUHTqqoqO6ckT9p0ZLLHfbALsy0jIOZUno0uVgYPzbWkvXW +j76Q27uRmQKBgG38qgtqQoxP/MbkAbO9HASyhqZGWETNp9dCNr6ujwUXhbWSOHMV +rPIEdykT/kAaf3aWkm9NTqx51jRO/wpcfG6lYO4IirqcuX4ZZ+bopWSJZENCfSzA +rbrPr0AiNg5H9YemzA8lVLv7tepuo+YsQrVZGOazpFtb1O/FNB+tT09BAoGBAMlG +zCyhOasp/cBn3pJxHhq7kROWzKdzj+cXHJ17VW5ZFztgvDUe+PppAQB6pOFFXHVs +XxZhc8Me8FitXTF7fiN5UzkMH2ifxz3Nd5UDwqnsTppRq08ulLom02NDoBJgYdZr +xugUNigIo4l6cUv/aBhFDifOC3lDWkGGgmFI9IiJAoGAUMIiyteV7zqrc3ncrnYu +Nvg90VeA7CMa0SvmOMYS0M8fUUHtbthfr64c2fWM9JFflApRtVkHSclRMI1RqmVW +SvDqS4kxb0NC5HiWioRHb3PlEqL8F076lySD/25sNwWwHwMq1MJPOi7cEXc1YtWS +26WD/C6dauV5FnMa7eX1D3I= -----END PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/user.key.pkcs8 b/tests/hwsim/auth_serv/user.key.pkcs8 index 655503da9..8302fbbbf 100644 --- a/tests/hwsim/auth_serv/user.key.pkcs8 +++ b/tests/hwsim/auth_serv/user.key.pkcs8 @@ -1,17 +1,30 @@ -----BEGIN ENCRYPTED PRIVATE KEY----- -MIICxjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQIt5s8O/vC7Z0CAggA -MBQGCCqGSIb3DQMHBAh1l9fSi61IRASCAoDGCULhl5nYsWTyimj9idh/1z78xJu6 -Q+Ap6u/UiEQh3riX5DYojJPZfYTJ44IOh/Jfbv/ipr4IynDnAiZyhs8NWYAXTk2i -U5yb1Zsf3lRxKQG8u8BhkxDdUs9GSbajvF81fWkZVpMQw1aBWVxRfXlNrqx0ObZD -HdxyJX/wGMlV41r50LlyMOH9fiULX0ylGI9HtTNkxmUWtj9F7ATHp7qPdFGMoWzV -LOoR5KqGmi4WhE3t+02wmlyeSXe4T4kiLGZ6T7sR6szjNHUFkWgwe2oFfd0HZDvO -wC1HoUKeRM/c4bP+HtNo6ZeudSbXd4p822WvqbKgDldXqeq5KUHye6hQfF06E/mH -2GnHLiGBvgMIOERitm9OTW4V2hPDGOVsyfu/fUdWoo0AoLmfDStRk7zqt8mkpRyZ -sfqltTvbCYA9E1GT86WjF+Ugq2iEITf9rQZAyAb6pNM2CWyLGihjKhXRvR19w0rQ -33KlccnDwbZMCwBV6njWnNYF5ir3gWMDvTaC+DGUbACNHo3hVQyHWEi7X5YdbBy/ -1Y94+5pbGohTQRWuMmwzc5sFWeweewoXWBsauK4EU5P4WxT3D8iCr96qsftmTn2V -tD3k2W4vXBcqZkIswllqSQDYSnaxnSe/cUoYm3iehZRQutZ0PaBWmOy6jmJpEU/Q -RTWsu7zyD/18o+yxkZR68eQn11zbIuBWjj1xDeqmjbYkh8XDC1Q6fVeFJxF9mhyF -ttK/SPXuqyBi8eX13ViPEbIVOLpsr6S2ig3hN0/OIWVPblchYEXy1+VV4nwhA8Np -J89pD8vfbcVTDjHCu9HhcMdT/zFsWehe8yw5zM3WsGx6NB/xJS2onRhs +MIIFDjBABgkqhkiG9w0BBQ0wMzAbBgkqhkiG9w0BBQwwDgQI2spAA/WpqE0CAggA +MBQGCCqGSIb3DQMHBAi7csj8UwjU3ASCBMgK0/gob5gOgeDoZVERabnAazadQ7I9 +/QuAc75PEkl99YfjhiRXJyWWiOKNkGjgqTsXEfGp73/c3ilzKeoOtg/lhppZJ8VZ +z2ePXO+BOx/xlgeLj+fEmXAjKZZBJ76FCUH/P6sWe8MTLMN1g67QeK6akwj7KCzO +yPNOtL9FJbcq/Y0HxDy+266G2Y9ZVwtY45uOFXClWli1aRMz0/FRt7ijr5x7JsZj +kqUgB7qPl2+wMEXLhU/m8Gn2JdkxRsrDn7Hq86TOAF+CpWpjxGTEZFqzrMcVXJ2I +2oXntqwQdq9clLaMjPNP7eGZ7tmu3cQX6IypScZirJWgsb2+t3Hv3108wS9WZ7ZS +eTvg8rVgrorP8lMPFqCuljEZyIWryN5EZ85/WlxjgpZQnnvEmNgckPcQM9KfjT9l +UXsd3yaS+K6vA/NMgutSEQSFXLilpgr6wz19IvzIEeaGIU78GbBfSK/7kFWSb3WD +mmub9LN9CKgwGMc640hHHY7EUX71QIxLitcA/lIxftnjPQ5brh7P+0gwray01i1Y +SGaqLPNbgU+tLC7WnbadanTYRuMheTLmMgf8aIOiU9IT+JFiwm1s0jcVLlZyIsWF +HH9xNcf4SYz1lUGcHnn/IlMd6PGucicmd17Qewi5Y/vil48r799Fr1KO/GCbxtkP +qMjVqql1vRIo6tY++n9uwnTgg5NGrgLsFAWusulvEaC2BCTh1XqwtIC09zaonhy5 +30nadFWDnmR4MpPksjCBs5MCt2dBNF72JH/cFSTH7JpqDuthMJcprKc9b3MhQEqK +srSr2HnDlOir6Ubvz2LCyAsuKui1B4UOnZ8q3lHPjIXHCZBWcdj+hLCmgncf/Sjq +xvh0AmwPvn+kcG7W1DQ/ZfG7uh5oui4F9laVV3nuyOPzxdiuNFqYjHLb7rVgQOvK +jjHYhd2pJAYDO13GrXVG1H2ipEUr8u/uDlr7HLdtvAZqsTSNMQZk3t2/TI2nJDli +BPyJO72LVvwV0Jy5yH24qFwrzOmOcnNv1H14hPdwOOvhEQIWbAXRPTdf/ukC7HEb +mKBfToPHALxnKPmcp9iERkcNZ8OfLqRdjCvZoD7K1caZFqv9Uc3U2kaQT0b9lm+1 +3UDd1n0YfxA/iJ0S2/KSroDAt/wWnznuJ9PlzpQfZ2BqlAxeFQ0RH1K97D6be5IW +bxFxwkOwVK98j/g0+Y8/I0P2kNYH7WZ0ipkyM16TuhzUMKIuaoFxywwWaZg16F1x +YJsKjjpDCAWAl1fARvMiUHko28drBRGbFzrRzBwtE9+jxGWAF48xStswrzQV2/Ct +8Vll5BAfzSW8MLlvgJUECxFMOgsjS1GveHDcmEQ3z3JWBxGEXrYOYj0iDFNprrYu +Q5e7q41R4BL7CxN6JYiLWJXw3K5hXEzaS8vB96r+2CCRMw2IQ2n7OTBBsEIqIV5f +v++PKOwtZKpasnA7lblRZp8M/XFSOj591EBzwKGsXkOme7StZTngKjZKzf2xE56p +TRPpxNeyi4Y9U7QuO0q/AOcQG0spI0c4X8QlIPwByL1CvVLiWnnmlCiU9g8fl0pk +pVFASYyQPe0wAMU5C+zogf6K5N6rEcLbM3kNbvNE1zvPgzZpkAT6W41UZmB2828C +Dx8= -----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/user.key.pkcs8.pkcs5v15 b/tests/hwsim/auth_serv/user.key.pkcs8.pkcs5v15 index 2626d3be8..028177658 100644 --- a/tests/hwsim/auth_serv/user.key.pkcs8.pkcs5v15 +++ b/tests/hwsim/auth_serv/user.key.pkcs8.pkcs5v15 @@ -1,17 +1,29 @@ -----BEGIN ENCRYPTED PRIVATE KEY----- -MIICoTAbBgkqhkiG9w0BBQMwDgQIJ5xD8pUUfDsCAggABIICgKaalc1M4urq1NJ8 -AJoiuAcp1sNon6FUdDUtcQNFnG9H9/nt5FseYBA4tlRtJq1Qj9ow04VViJB9guTp -kxEt2onIyPSwblGtwkM0mboyVilmqyWEPWzI2T59nphWTnLfSmBSs756k581duks -qtaIm+yvUyI1cA1BHHaOhMApgNFzI7OFkAto55OG7kfJgcmMj1gSjSpNJ6XsofEp -BYLl9yPzbAF/Cxci7zTiKhYe/FbvW6qEJw+EKk5L+nKx+UlP7Ssjr+rhmeB142pb -7x4Zbelyo4SipWSpru7dZEyKFd/ZcXByoORjQT8sQaF36zVXmmv6gURKrWlznfFz -WwaeeI+4erld98A4tXuRjwmGbkzYnUNjq1cz2y7zvW34Dgse6KaP1iOsvmHA7K+j -hJI4jJFHvCRDGxIFZm4qZPBapPWqlN6vRJSVAX7YASqRcaNO2m6Y0umUgCtab2uF -k4D3ahHMg0XtcLvEr0HaklGWT5YIkcDuH+Los2NwSn1z5Q4nLnmLBfmfm75oKv1O -X/f627b4MLQxAnrcjQ2Wk0sL4a+Rnbenbi7MlyqA7Gz9fxLQdB7qrRehAiJxo+3e -ddhvsZ9pgZeUY+o/QkX4t4oxG09BhGVF5l+d46FU6hgPjFeRiSt7st5SdU2MK4la -Kqw6a7rDpfhb6WLMsnJyN0JwOaoOoy4UOpZYrdvSHwDvHur8YScd2DsPLMQMs0Zo -1mjfsYiElQLRk/wSjpyqBw/3ULFTsM17Z4mTgvTdDzBd5UycvbGJ/tnDV0cpXuJg -FVboPYqrGk5ChPePubyRa2e57HFQVu7kjzuS9NSdnKr/IVEr9Qn9OkRmprpm5Y6J -PgfA5wA= +MIIE6TAbBgkqhkiG9w0BBQMwDgQIuIvpaVfmxx8CAggABIIEyMeuOVWbTSBwOkM1 +W3SdLlK0quEYilKanms32+3L7esusdyVU2u8J8tiiAvh84/xaCet99V7g/qYIYE7 +7wHTuB77BPGHRMZCKX2GOwJWxNVWUimB+kUX0yYIUwJx3CO3SExVPd2lcjnTMq5D +PtaIHgJsPLU8wE3A1sVEGnfjE+73JtU/NJ7tS49WXNvQGd9ZeL4z3SqWt4HWmDdE +TVOiAcQ2V7xrpfLP71ElW3D9oiL5Ba7NTCSYtLNfpQOKTiz8QQWzpkT1+IXNZvig +yyYsNEZDzHQLmZXJVPsbHL8eoqzEpeH7mz/guQPBv1Rl8/PoiNY1bT8RV+EIp0Ne +6FNv2OiQtV50XNRlM5c3gS9RvWEYwZ8PCCc3ZCaRw5dH1dghiBk91i17//GLkyV1 +gZUNrT7YqlwPBiksOwFYsGPgWP7tT1aKeEXaLXXtx7pIhRqUN9IJFSVs5hmSkSmk +a4IuZGWEhhXpPm8cKsmrrMOXH3t48qR7OwUaERhcC4Qr23J1/8Whh8xNabIO0VXY +HCiAdtlMO70GPlYq06lM+L5eF697qB/065Pf4bhjav8rs5QNvt5GzWWYo9uDaEib +8n6tuOTxcf6yoe2fWgEpRk6jh9G9IS89pksusKDfizQg68q/Na1kmor7zT2FJAbC +S/VCOfs8MH2zd8ZnEsvoUhR5ibjBU8aUe9ir5OT5vjaazRLpod2X7LKWdcb7irZA +MvR9e1L+Z3RPLPoR8moYxLXZjd4F78rDDTYVFrYJGZTRmkJ9ukNzsI2ZzeRzNhqN +kHDsSsjMYCI/QkTOFCOmoNrUOGiH1cXqRc0JD5PY7FRS+8qvw73uAFV7yTAmxikQ +5IeNZvD+zJ6cvDb2ZR5iCmTA2f5uxsKl2hBe6uCdLLDPtlYHS0ZSmUolco6JrkDP +ns5BR3e06C6YeHwM694dTGeffIFfKmVEkYBaJ8Hcuey9I2L2N69222pPcrUT947o +TCXgZdjTNKSQEvEBPDHo9GRoJimnZODomJ9f/Da7BBIp+gHfE2rTS2+rUsU+5Kby +AXJnaLpWu9zgSri6lNAtQZkmk3haL255AtycyLGuITxKTxjVSmZBQV/6zQQwcJNv +e9PGNpI+EccjdjcI/UxDnW9ShuBbPTClrFmrE0jQjg4LZIR87pSO8jaBpg/2Q5ws +nUnLrHbXuHuJqeFR1gg0zfkvulS5ldPdqDYeTEOpATmTcFHYTolwUa+cdJbeeo3P +6s2RAyY9eGOgkgW8P0/nmfaHhVe8JBaHATx9liB3CFQ6kiU63YcBdgGdyzsYcIOK +MR20MT9dq4l+Sij3EZABFqgCEypMgt+TUlzIXZbWBSaWmi8ScFAlQw9LmVuaOMMV +hpTIuCenWVJVtWaHUIZkT316uENX3rQnDm1jR6UBSxFhKIsh+afeQMS6F656giAe +rcwqkIDbglfvhN6NmjQppbfMpmiFE71XFmPBzofC3MvIh/2hB9tvEBnYKoJCMy1c +XEbHynt7bRDm47Ev6gjAVWMZ1h40r79vvavK/vCA1b6Nd/F4gU+lGdB0tj/Pv2di +4jvhiyE90tDCSHAe0BOnPFdWkLvru9BU2xixb/pegRT722jZj9PJb4jY79wT3PdM +QHb1ZpXzRuidMI1ICQ== -----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/user.pem b/tests/hwsim/auth_serv/user.pem index f0b0962b0..66be8f81a 100644 --- a/tests/hwsim/auth_serv/user.pem +++ b/tests/hwsim/auth_serv/user.pem @@ -2,34 +2,43 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - d8:d3:e3:a6:cb:e3:cd:25 + d8:d3:e3:a6:cb:e3:cd:65 Signature Algorithm: sha256WithRSAEncryption - Issuer: C=FI, O=w1.fi, CN=Root CA + Issuer: C=FI, L=Tuusula, O=w1.fi, CN=Root CA Validity - Not Before: Oct 4 13:02:23 2019 GMT - Not After : Oct 3 13:02:23 2020 GMT + Not Before: May 2 19:55:38 2020 GMT + Not After : May 2 19:55:38 2021 GMT Subject: C=FI, O=w1.fi, CN=Test User Subject Public Key Info: Public Key Algorithm: rsaEncryption - RSA Public-Key: (1024 bit) + RSA Public-Key: (2048 bit) Modulus: - 00:a6:96:2e:9b:22:8c:df:94:be:8b:89:49:f6:78: - 76:a2:60:7e:14:95:f3:96:fe:ab:19:25:03:34:64: - 74:01:3e:a8:9f:7c:f1:47:61:60:4c:82:92:28:7c: - 2b:a0:0e:cb:87:bf:59:eb:d7:f3:61:22:3b:14:f3: - ab:31:f6:5a:95:1f:b8:7a:b8:2c:3c:a9:61:53:78: - 9b:e8:3e:50:ec:c2:d6:44:e7:43:cd:bc:3e:4e:e7: - 46:fe:92:9e:c3:98:0f:29:58:c8:cb:89:01:75:47: - e9:95:57:0f:76:c5:2f:05:5e:c7:1e:0d:f2:3c:12: - 63:5d:b9:54:19:af:7f:40:6b + 00:bc:24:08:d9:07:6d:19:0e:94:5c:6b:d9:8a:84: + 1b:03:22:e2:1a:06:42:d3:0b:60:8d:5f:31:04:06: + fa:a2:40:6a:0c:24:29:58:cd:83:bf:3a:9d:7f:37: + 0d:4d:27:5d:d5:57:57:1c:f3:be:75:3f:3a:4c:44: + 6f:02:2f:5b:8b:2c:b0:5c:47:29:19:31:08:d1:28: + f5:1e:9c:5b:9c:b7:e7:6b:40:35:10:3e:7f:66:67: + 16:a1:4e:68:8a:71:cc:32:58:e3:08:87:a2:2a:07: + 2d:7f:73:f6:43:e5:7f:f4:f6:74:ae:27:e8:d2:5c: + ae:9b:82:d9:a5:2a:72:76:84:2f:e3:62:aa:41:1e: + de:33:b7:64:f8:79:6f:fa:09:b5:bc:b0:8c:cd:34: + 82:2d:c4:10:55:89:ea:6c:38:92:fe:61:d6:64:84: + 04:d4:0a:37:32:37:8d:c3:55:d1:fc:ab:b8:55:06: + a9:00:4f:31:e2:42:f1:e7:b4:2e:9c:45:0d:dc:a9: + f9:ad:b2:77:c1:f0:b1:c3:a2:5a:26:90:bd:19:2f: + 46:1d:a5:21:3d:f0:35:62:94:c8:cf:33:3f:d8:a2: + 5d:df:cc:58:00:08:8d:ed:b1:04:c5:2b:3f:1a:15: + f6:92:08:d4:f1:42:cd:6c:db:f2:ff:e0:6e:69:84: + d8:8b Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Basic Constraints: CA:FALSE X509v3 Subject Key Identifier: - 81:DE:DF:E9:5A:00:1A:CA:67:D6:06:DD:65:B2:4E:C5:9A:04:43:7D + FB:85:00:A8:DF:D6:0C:0E:A7:E3:39:61:D9:BE:CE:2A:EF:6D:28:D8 X509v3 Authority Key Identifier: - keyid:B8:92:DE:FD:8A:18:B3:30:C3:9F:55:F3:33:5D:B4:C8:29:8A:41:14 + keyid:A4:FD:B9:39:1B:81:B3:AA:EB:88:1D:D4:81:A9:B5:11:70:CC:A7:E1 Authority Information Access: OCSP - URI:http://server.w1.fi:8888/ @@ -37,27 +46,40 @@ Certificate: X509v3 Extended Key Usage: TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption - 98:05:c3:45:76:9e:87:4b:6b:68:56:71:81:6c:3d:99:29:02: - 6e:00:9d:fd:2b:8a:81:c3:d4:57:f7:43:34:08:df:4a:f0:59: - a4:3c:aa:86:a2:e2:06:3f:2c:41:b8:db:aa:e1:25:b3:8f:ab: - 85:ff:da:de:e4:3c:a6:12:3a:25:27:c5:17:f5:6c:9e:4d:54: - 36:60:df:f1:95:8f:dd:a6:97:13:ab:9f:d8:39:1f:88:29:3a: - 90:73:65:08:78:e9:64:b3:c0:34:a2:b4:a9:8e:b7:f9:f8:3f: - fb:b6:cb:58:2d:55:2a:57:55:b9:08:c1:6b:b8:f2:25:a2:9a: - 95:a2 + 94:10:ec:75:db:4d:98:80:bd:b7:b2:b1:4d:b8:99:0a:ba:e1: + 47:d4:ef:50:48:5b:89:97:8b:ee:ee:56:2e:e6:ba:2d:0c:90: + 59:29:a1:c9:10:08:9a:c7:e9:57:42:5a:f6:7e:72:cd:d9:ff: + 8b:b2:13:6f:6e:e1:49:04:a5:82:cd:10:59:37:a5:9a:b2:2c: + 6e:a7:9e:ba:1f:e3:b7:79:79:37:65:a8:9b:49:39:c2:13:7d: + 6d:a8:37:23:c4:10:c9:73:25:67:1f:78:fb:b6:86:00:c1:1a: + 60:d7:5e:b9:63:c6:43:41:dd:37:0f:39:c9:fa:ff:8a:f9:62: + 59:00:e6:91:cd:79:28:82:db:30:88:c5:b8:79:8e:63:4c:65: + 50:3d:d2:65:b3:45:62:e5:d1:6f:1c:c1:1f:c2:b5:1a:0f:31: + 75:62:b3:7d:0b:8d:36:f9:43:eb:26:59:59:29:39:ad:37:0c: + 4f:95:7e:86:05:f5:70:fa:45:de:3c:f5:7e:e1:29:bc:82:d3: + a0:63:73:a3:e1:25:f3:5a:14:2d:c7:78:da:aa:e2:8a:df:08: + c5:be:1f:d3:9f:70:0b:7d:ea:5b:f4:2d:22:94:e6:95:92:50: + e2:55:72:13:c5:a1:3a:44:c4:25:18:9d:9d:a9:c8:c0:ea:7a: + d6:76:91:4e -----BEGIN CERTIFICATE----- -MIICeTCCAeKgAwIBAgIJANjT46bL480lMA0GCSqGSIb3DQEBCwUAMC8xCzAJBgNV -BAYTAkZJMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UEAwwHUm9vdCBDQTAeFw0xOTEw -MDQxMzAyMjNaFw0yMDEwMDMxMzAyMjNaMDExCzAJBgNVBAYTAkZJMQ4wDAYDVQQK -DAV3MS5maTESMBAGA1UEAwwJVGVzdCBVc2VyMIGfMA0GCSqGSIb3DQEBAQUAA4GN -ADCBiQKBgQCmli6bIozflL6LiUn2eHaiYH4UlfOW/qsZJQM0ZHQBPqiffPFHYWBM -gpIofCugDsuHv1nr1/NhIjsU86sx9lqVH7h6uCw8qWFTeJvoPlDswtZE50PNvD5O -50b+kp7DmA8pWMjLiQF1R+mVVw92xS8FXsceDfI8EmNduVQZr39AawIDAQABo4Ga -MIGXMAkGA1UdEwQCMAAwHQYDVR0OBBYEFIHe3+laABrKZ9YG3WWyTsWaBEN9MB8G -A1UdIwQYMBaAFLiS3v2KGLMww59V8zNdtMgpikEUMDUGCCsGAQUFBwEBBCkwJzAl -BggrBgEFBQcwAYYZaHR0cDovL3NlcnZlci53MS5maTo4ODg4LzATBgNVHSUEDDAK -BggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOBgQCYBcNFdp6HS2toVnGBbD2ZKQJu -AJ39K4qBw9RX90M0CN9K8FmkPKqGouIGPyxBuNuq4SWzj6uF/9re5DymEjolJ8UX -9WyeTVQ2YN/xlY/dppcTq5/YOR+IKTqQc2UIeOlks8A0orSpjrf5+D/7tstYLVUq -V1W5CMFruPIlopqVog== +MIIDkDCCAnigAwIBAgIJANjT46bL481lMA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV +BAYTAkZJMRAwDgYDVQQHDAdUdXVzdWxhMQ4wDAYDVQQKDAV3MS5maTEQMA4GA1UE +AwwHUm9vdCBDQTAeFw0yMDA1MDIxOTU1MzhaFw0yMTA1MDIxOTU1MzhaMDExCzAJ +BgNVBAYTAkZJMQ4wDAYDVQQKDAV3MS5maTESMBAGA1UEAwwJVGVzdCBVc2VyMIIB +IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvCQI2QdtGQ6UXGvZioQbAyLi +GgZC0wtgjV8xBAb6okBqDCQpWM2DvzqdfzcNTSdd1VdXHPO+dT86TERvAi9biyyw +XEcpGTEI0Sj1HpxbnLfna0A1ED5/ZmcWoU5oinHMMljjCIeiKgctf3P2Q+V/9PZ0 +rifo0lyum4LZpSpydoQv42KqQR7eM7dk+Hlv+gm1vLCMzTSCLcQQVYnqbDiS/mHW +ZIQE1Ao3MjeNw1XR/Ku4VQapAE8x4kLx57QunEUN3Kn5rbJ3wfCxw6JaJpC9GS9G +HaUhPfA1YpTIzzM/2KJd38xYAAiN7bEExSs/GhX2kgjU8ULNbNvy/+BuaYTYiwID +AQABo4GaMIGXMAkGA1UdEwQCMAAwHQYDVR0OBBYEFPuFAKjf1gwOp+M5Ydm+zirv +bSjYMB8GA1UdIwQYMBaAFKT9uTkbgbOq64gd1IGptRFwzKfhMDUGCCsGAQUFBwEB +BCkwJzAlBggrBgEFBQcwAYYZaHR0cDovL3NlcnZlci53MS5maTo4ODg4LzATBgNV +HSUEDDAKBggrBgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAlBDsddtNmIC9t7Kx +TbiZCrrhR9TvUEhbiZeL7u5WLua6LQyQWSmhyRAImsfpV0Ja9n5yzdn/i7ITb27h +SQSlgs0QWTelmrIsbqeeuh/jt3l5N2Wom0k5whN9bag3I8QQyXMlZx94+7aGAMEa +YNdeuWPGQ0HdNw85yfr/ivliWQDmkc15KILbMIjFuHmOY0xlUD3SZbNFYuXRbxzB +H8K1Gg8xdWKzfQuNNvlD6yZZWSk5rTcMT5V+hgX1cPpF3jz1fuEpvILToGNzo+El +81oULcd42qriit8Ixb4f059wC33qW/QtIpTmlZJQ4lVyE8WhOkTEJRidnanIwOp6 +1naRTg== -----END CERTIFICATE----- diff --git a/tests/hwsim/auth_serv/user.pkcs12 b/tests/hwsim/auth_serv/user.pkcs12 index 30fd17969..13d97acc9 100644 Binary files a/tests/hwsim/auth_serv/user.pkcs12 and b/tests/hwsim/auth_serv/user.pkcs12 differ diff --git a/tests/hwsim/auth_serv/user.rsa-key b/tests/hwsim/auth_serv/user.rsa-key index 4c3cfbfb9..c77924a3e 100644 --- a/tests/hwsim/auth_serv/user.rsa-key +++ b/tests/hwsim/auth_serv/user.rsa-key @@ -1,15 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -MIICXgIBAAKBgQCmli6bIozflL6LiUn2eHaiYH4UlfOW/qsZJQM0ZHQBPqiffPFH -YWBMgpIofCugDsuHv1nr1/NhIjsU86sx9lqVH7h6uCw8qWFTeJvoPlDswtZE50PN -vD5O50b+kp7DmA8pWMjLiQF1R+mVVw92xS8FXsceDfI8EmNduVQZr39AawIDAQAB -AoGBAJBKEtJCidx6nNSFtK+sRa19gJdaDqQhr5dW7MCrpaMSX8HM2bvnBx8eFXTF -oI/BYN8SidNyuBbRLHWIXScoZ+nOhmLChexxxqNlgOtVR8YKkQfwmcwC8tiUf968 -xJb61UOWVYdeQ4qTacH8D/W1uj/fQKJj0FZ2d6dR4FOViuvJAkEA1x2xVGF9yPUm -JUeCYT8uaL9kPFh7uKfa1lxgTu+bku39xWQmxlCymRDrIlRW5aMlHabyyHe8L29+ -N2tRADpwvQJBAMY/VKrCjAHZV0w60/TXEJiSlreevIBFeP+OX46U823Z3RDrQjMF -gVhL/0soloFncD3gVYkRhMj65C1f0rXnrEcCQQCHzekLmlisq4efdVusRRTpcBq5 -tiq1UtLnDX6HluEiizjwit+nx35Y/8NR8ujBJJPj+me/g0e8sqh+GDQU7tAJAkAO -7mYqFk0FNqFklGmyXyBY3XGMkuAPqSvb05VO39kVxPrpc06hGSEMzWyE9KGhTXEe -t+65TCB8Iqlc4YK1QKWxAkEAyuUKlxOmdlR0zRJwpIvWL5IIz4S8UooUDA0mkdBD -ZK3tDnLRVLn28Mx+wxIc1egkNVMPvQLuQDhc3G9bXxnMzw== +MIIEowIBAAKCAQEAvCQI2QdtGQ6UXGvZioQbAyLiGgZC0wtgjV8xBAb6okBqDCQp +WM2DvzqdfzcNTSdd1VdXHPO+dT86TERvAi9biyywXEcpGTEI0Sj1HpxbnLfna0A1 +ED5/ZmcWoU5oinHMMljjCIeiKgctf3P2Q+V/9PZ0rifo0lyum4LZpSpydoQv42Kq +QR7eM7dk+Hlv+gm1vLCMzTSCLcQQVYnqbDiS/mHWZIQE1Ao3MjeNw1XR/Ku4VQap +AE8x4kLx57QunEUN3Kn5rbJ3wfCxw6JaJpC9GS9GHaUhPfA1YpTIzzM/2KJd38xY +AAiN7bEExSs/GhX2kgjU8ULNbNvy/+BuaYTYiwIDAQABAoIBAAFRU0qJ1cbGJl3b +V4Oz1yiXdvPttUwbGUsELqizj8/RGa0KF8wKbHDLbUz1yr8Oloam/PIz9tKFZdgg +5pIiWMbJwlZzHSOTB1fHrKfROocHdrR2l6iMd4H1GOB6VxsZHu//VV+663TV5git +fD0Pf2zsyPZrSyMmCQcHzJRujqyrz0KHi8KGYjA7wN50vGv03kzzVyNZnexh3z16 +jrpgJ4FdBOBbk+135GngVc2rWlErWA/VhIY7YhGoQiVqrTe1P2auKigel661cnvA +YsQzUX/0J8+Uj64VpN61jxAKjwXKjhIq0GqUACPnve+Iq6MKtVjlFeMQ2FqvEKF6 +zFhcBRECgYEA48MbPovj993n2nk1xgIyv6oni5+yb5xyMQDjyvqsz2O+W9NVNCR/ +akSrNSdncVEEBVrtq1rWywFQ3/Hrf1ES/GQKgstlPBzlCbrvsfZDaC0cURLmPRIT +HkOj+nJUxsdX4CHPQV7E/lIzCuiPkdycGRMC2H9xPNSlPQpiqQn1GcMCgYEA03dk +0bvXyG5iKwH+krb7Eg9jlkP0QWrzRKSEix+f6K77d5F8vSOmwMlvhch2eOttAhNu +H87LVh/JdxdYyLwn99sGvHE4tRAO5UYfIFUQtLNgnRE7Hu5VB06qqKjunJE/adGS +yx32wC7MtIyDmVJ6NLlYGD821pL11o++kNu7kZkCgYBt/KoLakKMT/zG5AGzvRwE +soamRlhEzafXQja+ro8FF4W1kjhzFazyBHcpE/5AGn92lpJvTU6sedY0Tv8KXHxu +pWDuCIq6nLl+GWfm6KVkiWRDQn0swK26z69AIjYOR/WHpswPJVS7+7XqbqPmLEK1 +WRjms6RbW9TvxTQfrU9PQQKBgQDJRswsoTmrKf3AZ96ScR4au5ETlsync4/nFxyd +e1VuWRc7YLw1Hvj6aQEAeqThRVx1bF8WYXPDHvBYrV0xe34jeVM5DB9on8c9zXeV +A8Kp7E6aUatPLpS6JtNjQ6ASYGHWa8boFDYoCKOJenFL/2gYRQ4nzgt5Q1pBhoJh +SPSIiQKBgFDCIsrXle86q3N53K52Ljb4PdFXgOwjGtEr5jjGEtDPH1FB7W7YX6+u +HNn1jPSRX5QKUbVZB0nJUTCNUaplVkrw6kuJMW9DQuR4loqER29z5RKi/BdO+pck +g/9ubDcFsB8DKtTCTzou3BF3NWLVktulg/wunWrleRZzGu3l9Q9y -----END RSA PRIVATE KEY----- diff --git a/tests/hwsim/auth_serv/user2.pkcs12 b/tests/hwsim/auth_serv/user2.pkcs12 index f2eeed8f6..8957a5655 100644 Binary files a/tests/hwsim/auth_serv/user2.pkcs12 and b/tests/hwsim/auth_serv/user2.pkcs12 differ diff --git a/tests/hwsim/auth_serv/user3.pkcs12 b/tests/hwsim/auth_serv/user3.pkcs12 index e40af9de4..46ae62e82 100644 Binary files a/tests/hwsim/auth_serv/user3.pkcs12 and b/tests/hwsim/auth_serv/user3.pkcs12 differ diff --git a/tests/hwsim/bss-1.conf b/tests/hwsim/bss-1.conf deleted file mode 100644 index b465dcbbd..000000000 --- a/tests/hwsim/bss-1.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3 -bssid=02:00:00:00:03:00 -ctrl_interface=/var/run/hostapd - -ssid=bss-1 diff --git a/tests/hwsim/bss-2-dup.conf b/tests/hwsim/bss-2-dup.conf deleted file mode 100644 index 9f63c9ddc..000000000 --- a/tests/hwsim/bss-2-dup.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3-2 -bssid=02:00:00:00:03:00 -ctrl_interface=/var/run/hostapd - -ssid=bss-2 diff --git a/tests/hwsim/bss-2.conf b/tests/hwsim/bss-2.conf deleted file mode 100644 index 7a8c64c15..000000000 --- a/tests/hwsim/bss-2.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3-2 -bssid=02:00:00:00:03:01 -ctrl_interface=/var/run/hostapd - -ssid=bss-2 diff --git a/tests/hwsim/bss-3.conf b/tests/hwsim/bss-3.conf deleted file mode 100644 index fe671def4..000000000 --- a/tests/hwsim/bss-3.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3-3 -bssid=02:00:00:00:03:02 -ctrl_interface=/var/run/hostapd - -ssid=bss-3 diff --git a/tests/hwsim/bss-4.conf b/tests/hwsim/bss-4.conf deleted file mode 100644 index 4028794cc..000000000 --- a/tests/hwsim/bss-4.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3-4 -bssid=02:00:00:00:03:03 -ctrl_interface=/var/run/hostapd - -ssid=bss-4 diff --git a/tests/hwsim/bss-5.conf b/tests/hwsim/bss-5.conf deleted file mode 100644 index 8b8836812..000000000 --- a/tests/hwsim/bss-5.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3-5 -bssid=02:00:00:00:03:04 -ctrl_interface=/var/run/hostapd - -ssid=bss-5 diff --git a/tests/hwsim/bss-6.conf b/tests/hwsim/bss-6.conf deleted file mode 100644 index 66a0d0c5e..000000000 --- a/tests/hwsim/bss-6.conf +++ /dev/null @@ -1,11 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 - -interface=wlan3-6 -bssid=02:00:00:00:03:05 -ctrl_interface=/var/run/hostapd - -ssid=bss-6 diff --git a/tests/hwsim/bss-ht40-1.conf b/tests/hwsim/bss-ht40-1.conf deleted file mode 100644 index a338c6b66..000000000 --- a/tests/hwsim/bss-ht40-1.conf +++ /dev/null @@ -1,12 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 -ht_capab=[HT40+] - -interface=wlan3 -bssid=02:00:00:00:03:00 -ctrl_interface=/var/run/hostapd - -ssid=bss-1 diff --git a/tests/hwsim/bss-ht40-2.conf b/tests/hwsim/bss-ht40-2.conf deleted file mode 100644 index c7e27ce3d..000000000 --- a/tests/hwsim/bss-ht40-2.conf +++ /dev/null @@ -1,12 +0,0 @@ -driver=nl80211 - -hw_mode=g -channel=1 -ieee80211n=1 -ht_capab=[HT40+] - -interface=wlan3-2 -bssid=02:00:00:00:03:01 -ctrl_interface=/var/run/hostapd - -ssid=bss-2 diff --git a/tests/hwsim/build.sh b/tests/hwsim/build.sh index 165d808fd..cb4700166 100755 --- a/tests/hwsim/build.sh +++ b/tests/hwsim/build.sh @@ -26,25 +26,29 @@ while [ "$1" != "" ]; do esac done +JOBS=`nproc` +if [ -z "$ABC" ]; then + JOBS=8 +fi + echo "Building TNC testing tools" cd tnc -make clean > /dev/null -make QUIET=1 -j8 +make QUIET=1 -j$JOBS echo "Building wlantest" cd ../../../wlantest -make clean > /dev/null -make QUIET=1 -j8 > /dev/null +make QUIET=1 -j$JOBS > /dev/null echo "Building hs20-osu-client" cd ../hs20/client/ -make clean > /dev/null 2>&1 make QUIET=1 CONFIG_NO_BROWSER=1 echo "Building hostapd" cd ../../hostapd if [ ! -e .config -o $force_config -eq 1 ]; then - cp ../tests/hwsim/example-hostapd.config .config + if ! cmp ../tests/hwsim/example-hostapd.config .config >/dev/null 2>&1 ; then + cp ../tests/hwsim/example-hostapd.config .config + fi fi if [ $use_lcov -eq 1 ]; then @@ -55,13 +59,14 @@ if [ $use_lcov -eq 1 ]; then fi fi -make clean > /dev/null -make QUIET=1 -j8 hostapd hostapd_cli hlr_auc_gw +make QUIET=1 -j$JOBS hostapd hostapd_cli hlr_auc_gw echo "Building wpa_supplicant" cd ../wpa_supplicant if [ ! -e .config -o $force_config -eq 1 ]; then - cp ../tests/hwsim/example-wpa_supplicant.config .config + if ! cmp ../tests/hwsim/example-wpa_supplicant.config .config >/dev/null 2>&1 ; then + cp ../tests/hwsim/example-wpa_supplicant.config .config + fi fi if [ $use_lcov -eq 1 ]; then @@ -72,8 +77,7 @@ if [ $use_lcov -eq 1 ]; then fi fi -make clean > /dev/null if [ -z $FIPSLD_CC ]; then export FIPSLD_CC=gcc fi -make QUIET=1 -j8 +make QUIET=1 -j$JOBS diff --git a/tests/hwsim/example-hostapd.config b/tests/hwsim/example-hostapd.config index d93c4d252..972d35c75 100644 --- a/tests/hwsim/example-hostapd.config +++ b/tests/hwsim/example-hostapd.config @@ -48,7 +48,6 @@ CONFIG_VLAN_NETLINK=y CONFIG_LIBNL32=y CONFIG_LIBNL3_ROUTE=y CONFIG_IEEE80211R=y -CONFIG_IEEE80211N=y CONFIG_IEEE80211AC=y CONFIG_IEEE80211AX=y @@ -72,6 +71,7 @@ CONFIG_INTERWORKING=y CONFIG_HS20=y CONFIG_SQLITE=y CONFIG_SAE=y +CONFIG_SAE_PK=y CFLAGS += -DALL_DH_GROUPS CONFIG_FST=y @@ -111,3 +111,4 @@ CONFIG_FILS_SK_PFS=y CONFIG_OWE=y CONFIG_DPP=y CONFIG_DPP2=y +CONFIG_WEP=y diff --git a/tests/hwsim/example-wpa_supplicant.config b/tests/hwsim/example-wpa_supplicant.config index 397a6f173..9e3cc67e4 100644 --- a/tests/hwsim/example-wpa_supplicant.config +++ b/tests/hwsim/example-wpa_supplicant.config @@ -58,7 +58,6 @@ CONFIG_CTRL_IFACE_DBUS_NEW=y CONFIG_CTRL_IFACE_DBUS_INTRO=y CONFIG_IEEE80211R=y -CONFIG_IEEE80211N=y CONFIG_IEEE80211AC=y CONFIG_IEEE80211AX=y @@ -117,6 +116,7 @@ CONFIG_EXT_PASSWORD_TEST=y CONFIG_EAP_UNAUTH_TLS=y CONFIG_SAE=y +CONFIG_SAE_PK=y CFLAGS += -DALL_DH_GROUPS CONFIG_WNM=y @@ -154,3 +154,4 @@ CONFIG_PMKSA_CACHE_EXTERNAL=y CONFIG_OWE=y CONFIG_DPP=y CONFIG_DPP2=y +CONFIG_WEP=y diff --git a/tests/hwsim/hostapd.accept b/tests/hwsim/hostapd.accept deleted file mode 100644 index ce455b1a2..000000000 --- a/tests/hwsim/hostapd.accept +++ /dev/null @@ -1,2 +0,0 @@ -02:00:00:00:00:00 1 -02:00:00:00:01:00 2 diff --git a/tests/hwsim/hostapd.accept2 b/tests/hwsim/hostapd.accept2 deleted file mode 100644 index 3d41e348a..000000000 --- a/tests/hwsim/hostapd.accept2 +++ /dev/null @@ -1,3 +0,0 @@ -02:00:00:00:00:00 1 -02:00:00:00:01:00 2 -02:00:00:00:02:00 3 diff --git a/tests/hwsim/hostapd.macaddr b/tests/hwsim/hostapd.macaddr deleted file mode 100644 index a3b7878b5..000000000 --- a/tests/hwsim/hostapd.macaddr +++ /dev/null @@ -1,7 +0,0 @@ -02:00:00:00:00:00 -02:00:00:00:00:12 -02:00:00:00:00:34 --02:00:00:00:00:12 --02:00:00:00:00:34 -01:01:01:01:01:01 -03:01:01:01:01:03 diff --git a/tests/hwsim/hostapd.py b/tests/hwsim/hostapd.py index fac287e99..571757506 100644 --- a/tests/hwsim/hostapd.py +++ b/tests/hwsim/hostapd.py @@ -5,10 +5,12 @@ # See README for more details. import os +import re import time import logging import binascii import struct +import tempfile import wpaspy import remotehost import utils @@ -135,6 +137,9 @@ class HostapdGlobal: self.ctrl.terminate() self.ctrl = None + def send_file(self, src, dst): + self.host.send_file(src, dst) + class Hostapd: def __init__(self, ifname, bssidx=0, hostname=None, port=8877): self.hostname = hostname @@ -191,6 +196,9 @@ class Hostapd: def set(self, field, value): if "OK" not in self.request("SET " + field + " " + value): + if "TKIP" in value and (field == "wpa_pairwise" or \ + field == "rsn_pairwise"): + raise utils.HwsimSkip("Cipher TKIP not supported") raise Exception("Failed to set hostapd parameter " + field) def set_defaults(self): @@ -524,6 +532,9 @@ class Hostapd: def note(self, txt): self.request("NOTE " + txt) + def send_file(self, src, dst): + self.host.send_file(src, dst) + def add_ap(apdev, params, wait_enabled=True, no_enable=False, timeout=30, global_ctrl_override=None, driver=False): if isinstance(apdev, dict): @@ -551,7 +562,7 @@ def add_ap(apdev, params, wait_enabled=True, no_enable=False, timeout=30, raise Exception("Could not ping hostapd") hapd.set_defaults() fields = ["ssid", "wpa_passphrase", "nas_identifier", "wpa_key_mgmt", - "wpa", + "wpa", "wpa_deny_ptk0_rekey", "wpa_pairwise", "rsn_pairwise", "auth_server_addr", "acct_server_addr", "osu_server_uri"] for field in fields: @@ -587,6 +598,8 @@ def add_bss(apdev, ifname, confname, ignore_error=False): hostname = None port = 8878 hapd_global = HostapdGlobal(apdev) + confname = cfg_file(apdev, confname, ifname) + hapd_global.send_file(confname, confname) hapd_global.add_bss(phy, confname, ignore_error) port = hapd_global.get_ctrl_iface_port(ifname) hapd = Hostapd(ifname, hostname=hostname, port=port) @@ -605,6 +618,8 @@ def add_iface(apdev, confname): hostname = None port = 8878 hapd_global = HostapdGlobal(apdev) + confname = cfg_file(apdev, confname, ifname) + hapd_global.send_file(confname, confname) hapd_global.add_iface(ifname, confname) port = hapd_global.get_ctrl_iface_port(ifname) hapd = Hostapd(ifname, hostname=hostname, port=port) @@ -747,3 +762,78 @@ def ht40_minus_params(channel="1", ssid=None, country=None): def cmd_execute(apdev, cmd, shell=False): hapd_global = HostapdGlobal(apdev) return hapd_global.cmd_execute(cmd, shell=shell) + +def send_file(apdev, src, dst): + hapd_global = HostapdGlobal(apdev) + return hapd_global.send_file(src, dst) + +def acl_file(dev, apdev, conf): + fd, filename = tempfile.mkstemp(dir='/tmp', prefix=conf + '-') + f = os.fdopen(fd, 'w') + + if conf == 'hostapd.macaddr': + mac0 = dev[0].get_status_field("address") + f.write(mac0 + '\n') + f.write("02:00:00:00:00:12\n") + f.write("02:00:00:00:00:34\n") + f.write("-02:00:00:00:00:12\n") + f.write("-02:00:00:00:00:34\n") + f.write("01:01:01:01:01:01\n") + f.write("03:01:01:01:01:03\n") + elif conf == 'hostapd.accept': + mac0 = dev[0].get_status_field("address") + mac1 = dev[1].get_status_field("address") + f.write(mac0 + " 1\n") + f.write(mac1 + " 2\n") + elif conf == 'hostapd.accept2': + mac0 = dev[0].get_status_field("address") + mac1 = dev[1].get_status_field("address") + mac2 = dev[2].get_status_field("address") + f.write(mac0 + " 1\n") + f.write(mac1 + " 2\n") + f.write(mac2 + " 3\n") + else: + f.close() + os.unlink(filename) + return conf + + return filename + +def bssid_inc(apdev, inc=1): + parts = apdev['bssid'].split(':') + parts[5] = '%02x' % (int(parts[5], 16) + int(inc)) + bssid = '%s:%s:%s:%s:%s:%s' % (parts[0], parts[1], parts[2], + parts[3], parts[4], parts[5]) + return bssid + +def cfg_file(apdev, conf, ifname=None): + match = re.search(r'^bss-.+', conf) + if match: + # put cfg file in /tmp directory + fd, fname = tempfile.mkstemp(dir='/tmp', prefix=conf + '-') + f = os.fdopen(fd, 'w') + idx = ''.join(filter(str.isdigit, conf.split('-')[-1])) + if ifname is None: + ifname = apdev['ifname'] + if idx != '1': + ifname = ifname + '-' + idx + + f.write("driver=nl80211\n") + f.write("ctrl_interface=/var/run/hostapd\n") + f.write("hw_mode=g\n") + f.write("channel=1\n") + f.write("ieee80211n=1\n") + if conf.startswith('bss-ht40-'): + f.write("ht_capab=[HT40+]\n") + f.write("interface=%s\n" % ifname) + + f.write("ssid=bss-%s\n" % idx) + if conf == 'bss-2-dup.conf': + bssid = apdev['bssid'] + else: + bssid = bssid_inc(apdev, int(idx) - 1) + f.write("bssid=%s\n" % bssid) + + return fname + + return conf diff --git a/tests/hwsim/multi-bss-acs.conf b/tests/hwsim/multi-bss-acs.conf index 4e1db46c0..f5a25e82b 100644 --- a/tests/hwsim/multi-bss-acs.conf +++ b/tests/hwsim/multi-bss-acs.conf @@ -22,7 +22,7 @@ bss=wlan3-3 bssid=02:00:00:00:03:02 ctrl_interface=/var/run/hostapd ssid=bss-3 -wpa=1 -wpa_key_mgmt=WPA-PSK -rsn_pairwise=TKIP -wpa_passphrase=qwertyuiop +wpa=2 +wpa_key_mgmt=SAE +rsn_pairwise=CCMP +sae_password=qwertyuiop diff --git a/tests/hwsim/remotehost.py b/tests/hwsim/remotehost.py index 50f46c310..a5b85ac7d 100644 --- a/tests/hwsim/remotehost.py +++ b/tests/hwsim/remotehost.py @@ -7,6 +7,8 @@ import logging import subprocess import threading +import tempfile +import os logger = logging.getLogger() @@ -17,12 +19,15 @@ def remote_compatible(func): def execute_thread(command, reply): cmd = ' '.join(command) logger.debug("thread run: " + cmd) + err = tempfile.TemporaryFile() try: status = 0 - buf = subprocess.check_output(command, stderr=subprocess.STDOUT).decode() + buf = subprocess.check_output(command, stderr=err).decode() except subprocess.CalledProcessError as e: status = e.returncode - buf = e.output + err.seek(0) + buf = err.read() + err.close() logger.debug("thread cmd: " + cmd) logger.debug("thread exit status: " + str(status)) @@ -30,6 +35,17 @@ def execute_thread(command, reply): reply.append(status) reply.append(buf) +def gen_reaper_file(conf): + fd, filename = tempfile.mkstemp(dir='/tmp', prefix=conf + '-') + f = os.fdopen(fd, 'w') + + f.write("#!/bin/sh\n") + f.write("name=\"$(basename $0)\"\n") + f.write("echo $$ > /tmp/$name.pid\n") + f.write("exec \"$@\"\n"); + + return filename; + class Host(): def __init__(self, host=None, ifname=None, port=None, name="", user="root"): self.host = host @@ -41,17 +57,21 @@ class Host(): self.ifname = ifname self.port = port self.dev = None + self.monitor_params = [] if self.name == "" and host != None: self.name = host def local_execute(self, command): logger.debug("execute: " + str(command)) + err = tempfile.TemporaryFile() try: status = 0 - buf = subprocess.check_output(command, stderr=subprocess.STDOUT) + buf = subprocess.check_output(command, stderr=err) except subprocess.CalledProcessError as e: status = e.returncode - buf = e.output + err.seek(0) + buf = err.read() + err.close() logger.debug("status: " + str(status)) logger.debug("buf: " + str(buf)) @@ -64,39 +84,160 @@ class Host(): cmd = ["ssh", self.user + "@" + self.host, ' '.join(command)] _cmd = self.name + " execute: " + ' '.join(cmd) logger.debug(_cmd) + err = tempfile.TemporaryFile() try: status = 0 - buf = subprocess.check_output(cmd, stderr=subprocess.STDOUT) + buf = subprocess.check_output(cmd, stderr=err) except subprocess.CalledProcessError as e: status = e.returncode - buf = e.output + err.seek(0) + buf = err.read() + err.close() logger.debug(self.name + " status: " + str(status)) logger.debug(self.name + " buf: " + str(buf)) return status, buf.decode() # async execute - def execute_run(self, command, res): - if self.host is None: - cmd = command + def thread_run(self, command, res, use_reaper=True): + if use_reaper: + filename = gen_reaper_file("reaper") + self.send_file(filename, filename) + self.execute(["chmod", "755", filename]) + _command = [filename] + command else: - cmd = ["ssh", self.user + "@" + self.host, ' '.join(command)] - _cmd = self.name + " execute_run: " + ' '.join(cmd) + filename = "" + _command = command + + if self.host is None: + cmd = _command + else: + cmd = ["ssh", self.user + "@" + self.host, ' '.join(_command)] + _cmd = self.name + " thread_run: " + ' '.join(cmd) logger.debug(_cmd) - t = threading.Thread(target=execute_thread, args=(cmd, res)) + t = threading.Thread(target=execute_thread, name=filename, args=(cmd, res)) t.start() return t - def wait_execute_complete(self, t, wait=None): + def thread_stop(self, t): + if t.name.find("reaper") == -1: + raise Exception("use_reaper required") + + pid_file = t.name + ".pid" + + if t.isAlive(): + cmd = ["kill `cat " + pid_file + "`"] + self.execute(cmd) + + # try again + self.wait_execute_complete(t, 5) + if t.isAlive(): + cmd = ["kill `cat " + pid_file + "`"] + self.execute(cmd) + + # try with -9 + self.wait_execute_complete(t, 5) + if t.isAlive(): + cmd = ["kill -9 `cat " + pid_file + "`"] + self.execute(cmd) + + self.wait_execute_complete(t, 5) + if t.isAlive(): + raise Exception("thread still alive") + + self.execute(["rm", pid_file]) + self.execute(["rm", t.name]) + self.local_execute(["rm", t.name]) + + def thread_wait(self, t, wait=None): if wait == None: wait_str = "infinite" else: wait_str = str(wait) + "s" - logger.debug(self.name + " wait_execute_complete(" + wait_str + "): ") + logger.debug(self.name + " thread_wait(" + wait_str + "): ") if t.isAlive(): t.join(wait) + def pending(self, s, timeout=0): + [r, w, e] = select.select([s], [], [], timeout) + if r: + return True + return False + + def proc_run(self, command): + filename = gen_reaper_file("reaper") + self.send_file(filename, filename) + self.execute(["chmod", "755", filename]) + _command = [filename] + command + + if self.host: + cmd = ["ssh", self.user + "@" + self.host, ' '.join(_command)] + else: + cmd = _command + + _cmd = self.name + " proc_run: " + ' '.join(cmd) + logger.debug(_cmd) + err = tempfile.TemporaryFile() + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=err) + proc.reaper_file = filename + return proc + + def proc_wait_event(self, proc, events, timeout=10): + if not isinstance(events, list): + raise Exception("proc_wait_event() events not a list") + + logger.debug(self.name + " proc_wait_event: " + ' '.join(events) + " timeout: " + str(timeout)) + start = os.times()[4] + try: + while True: + while self.pending(proc.stdout): + line = proc.stdout.readline() + if not line: + return None + line = line.decode() + logger.debug(line.strip('\n')) + for event in events: + if event in line: + return line + now = os.times()[4] + remaining = start + timeout - now + if remaining <= 0: + break + if not self.pending(proc.stdout, timeout=remaining): + break + except: + pass + return None + + def proc_stop(self, proc): + if not proc: + return + + self.execute(["kill `cat " + proc.reaper_file + ".pid`"]) + self.execute(["rm", proc.reaper_file + ".pid"]) + self.execute(["rm", proc.reaper_file]) + self.local_execute(["rm", proc.reaper_file]) + proc.kill() + + def proc_dump(self, proc): + if not proc: + return "" + return proc.stdout.read() + + def execute_and_wait_event(self, command, events, timeout=10): + proc = None + ev = None + + try: + proc = self.proc_run(command) + ev = self.proc_wait_event(proc, events, timeout) + except: + pass + + self.proc_stop(proc) + return ev + def add_log(self, log_file): self.logs.append(log_file) @@ -106,3 +247,9 @@ class Host(): self.local_execute(["scp", self.user + "@[" + self.host + "]:" + log, local_log_dir]) self.execute(["rm", log]) del self.logs[:] + + def send_file(self, src, dst): + if self.host is None: + return + self.local_execute(["scp", src, + self.user + "@[" + self.host + "]:" + dst]) diff --git a/tests/hwsim/run-all.sh b/tests/hwsim/run-all.sh index 495c9fa74..ee48cd058 100755 --- a/tests/hwsim/run-all.sh +++ b/tests/hwsim/run-all.sh @@ -122,7 +122,13 @@ if ! ./start.sh $VM $VALGRIND $TRACE channels=$NUM_CH; then exit 1 fi -sudo ./run-tests.py -D --logdir "$LOGDIR" $TRACE_ARGS -q $DB $RUN_TEST_ARGS || errors=1 +# Only use sudo if not already root. +if [ "$(id -u)" != 0 ]; then + SUDO=sudo +else + SUDO= +fi +${SUDO} ./run-tests.py -D --logdir "$LOGDIR" $TRACE_ARGS -q $DB $RUN_TEST_ARGS || errors=1 ./stop.sh diff --git a/tests/hwsim/run-tests.py b/tests/hwsim/run-tests.py index b201cd78d..019533f54 100755 --- a/tests/hwsim/run-tests.py +++ b/tests/hwsim/run-tests.py @@ -187,6 +187,18 @@ def rename_log(logdir, basename, testname, dev): logger.info("Failed to rename log files") logger.info(e) +def is_long_duration_test(t): + return hasattr(t, "long_duration_test") and t.long_duration_test + +def get_test_description(t): + if t.__doc__ is None: + desc = "MISSING DESCRIPTION" + else: + desc = t.__doc__ + if is_long_duration_test(t): + desc += " [long]" + return desc + def main(): tests = [] test_modules = [] @@ -319,13 +331,10 @@ def main(): if args.update_tests_db: for t in tests_to_run: name = t.__name__.replace('test_', '', 1) - if t.__doc__ is None: - print(name + " - MISSING DESCRIPTION") - else: - print(name + " - " + t.__doc__) + print(name + " - " + get_test_description(t)) if conn: sql = 'INSERT OR REPLACE INTO tests(test,description) VALUES (?, ?)' - params = (name, t.__doc__) + params = (name, get_test_description(t)) try: conn.execute(sql, params) except Exception as e: @@ -512,10 +521,13 @@ def main(): sys.exit(1) skip_reason = None try: + if is_long_duration_test(t) and not args.long: + raise HwsimSkip("Skip test case with long duration due to --long not specified") if t.__code__.co_argcount > 2: params = {} params['logdir'] = args.logdir - params['long'] = args.long + params['name'] = name + params['prefix'] = os.path.join(args.logdir, name) t(dev, apdev, params) elif t.__code__.co_argcount > 1: t(dev, apdev) @@ -525,7 +537,9 @@ def main(): if check_country_00: for d in dev: country = d.get_driver_status_field("country") - if country != "00": + if country is None: + logger.info(d.ifname + ": Could not fetch country code after the test case run") + elif country != "00": d.dump_monitor() logger.info(d.ifname + ": Country code not reset back to 00: is " + country) print(d.ifname + ": Country code not reset back to 00: is " + country) diff --git a/tests/hwsim/start.sh b/tests/hwsim/start.sh index 7a26d2825..ac43d10af 100755 --- a/tests/hwsim/start.sh +++ b/tests/hwsim/start.sh @@ -110,7 +110,7 @@ else NUM_CH=1 fi -test -f /proc/modules && sudo modprobe mac80211_hwsim radios=7 channels=$NUM_CH support_p2p_device=0 dyndbg=+p +test -d /sys/module/mac80211_hwsim || sudo modprobe mac80211_hwsim radios=7 channels=$NUM_CH support_p2p_device=0 dyndbg=+p sudo ifconfig hwsim0 up sudo $WLANTEST -i hwsim0 -n $LOGDIR/hwsim0.pcapng -c -dtN -L $LOGDIR/hwsim0 & diff --git a/tests/hwsim/test_ap_acs.py b/tests/hwsim/test_ap_acs.py index fe88d0171..eb245e7c3 100644 --- a/tests/hwsim/test_ap_acs.py +++ b/tests/hwsim/test_ap_acs.py @@ -9,8 +9,7 @@ logger = logging.getLogger() import time import hostapd -from utils import skip_with_fips, alloc_fail, fail_test, HwsimSkip, clear_regdom -from test_ap_ht import clear_scan_cache +from utils import * from test_dfs import wait_dfs_event def force_prev_ap_on_24g(ap): @@ -38,7 +37,7 @@ def wait_acs(hapd, return_after_acs=False): state = hapd.get_status_field("state") if state != "ACS": - raise Exception("Unexpected interface state") + raise Exception("Unexpected interface state %s (expected ACS)" % state) ev = hapd.wait_event(["ACS-COMPLETED", "ACS-FAILED", "AP-ENABLED", "AP-DISABLED"], timeout=20) @@ -58,7 +57,7 @@ def wait_acs(hapd, return_after_acs=False): state = hapd.get_status_field("state") if state != "ENABLED": - raise Exception("Unexpected interface state") + raise Exception("Unexpected interface state %s (expected ENABLED)" % state) def test_ap_acs(dev, apdev): """Automatic channel selection""" @@ -91,16 +90,23 @@ def test_ap_acs_chanlist(dev, apdev): def test_ap_acs_freqlist(dev, apdev): """Automatic channel selection with freqlist set""" + run_ap_acs_freqlist(dev, apdev, [2412, 2437, 2462]) + +def test_ap_acs_freqlist2(dev, apdev): + """Automatic channel selection with freqlist set""" + run_ap_acs_freqlist(dev, apdev, [2417, 2432, 2457]) + +def run_ap_acs_freqlist(dev, apdev, freqlist): force_prev_ap_on_24g(apdev[0]) params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678") params['channel'] = '0' - params['freqlist'] = '2412 2437 2462' + params['freqlist'] = ','.join([str(x) for x in freqlist]) hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) wait_acs(hapd) freq = int(hapd.get_status_field("freq")) - if freq not in [2412, 2437, 2462]: - raise Exception("Unexpected frequency: " + freq) + if freq not in freqlist: + raise Exception("Unexpected frequency: %d" % freq) dev[0].connect("test-acs", psk="12345678", scan_freq=str(freq)) @@ -118,6 +124,7 @@ def test_ap_acs_invalid_chanlist(dev, apdev): def test_ap_multi_bss_acs(dev, apdev): """hostapd start with a multi-BSS configuration file using ACS""" skip_with_fips(dev[0]) + check_sae_capab(dev[2]) force_prev_ap_on_24g(apdev[0]) # start the actual test @@ -131,7 +138,8 @@ def test_ap_multi_bss_acs(dev, apdev): dev[0].connect("bss-1", key_mgmt="NONE", scan_freq=freq) dev[1].connect("bss-2", psk="12345678", scan_freq=freq) - dev[2].connect("bss-3", psk="qwertyuiop", scan_freq=freq) + dev[2].set("sae_groups", "") + dev[2].connect("bss-3", key_mgmt="SAE", psk="qwertyuiop", scan_freq=freq) def test_ap_acs_40mhz(dev, apdev): """Automatic channel selection for 40 MHz channel""" @@ -387,10 +395,9 @@ def test_ap_acs_errors(dev, apdev): if not ev: raise Exception("ACS start timed out") -def test_ap_acs_dfs(dev, apdev, params): - """Automatic channel selection, HT scan, and DFS [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_ap_acs_dfs(dev, apdev): + """Automatic channel selection, HT scan, and DFS""" try: hapd = None force_prev_ap_on_5g(apdev[0]) @@ -469,10 +476,9 @@ def test_ap_acs_exclude_dfs(dev, apdev, params): dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5) dev[0].flush_scan_cache() -def test_ap_acs_vht160_dfs(dev, apdev, params): - """Automatic channel selection 160 MHz, HT scan, and DFS [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_ap_acs_vht160_dfs(dev, apdev): + """Automatic channel selection 160 MHz, HT scan, and DFS""" try: hapd = None force_prev_ap_on_5g(apdev[0]) @@ -515,3 +521,104 @@ def test_ap_acs_vht160_dfs(dev, apdev, params): hostapd.cmd_execute(apdev[0], ['iw', 'reg', 'set', '00']) dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5) dev[0].flush_scan_cache() + +def test_ap_acs_hw_mode_any(dev, apdev): + """Automatic channel selection with hw_mode=any""" + force_prev_ap_on_24g(apdev[0]) + params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678") + params['channel'] = '0' + params['hw_mode'] = 'any' + hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) + wait_acs(hapd) + + freq = hapd.get_status_field("freq") + if int(freq) < 2400: + raise Exception("Unexpected frequency") + + dev[0].connect("test-acs", psk="12345678", scan_freq=freq) + +def test_ap_acs_hw_mode_any_5ghz(dev, apdev): + """Automatic channel selection with hw_mode=any and 5 GHz""" + try: + hapd = None + force_prev_ap_on_5g(apdev[0]) + params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678") + params['hw_mode'] = 'any' + params['channel'] = '0' + params['country_code'] = 'US' + params['acs_chan_bias'] = '36:0.7 40:0.7 44:0.7 48:0.7' + hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) + wait_acs(hapd) + freq = hapd.get_status_field("freq") + if int(freq) < 5000: + raise Exception("Unexpected frequency") + + dev[0].connect("test-acs", psk="12345678", scan_freq=freq) + dev[0].wait_regdom(country_ie=True) + finally: + clear_regdom(hapd, dev) + +def test_ap_acs_with_fallback_to_20(dev, apdev): + """Automatic channel selection with fallback to 20 MHz""" + force_prev_ap_on_24g(apdev[0]) + params = {"ssid": "legacy-20", + "channel": "7", "ieee80211n": "0"} + hostapd.add_ap(apdev[1], params) + params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678") + params['channel'] = '0' + params['acs_chan_bias'] = '6:0.1' + params['ht_capab'] = '[HT40+]' + hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) + wait_acs(hapd) + + freq = hapd.get_status_field("freq") + if int(freq) < 2400: + raise Exception("Unexpected frequency") + + dev[0].connect("test-acs", psk="12345678", scan_freq=freq) + sig = dev[0].request("SIGNAL_POLL").splitlines() + logger.info("SIGNAL_POLL: " + str(sig)) + if "WIDTH=20 MHz" not in sig: + raise Exception("Station did not report 20 MHz bandwidth") + +def test_ap_acs_rx_during(dev, apdev): + """Automatic channel selection and RX during ACS""" + force_prev_ap_on_24g(apdev[0]) + params = hostapd.wpa2_params(ssid="test-acs", passphrase="12345678") + params['channel'] = '0' + params['chanlist'] = '1 6 11' + hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) + + time.sleep(0.1) + hapd.set("ext_mgmt_frame_handling", "1") + bssid = hapd.own_addr().replace(':', '') + addr = "020304050607" + broadcast = 6*"ff" + + probereq = "40000000" + broadcast + addr + broadcast + "1000" + probereq += "0000" + "010802040b160c121824" + "32043048606c" + "030100" + if "OK" not in hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % probereq): + raise Exception("MGMT_RX_PROCESS failed") + + probereq = "40000000" + broadcast + addr + broadcast + "1000" + probereq += "0000" + "010102" + if "OK" not in hapd.request("MGMT_RX_PROCESS freq=2437 datarate=0 ssi_signal=-30 frame=%s" % probereq): + raise Exception("MGMT_RX_PROCESS failed") + + auth = "b0003a01" + bssid + addr + bssid + '1000000001000000' + if "OK" not in hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % auth): + raise Exception("MGMT_RX_PROCESS failed") + hapd.set("ext_mgmt_frame_handling", "0") + + time.sleep(0.2) + try: + for i in range(3): + dev[i].request("SCAN_INTERVAL 1") + dev[i].connect("test-acs", psk="12345678", + scan_freq="2412 2437 2462", wait_connect=False) + wait_acs(hapd) + for i in range(3): + dev[i].wait_connected() + finally: + for i in range(3): + dev[i].request("SCAN_INTERVAL 5") diff --git a/tests/hwsim/test_ap_ciphers.py b/tests/hwsim/test_ap_ciphers.py index ae78e0ccc..d9f827aaf 100644 --- a/tests/hwsim/test_ap_ciphers.py +++ b/tests/hwsim/test_ap_ciphers.py @@ -13,10 +13,12 @@ import subprocess import hwsim_utils import hostapd -from utils import HwsimSkip, skip_with_fips, require_under_vm +from utils import * from wlantest import Wlantest from wpasupplicant import WpaSupplicant +KT_PTK, KT_GTK, KT_IGTK, KT_BIGTK = range(4) + def check_cipher(dev, ap, cipher, group_cipher=None): if cipher not in dev.get_capability("pairwise"): raise HwsimSkip("Cipher %s not supported" % cipher) @@ -78,12 +80,14 @@ def check_group_mgmt_cipher(dev, ap, cipher, sta_req_cipher=None): def test_ap_cipher_tkip(dev, apdev): """WPA2-PSK/TKIP connection""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) check_cipher(dev[0], apdev[0], "TKIP") @remote_compatible def test_ap_cipher_tkip_countermeasures_ap(dev, apdev): """WPA-PSK/TKIP countermeasures (detected by AP)""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) testfile = "/sys/kernel/debug/ieee80211/%s/netdev:%s/tkip_mic_test" % (dev[0].get_driver_status_field("phyname"), dev[0].ifname) if dev[0].cmd_execute(["ls", testfile])[0] != 0: raise HwsimSkip("tkip_mic_test not supported in mac80211") @@ -118,6 +122,7 @@ def test_ap_cipher_tkip_countermeasures_ap(dev, apdev): def test_ap_cipher_tkip_countermeasures_ap_mixed_mode(dev, apdev): """WPA+WPA2-PSK/TKIP countermeasures (detected by mixed mode AP)""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) testfile = "/sys/kernel/debug/ieee80211/%s/netdev:%s/tkip_mic_test" % (dev[0].get_driver_status_field("phyname"), dev[0].ifname) if dev[0].cmd_execute(["ls", testfile])[0] != 0: raise HwsimSkip("tkip_mic_test not supported in mac80211") @@ -166,6 +171,7 @@ def test_ap_cipher_tkip_countermeasures_ap_mixed_mode(dev, apdev): def test_ap_cipher_tkip_countermeasures_sta(dev, apdev): """WPA-PSK/TKIP countermeasures (detected by STA)""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) params = {"ssid": "tkip-countermeasures", "wpa_passphrase": "12345678", "wpa": "1", @@ -197,11 +203,11 @@ def test_ap_cipher_tkip_countermeasures_sta(dev, apdev): if ev is not None: raise Exception("Unexpected connection during TKIP countermeasures") -def test_ap_cipher_tkip_countermeasures_sta2(dev, apdev, params): - """WPA-PSK/TKIP countermeasures (detected by two STAs) [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_ap_cipher_tkip_countermeasures_sta2(dev, apdev): + """WPA-PSK/TKIP countermeasures (detected by two STAs)""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) params = {"ssid": "tkip-countermeasures", "wpa_passphrase": "12345678", "wpa": "1", @@ -365,6 +371,7 @@ def test_ap_cipher_gcmp_ccmp(dev, apdev, params): def test_ap_cipher_mixed_wpa_wpa2(dev, apdev): """WPA2-PSK/CCMP/ and WPA-PSK/TKIP mixed configuration""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) ssid = "test-wpa-wpa2-psk" passphrase = "12345678" params = {"ssid": ssid, @@ -478,15 +485,23 @@ def test_ap_cipher_bip_req_mismatch(dev, apdev): dev[0].select_network(id) dev[0].wait_connected() -def get_rx_spec(phy, gtk=False): +def get_rx_spec(phy, keytype=KT_PTK): keys = "/sys/kernel/debug/ieee80211/%s/keys" % (phy) try: for key in os.listdir(keys): keydir = keys + "/" + key - files = os.listdir(keydir) - if not gtk and "station" not in files: + with open(keydir + '/keyidx') as f: + keyid = int(f.read()) + if keytype in (KT_PTK, KT_GTK) and keyid not in (0, 1, 2, 3): continue - if gtk and "station" in files: + if keytype == KT_IGTK and keyid not in (4, 5): + continue + if keytype == KT_BIGTK and keyid not in (6, 7): + continue + files = os.listdir(keydir) + if keytype == KT_PTK and "station" not in files: + continue + if keytype != KT_PTK and "station" in files: continue with open(keydir + "/rx_spec") as f: return f.read() @@ -494,15 +509,23 @@ def get_rx_spec(phy, gtk=False): raise HwsimSkip("debugfs not supported in mac80211") return None -def get_tk_replay_counter(phy, gtk=False): +def get_tk_replay_counter(phy, keytype=KT_PTK): keys = "/sys/kernel/debug/ieee80211/%s/keys" % (phy) try: for key in os.listdir(keys): keydir = keys + "/" + key - files = os.listdir(keydir) - if not gtk and "station" not in files: + with open(keydir + '/keyidx') as f: + keyid = int(f.read()) + if keytype in (KT_PTK, KT_GTK) and keyid not in (0, 1, 2, 3): continue - if gtk and "station" in files: + if keytype == KT_IGTK and keyid not in (4, 5): + continue + if keytype == KT_BIGTK and keyid not in (6, 7): + continue + files = os.listdir(keydir) + if keytype == KT_PTK and "station" not in files: + continue + if keytype != KT_PTK and "station" in files: continue with open(keydir + "/replays") as f: return int(f.read()) @@ -516,6 +539,7 @@ def test_ap_cipher_replay_protection_ap_ccmp(dev, apdev): def test_ap_cipher_replay_protection_ap_tkip(dev, apdev): """TKIP replay protection on AP""" + skip_without_tkip(dev[0]) run_ap_cipher_replay_protection_ap(dev, apdev, "TKIP") def test_ap_cipher_replay_protection_ap_gcmp(dev, apdev): @@ -572,6 +596,7 @@ def test_ap_cipher_replay_protection_sta_ccmp(dev, apdev): def test_ap_cipher_replay_protection_sta_tkip(dev, apdev): """TKIP replay protection on STA (TK)""" + skip_without_tkip(dev[0]) run_ap_cipher_replay_protection_sta(dev, apdev, "TKIP") def test_ap_cipher_replay_protection_sta_gcmp(dev, apdev): @@ -582,19 +607,20 @@ def test_ap_cipher_replay_protection_sta_gcmp(dev, apdev): def test_ap_cipher_replay_protection_sta_gtk_ccmp(dev, apdev): """CCMP replay protection on STA (GTK)""" - run_ap_cipher_replay_protection_sta(dev, apdev, "CCMP", gtk=True) + run_ap_cipher_replay_protection_sta(dev, apdev, "CCMP", keytype=KT_GTK) def test_ap_cipher_replay_protection_sta_gtk_tkip(dev, apdev): """TKIP replay protection on STA (GTK)""" - run_ap_cipher_replay_protection_sta(dev, apdev, "TKIP", gtk=True) + skip_without_tkip(dev[0]) + run_ap_cipher_replay_protection_sta(dev, apdev, "TKIP", keytype=KT_GTK) def test_ap_cipher_replay_protection_sta_gtk_gcmp(dev, apdev): """GCMP replay protection on STA (GTK)""" if "GCMP" not in dev[0].get_capability("pairwise"): raise HwsimSkip("GCMP not supported") - run_ap_cipher_replay_protection_sta(dev, apdev, "GCMP", gtk=True) + run_ap_cipher_replay_protection_sta(dev, apdev, "GCMP", keytype=KT_GTK) -def run_ap_cipher_replay_protection_sta(dev, apdev, cipher, gtk=False): +def run_ap_cipher_replay_protection_sta(dev, apdev, cipher, keytype=KT_PTK): params = {"ssid": "test-wpa2-psk", "wpa_passphrase": "12345678", "wpa": "2", @@ -613,7 +639,7 @@ def run_ap_cipher_replay_protection_sta(dev, apdev, cipher, gtk=False): hapd.wait_sta() if cipher != "TKIP": - replays = get_tk_replay_counter(phy, gtk) + replays = get_tk_replay_counter(phy, keytype) if replays != 0: raise Exception("Unexpected replay reported (1)") @@ -621,11 +647,11 @@ def run_ap_cipher_replay_protection_sta(dev, apdev, cipher, gtk=False): hwsim_utils.test_connectivity(dev[0], hapd) if cipher != "TKIP": - replays = get_tk_replay_counter(phy, gtk) + replays = get_tk_replay_counter(phy, keytype) if replays != 0: raise Exception("Unexpected replay reported (2)") - addr = "ff:ff:ff:ff:ff:ff" if gtk else dev[0].own_addr() + addr = "ff:ff:ff:ff:ff:ff" if keytype != KT_PTK else dev[0].own_addr() if "OK" not in hapd.request("RESET_PN " + addr): raise Exception("RESET_PN failed") time.sleep(0.1) @@ -633,28 +659,13 @@ def run_ap_cipher_replay_protection_sta(dev, apdev, cipher, gtk=False): success_expected=False) if cipher != "TKIP": - replays = get_tk_replay_counter(phy, gtk) + replays = get_tk_replay_counter(phy, keytype) if replays < 1: raise Exception("Replays not reported") +@disable_ipv6 def test_ap_wpa2_delayed_m3_retransmission(dev, apdev): """Delayed M3 retransmission""" - require_under_vm() - try: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - run_ap_wpa2_delayed_m3_retransmission(dev, apdev) - finally: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - -def run_ap_wpa2_delayed_m3_retransmission(dev, apdev): params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") hapd = hostapd.add_ap(apdev[0], params) @@ -671,14 +682,14 @@ def run_ap_wpa2_delayed_m3_retransmission(dev, apdev): hwsim_utils.test_connectivity(dev[0], hapd) time.sleep(0.1) - before_tk = get_rx_spec(phy, gtk=False).splitlines() - before_gtk = get_rx_spec(phy, gtk=True).splitlines() + before_tk = get_rx_spec(phy, keytype=KT_PTK).splitlines() + before_gtk = get_rx_spec(phy, keytype=KT_GTK).splitlines() addr = dev[0].own_addr() if "OK" not in hapd.request("RESEND_M3 " + addr): raise Exception("RESEND_M3 failed") time.sleep(0.1) - after_tk = get_rx_spec(phy, gtk=False).splitlines() - after_gtk = get_rx_spec(phy, gtk=True).splitlines() + after_tk = get_rx_spec(phy, keytype=KT_PTK).splitlines() + after_gtk = get_rx_spec(phy, keytype=KT_GTK).splitlines() if "OK" not in hapd.request("RESET_PN " + addr): raise Exception("RESET_PN failed") @@ -700,39 +711,15 @@ def run_ap_wpa2_delayed_m3_retransmission(dev, apdev): if a < b: raise Exception("GTK RX counter decreased: idx=%d before=%d after=%d" % (i, b, a)) +@disable_ipv6 def test_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev): """Delayed M1+M3 retransmission""" - require_under_vm() - try: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev) - finally: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) + run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, False) +@disable_ipv6 def test_ap_wpa2_delayed_m1_m3_retransmission2(dev, apdev): """Delayed M1+M3 retransmission (change M1 ANonce)""" - require_under_vm() - try: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, True) - finally: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) + run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, True) def run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, change_m1_anonce=False): @@ -752,8 +739,8 @@ def run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, hwsim_utils.test_connectivity(dev[0], hapd) time.sleep(0.1) - before_tk = get_rx_spec(phy, gtk=False).splitlines() - before_gtk = get_rx_spec(phy, gtk=True).splitlines() + before_tk = get_rx_spec(phy, keytype=KT_PTK).splitlines() + before_gtk = get_rx_spec(phy, keytype=KT_GTK).splitlines() addr = dev[0].own_addr() if change_m1_anonce: if "OK" not in hapd.request("RESEND_M1 " + addr + " change-anonce"): @@ -763,8 +750,8 @@ def run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, if "OK" not in hapd.request("RESEND_M3 " + addr): raise Exception("RESEND_M3 failed") time.sleep(0.1) - after_tk = get_rx_spec(phy, gtk=False).splitlines() - after_gtk = get_rx_spec(phy, gtk=True).splitlines() + after_tk = get_rx_spec(phy, keytype=KT_PTK).splitlines() + after_gtk = get_rx_spec(phy, keytype=KT_GTK).splitlines() if "OK" not in hapd.request("RESET_PN " + addr): raise Exception("RESET_PN failed") @@ -786,24 +773,9 @@ def run_ap_wpa2_delayed_m1_m3_retransmission(dev, apdev, if a < b: raise Exception("GTK RX counter decreased: idx=%d before=%d after=%d" % (i, b, a)) +@disable_ipv6 def test_ap_wpa2_delayed_group_m1_retransmission(dev, apdev): """Delayed group M1 retransmission""" - require_under_vm() - try: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=1'], - stdout=open('/dev/null', 'w')) - run_ap_wpa2_delayed_group_m1_retransmission(dev, apdev) - finally: - subprocess.call(['sysctl', '-w', 'net.ipv6.conf.all.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - subprocess.call(['sysctl', '-w', - 'net.ipv6.conf.default.disable_ipv6=0'], - stdout=open('/dev/null', 'w')) - -def run_ap_wpa2_delayed_group_m1_retransmission(dev, apdev): params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") hapd = hostapd.add_ap(apdev[0], params) @@ -820,14 +792,14 @@ def run_ap_wpa2_delayed_group_m1_retransmission(dev, apdev): hwsim_utils.test_connectivity(dev[0], hapd) time.sleep(0.1) - before = get_rx_spec(phy, gtk=True).splitlines() + before = get_rx_spec(phy, keytype=KT_GTK).splitlines() addr = dev[0].own_addr() if "OK" not in hapd.request("RESEND_GROUP_M1 " + addr): raise Exception("RESEND_GROUP_M1 failed") time.sleep(0.1) - after = get_rx_spec(phy, gtk=True).splitlines() + after = get_rx_spec(phy, keytype=KT_GTK).splitlines() - if "OK" not in hapd.request("RESET_PN " + addr): + if "OK" not in hapd.request("RESET_PN ff:ff:ff:ff:ff:ff"): raise Exception("RESET_PN failed") time.sleep(0.1) hwsim_utils.test_connectivity(dev[0], hapd, timeout=1, @@ -841,6 +813,54 @@ def run_ap_wpa2_delayed_group_m1_retransmission(dev, apdev): if a < b: raise Exception("RX counter decreased: idx=%d before=%d after=%d" % (i, b, a)) +@disable_ipv6 +def test_ap_wpa2_delayed_group_m1_retransmission_igtk(dev, apdev): + """Delayed group M1 retransmission (check IGTK protection)""" + params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678", + ieee80211w="2") + hapd = hostapd.add_ap(apdev[0], params) + + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase("12345678") + + phy = dev[0].get_driver_status_field("phyname") + dev[0].connect("test-wpa2-psk", psk="12345678", scan_freq="2412", + ieee80211w="1") + hapd.wait_sta() + + hwsim_utils.test_connectivity(dev[0], hapd, timeout=1) + + # deauth once to see that works OK + addr = dev[0].own_addr() + hapd.request("DEAUTHENTICATE ff:ff:ff:ff:ff:ff") + dev[0].wait_disconnected(timeout=10) + + # now to check the protection + dev[0].request("RECONNECT") + dev[0].wait_connected() + hapd.wait_sta() + + hwsim_utils.test_connectivity(dev[0], hapd, timeout=1) + + if "OK" not in hapd.request("RESEND_GROUP_M1 " + addr): + raise Exception("RESEND_GROUP_M1 failed") + if "OK" not in hapd.request("RESET_PN ff:ff:ff:ff:ff:ff IGTK"): + raise Exception("RESET_PN failed") + + time.sleep(0.1) + hapd.request("DEAUTHENTICATE ff:ff:ff:ff:ff:ff test=1") + + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.1) + if ev is not None: + raise Exception("Unexpected disconnection") + + hwsim_utils.test_connectivity(dev[0], hapd, timeout=1) + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + def test_ap_wpa2_delayed_m1_m3_zero_tk(dev, apdev): """Delayed M1+M3 retransmission and zero TK""" params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") @@ -987,6 +1007,7 @@ def test_ap_wpa2_plaintext_group_m1_pmf(dev, apdev): def test_ap_wpa2_gtk_initial_rsc_tkip(dev, apdev): """Initial group cipher RSC (TKIP)""" + skip_without_tkip(dev[0]) run_ap_wpa2_gtk_initial_rsc(dev, apdev, "TKIP") def test_ap_wpa2_gtk_initial_rsc_ccmp(dev, apdev): diff --git a/tests/hwsim/test_ap_config.py b/tests/hwsim/test_ap_config.py index dc05a4854..b1d9d2133 100644 --- a/tests/hwsim/test_ap_config.py +++ b/tests/hwsim/test_ap_config.py @@ -161,10 +161,9 @@ def run_ap_config_reload_on_sighup(dev, apdev, params, ht=True): name = "ap_config_reload_on_sighup" if not ht: name += "_no_ht" - pidfile = os.path.join(params['logdir'], name + "-hostapd.pid") - logfile = os.path.join(params['logdir'], name + "-hostapd-log") - conffile = os.path.join(os.getcwd(), params['logdir'], - name + "-hostapd.conf") + pidfile = params['prefix'] + ".hostapd.pid" + logfile = params['prefix'] + ".hostapd.log" + conffile = params['prefix'] + ".hostapd.conf" prg = os.path.join(params['logdir'], 'alt-hostapd/hostapd/hostapd') if not os.path.exists(prg): prg = '../../hostapd/hostapd' @@ -208,11 +207,9 @@ def run_ap_config_reload_on_sighup(dev, apdev, params, ht=True): def test_ap_config_reload_on_sighup_bss_changes(dev, apdev, params): """hostapd configuration reload modification from file on SIGHUP with bss remove/add""" - name = "ap_config_reload_on_sighup_bss_changes" - pidfile = os.path.join(params['logdir'], name + "-hostapd.pid") - logfile = os.path.join(params['logdir'], name + "-hostapd-log") - conffile = os.path.join(os.getcwd(), params['logdir'], - name + "-hostapd.conf") + pidfile = params['prefix'] + ".hostapd.pid" + logfile = params['prefix'] + ".hostapd-log" + conffile = params['prefix'] + ".hostapd.conf" prg = os.path.join(params['logdir'], 'alt-hostapd/hostapd/hostapd') if not os.path.exists(prg): prg = '../../hostapd/hostapd' @@ -364,7 +361,7 @@ def test_ap_config_invalid_value(dev, apdev, params): def test_ap_config_eap_user_file_parsing(dev, apdev, params): """hostapd eap_user_file parsing""" - tmp = os.path.join(params['logdir'], 'ap_config_eap_user_file_parsing.tmp') + tmp = params['prefix'] + '.tmp' hapd = hostapd.add_ap(apdev[0], {"ssid": "foobar"}) for i in range(2): @@ -429,8 +426,6 @@ def test_ap_config_set_oom(dev, apdev): tests = [(1, "hostapd_parse_das_client", "SET radius_das_client 192.168.1.123 pw"), - (1, "hostapd_config_read_wep", "SET wep_key0 \"hello\""), - (1, "hostapd_config_read_wep", "SET wep_key0 0102030405"), (1, "hostapd_parse_chanlist", "SET chanlist 1 6 11-13"), (1, "hostapd_config_bss", "SET bss foo"), (2, "hostapd_config_bss", "SET bss foo"), @@ -486,6 +481,9 @@ def test_ap_config_set_oom(dev, apdev): (1, "hostapd_parse_intlist", "SET sae_groups 19 25"), (1, "hostapd_parse_intlist", "SET basic_rates 10 20 55 110"), (1, "hostapd_parse_intlist", "SET supported_rates 10 20 55 110")] + if "WEP40" in dev[0].get_capability("group"): + tests += [(1, "hostapd_config_read_wep", "SET wep_key0 \"hello\""), + (1, "hostapd_config_read_wep", "SET wep_key0 0102030405")] for count, func, cmd in tests: with alloc_fail(hapd, count, func): if "FAIL" not in hapd.request(cmd): @@ -533,14 +531,15 @@ def test_ap_config_set_oom(dev, apdev): def test_ap_config_set_errors(dev, apdev): """hostapd configuration parsing errors""" hapd = hostapd.add_ap(apdev[0], {"ssid": "foobar"}) - hapd.set("wep_key0", '"hello"') - hapd.set("wep_key1", '"hello"') - hapd.set("wep_key0", '') - hapd.set("wep_key0", '"hello"') - if "FAIL" not in hapd.request("SET wep_key1 \"hello\""): - raise Exception("SET wep_key1 allowed to override existing key") - hapd.set("wep_key1", '') - hapd.set("wep_key1", '"hello"') + if "WEP40" in dev[0].get_capability("group"): + hapd.set("wep_key0", '"hello"') + hapd.set("wep_key1", '"hello"') + hapd.set("wep_key0", '') + hapd.set("wep_key0", '"hello"') + if "FAIL" not in hapd.request("SET wep_key1 \"hello\""): + raise Exception("SET wep_key1 allowed to override existing key") + hapd.set("wep_key1", '') + hapd.set("wep_key1", '"hello"') hapd.set("auth_server_addr", "127.0.0.1") hapd.set("acct_server_addr", "127.0.0.1") diff --git a/tests/hwsim/test_ap_csa.py b/tests/hwsim/test_ap_csa.py index 2bf9c9a8a..744d1e1f2 100644 --- a/tests/hwsim/test_ap_csa.py +++ b/tests/hwsim/test_ap_csa.py @@ -11,7 +11,7 @@ logger = logging.getLogger() import hwsim_utils import hostapd -from utils import HwsimSkip +from utils import * def connect(dev, apdev, scan_freq="2412", **kwargs): params = {"ssid": "ap-csa", @@ -55,13 +55,6 @@ def wait_channel_switch(dev, freq): if "freq=%d" % freq not in ev: raise Exception("Unexpected frequency: " + ev) -# This function checks whether the provided dev, which may be either -# WpaSupplicant or Hostapd supports CSA. -def csa_supported(dev): - res = dev.get_driver_status() - if (int(res['capa.flags'], 0) & 0x80000000) == 0: - raise HwsimSkip("CSA not supported") - @remote_compatible def test_ap_csa_1_switch(dev, apdev): """AP Channel Switch, one switch""" diff --git a/tests/hwsim/test_ap_dynamic.py b/tests/hwsim/test_ap_dynamic.py index 7a2ddcc7d..96d35b9a2 100644 --- a/tests/hwsim/test_ap_dynamic.py +++ b/tests/hwsim/test_ap_dynamic.py @@ -13,7 +13,7 @@ import os import hwsim_utils import hostapd -from utils import alloc_fail, require_under_vm, get_phy +from utils import * from test_ap_acs import force_prev_ap_on_24g @remote_compatible @@ -37,7 +37,7 @@ def test_ap_change_ssid(dev, apdev): dev[0].set_network_quoted(id, "ssid", "test-wpa2-psk-new") dev[0].connect_network(id) -def multi_check(dev, check, scan_opt=True): +def multi_check(apdev, dev, check, scan_opt=True): id = [] num_bss = len(check) for i in range(0, num_bss): @@ -51,7 +51,7 @@ def multi_check(dev, check, scan_opt=True): for i in range(num_bss): if not check[i]: continue - bssid = '02:00:00:00:03:0' + str(i) + bssid = hostapd.bssid_inc(apdev, i) if scan_opt: dev[i].scan_for_bss(bssid, freq=2412) id.append(dev[i].connect("bss-" + str(i + 1), key_mgmt="NONE", @@ -98,59 +98,59 @@ def _test_ap_bss_add_remove(dev, apdev): ifname3 = apdev[0]['ifname'] + '-3' logger.info("Set up three BSSes one by one") hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf') - multi_check(dev, [True, False, False]) + multi_check(apdev[0], dev, [True, False, False]) hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') - multi_check(dev, [True, True, False]) + multi_check(apdev[0], dev, [True, True, False]) hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf') - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) logger.info("Remove the last BSS and re-add it") hostapd.remove_bss(apdev[0], ifname3) - multi_check(dev, [True, True, False]) + multi_check(apdev[0], dev, [True, True, False]) hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf') - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) logger.info("Remove the middle BSS and re-add it") hostapd.remove_bss(apdev[0], ifname2) - multi_check(dev, [True, False, True]) + multi_check(apdev[0], dev, [True, False, True]) hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) logger.info("Remove the first BSS and re-add it and other BSSs") hostapd.remove_bss(apdev[0], ifname1) - multi_check(dev, [False, False, False]) + multi_check(apdev[0], dev, [False, False, False]) hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf') hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf') - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) logger.info("Remove two BSSes and re-add them") hostapd.remove_bss(apdev[0], ifname2) - multi_check(dev, [True, False, True]) + multi_check(apdev[0], dev, [True, False, True]) hostapd.remove_bss(apdev[0], ifname3) - multi_check(dev, [True, False, False]) + multi_check(apdev[0], dev, [True, False, False]) hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') - multi_check(dev, [True, True, False]) + multi_check(apdev[0], dev, [True, True, False]) hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf') - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) logger.info("Remove three BSSes in and re-add them") hostapd.remove_bss(apdev[0], ifname3) - multi_check(dev, [True, True, False]) + multi_check(apdev[0], dev, [True, True, False]) hostapd.remove_bss(apdev[0], ifname2) - multi_check(dev, [True, False, False]) + multi_check(apdev[0], dev, [True, False, False]) hostapd.remove_bss(apdev[0], ifname1) - multi_check(dev, [False, False, False]) + multi_check(apdev[0], dev, [False, False, False]) hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf') - multi_check(dev, [True, False, False]) + multi_check(apdev[0], dev, [True, False, False]) hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') - multi_check(dev, [True, True, False]) + multi_check(apdev[0], dev, [True, True, False]) hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf') - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) logger.info("Test error handling if a duplicate ifname is tried") hostapd.add_bss(apdev[0], ifname3, 'bss-3.conf', ignore_error=True) - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) def test_ap_bss_add_remove_during_ht_scan(dev, apdev): """Dynamic BSS add during HT40 co-ex scan""" @@ -158,22 +158,27 @@ def test_ap_bss_add_remove_during_ht_scan(dev, apdev): dev[i].flush_scan_cache() ifname1 = apdev[0]['ifname'] ifname2 = apdev[0]['ifname'] + '-2' - hostapd.add_bss(apdev[0], ifname1, 'bss-ht40-1.conf') - hostapd.add_bss(apdev[0], ifname2, 'bss-ht40-2.conf') - multi_check(dev, [True, True], scan_opt=False) + confname1 = hostapd.cfg_file(apdev[0], "bss-ht40-1.conf") + confname2 = hostapd.cfg_file(apdev[0], "bss-ht40-2.conf") + hapd_global = hostapd.HostapdGlobal(apdev) + hapd_global.send_file(confname1, confname1) + hapd_global.send_file(confname2, confname2) + hostapd.add_bss(apdev[0], ifname1, confname1) + hostapd.add_bss(apdev[0], ifname2, confname2) + multi_check(apdev[0], dev, [True, True], scan_opt=False) hostapd.remove_bss(apdev[0], ifname2) hostapd.remove_bss(apdev[0], ifname1) - hostapd.add_bss(apdev[0], ifname1, 'bss-ht40-1.conf') - hostapd.add_bss(apdev[0], ifname2, 'bss-ht40-2.conf') + hostapd.add_bss(apdev[0], ifname1, confname1) + hostapd.add_bss(apdev[0], ifname2, confname2) hostapd.remove_bss(apdev[0], ifname2) - multi_check(dev, [True, False], scan_opt=False) + multi_check(apdev[0], dev, [True, False], scan_opt=False) hostapd.remove_bss(apdev[0], ifname1) - hostapd.add_bss(apdev[0], ifname1, 'bss-ht40-1.conf') - hostapd.add_bss(apdev[0], ifname2, 'bss-ht40-2.conf') + hostapd.add_bss(apdev[0], ifname1, confname1) + hostapd.add_bss(apdev[0], ifname2, confname2) hostapd.remove_bss(apdev[0], ifname1) - multi_check(dev, [False, False]) + multi_check(apdev[0], dev, [False, False]) def test_ap_multi_bss_config(dev, apdev): """hostapd start with a multi-BSS configuration file""" @@ -185,18 +190,18 @@ def test_ap_multi_bss_config(dev, apdev): logger.info("Set up three BSSes with one configuration file") hapd = hostapd.add_iface(apdev[0], 'multi-bss.conf') hapd.enable() - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) hostapd.remove_bss(apdev[0], ifname2) - multi_check(dev, [True, False, True]) + multi_check(apdev[0], dev, [True, False, True]) hostapd.remove_bss(apdev[0], ifname3) - multi_check(dev, [True, False, False]) + multi_check(apdev[0], dev, [True, False, False]) hostapd.remove_bss(apdev[0], ifname1) - multi_check(dev, [False, False, False]) + multi_check(apdev[0], dev, [False, False, False]) hapd = hostapd.add_iface(apdev[0], 'multi-bss.conf') hapd.enable() hostapd.remove_bss(apdev[0], ifname1) - multi_check(dev, [False, False, False]) + multi_check(apdev[0], dev, [False, False, False]) def invalid_ap(ap): logger.info("Trying to start AP " + ap['ifname'] + " with invalid configuration") @@ -404,21 +409,23 @@ def test_ap_bss_add_out_of_memory(dev, apdev): ifname1 = apdev[0]['ifname'] ifname2 = apdev[0]['ifname'] + '-2' - hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-1.conf', 1, 'hostapd_add_iface') + confname1 = hostapd.cfg_file(apdev[0], "bss-1.conf") + confname2 = hostapd.cfg_file(apdev[0], "bss-2.conf") + hapd_bss_out_of_mem(hapd2, 'phy3', confname1, 1, 'hostapd_add_iface') for i in range(1, 3): - hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-1.conf', + hapd_bss_out_of_mem(hapd2, 'phy3', confname1, i, 'hostapd_interface_init_bss') - hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-1.conf', + hapd_bss_out_of_mem(hapd2, 'phy3', confname1, 1, 'ieee802_11_build_ap_params') - hostapd.add_bss(apdev[0], ifname1, 'bss-1.conf') + hostapd.add_bss(apdev[0], ifname1, confname1) - hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-2.conf', + hapd_bss_out_of_mem(hapd2, 'phy3', confname2, 1, 'hostapd_interface_init_bss') - hapd_bss_out_of_mem(hapd2, 'phy3', 'bss-2.conf', + hapd_bss_out_of_mem(hapd2, 'phy3', confname2, 1, 'ieee802_11_build_ap_params') - hostapd.add_bss(apdev[0], ifname2, 'bss-2.conf') + hostapd.add_bss(apdev[0], ifname2, confname2) hostapd.remove_bss(apdev[0], ifname2) hostapd.remove_bss(apdev[0], ifname1) @@ -495,19 +502,23 @@ def test_ap_duplicate_bssid(dev, apdev): def test_ap_bss_config_file(dev, apdev, params): """hostapd BSS config file""" - pidfile = os.path.join(params['logdir'], "ap_bss_config_file-hostapd.pid") - logfile = os.path.join(params['logdir'], "ap_bss_config_file-hostapd-log") + pidfile = params['prefix'] + ".hostapd.pid" + logfile = params['prefix'] + ".hostapd-log" prg = os.path.join(params['logdir'], 'alt-hostapd/hostapd/hostapd') if not os.path.exists(prg): prg = '../../hostapd/hostapd' phy = get_phy(apdev[0]) + confname1 = hostapd.cfg_file(apdev[0], "bss-1.conf") + confname2 = hostapd.cfg_file(apdev[0], "bss-2.conf") + confname3 = hostapd.cfg_file(apdev[0], "bss-3.conf") + cmd = [prg, '-B', '-dddt', '-P', pidfile, '-f', logfile, '-S', '-T', - '-b', phy + ':bss-1.conf', '-b', phy + ':bss-2.conf', - '-b', phy + ':bss-3.conf'] + '-b', phy + ':' + confname1, '-b', phy + ':' + confname2, + '-b', phy + ':' + confname3] res = subprocess.check_call(cmd) if res != 0: raise Exception("Could not start hostapd: %s" % str(res)) - multi_check(dev, [True, True, True]) + multi_check(apdev[0], dev, [True, True, True]) for i in range(0, 3): dev[i].request("DISCONNECT") diff --git a/tests/hwsim/test_ap_eap.py b/tests/hwsim/test_ap_eap.py index 913132275..7395c79cc 100644 --- a/tests/hwsim/test_ap_eap.py +++ b/tests/hwsim/test_ap_eap.py @@ -24,7 +24,7 @@ import tempfile import hwsim_utils from hwsim import HWSimRadio import hostapd -from utils import HwsimSkip, alloc_fail, fail_test, skip_with_fips, wait_fail_trigger, require_under_vm +from utils import * from wpasupplicant import WpaSupplicant from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations, set_test_assoc_ie @@ -2731,7 +2731,7 @@ def test_ap_wpa2_eap_ttls_server_cert_hash(dev, apdev): """WPA2-Enterprise connection using EAP-TTLS and server certificate hash""" check_cert_probe_support(dev[0]) skip_with_fips(dev[0]) - srv_cert_hash = "f6b9d0b2bc3f106ff01542161647036992de889267005d93fac1c7274bfca5bb" + srv_cert_hash = "f75a953c1aa9967926525d4d860d1ff7e872f7088782f060768d12aecbd5f25e" params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS", @@ -3026,10 +3026,9 @@ def test_ap_wpa2_eap_eke(dev, apdev): eap_connect(dev[0], hapd, "EKE", "eke user", password="hello1", expect_failure=True) -def test_ap_wpa2_eap_eke_many(dev, apdev, params): - """WPA2-Enterprise connection using EAP-EKE (many connections) [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_ap_wpa2_eap_eke_many(dev, apdev): + """WPA2-Enterprise connection using EAP-EKE (many connections)""" params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") hostapd.add_ap(apdev[0], params) success = 0 @@ -3304,6 +3303,7 @@ def test_ap_wpa2_eap_psk_oom(dev, apdev): def test_ap_wpa_eap_peap_eap_mschapv2(dev, apdev): """WPA-Enterprise connection using EAP-PEAP/EAP-MSCHAPv2""" + skip_without_tkip(dev[0]) check_eap_capa(dev[0], "MSCHAPV2") params = hostapd.wpa_eap_params(ssid="test-wpa-eap") hapd = hostapd.add_ap(apdev[0], params) @@ -4175,7 +4175,7 @@ def ocsp_req(outfile): "-reqout", outfile, '-issuer', 'auth_serv/ca.pem', '-sha256', - '-serial', '0xD8D3E3A6CBE3CD1F', + '-serial', '0xD8D3E3A6CBE3CD5F', '-no_nonce'] run_openssl(arg) if not os.path.exists(outfile): @@ -5131,6 +5131,46 @@ def test_ap_wpa2_eap_reauth(dev, apdev): if state != "COMPLETED": raise Exception("Reauthentication did not complete") +def test_ap_wpa2_eap_reauth_ptk_rekey_blocked_ap(dev, apdev): + """WPA2-Enterprise and Authenticator forcing reauthentication with PTK rekey blocked on AP""" + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + params['eap_reauth_period'] = '2' + params['wpa_deny_ptk0_rekey'] = '2' + hapd = hostapd.add_ap(apdev[0], params) + eap_connect(dev[0], hapd, "PAX", "pax.user@example.com", + password_hex="0123456789abcdef0123456789abcdef") + logger.info("Wait for disconnect due to reauth") + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "CTRL-EVENT-DISCONNECTED"], timeout=10) + if ev is None: + raise Exception("Timeout on reauthentication") + if "CTRL-EVENT-EAP-STARTED" in ev: + raise Exception("Reauthentication without disconnect") + + ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=1) + if ev is None: + raise Exception("Timeout on reconnect") + +def test_ap_wpa2_eap_reauth_ptk_rekey_blocked_sta(dev, apdev): + """WPA2-Enterprise and Authenticator forcing reauthentication with PTK rekey blocked on station""" + params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + params['eap_reauth_period'] = '2' + hapd = hostapd.add_ap(apdev[0], params) + eap_connect(dev[0], hapd, "PAX", "pax.user@example.com", + password_hex="0123456789abcdef0123456789abcdef", + wpa_deny_ptk0_rekey="2") + logger.info("Wait for disconnect due to reauth") + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "CTRL-EVENT-DISCONNECTED"], timeout=10) + if ev is None: + raise Exception("Timeout on reauthentication") + if "CTRL-EVENT-EAP-STARTED" in ev: + raise Exception("Reauthentication without disconnect") + + ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=1) + if ev is None: + raise Exception("Timeout on reconnect") + def test_ap_wpa2_eap_request_identity_message(dev, apdev): """Optional displayable message in EAP Request-Identity""" params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") @@ -5799,7 +5839,17 @@ def check_tls_ver(dev, hapd, phase1, expected): def test_ap_wpa2_eap_tls_versions(dev, apdev): """EAP-TLS and TLS version configuration""" - params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") + params = {"ssid": "test-wpa2-eap", + "wpa": "2", + "wpa_key_mgmt": "WPA-EAP", + "rsn_pairwise": "CCMP", + "ieee8021x": "1", + "eap_server": "1", + "tls_flags": "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][ENABLE-TLSv1.2][ENABLE-TLSv1.3]", + "eap_user_file": "auth_serv/eap_user.conf", + "ca_cert": "auth_serv/ca.pem", + "server_cert": "auth_serv/server.pem", + "private_key": "auth_serv/server.key"} hapd = hostapd.add_ap(apdev[0], params) tls = dev[0].request("GET tls_library") @@ -5818,9 +5868,9 @@ def test_ap_wpa2_eap_tls_versions(dev, apdev): check_tls_ver(dev[0], hapd, "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1", "TLSv1.2") check_tls_ver(dev[1], hapd, - "tls_disable_tlsv1_0=1 tls_disable_tlsv1_2=1", "TLSv1.1") + "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=0 tls_disable_tlsv1_2=1", "TLSv1.1") check_tls_ver(dev[2], hapd, - "tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1") + "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1") if "run=OpenSSL 1.1.1" in tls: check_tls_ver(dev[0], hapd, "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1 tls_disable_tlsv1_3=0", "TLSv1.3") @@ -5846,7 +5896,7 @@ def test_ap_wpa2_eap_tls_versions_server(dev, apdev): hapd.disable() hapd.set("tls_flags", flags) hapd.enable() - check_tls_ver(dev[0], hapd, "", exp) + check_tls_ver(dev[0], hapd, "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=0 tls_disable_tlsv1_2=0 tls_disable_tlsv1_3=0", exp) def test_ap_wpa2_eap_tls_13(dev, apdev): """EAP-TLS and TLS 1.3""" @@ -6696,7 +6746,7 @@ def test_ap_wpa2_eap_assoc_rsn(dev, apdev): dev[0].request("REMOVE_NETWORK all") dev[0].wait_disconnected() - tests = [("Invalid group cipher", "30060100000fac02", 41), + tests = [("Invalid group cipher", "30060100000fac02", [40, 41]), ("Invalid pairwise cipher", "300c0100000fac040100000fac02", 42)] for title, ie, status in tests: logger.info(title) @@ -6708,7 +6758,15 @@ def test_ap_wpa2_eap_assoc_rsn(dev, apdev): ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"]) if ev is None: raise Exception("Association rejection not reported") - if "status_code=" + str(status) not in ev: + ok = False + if isinstance(status, list): + for i in status: + ok = "status_code=" + str(i) in ev + if ok: + break + else: + ok = "status_code=" + str(status) in ev + if not ok: raise Exception("Unexpected status code: " + ev) dev[0].request("REMOVE_NETWORK all") dev[0].dump_monitor() @@ -7202,6 +7260,7 @@ def run_openssl_systemwide_policy(iface, apdev, test_params): def test_ap_wpa2_eap_tls_tod(dev, apdev): """EAP-TLS server certificate validation and TOD-STRICT""" + check_tls_tod(dev[0]) params = int_eap_server_params() params["server_cert"] = "auth_serv/server-certpol.pem" params["private_key"] = "auth_serv/server-certpol.key" @@ -7231,6 +7290,7 @@ def test_ap_wpa2_eap_tls_tod(dev, apdev): def test_ap_wpa2_eap_tls_tod_tofu(dev, apdev): """EAP-TLS server certificate validation and TOD-TOFU""" + check_tls_tod(dev[0]) params = int_eap_server_params() params["server_cert"] = "auth_serv/server-certpol2.pem" params["private_key"] = "auth_serv/server-certpol2.key" @@ -7274,3 +7334,39 @@ def test_ap_wpa2_eap_sake_no_control_port(dev, apdev): eap_connect(wpas, hapd, "SAKE", "sake user", password_hex="ff23456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", expect_failure=True) + +def test_ap_wpa3_eap_transition_disable(dev, apdev): + """WPA3-Enterprise transition disable indication""" + skip_without_tkip(dev[0]) + params = hostapd.wpa2_eap_params(ssid="test-wpa3-eap") + params["ieee80211w"] = "1" + params['transition_disable'] = '0x04' + hapd = hostapd.add_ap(apdev[0], params) + id = dev[0].connect("test-wpa3-eap", key_mgmt="WPA-EAP", ieee80211w="1", + proto="WPA WPA2", pairwise="CCMP", group="TKIP CCMP", + eap="GPSK", identity="gpsk user", + password="abcdefghijklmnop0123456789abcdef", + scan_freq="2412") + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "04": + raise Exception("Unexpected transition disable bitmap: " + ev) + + val = dev[0].get_network(id, "ieee80211w") + if val != "2": + raise Exception("Unexpected ieee80211w value: " + val) + val = dev[0].get_network(id, "key_mgmt") + if val != "WPA-EAP": + raise Exception("Unexpected key_mgmt value: " + val) + val = dev[0].get_network(id, "group") + if val != "CCMP": + raise Exception("Unexpected group value: " + val) + val = dev[0].get_network(id, "proto") + if val != "RSN": + raise Exception("Unexpected proto value: " + val) + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].request("RECONNECT") + dev[0].wait_connected() diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index 8efdc5e54..f2ca6f1ea 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -18,7 +18,7 @@ import hwsim_utils from hwsim import HWSimRadio import hostapd from tshark import run_tshark -from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger, skip_with_fips, parse_ie +from utils import * from wlantest import Wlantest from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations from test_rrm import check_beacon_req @@ -130,7 +130,7 @@ def ft_params2_r0kh_mismatch(rsn=True, ssid=None, passphrase=None): def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False, sae=False, eap=False, fail_test=False, roams=1, - pairwise_cipher="CCMP", group_cipher="TKIP CCMP", ptk_rekey="0", + pairwise_cipher="CCMP", group_cipher="CCMP", ptk_rekey="0", test_connectivity=True, eap_identity="gpsk user", conndev=False, force_initial_conn_to_first_ap=False, sha384=False, group_mgmt=None, ocv=None, sae_password=None, @@ -336,50 +336,62 @@ def test_ap_ft_vlan(dev, apdev): """WPA2-PSK-FT AP with VLAN""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) + hostapd.send_file(apdev[1], filename, filename) params = ft_params1(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd1 = hostapd.add_ap(apdev[1]['ifname'], params) run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1") if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"): raise Exception("Scan results missing RSN element info") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_ft_vlan_disconnected(dev, apdev): """WPA2-PSK-FT AP with VLAN and local key generation""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) + hostapd.send_file(apdev[1], filename, filename) params = ft_params1a(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename params['ft_psk_generate_local'] = "1" hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2a(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename params['ft_psk_generate_local'] = "1" hapd1 = hostapd.add_ap(apdev[1]['ifname'], params) run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1") if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"): raise Exception("Scan results missing RSN element info") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_ft_vlan_2(dev, apdev): """WPA2-PSK-FT AP with VLAN and dest-AP does not have VLAN info locally""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = ft_params1(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2(ssid=ssid, passphrase=passphrase) @@ -390,6 +402,8 @@ def test_ap_ft_vlan_2(dev, apdev): force_initial_conn_to_first_ap=True) if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"): raise Exception("Scan results missing RSN element info") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_ft_many(dev, apdev): """WPA2-PSK-FT AP multiple times""" @@ -407,22 +421,28 @@ def test_ap_ft_many_vlan(dev, apdev): """WPA2-PSK-FT AP with VLAN multiple times""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) + hostapd.send_file(apdev[1], filename, filename) params = ft_params1(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd1 = hostapd.add_ap(apdev[1]['ifname'], params) run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, roams=50, conndev="brvlan1") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_ft_mixed(dev, apdev): """WPA2-PSK-FT mixed-mode AP""" + skip_without_tkip(dev[0]) ssid = "test-ft-mixed" passphrase = "12345678" @@ -435,7 +455,8 @@ def test_ap_ft_mixed(dev, apdev): params = ft_params2(rsn=False, ssid=ssid, passphrase=passphrase) hapd1 = hostapd.add_ap(apdev[1], params) - run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase) + run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, + group_cipher="TKIP CCMP") def test_ap_ft_pmf(dev, apdev): """WPA2-PSK-FT AP with PMF""" @@ -656,7 +677,7 @@ def run_ap_ft_separate_hostapd(dev, apdev, params, over_ds): hapd1 = hostapd.add_ap(apdev2[1], params) run_roams(dev[0], apdev2, hapd0, hapd1, ssid, passphrase, - over_ds=over_ds, test_connectivity=False) + over_ds=over_ds, test_connectivity=False, roams=2) hglobal.terminate() @@ -707,20 +728,25 @@ def test_ap_ft_vlan_over_ds(dev, apdev): """WPA2-PSK-FT AP over DS with VLAN""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) + hostapd.send_file(apdev[1], filename, filename) params = ft_params1(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd1 = hostapd.add_ap(apdev[1]['ifname'], params) run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True, conndev="brvlan1") check_mib(dev[0], [("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-4"), ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-4")]) + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_ft_over_ds_many(dev, apdev): """WPA2-PSK-FT AP over DS multiple times""" @@ -739,18 +765,23 @@ def test_ap_ft_vlan_over_ds_many(dev, apdev): """WPA2-PSK-FT AP over DS with VLAN multiple times""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) + hostapd.send_file(apdev[1], filename, filename) params = ft_params1(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd1 = hostapd.add_ap(apdev[1]['ifname'], params) run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True, roams=50, conndev="brvlan1") + if filename.startswith('/tmp/'): + os.unlink(filename) @remote_compatible def test_ap_ft_over_ds_unknown_target(dev, apdev): @@ -944,22 +975,30 @@ def test_ap_ft_over_ds_pull_vlan(dev, apdev): """WPA2-PSK-FT AP over DS (pull PMK) with VLAN""" ssid = "test-ft" passphrase = "12345678" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) + hostapd.send_file(apdev[1], filename, filename) params = ft_params1(ssid=ssid, passphrase=passphrase) params["pmk_r1_push"] = "0" params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd0 = hostapd.add_ap(apdev[0]['ifname'], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params["pmk_r1_push"] = "0" params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd1 = hostapd.add_ap(apdev[1]['ifname'], params) run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True, conndev="brvlan1") + if filename.startswith('/tmp/'): + os.unlink(filename) -def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None): +def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None, + rsne_override=None, rsnxe_override=None, + no_beacon_rsnxe2=False, ext_key_id=False, + skip_prune_assoc=False, ft_rsnxe_used=False): if "SAE" not in dev.get_capability("auth_alg"): raise HwsimSkip("SAE not supported") ssid = "test-ft" @@ -971,6 +1010,16 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None): params['wpa_ptk_rekey'] = str(wpa_ptk_rekey) if sae_pwe is not None: params['sae_pwe'] = sae_pwe + if rsne_override: + params['rsne_override_ft'] = rsne_override + if rsnxe_override: + params['rsnxe_override_ft'] = rsnxe_override + if ext_key_id: + params['extended_key_id'] = '1' + if skip_prune_assoc: + params['skip_prune_assoc'] = '1' + if ft_rsnxe_used: + params['ft_rsnxe_used'] = '1' hapd0 = hostapd.add_ap(apdev[0], params) params = ft_params2(ssid=ssid, passphrase=passphrase) params['wpa_key_mgmt'] = "FT-SAE" @@ -978,6 +1027,18 @@ def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None): params['wpa_ptk_rekey'] = str(wpa_ptk_rekey) if sae_pwe is not None: params['sae_pwe'] = sae_pwe + if rsne_override: + params['rsne_override_ft'] = rsne_override + if rsnxe_override: + params['rsnxe_override_ft'] = rsnxe_override + if no_beacon_rsnxe2: + params['no_beacon_rsnxe'] = "1" + if ext_key_id: + params['extended_key_id'] = '1' + if skip_prune_assoc: + params['skip_prune_assoc'] = '1' + if ft_rsnxe_used: + params['ft_rsnxe_used'] = '1' hapd1 = hostapd.add_ap(apdev[1], params) key_mgmt = hapd1.get_config()['key_mgmt'] if key_mgmt.split(' ')[0] != "FT-SAE": @@ -1006,6 +1067,39 @@ def test_ap_ft_sae_h2e_and_loop(dev, apdev): hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2") run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True) +def test_ap_ft_sae_h2e_and_loop2(dev, apdev): + """WPA2-PSK-FT-SAE AP (AP loop, STA H2E)""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="0") + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True) + finally: + dev[0].set("sae_pwe", "0") + +def test_ap_ft_sae_h2e_downgrade_attack(dev, apdev): + """WPA2-PSK-FT-SAE AP (H2E downgrade attack)""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2", + no_beacon_rsnxe2=True) + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True, + force_initial_conn_to_first_ap=True, + return_after_initial=True) + dev[0].scan_for_bss(hapd1.own_addr(), freq="2412") + if "OK" not in dev[0].request("ROAM " + hapd1.own_addr()): + raise Exception("ROAM command failed") + # The target AP is expected to discard Reassociation Response frame due + # to RSNXE Used mismatch. This will result in roaming timeout and + # returning back to the old AP. + ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT", + "CTRL-EVENT-CONNECTED"], timeout=10) + if ev and "CTRL-EVENT-ASSOC-REJECT" in ev: + pass + elif ev and hapd1.own_addr() in ev: + raise Exception("Roaming succeeded unexpectedly") + finally: + dev[0].set("sae_pwe", "0") + def test_ap_ft_sae_ptk_rekey0(dev, apdev): """WPA2-PSK-FT-SAE AP and PTK rekey triggered by station""" hapd0, hapd1 = start_ft_sae(dev[0], apdev) @@ -1027,6 +1121,24 @@ def test_ap_ft_sae_ptk_rekey_ap(dev, apdev): only_one_way=True) check_ptk_rekey(dev[0], hapd0, hapd1) +def test_ap_ft_sae_ptk_rekey_ap_ext_key_id(dev, apdev): + """WPA2-PSK-FT-SAE AP and PTK rekey triggered by AP (Ext Key ID)""" + check_ext_key_id_capa(dev[0]) + try: + dev[0].set("extended_key_id", "1") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, wpa_ptk_rekey=2, + ext_key_id=True) + check_ext_key_id_capa(hapd0) + check_ext_key_id_capa(hapd1) + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True, + only_one_way=True) + check_ptk_rekey(dev[0], hapd0, hapd1) + idx = int(dev[0].request("GET last_tk_key_idx")) + if idx != 1: + raise Exception("Unexpected Key ID after TK rekey: %d" % idx) + finally: + dev[0].set("extended_key_id", "0") + def test_ap_ft_sae_over_ds(dev, apdev): """WPA2-PSK-FT-SAE AP over DS""" hapd0, hapd1 = start_ft_sae(dev[0], apdev) @@ -1054,6 +1166,105 @@ def test_ap_ft_sae_over_ds_ptk_rekey_ap(dev, apdev): over_ds=True, only_one_way=True) check_ptk_rekey(dev[0], hapd0, hapd1) +def test_ap_ft_sae_h2e_rsne_override(dev, apdev): + """WPA2-PSK-FT-SAE AP (H2E) and RSNE override (same value)""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2", + rsne_override="30260100000fac040100000fac040100000fac090c000100" + 16*"ff") + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True) + finally: + dev[0].set("sae_pwe", "0") + +def test_ap_ft_sae_h2e_rsnxe_override(dev, apdev): + """WPA2-PSK-FT-SAE AP (H2E) and RSNXE override (same value)""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2", + rsnxe_override="F40120") + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True) + finally: + dev[0].set("sae_pwe", "0") + +def test_ap_ft_sae_h2e_rsne_mismatch(dev, apdev): + """WPA2-PSK-FT-SAE AP (H2E) and RSNE mismatch""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2", + rsne_override="30260100000fac040100000fac040100000fac090c010100" + 16*"ff") + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True, + fail_test=True) + finally: + dev[0].set("sae_pwe", "0") + +def test_ap_ft_sae_h2e_rsne_mismatch_pmkr1name(dev, apdev): + """WPA2-PSK-FT-SAE AP (H2E) and RSNE mismatch in PMKR1Name""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2", + rsne_override="30260100000fac040100000fac040100000fac090c000100" + 16*"00") + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True, + fail_test=True) + finally: + dev[0].set("sae_pwe", "0") + +def test_ap_ft_sae_h2e_rsnxe_mismatch(dev, apdev): + """WPA2-PSK-FT-SAE AP (H2E) and RSNXE mismatch""" + try: + dev[0].set("sae_pwe", "2") + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2", + rsnxe_override="F40160") + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True, + fail_test=True) + finally: + dev[0].set("sae_pwe", "0") + +def test_ap_ft_sae_rsnxe_used_mismatch(dev, apdev): + """FT-SAE AP and unexpected RSNXE Used in ReassocReq""" + try: + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2") + dev[0].set("sae_pwe", "0") + dev[0].set("ft_rsnxe_used", "1") + next = run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", + sae=True, return_after_initial=True) + if "OK" not in dev[0].request("ROAM " + next): + raise Exception("ROAM command failed") + # The target AP is expected to discard Reassociation Request frame due + # to RSNXE Used mismatch. This will result in roaming timeout and + # returning back to the old AP. + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5) + if ev and next in ev: + raise Exception("Roaming succeeded unexpectedly") + finally: + dev[0].set("sae_pwe", "0") + +def test_ap_ft_sae_rsnxe_used_mismatch2(dev, apdev): + """FT-SAE AP and unexpected RSNXE Used in ReassocResp""" + try: + hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="0", + ft_rsnxe_used=True) + dev[0].set("sae_pwe", "2") + next = run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", + sae=True, return_after_initial=True) + if "OK" not in dev[0].request("ROAM " + next): + raise Exception("ROAM command failed") + # The STA is expected to discard Reassociation Response frame due to + # RSNXE Used mismatch. This will result in returning back to the old AP. + ev = dev[0].wait_disconnected() + if next not in ev: + raise Exception("Unexpected disconnection BSSID: " + ev) + if "reason=13 locally_generated=1" not in ev: + raise Exception("Unexpected disconnection reason: " + ev) + ev = dev[0].wait_connected() + if next in ev: + raise Exception("Roaming succeeded unexpectedly") + + hapd0.set("ft_rsnxe_used", "0") + hapd1.set("ft_rsnxe_used", "0") + dev[0].roam(next); + finally: + dev[0].set("sae_pwe", "0") + def test_ap_ft_sae_pw_id(dev, apdev): """FT-SAE with Password Identifier""" if "SAE" not in dev[0].get_capability("auth_alg"): @@ -1319,6 +1530,7 @@ def test_ap_ft_eap_pull(dev, apdev): generic_ap_ft_eap_pull(dev, apdev) def test_ap_ft_eap_pull_vlan(dev, apdev): + """WPA2-EAP-FT AP (pull PMK) - with VLAN""" generic_ap_ft_eap_pull(dev, apdev, vlan=True) def test_ap_ft_eap_pull_wildcard(dev, apdev): @@ -1872,7 +2084,7 @@ def test_ap_ft_oom(dev, apdev): """WPA2-PSK-FT and OOM""" dst = setup_ap_ft_oom(dev, apdev) with alloc_fail(dev[0], 1, "wpa_ft_gen_req_ies"): - dev[0].roam(dst) + dev[0].roam(dst, check_bssid=False, fail_test=True) def test_ap_ft_oom2(dev, apdev): """WPA2-PSK-FT and OOM (2)""" @@ -1915,7 +2127,7 @@ def test_ap_ft_ap_oom(dev, apdev): bssid1 = hapd1.own_addr() dev[0].scan_for_bss(bssid1, freq="2412") # This roam will fail due to missing PMK-R0 (OOM prevented storing it) - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) def test_ap_ft_ap_oom2(dev, apdev): """WPA2-PSK-FT and AP OOM 2""" @@ -1960,15 +2172,15 @@ def test_ap_ft_ap_oom3(dev, apdev): dev[0].scan_for_bss(bssid1, freq="2412") with alloc_fail(hapd1, 1, "wpa_ft_pull_pmk_r1"): # This will fail due to not being able to send out PMK-R1 pull request - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 2, "os_get_random;wpa_ft_pull_pmk_r1"): # This will fail due to not being able to send out PMK-R1 pull request - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 2, "aes_siv_encrypt;wpa_ft_pull_pmk_r1"): # This will fail due to not being able to send out PMK-R1 pull request - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) def test_ap_ft_ap_oom3b(dev, apdev): """WPA2-PSK-FT and AP OOM 3b""" @@ -2042,23 +2254,23 @@ def test_ap_ft_ap_oom5(dev, apdev): dev[0].scan_for_bss(bssid1, freq="2412") with alloc_fail(hapd1, 1, "=wpa_ft_process_auth_req"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 1, "os_get_random;wpa_ft_process_auth_req"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 1, "sha256_prf_bits;wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 3, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 1, "wpa_derive_pmk_r1_name;wpa_ft_process_auth_req"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) def test_ap_ft_ap_oom6(dev, apdev): """WPA2-PSK-FT and AP OOM 6""" @@ -2197,10 +2409,10 @@ def test_ap_ft_ap_oom8(dev, apdev): dev[0].scan_for_bss(bssid1, freq="2412") with fail_test(hapd1, 1, "wpa_derive_pmk_r0;wpa_ft_psk_pmk_r1"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) with fail_test(hapd1, 1, "wpa_derive_pmk_r1;wpa_ft_psk_pmk_r1"): # This will fail to roam - dev[0].roam(bssid1) + dev[0].roam(bssid1, check_bssid=False) def test_ap_ft_ap_oom9(dev, apdev): """WPA2-PSK-FT and AP OOM 9""" @@ -3147,3 +3359,55 @@ def test_ap_ft_r0_key_expiration(dev, apdev): dev[0].dump_monitor() dev[0].request("RECONNECT") dev[0].wait_connected() + +def test_ap_ft_no_full_ap_client_state(dev, apdev): + """WPA2-PSK-FT AP with full_ap_client_state=0""" + run_ap_ft_skip_prune_assoc(dev, apdev, False, False) + +def test_ap_ft_skip_prune_assoc(dev, apdev): + """WPA2-PSK-FT AP with skip_prune_assoc""" + run_ap_ft_skip_prune_assoc(dev, apdev, True, True) + +def test_ap_ft_skip_prune_assoc2(dev, apdev): + """WPA2-PSK-FT AP with skip_prune_assoc (disable full_ap_client_state)""" + run_ap_ft_skip_prune_assoc(dev, apdev, True, False, test_connectivity=False) + +def test_ap_ft_skip_prune_assoc_pmf(dev, apdev): + """WPA2-PSK-FT/PMF AP with skip_prune_assoc""" + run_ap_ft_skip_prune_assoc(dev, apdev, True, True, pmf=True) + +def test_ap_ft_skip_prune_assoc_pmf_over_ds(dev, apdev): + """WPA2-PSK-FT/PMF AP with skip_prune_assoc (over DS)""" + run_ap_ft_skip_prune_assoc(dev, apdev, True, True, pmf=True, over_ds=True) + +def run_ap_ft_skip_prune_assoc(dev, apdev, skip_prune_assoc, + full_ap_client_state, test_connectivity=True, + pmf=False, over_ds=False): + ssid = "test-ft" + passphrase = "12345678" + + params = ft_params1(ssid=ssid, passphrase=passphrase) + if skip_prune_assoc: + params['skip_prune_assoc'] = '1' + if not full_ap_client_state: + params['driver_params'] = "full_ap_client_state=0" + if pmf: + params["ieee80211w"] = "2" + hapd0 = hostapd.add_ap(apdev[0], params) + params = ft_params2(ssid=ssid, passphrase=passphrase) + if skip_prune_assoc: + params['skip_prune_assoc'] = '1' + if not full_ap_client_state: + params['driver_params'] = "full_ap_client_state=0" + if pmf: + params["ieee80211w"] = "2" + hapd1 = hostapd.add_ap(apdev[1], params) + + run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, + ieee80211w="2" if pmf else "0", + over_ds=over_ds, test_connectivity=test_connectivity) + +def test_ap_ft_sae_skip_prune_assoc(dev, apdev): + """WPA2-PSK-FT-SAE AP with skip_prune_assoc""" + hapd0, hapd1 = start_ft_sae(dev[0], apdev, skip_prune_assoc=True) + run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True) diff --git a/tests/hwsim/test_ap_hs20.py b/tests/hwsim/test_ap_hs20.py index 374ba2278..c8ba76770 100644 --- a/tests/hwsim/test_ap_hs20.py +++ b/tests/hwsim/test_ap_hs20.py @@ -17,7 +17,7 @@ import socket import subprocess import hostapd -from utils import HwsimSkip, skip_with_fips, alloc_fail, fail_test, wait_fail_trigger +from utils import * import hwsim_utils from tshark import run_tshark from wlantest import Wlantest @@ -727,6 +727,61 @@ def test_ap_hs20_auto_interworking(dev, apdev): if status['hs20'] != "3": raise Exception("Unexpected HS 2.0 support indication") +def test_ap_hs20_auto_interworking_global_pmf(dev, apdev): + """Hotspot 2.0 connection with auto_interworking=1 and pmf=2""" + check_eap_capa(dev[0], "MSCHAPV2") + bssid = apdev[0]['bssid'] + params = hs20_ap_params() + params['hessid'] = bssid + hostapd.add_ap(apdev[0], params) + + dev[0].hs20_enable(auto_interworking=True) + id = dev[0].add_cred_values({'realm': "example.com", + 'username': "hs20-test", + 'password': "password", + 'ca_cert': "auth_serv/ca.pem", + 'domain': "example.com", + 'update_identifier': "1234"}) + try: + dev[0].set("pmf", "2") + dev[0].request("REASSOCIATE") + dev[0].wait_connected(timeout=15) + pmf = dev[0].get_status_field("pmf") + if pmf != "1": + raise Exception("Unexpected PMF state: " + str(pmf)) + finally: + dev[0].set("pmf", "0") + +def test_ap_hs20_auto_interworking_global_pmf_fail(dev, apdev): + """Hotspot 2.0 connection with auto_interworking=1 and pmf=2 failure""" + check_eap_capa(dev[0], "MSCHAPV2") + bssid = apdev[0]['bssid'] + params = hs20_ap_params() + params['ieee80211w'] = "0" + params['hessid'] = bssid + hostapd.add_ap(apdev[0], params) + + dev[0].hs20_enable(auto_interworking=True) + id = dev[0].add_cred_values({'realm': "example.com", + 'username': "hs20-test", + 'password': "password", + 'ca_cert': "auth_serv/ca.pem", + 'domain': "example.com", + 'update_identifier': "1234"}) + try: + dev[0].set("pmf", "2") + dev[0].request("REASSOCIATE") + for i in range(2): + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "INTERWORKING-SELECTED"], timeout=15) + if ev is None: + raise Exception("Connection result not reported") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + dev[0].request("DISCONNECT") + finally: + dev[0].set("pmf", "0") + @remote_compatible def test_ap_hs20_auto_interworking_no_match(dev, apdev): """Hotspot 2.0 connection with auto_interworking=1 and no matching network""" @@ -2547,6 +2602,41 @@ def test_ap_hs20_deauth_req_without_pmf(dev, apdev): if "FAIL" not in hapd.request("HS20_DEAUTH_REQ " + addr + " 1 120 http://example.com/"): raise Exception("HS20_DEAUTH_REQ accepted during OOM") +def test_ap_hs20_deauth_req_pmf_htc(dev, apdev): + """Hotspot 2.0 connection and deauthentication request PMF misbehavior (+HTC)""" + try: + run_ap_hs20_deauth_req_pmf_htc(dev, apdev) + finally: + stop_monitor(apdev[1]["ifname"]) + +def run_ap_hs20_deauth_req_pmf_htc(dev, apdev): + check_eap_capa(dev[0], "MSCHAPV2") + dev[0].request("SET pmf 0") + hapd = eap_test(dev[0], apdev[0], "21[3:26]", "TTLS", "user", release=1) + dev[0].dump_monitor() + addr = dev[0].own_addr() + hapd.wait_sta() + + sock = start_monitor(apdev[1]["ifname"]) + radiotap = radiotap_build() + bssid = hapd.own_addr().replace(':', '') + addr = dev[0].own_addr().replace(':', '') + payload = "0a1a0101dd1b506f9a0101780013687474703a2f2f6578616d706c652e636f6d2f" + # Claim there is a HT Control field, but then start the frame body from + # there and do not encrypt the Robust Action frame. + frame = binascii.unhexlify("d0803a01" + addr + 2 * bssid + "0000" + payload) + # Claim there is a HT Control field and start the frame body in the correct + # location, but do not encrypt the Robust Action frame. Make the first octet + # of HT Control field use a non-robust Action Category value. + frame2 = binascii.unhexlify("d0803a01" + addr + 2 * bssid + "0000" + "04000000" + payload) + + sock.send(radiotap + frame) + sock.send(radiotap + frame2) + + ev = dev[0].wait_event(["HS20-DEAUTH-IMMINENT-NOTICE"], timeout=1) + if ev is not None: + raise Exception("Deauth imminent notice without PMF accepted") + def test_ap_hs20_remediation_required(dev, apdev): """Hotspot 2.0 connection and remediation required from RADIUS""" check_eap_capa(dev[0], "MSCHAPV2") @@ -2662,8 +2752,9 @@ def test_ap_hs20_osen(dev, apdev): dev[1].connect("osen", key_mgmt="NONE", scan_freq="2412", wait_connect=False) - dev[2].connect("osen", key_mgmt="NONE", wep_key0='"hello"', - scan_freq="2412", wait_connect=False) + if "WEP40" in dev[2].get_capability("group"): + dev[2].connect("osen", key_mgmt="NONE", wep_key0='"hello"', + scan_freq="2412", wait_connect=False) dev[0].flush_scan_cache() dev[0].connect("osen", proto="OSEN", key_mgmt="OSEN", pairwise="CCMP", group="GTK_NOT_USED CCMP", @@ -3849,7 +3940,7 @@ def test_ap_hs20_remediation_sql(dev, apdev, params): import sqlite3 except ImportError: raise HwsimSkip("No sqlite3 module available") - dbfile = os.path.join(params['logdir'], "eap-user.db") + dbfile = params['prefix'] + ".eap-user.db" try: os.remove(dbfile) except: @@ -3913,7 +4004,7 @@ def test_ap_hs20_sim_provisioning(dev, apdev, params): import sqlite3 except ImportError: raise HwsimSkip("No sqlite3 module available") - dbfile = os.path.join(params['logdir'], "ap_hs20_sim_provisioning-eap-user.db") + dbfile = params['prefix'] + ".eap-user.db" try: os.remove(dbfile) except: @@ -4631,16 +4722,10 @@ def tshark_get_na(cap): return frames def _test_proxyarp_open(dev, apdev, params, ebtables=False): - prefix = "proxyarp_open" - if ebtables: - prefix += "_ebtables" - cap_br = os.path.join(params['logdir'], prefix + ".ap-br0.pcap") - cap_dev0 = os.path.join(params['logdir'], - prefix + ".%s.pcap" % dev[0].ifname) - cap_dev1 = os.path.join(params['logdir'], - prefix + ".%s.pcap" % dev[1].ifname) - cap_dev2 = os.path.join(params['logdir'], - prefix + ".%s.pcap" % dev[2].ifname) + cap_br = params['prefix'] + ".ap-br0.pcap" + cap_dev0 = params['prefix'] + ".%s.pcap" % dev[0].ifname + cap_dev1 = params['prefix'] + ".%s.pcap" % dev[1].ifname + cap_dev2 = params['prefix'] + ".%s.pcap" % dev[2].ifname bssid = apdev[0]['bssid'] params = {'ssid': 'open'} @@ -4671,9 +4756,12 @@ def _test_proxyarp_open(dev, apdev, params, ebtables=False): if ebtables: for chain in ['FORWARD', 'OUTPUT']: try: - subprocess.call(['ebtables', '-A', chain, '-p', 'ARP', - '-d', 'Broadcast', '-o', apdev[0]['ifname'], - '-j', 'DROP']) + err = subprocess.call(['ebtables', '-A', chain, '-p', 'ARP', + '-d', 'Broadcast', + '-o', apdev[0]['ifname'], + '-j', 'DROP']) + if err != 0: + raise except: raise HwsimSkip("No ebtables available") @@ -4956,17 +5044,10 @@ def _test_proxyarp_open(dev, apdev, params, ebtables=False): # raise Exception("br did not get ARP response for 192.168.1.123") def _test_proxyarp_open_ipv6(dev, apdev, params, ebtables=False): - prefix = "proxyarp_open" - if ebtables: - prefix += "_ebtables" - prefix += "_ipv6" - cap_br = os.path.join(params['logdir'], prefix + ".ap-br0.pcap") - cap_dev0 = os.path.join(params['logdir'], - prefix + ".%s.pcap" % dev[0].ifname) - cap_dev1 = os.path.join(params['logdir'], - prefix + ".%s.pcap" % dev[1].ifname) - cap_dev2 = os.path.join(params['logdir'], - prefix + ".%s.pcap" % dev[2].ifname) + cap_br = params['prefix'] + ".ap-br0.pcap" + cap_dev0 = params['prefix'] + ".%s.pcap" % dev[0].ifname + cap_dev1 = params['prefix'] + ".%s.pcap" % dev[1].ifname + cap_dev2 = params['prefix'] + ".%s.pcap" % dev[2].ifname bssid = apdev[0]['bssid'] params = {'ssid': 'open'} @@ -4997,10 +5078,15 @@ def _test_proxyarp_open_ipv6(dev, apdev, params, ebtables=False): if ebtables: for chain in ['FORWARD', 'OUTPUT']: try: - subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast', - '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp', - '--ip6-icmp-type', 'neighbor-solicitation', - '-o', apdev[0]['ifname'], '-j', 'DROP']) + err = subprocess.call(['ebtables', '-A', chain, + '-d', 'Multicast', + '-p', 'IPv6', + '--ip6-protocol', 'ipv6-icmp', + '--ip6-icmp-type', + 'neighbor-solicitation', + '-o', apdev[0]['ifname'], '-j', 'DROP']) + if err != 0: + raise subprocess.call(['ebtables', '-A', chain, '-d', 'Multicast', '-p', 'IPv6', '--ip6-protocol', 'ipv6-icmp', '--ip6-icmp-type', 'neighbor-advertisement', @@ -5988,6 +6074,9 @@ def test_ap_hs20_set_profile_failures(dev, apdev): def test_ap_hs20_unexpected(dev, apdev): """Unexpected Hotspot 2.0 AP configuration""" + skip_without_tkip(dev[0]) + skip_without_tkip(dev[1]) + skip_without_tkip(dev[2]) check_eap_capa(dev[0], "MSCHAPV2") bssid = apdev[0]['bssid'] params = hostapd.wpa_eap_params(ssid="test-hs20-fake") @@ -6170,7 +6259,7 @@ def run_ap_hs20_terms_and_conditions_sql(dev, apdev, params, url_template, import sqlite3 except ImportError: raise HwsimSkip("No sqlite3 module available") - dbfile = os.path.join(params['logdir'], "eap-user.db") + dbfile = params['prefix'] + ".eap-user.db" try: os.remove(dbfile) except: diff --git a/tests/hwsim/test_ap_ht.py b/tests/hwsim/test_ap_ht.py index dc4c5b9d7..99adb12a3 100644 --- a/tests/hwsim/test_ap_ht.py +++ b/tests/hwsim/test_ap_ht.py @@ -12,26 +12,8 @@ import struct import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, alloc_fail, parse_ie, clear_regdom +from utils import * import hwsim_utils -from test_ap_csa import csa_supported - -def clear_scan_cache(apdev): - ifname = apdev['ifname'] - hostapd.cmd_execute(apdev, ['ifconfig', ifname, 'up']) - hostapd.cmd_execute(apdev, ['iw', ifname, 'scan', 'trigger', 'freq', '2412', - 'flush']) - time.sleep(0.1) - hostapd.cmd_execute(apdev, ['ifconfig', ifname, 'down']) - -def set_world_reg(apdev0=None, apdev1=None, dev0=None): - if apdev0: - hostapd.cmd_execute(apdev0, ['iw', 'reg', 'set', '00']) - if apdev1: - hostapd.cmd_execute(apdev1, ['iw', 'reg', 'set', '00']) - if dev0: - dev0.cmd_execute(['iw', 'reg', 'set', '00']) - time.sleep(0.1) def test_ap_ht40_scan(dev, apdev): """HT40 co-ex scan""" @@ -73,6 +55,18 @@ def test_ap_ht40_scan(dev, apdev): sta = hapd.get_sta(dev[0].own_addr()) logger.info("hostapd STA: " + str(sta)) + res = dev[0].request("SIGNAL_POLL") + logger.info("STA SIGNAL_POLL:\n" + res.strip()) + sig = res.splitlines() + if "WIDTH=40 MHz" not in sig: + raise Exception("Not a 40 MHz connection") + + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 84: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) + def test_ap_ht_wifi_generation(dev, apdev): """HT and wifi_generation""" clear_scan_cache(apdev[0]) @@ -892,6 +886,13 @@ def test_ap_require_ht(dev, apdev): ampdu_density="1", disable_ht40="1", disable_sgi="1", disable_ldpc="1", rx_stbc="2", tx_stbc="1") + sta = hapd.get_sta(dev[0].own_addr()) + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 81: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) + def test_ap_ht_stbc(dev, apdev): """HT STBC overrides""" params = {"ssid": "ht"} @@ -1005,7 +1006,10 @@ def test_ap_ht_40mhz_intolerant_ap(dev, apdev): logger.info("Waiting for co-ex report from STA") ok = False - for i in range(0, 20): + for i in range(4): + ev = dev[0].wait_event(['CTRL-EVENT-SCAN-RESULTS'], timeout=20) + if ev is None: + raise Exception("No OBSS scan seen") time.sleep(1) if hapd.get_status_field("secondary_channel") == "0": logger.info("AP moved to 20 MHz channel") @@ -1165,21 +1169,37 @@ def test_ap_ht40_csa3(dev, apdev): set_world_reg(apdev[0], None, dev[0]) dev[0].flush_scan_cache() -@remote_compatible -def test_ap_ht_smps(dev, apdev): - """SMPS AP configuration options""" - params = {"ssid": "ht1", "ht_capab": "[SMPS-STATIC]"} - try: - hapd = hostapd.add_ap(apdev[0], params) - except: - raise HwsimSkip("Assume mac80211_hwsim was not recent enough to support SMPS") - params = {"ssid": "ht2", "ht_capab": "[SMPS-DYNAMIC]"} - hapd2 = hostapd.add_ap(apdev[1], params) +def test_ap_ht_20_to_40_csa(dev, apdev): + """HT with 20 MHz channel width doing CSA to 40 MHz""" + csa_supported(dev[0]) - dev[0].connect("ht1", key_mgmt="NONE", scan_freq="2412") - dev[1].connect("ht2", key_mgmt="NONE", scan_freq="2412") - hwsim_utils.test_connectivity(dev[0], hapd) - hwsim_utils.test_connectivity(dev[1], hapd2) + params = {"ssid": "ht", + "channel": "1", + "ieee80211n": "1"} + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].connect("ht", key_mgmt="NONE", scan_freq="2412") + hapd.wait_sta() + res = dev[0].request("SIGNAL_POLL") + logger.info("SIGNAL_POLL:\n" + res) + sig = res.splitlines() + if 'WIDTH=20 MHz' not in sig: + raise Exception("20 MHz channel bandwidth not used on the original channel") + + hapd.request("CHAN_SWITCH 5 2462 ht sec_channel_offset=-1 bandwidth=40") + ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) + if ev is None: + raise Exception("CSA finished event timed out") + if "freq=2462" not in ev: + raise Exception("Unexpected channel in CSA finished event") + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5) + if ev is not None: + raise Exception("Unexpected STA disconnection during CSA") + res = dev[0].request("SIGNAL_POLL") + logger.info("SIGNAL_POLL:\n" + res) + sig = res.splitlines() + if 'WIDTH=40 MHz' not in sig: + raise Exception("40 MHz channel bandwidth not used on the new channel") @remote_compatible def test_prefer_ht20(dev, apdev): diff --git a/tests/hwsim/test_ap_mixed.py b/tests/hwsim/test_ap_mixed.py index 81b85e6aa..e758ae923 100644 --- a/tests/hwsim/test_ap_mixed.py +++ b/tests/hwsim/test_ap_mixed.py @@ -9,11 +9,12 @@ logger = logging.getLogger() import hostapd import hwsim_utils -from utils import skip_with_fips +from utils import * def test_ap_mixed_security(dev, apdev): """WPA/WPA2 with PSK, EAP, SAE, FT in a single BSS""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) dev[0].flush_scan_cache() sae = "SAE" in dev[2].get_capability("auth_alg") ssid = "test-mixed" diff --git a/tests/hwsim/test_ap_open.py b/tests/hwsim/test_ap_open.py index fd9919bb1..62b44461b 100644 --- a/tests/hwsim/test_ap_open.py +++ b/tests/hwsim/test_ap_open.py @@ -18,7 +18,6 @@ from tshark import run_tshark from utils import * from wpasupplicant import WpaSupplicant from wlantest import WlantestCapture -from test_ap_ht import set_world_reg @remote_compatible def test_ap_open(dev, apdev): @@ -278,6 +277,7 @@ def hapd_out_of_mem(hapd, apdev, count, func): def test_ap_open_out_of_memory(dev, apdev): """hostapd failing to setup interface due to allocation failure""" hapd = hostapd.add_ap(apdev[0], {"ssid": "open"}) + flags2 = hapd.request("DRIVER_FLAGS2").splitlines()[1:] hapd_out_of_mem(hapd, apdev[1], 1, "hostapd_alloc_bss_data") for i in range(1, 3): @@ -293,8 +293,9 @@ def test_ap_open_out_of_memory(dev, apdev): for i in range(1, 3): hapd_out_of_mem(hapd, apdev[1], i, "=wpa_driver_nl80211_drv_init") - # eloop_register_read_sock() call from i802_init() - hapd_out_of_mem(hapd, apdev[1], 1, "eloop_sock_table_add_sock;?eloop_register_sock;?eloop_register_read_sock;=i802_init") + if 'CONTROL_PORT_RX' not in flags2: + # eloop_register_read_sock() call from i802_init() + hapd_out_of_mem(hapd, apdev[1], 1, "eloop_sock_table_add_sock;?eloop_register_sock;?eloop_register_read_sock;=i802_init") # verify that a new interface can still be added when memory allocation does # not fail @@ -505,7 +506,7 @@ def test_ap_open_sta_ps(dev, apdev): run_ap_open_sta_ps(dev, hapd) finally: dev[0].cmd_execute(['iw', 'dev', dev[0].ifname, - 'set', 'power_save', 'on']) + 'set', 'power_save', 'off']) def run_ap_open_sta_ps(dev, hapd): hwsim_utils.test_connectivity(dev[0], hapd) @@ -527,6 +528,11 @@ def run_ap_open_sta_ps(dev, hapd): if not ok: raise Exception("STA did not enter power save") + + dev[0].dump_monitor() + hapd.dump_monitor() + hapd.request("DEAUTHENTICATE " + dev[0].own_addr()) + dev[0].wait_disconnected() except FileNotFoundError: raise HwsimSkip("Kernel does not support inspecting HW PS state") diff --git a/tests/hwsim/test_ap_params.py b/tests/hwsim/test_ap_params.py index 8e4ab8e3b..791805743 100644 --- a/tests/hwsim/test_ap_params.py +++ b/tests/hwsim/test_ap_params.py @@ -15,7 +15,7 @@ import time import hwsim_utils import hostapd from tshark import run_tshark -from utils import alloc_fail, HwsimSkip, parse_ie +from utils import * @remote_compatible def test_ap_fragmentation_rts_set_high(dev, apdev): @@ -140,8 +140,10 @@ def test_ap_acl_accept(dev, apdev): """MAC ACL accept list""" ssid = "acl" params = {} + filename = hostapd.acl_file(dev, apdev, 'hostapd.macaddr') + hostapd.send_file(apdev[0], filename, filename) params['ssid'] = ssid - params['accept_mac_file'] = "hostapd.macaddr" + params['accept_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412") @@ -156,13 +158,17 @@ def test_ap_acl_accept(dev, apdev): ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) if ev is not None: raise Exception("Unexpected association") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_acl_deny(dev, apdev): """MAC ACL deny list""" ssid = "acl" params = {} + filename = hostapd.acl_file(dev, apdev, 'hostapd.macaddr') + hostapd.send_file(apdev[0], filename, filename) params['ssid'] = ssid - params['deny_mac_file'] = "hostapd.macaddr" + params['deny_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", passive=True) dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412", wait_connect=False) @@ -171,13 +177,17 @@ def test_ap_acl_deny(dev, apdev): ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) if ev is not None: raise Exception("Unexpected association") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_acl_mgmt(dev, apdev): """MAC ACL accept/deny management""" ssid = "acl" params = {} + filename = hostapd.acl_file(dev, apdev, 'hostapd.macaddr') + hostapd.send_file(apdev[0], filename, filename) params['ssid'] = ssid - params['deny_mac_file'] = "hostapd.macaddr" + params['deny_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) accept = hapd.request("ACCEPT_ACL SHOW").splitlines() @@ -241,6 +251,8 @@ def test_ap_acl_mgmt(dev, apdev): hapd.request("DENY_ACL ADD_MAC " + dev[0].own_addr()) dev[0].wait_disconnected() dev[0].request("DISCONNECT") + if filename.startswith('/tmp/'): + os.unlink(filename) @remote_compatible def test_ap_wds_sta(dev, apdev): @@ -288,6 +300,43 @@ def test_ap_wds_sta(dev, apdev): dev[0].cmd_execute(['ip', 'link', 'set', 'dev', 'wds-br0', 'down']) dev[0].cmd_execute(['brctl', 'delbr', 'wds-br0']) +def test_ap_wds_sta_eap(dev, apdev): + """WPA2-EAP AP with STA using 4addr mode""" + ssid = "test-wpa2-eap" + params = hostapd.wpa2_eap_params(ssid=ssid) + params['wds_sta'] = "1" + params['wds_bridge'] = "wds-br0" + hapd = hostapd.add_ap(apdev[0], params) + + try: + dev[0].cmd_execute(['brctl', 'addbr', 'wds-br0']) + dev[0].cmd_execute(['brctl', 'setfd', 'wds-br0', '0']) + dev[0].cmd_execute(['ip', 'link', 'set', 'dev', 'wds-br0', 'up']) + dev[0].cmd_execute(['iw', dev[0].ifname, 'set', '4addr', 'on']) + dev[0].connect(ssid, key_mgmt="WPA-EAP", eap="GPSK", + identity="gpsk user", + password="abcdefghijklmnop0123456789abcdef", + scan_freq="2412") + ev = hapd.wait_event(["WDS-STA-INTERFACE-ADDED"], timeout=10) + if ev is None: + raise Exception("No WDS-STA-INTERFACE-ADDED event seen") + if "sta_addr=" + dev[0].own_addr() not in ev: + raise Exception("No sta_addr match in " + ev) + if "ifname=" + hapd.ifname + ".sta" not in ev: + raise Exception("No ifname match in " + ev) + sta = hapd.get_sta(dev[0].own_addr()) + if "wds_sta_ifname" not in sta: + raise Exception("Missing wds_sta_ifname in STA data") + if "ifname=" + sta['wds_sta_ifname'] not in ev: + raise Exception("wds_sta_ifname %s not in event: %s" % + (sta['wds_sta_ifname'], ev)) + hwsim_utils.test_connectivity_iface(dev[0], hapd, "wds-br0", + max_tries=15) + finally: + dev[0].cmd_execute(['iw', dev[0].ifname, 'set', '4addr', 'off']) + dev[0].cmd_execute(['ip', 'link', 'set', 'dev', 'wds-br0', 'down']) + dev[0].cmd_execute(['brctl', 'delbr', 'wds-br0']) + def test_ap_wds_sta_open(dev, apdev): """Open AP with STA using 4addr mode""" ssid = "test-wds-open" @@ -322,6 +371,7 @@ def test_ap_wds_sta_open(dev, apdev): def test_ap_wds_sta_wep(dev, apdev): """WEP AP with STA using 4addr mode""" + check_wep_capa(dev[0]) ssid = "test-wds-wep" params = {} params['ssid'] = ssid @@ -551,6 +601,7 @@ def test_ap_beacon_rate_legacy(dev, apdev): hapd.set('beacon_rate', '55') hapd.enable() dev[0].connect('beacon-rate', key_mgmt="NONE", scan_freq="2412") + time.sleep(0.5) def test_ap_beacon_rate_legacy2(dev, apdev): """Open AP with Beacon frame TX rate 12 Mbps in VHT BSS""" @@ -573,6 +624,7 @@ def test_ap_beacon_rate_legacy2(dev, apdev): hapd.enable() dev[0].scan_for_bss(hapd.own_addr(), freq="5180") dev[0].connect('beacon-rate', key_mgmt="NONE", scan_freq="5180") + time.sleep(0.5) finally: dev[0].request("DISCONNECT") hapd.request("DISABLE") @@ -589,6 +641,7 @@ def test_ap_beacon_rate_ht(dev, apdev): hapd.set('beacon_rate', 'ht:0') hapd.enable() dev[0].connect('beacon-rate', key_mgmt="NONE", scan_freq="2412") + time.sleep(0.5) def test_ap_beacon_rate_ht2(dev, apdev): """Open AP with Beacon frame TX rate HT-MCS 1 in VHT BSS""" @@ -611,6 +664,7 @@ def test_ap_beacon_rate_ht2(dev, apdev): hapd.enable() dev[0].scan_for_bss(hapd.own_addr(), freq="5180") dev[0].connect('beacon-rate', key_mgmt="NONE", scan_freq="5180") + time.sleep(0.5) finally: dev[0].request("DISCONNECT") hapd.request("DISABLE") @@ -638,6 +692,7 @@ def test_ap_beacon_rate_vht(dev, apdev): hapd.enable() dev[0].scan_for_bss(hapd.own_addr(), freq="5180") dev[0].connect('beacon-rate', key_mgmt="NONE", scan_freq="5180") + time.sleep(0.5) finally: dev[0].request("DISCONNECT") hapd.request("DISABLE") @@ -646,6 +701,7 @@ def test_ap_beacon_rate_vht(dev, apdev): def test_ap_wep_to_wpa(dev, apdev): """WEP to WPA2-PSK configuration change in hostapd""" + check_wep_capa(dev[0]) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-to-wpa", "wep_key0": '"hello"'}) diff --git a/tests/hwsim/test_ap_pmf.py b/tests/hwsim/test_ap_pmf.py index 0a3645731..6c2a58ac4 100644 --- a/tests/hwsim/test_ap_pmf.py +++ b/tests/hwsim/test_ap_pmf.py @@ -6,14 +6,14 @@ from remotehost import remote_compatible import binascii +import os import time import logging logger = logging.getLogger() import hwsim_utils import hostapd -from utils import alloc_fail, fail_test, wait_fail_trigger, HwsimSkip, \ - radiotap_build, start_monitor, stop_monitor +from utils import * from wlantest import Wlantest from wpasupplicant import WpaSupplicant @@ -59,24 +59,30 @@ def test_ap_pmf_required(dev, apdev): dev[1].p2p_interface_addr()) < 1: raise Exception("STA did not reply to SA Query") -@remote_compatible -def test_ocv_sa_query(dev, apdev): - """Test SA Query with OCV""" +def start_ocv_ap(apdev): ssid = "test-pmf-required" params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") params["wpa_key_mgmt"] = "WPA-PSK-SHA256" params["ieee80211w"] = "2" params["ocv"] = "1" try: - hapd = hostapd.add_ap(apdev[0], params) + hapd = hostapd.add_ap(apdev, params) except Exception as e: if "Failed to set hostapd parameter ocv" in str(e): raise HwsimSkip("OCV not supported") raise + Wlantest.setup(hapd) wt = Wlantest() wt.flush() wt.add_passphrase("12345678") + + return hapd, ssid, wt + +@remote_compatible +def test_ocv_sa_query(dev, apdev): + """Test SA Query with OCV""" + hapd, ssid, wt = start_ocv_ap(apdev[0]) dev[0].connect(ssid, psk="12345678", ieee80211w="1", ocv="1", key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") @@ -84,7 +90,9 @@ def test_ocv_sa_query(dev, apdev): # Test that client can handle SA Query with OCI element if "OK" not in hapd.request("SA_QUERY " + dev[0].own_addr()): raise Exception("SA_QUERY failed") - time.sleep(0.1) + ev = hapd.wait_event(["OCV-FAILURE"], timeout=0.1) + if ev: + raise Exception("Unexpected OCV failure reported") if wt.get_sta_counter("valid_saqueryresp_tx", apdev[0]['bssid'], dev[0].own_addr()) < 1: raise Exception("STA did not reply to SA Query") @@ -99,21 +107,7 @@ def test_ocv_sa_query(dev, apdev): @remote_compatible def test_ocv_sa_query_csa(dev, apdev): """Test SA Query with OCV after channel switch""" - ssid = "test-pmf-required" - params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") - params["wpa_key_mgmt"] = "WPA-PSK-SHA256" - params["ieee80211w"] = "2" - params["ocv"] = "1" - try: - hapd = hostapd.add_ap(apdev[0], params) - except Exception as e: - if "Failed to set hostapd parameter ocv" in str(e): - raise HwsimSkip("OCV not supported") - raise - Wlantest.setup(hapd) - wt = Wlantest() - wt.flush() - wt.add_passphrase("12345678") + hapd, ssid, wt = start_ocv_ap(apdev[0]) dev[0].connect(ssid, psk="12345678", ieee80211w="1", ocv="1", key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") @@ -124,6 +118,44 @@ def test_ocv_sa_query_csa(dev, apdev): dev[0].own_addr()) < 1: raise Exception("STA did not start SA Query after channel switch") + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=16) + if ev is not None: + raise Exception("Unexpected disconnection") + +def test_ocv_sa_query_csa_no_resp(dev, apdev): + """Test SA Query with OCV after channel switch getting no response""" + hapd, ssid, wt = start_ocv_ap(apdev[0]) + dev[0].connect(ssid, psk="12345678", ieee80211w="1", ocv="1", + key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", + scan_freq="2412") + + hapd.set("ext_mgmt_frame_handling", "1") + hapd.request("CHAN_SWITCH 5 2437") + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5) + if ev is None: + raise Exception("Disconnection after CSA not reported") + if "locally_generated=1" not in ev: + raise Exception("Unexpectedly disconnected by AP: " + ev) + +def test_ocv_sa_query_csa_missing(dev, apdev): + """Test SA Query with OCV missing after channel switch""" + hapd, ssid, wt = start_ocv_ap(apdev[0]) + dev[0].connect(ssid, psk="12345678", ieee80211w="1", ocv="1", + key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", + scan_freq="2412") + + hapd.set("ext_mgmt_frame_handling", "1") + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + ev = hapd.wait_event(['MGMT-RX'], timeout=5) + if ev is None: + raise Exception("Deauthentication frame RX not reported") + hapd.set("ext_mgmt_frame_handling", "0") + hapd.request("CHAN_SWITCH 5 2437") + ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=20) + if ev is None: + raise Exception("No disconnection event received from hostapd") + @remote_compatible def test_ap_pmf_optional(dev, apdev): """WPA2-PSK AP with PMF optional""" @@ -247,6 +279,34 @@ def test_ap_pmf_assoc_comeback2(dev, apdev): dev[0].p2p_interface_addr()) < 1: raise Exception("AP did not use reassociation comeback request") +@remote_compatible +def test_ap_pmf_assoc_comeback_wps(dev, apdev): + """WPA2-PSK AP with PMF association comeback (WPS)""" + ssid = "assoc-comeback" + appin = "12345670" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + params["eap_server"] = "1" + params["wps_state"] = "2" + params["ap_pin"] = appin + hapd = hostapd.add_ap(apdev[0], params) + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase("12345678") + dev[0].connect(ssid, psk="12345678", ieee80211w="1", + key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", + scan_freq="2412") + hapd.set("ext_mgmt_frame_handling", "1") + dev[0].request("DISCONNECT") + dev[0].wait_disconnected(timeout=10) + hapd.set("ext_mgmt_frame_handling", "0") + dev[0].wps_reg(apdev[0]['bssid'], appin) + if wt.get_sta_counter("assocresp_comeback", apdev[0]['bssid'], + dev[0].p2p_interface_addr()) < 1: + raise Exception("AP did not use association comeback request") + def test_ap_pmf_ap_dropping_sa(dev, apdev): """WPA2-PSK PMF AP dropping SA""" ssid = "pmf" @@ -853,6 +913,7 @@ def run_ap_pmf_inject_data(dev, apdev): def test_ap_pmf_tkip_reject(dev, apdev): """Mixed mode BSS and MFP-enabled AP rejecting TKIP""" + skip_without_tkip(dev[0]) params = hostapd.wpa2_params(ssid="test-pmf", passphrase="12345678") params['wpa'] = '3' params["ieee80211w"] = "1" @@ -915,3 +976,229 @@ def test_ap_pmf_sa_query_timeout(dev, apdev): ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1.5) if ev is not None: raise Exception("Unexpected disconnection after reconnection seen") + +def mac80211_read_key(keydir): + vals = {} + for name in os.listdir(keydir): + try: + with open(os.path.join(keydir, name)) as f: + vals[name] = f.read().strip() + except OSError as e: + pass + return vals + +def check_mac80211_bigtk(dev, hapd): + sta_key = None + ap_key = None + + phy = dev.get_driver_status_field("phyname") + keys = "/sys/kernel/debug/ieee80211/%s/keys" % phy + try: + for key in os.listdir(keys): + keydir = os.path.join(keys, key) + vals = mac80211_read_key(keydir) + keyidx = int(vals['keyidx']) + if keyidx == 6 or keyidx == 7: + sta_key = vals; + break + except OSError as e: + raise HwsimSkip("debugfs not supported in mac80211 (STA)") + + phy = hapd.get_driver_status_field("phyname") + keys = "/sys/kernel/debug/ieee80211/%s/keys" % phy + try: + for key in os.listdir(keys): + keydir = os.path.join(keys, key) + vals = mac80211_read_key(keydir) + keyidx = int(vals['keyidx']) + if keyidx == 6 or keyidx == 7: + ap_key = vals; + break + except OSError as e: + raise HwsimSkip("debugfs not supported in mac80211 (AP)") + + if not sta_key: + raise Exception("Could not find STA key information from debugfs") + logger.info("STA key: " + str(sta_key)) + + if not ap_key: + raise Exception("Could not find AP key information from debugfs") + logger.info("AP key: " + str(ap_key)) + + if sta_key['key'] != ap_key['key']: + raise Exception("AP and STA BIGTK mismatch") + + if sta_key['keyidx'] != ap_key['keyidx']: + raise Exception("AP and STA BIGTK keyidx mismatch") + + if sta_key['algorithm'] != ap_key['algorithm']: + raise Exception("AP and STA BIGTK algorithm mismatch") + + replays = int(sta_key['replays']) + icverrors = int(sta_key['icverrors']) + if replays > 0 or icverrors > 0: + raise Exception("STA reported errors: replays=%d icverrors=%d" % replays, icverrors) + + rx_spec = int(sta_key['rx_spec'], base=16) + if rx_spec < 3: + raise Exception("STA did not update BIGTK receive counter sufficiently") + + tx_spec = int(ap_key['tx_spec'], base=16) + if tx_spec < 3: + raise Exception("AP did not update BIGTK BIPN sufficiently") + +def test_ap_pmf_beacon_protection_bip(dev, apdev): + """WPA2-PSK Beacon protection (BIP)""" + run_ap_pmf_beacon_protection(dev, apdev, "AES-128-CMAC") + +def test_ap_pmf_beacon_protection_bip_cmac_256(dev, apdev): + """WPA2-PSK Beacon protection (BIP-CMAC-256)""" + run_ap_pmf_beacon_protection(dev, apdev, "BIP-CMAC-256") + +def test_ap_pmf_beacon_protection_bip_gmac_128(dev, apdev): + """WPA2-PSK Beacon protection (BIP-GMAC-128)""" + run_ap_pmf_beacon_protection(dev, apdev, "BIP-GMAC-128") + +def test_ap_pmf_beacon_protection_bip_gmac_256(dev, apdev): + """WPA2-PSK Beacon protection (BIP-GMAC-256)""" + run_ap_pmf_beacon_protection(dev, apdev, "BIP-GMAC-256") + +def run_ap_pmf_beacon_protection(dev, apdev, cipher): + ssid = "test-beacon-prot" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + params["beacon_prot"] = "1" + params["group_mgmt_cipher"] = cipher + try: + hapd = hostapd.add_ap(apdev[0], params) + except Exception as e: + if "Failed to enable hostapd interface" in str(e): + raise HwsimSkip("Beacon protection not supported") + raise + + bssid = hapd.own_addr() + + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase("12345678") + + # STA with Beacon protection enabled + dev[0].connect(ssid, psk="12345678", ieee80211w="2", beacon_prot="1", + key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") + + # STA with Beacon protection disabled + dev[1].connect(ssid, psk="12345678", ieee80211w="2", + key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") + + time.sleep(1) + check_mac80211_bigtk(dev[0], hapd) + + valid_bip = wt.get_bss_counter('valid_bip_mmie', bssid) + invalid_bip = wt.get_bss_counter('invalid_bip_mmie', bssid) + missing_bip = wt.get_bss_counter('missing_bip_mmie', bssid) + logger.info("wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip)) + if valid_bip < 0 or invalid_bip > 0 or missing_bip > 0: + raise Exception("Unexpected wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip)) + +def test_ap_pmf_beacon_protection_mismatch(dev, apdev): + """WPA2-PSK Beacon protection MIC mismatch""" + run_ap_pmf_beacon_protection_mismatch(dev, apdev, False) + +def test_ap_pmf_beacon_protection_missing(dev, apdev): + """WPA2-PSK Beacon protection MME missing""" + run_ap_pmf_beacon_protection_mismatch(dev, apdev, True) + +def run_ap_pmf_beacon_protection_mismatch(dev, apdev, clear): + ssid = "test-beacon-prot" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + params["beacon_prot"] = "1" + params["group_mgmt_cipher"] = "AES-128-CMAC" + try: + hapd = hostapd.add_ap(apdev[0], params) + except Exception as e: + if "Failed to enable hostapd interface" in str(e): + raise HwsimSkip("Beacon protection not supported") + raise + + bssid = hapd.own_addr() + + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase("12345678") + + dev[0].connect(ssid, psk="12345678", ieee80211w="2", beacon_prot="1", + key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412") + + WPA_ALG_NONE = 0 + WPA_ALG_IGTK = 4 + KEY_FLAG_DEFAULT = 0x02 + KEY_FLAG_TX = 0x08 + KEY_FLAG_GROUP = 0x10 + KEY_FLAG_GROUP_TX_DEFAULT = KEY_FLAG_GROUP | KEY_FLAG_TX | KEY_FLAG_DEFAULT + + addr = "ff:ff:ff:ff:ff:ff" + + if clear: + res = hapd.request("SET_KEY %d %s %d %d %s %s %d" % (WPA_ALG_NONE, addr, 6, 1, 6*"00", "", KEY_FLAG_GROUP)) + else: + res = hapd.request("SET_KEY %d %s %d %d %s %s %d" % (WPA_ALG_IGTK, addr, 6, 1, 6*"00", 16*"00", KEY_FLAG_GROUP_TX_DEFAULT)) + if "OK" not in res: + raise Exception("SET_KEY failed") + + ev = dev[0].wait_event(["CTRL-EVENT-UNPROT-BEACON"], timeout=5) + if ev is None: + raise Exception("Unprotected Beacon frame not reported") + + ev = dev[0].wait_event(["CTRL-EVENT-BEACON-LOSS"], timeout=5) + if ev is None: + raise Exception("Beacon loss not reported") + + ev = hapd.wait_event(["CTRL-EVENT-UNPROT-BEACON"], timeout=5) + if ev is None: + raise Exception("WNM-Notification Request frame not reported") + +def test_ap_pmf_sta_global_require(dev, apdev): + """WPA2-PSK AP with PMF optional and wpa_supplicant pmf=2""" + ssid = "test-pmf-optional" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK" + params["ieee80211w"] = "1" + hapd = hostapd.add_ap(apdev[0], params) + try: + dev[0].set("pmf", "2") + dev[0].connect(ssid, psk="12345678", + key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", + scan_freq="2412") + pmf = dev[0].get_status_field("pmf") + if pmf != "1": + raise Exception("Unexpected PMF state: " + str(pmf)) + finally: + dev[0].set("pmf", "0") + +def test_ap_pmf_sta_global_require2(dev, apdev): + """WPA2-PSK AP with PMF optional and wpa_supplicant pmf=2 (2)""" + ssid = "test-pmf-optional" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK" + params["ieee80211w"] = "0" + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + try: + dev[0].scan_for_bss(bssid, freq=2412) + dev[0].set("pmf", "2") + dev[0].connect(ssid, psk="12345678", + key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2", + scan_freq="2412", wait_connect=False) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) + if ev is None: + raise Exception("Connection result not reported") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + finally: + dev[0].set("pmf", "0") diff --git a/tests/hwsim/test_ap_psk.py b/tests/hwsim/test_ap_psk.py index ac0fabc5d..db10377a4 100644 --- a/tests/hwsim/test_ap_psk.py +++ b/tests/hwsim/test_ap_psk.py @@ -19,11 +19,11 @@ import subprocess import time import hostapd -from utils import HwsimSkip, fail_test, skip_with_fips, start_monitor, stop_monitor, radiotap_build +from utils import * import hwsim_utils from wpasupplicant import WpaSupplicant from tshark import run_tshark -from wlantest import WlantestCapture +from wlantest import WlantestCapture, Wlantest def check_mib(dev, vals): mib = dev.get_mib() @@ -210,12 +210,57 @@ def test_ap_wpa2_ptk_rekey(dev, apdev): passphrase = 'qwertyuiop' params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) hapd = hostapd.add_ap(apdev[0], params) + + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase(passphrase) + dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412") - ev = dev[0].wait_event(["WPA: Key negotiation completed"]) + ev = dev[0].wait_event(["WPA: Key negotiation completed", + "CTRL-EVENT-DISCONNECTED"]) if ev is None: raise Exception("PTK rekey timed out") + if "CTRL-EVENT-DISCONNECTED" in ev: + raise Exception("Disconnect instead of rekey") hwsim_utils.test_connectivity(dev[0], hapd) +def test_ap_wpa2_ptk_rekey_blocked_ap(dev, apdev): + """WPA2-PSK AP and PTK rekey enforced by station and AP blocking it""" + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + params['wpa_deny_ptk0_rekey'] = "2" + hapd = hostapd.add_ap(apdev[0], params) + dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412") + ev = dev[0].wait_event(["WPA: Key negotiation completed", + "CTRL-EVENT-DISCONNECTED"]) + if ev is None: + raise Exception("PTK rekey timed out") + if "WPA: Key negotiation completed" in ev: + raise Exception("No disconnect, PTK rekey succeeded") + ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=1) + if ev is None: + raise Exception("Reconnect too slow") + +def test_ap_wpa2_ptk_rekey_blocked_sta(dev, apdev): + """WPA2-PSK AP and PTK rekey enforced by station while also blocking it""" + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + hapd = hostapd.add_ap(apdev[0], params) + dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", scan_freq="2412", + wpa_deny_ptk0_rekey="2") + ev = dev[0].wait_event(["WPA: Key negotiation completed", + "CTRL-EVENT-DISCONNECTED"]) + if ev is None: + raise Exception("PTK rekey timed out") + if "WPA: Key negotiation completed" in ev: + raise Exception("No disconnect, PTK rekey succeeded") + ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=1) + if ev is None: + raise Exception("Reconnect too slow") + def test_ap_wpa2_ptk_rekey_anonce(dev, apdev): """WPA2-PSK AP and PTK rekey enforced by station and ANonce change""" ssid = "test-wpa2-psk" @@ -288,6 +333,7 @@ def test_ap_wpa2_sha256_ptk_rekey_ap(dev, apdev): def test_ap_wpa_ptk_rekey(dev, apdev): """WPA-PSK/TKIP AP and PTK rekey enforced by station""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) ssid = "test-wpa-psk" passphrase = 'qwertyuiop' params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase) @@ -304,6 +350,7 @@ def test_ap_wpa_ptk_rekey(dev, apdev): def test_ap_wpa_ptk_rekey_ap(dev, apdev): """WPA-PSK/TKIP AP and PTK rekey enforced by AP""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) ssid = "test-wpa-psk" passphrase = 'qwertyuiop' params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase) @@ -449,6 +496,7 @@ def test_ap_wpa2_gtk_rekey_request(dev, apdev): def test_ap_wpa_gtk_rekey(dev, apdev): """WPA-PSK/TKIP AP and GTK rekey enforced by AP""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) ssid = "test-wpa-psk" passphrase = 'qwertyuiop' params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase) @@ -620,30 +668,39 @@ def test_ap_wpa2_ext_add_to_bridge(dev, apdev): hostapd.cmd_execute(apdev[0], ['brctl', 'delif', br_ifname, ifname]) hostapd.cmd_execute(apdev[0], ['brctl', 'delbr', br_ifname]) -def test_ap_wpa2_psk_ext(dev, apdev): - """WPA2-PSK AP using external EAPOL I/O""" - bssid = apdev[0]['bssid'] +def setup_psk_ext(dev, apdev, wpa_ptk_rekey=None): ssid = "test-wpa2-psk" passphrase = 'qwertyuiop' psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' params = hostapd.wpa2_params(ssid=ssid) params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) + if wpa_ptk_rekey: + params['wpa_ptk_rekey'] = wpa_ptk_rekey + hapd = hostapd.add_ap(apdev, params) hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) - addr = dev[0].p2p_interface_addr() + dev.request("SET ext_eapol_frame_io 1") + dev.connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) + return hapd + +def ext_4way_hs(hapd, dev): + bssid = hapd.own_addr() + addr = dev.own_addr() + first = None + last = None while True: ev = hapd.wait_event(["EAPOL-TX", "AP-STA-CONNECTED"], timeout=15) if ev is None: raise Exception("Timeout on EAPOL-TX from hostapd") if "AP-STA-CONNECTED" in ev: - dev[0].wait_connected(timeout=15) + dev.wait_connected(timeout=15) break - res = dev[0].request("EAPOL_RX " + bssid + " " + ev.split(' ')[2]) + if not first: + first = ev.split(' ')[2] + last = ev.split(' ')[2] + res = dev.request("EAPOL_RX " + bssid + " " + ev.split(' ')[2]) if "OK" not in res: raise Exception("EAPOL_RX to wpa_supplicant failed") - ev = dev[0].wait_event(["EAPOL-TX", "CTRL-EVENT-CONNECTED"], timeout=15) + ev = dev.wait_event(["EAPOL-TX", "CTRL-EVENT-CONNECTED"], timeout=15) if ev is None: raise Exception("Timeout on EAPOL-TX from wpa_supplicant") if "CTRL-EVENT-CONNECTED" in ev: @@ -651,19 +708,45 @@ def test_ap_wpa2_psk_ext(dev, apdev): res = hapd.request("EAPOL_RX " + addr + " " + ev.split(' ')[2]) if "OK" not in res: raise Exception("EAPOL_RX to hostapd failed") + return first, last + +def test_ap_wpa2_psk_ext(dev, apdev): + """WPA2-PSK AP using external EAPOL I/O""" + hapd = setup_psk_ext(dev[0], apdev[0]) + ext_4way_hs(hapd, dev[0]) + +def test_ap_wpa2_psk_unexpected(dev, apdev): + """WPA2-PSK and supplicant receiving unexpected EAPOL-Key frames""" + hapd = setup_psk_ext(dev[0], apdev[0]) + first, last = ext_4way_hs(hapd, dev[0]) + + # Not associated - Delay processing of received EAPOL frame (state=COMPLETED + # bssid=02:00:00:00:03:00) + other = "02:11:22:33:44:55" + res = dev[0].request("EAPOL_RX " + other + " " + first) + if "OK" not in res: + raise Exception("EAPOL_RX to wpa_supplicant failed") + + # WPA: EAPOL-Key Replay Counter did not increase - dropping packet + bssid = hapd.own_addr() + res = dev[0].request("EAPOL_RX " + bssid + " " + last) + if "OK" not in res: + raise Exception("EAPOL_RX to wpa_supplicant failed") + + # WPA: Invalid EAPOL-Key MIC - dropping packet + msg = last[0:18] + '01' + last[20:] + res = dev[0].request("EAPOL_RX " + bssid + " " + msg) + if "OK" not in res: + raise Exception("EAPOL_RX to wpa_supplicant failed") + + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=12) + if ev is not None: + raise Exception("Unexpected disconnection") def test_ap_wpa2_psk_ext_retry_msg_3(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4""" + hapd = setup_psk_ext(dev[0], apdev[0]) bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].p2p_interface_addr() # EAPOL-Key msg 1/4 @@ -721,16 +804,8 @@ def test_ap_wpa2_psk_ext_retry_msg_3(dev, apdev): def test_ap_wpa2_psk_ext_retry_msg_3b(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4 (b)""" + hapd = setup_psk_ext(dev[0], apdev[0]) bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].p2p_interface_addr() # EAPOL-Key msg 1/4 @@ -796,16 +871,8 @@ def test_ap_wpa2_psk_ext_retry_msg_3b(dev, apdev): def test_ap_wpa2_psk_ext_retry_msg_3c(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4 (c)""" + hapd = setup_psk_ext(dev[0], apdev[0]) bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].p2p_interface_addr() # EAPOL-Key msg 1/4 @@ -888,16 +955,8 @@ def test_ap_wpa2_psk_ext_retry_msg_3c(dev, apdev): def test_ap_wpa2_psk_ext_retry_msg_3d(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4 (d)""" + hapd = setup_psk_ext(dev[0], apdev[0]) bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].p2p_interface_addr() # EAPOL-Key msg 1/4 @@ -983,16 +1042,8 @@ def test_ap_wpa2_psk_ext_retry_msg_3d(dev, apdev): def test_ap_wpa2_psk_ext_retry_msg_3e(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and retry for EAPOL-Key msg 3/4 (e)""" + hapd = setup_psk_ext(dev[0], apdev[0]) bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].p2p_interface_addr() # EAPOL-Key msg 1/4 @@ -1089,17 +1140,8 @@ def test_ap_wpa2_psk_ext_retry_msg_3e(dev, apdev): def test_ap_wpa2_psk_ext_delayed_ptk_rekey(dev, apdev): """WPA2-PSK AP using external EAPOL I/O and delayed PTK rekey exchange""" + hapd = setup_psk_ext(dev[0], apdev[0], wpa_ptk_rekey="3") bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - params['wpa_ptk_rekey'] = '3' - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].p2p_interface_addr() # EAPOL-Key msg 1/4 @@ -1520,6 +1562,7 @@ def test_ap_wpa2_psk_ext_eapol_type_diff(dev, apdev): @remote_compatible def test_ap_wpa_psk_ext_eapol(dev, apdev): """WPA2-PSK AP using external EAPOL supplicant""" + skip_without_tkip(dev[0]) (bssid, ssid, hapd, snonce, pmk, addr, wpae) = eapol_test(apdev[0], dev[0], wpa2=False) @@ -2264,7 +2307,8 @@ def test_ap_wpa2_psk_supp_proto_too_long_gtk_in_group_msg(dev, apdev): key_info=0x13c2) counter += 1 send_eapol(dev[0], bssid, build_eapol(msg)) - ev = dev[0].wait_event(["WPA: Unsupported CCMP Group Cipher key length 33"]) + ev = dev[0].wait_event(["WPA: Unsupported CCMP Group Cipher key length 33", + "RSN: Too long GTK in GTK KDE (len=33)"]) if ev is None: raise Exception("Too long GTK KDE not reported") dev[0].wait_disconnected(timeout=1) @@ -2650,16 +2694,8 @@ def test_ap_wpa2_psk_ifdown(dev, apdev): def test_ap_wpa2_psk_drop_first_msg_4(dev, apdev): """WPA2-PSK and first EAPOL-Key msg 4/4 dropped""" + hapd = setup_psk_ext(dev[0], apdev[0]) bssid = apdev[0]['bssid'] - ssid = "test-wpa2-psk" - passphrase = 'qwertyuiop' - psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' - params = hostapd.wpa2_params(ssid=ssid) - params['wpa_psk'] = psk - hapd = hostapd.add_ap(apdev[0], params) - hapd.request("SET ext_eapol_frame_io 1") - dev[0].request("SET ext_eapol_frame_io 1") - dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False) addr = dev[0].own_addr() # EAPOL-Key msg 1/4 @@ -2758,6 +2794,7 @@ def test_ap_wpa2_psk_incorrect_passphrase(dev, apdev): def test_ap_wpa_ie_parsing(dev, apdev): """WPA IE parsing""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) ssid = "test-wpa-psk" passphrase = 'qwertyuiop' params = hostapd.wpa_params(ssid=ssid, passphrase=passphrase) @@ -2885,6 +2922,7 @@ def test_rsn_ie_proto_psk_sta(dev, apdev): @remote_compatible def test_ap_cli_order(dev, apdev): + """hostapd configuration parameter SET ordering""" ssid = "test-rsn-setup" passphrase = 'zzzzzzzz' @@ -2989,6 +3027,7 @@ def test_ap_wpa2_psk_assoc_rsn_pmkid(dev, apdev): def test_ap_wpa_psk_rsn_pairwise(dev, apdev): """WPA-PSK AP and only rsn_pairwise set""" + skip_without_tkip(dev[0]) params = {"ssid": "wpapsk", "wpa": "1", "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "TKIP", "wpa_passphrase": "1234567890"} hapd = hostapd.add_ap(apdev[0], params) @@ -3109,6 +3148,7 @@ def test_ap_wpa2_disable_eapol_retry_group(dev, apdev): def test_ap_wpa2_psk_mic_0(dev, apdev): """WPA2-PSK/TKIP and MIC=0 in EAPOL-Key msg 3/4""" + skip_without_tkip(dev[0]) bssid = apdev[0]['bssid'] ssid = "test-wpa2-psk" passphrase = 'qwertyuiop' @@ -3306,3 +3346,184 @@ def test_ap_wpa2_psk_no_control_port(dev, apdev): wpas.request("DISCONNECT") wpas.wait_disconnected() wpas.dump_monitor() + +def test_ap_wpa2_psk_ap_control_port(dev, apdev): + """WPA2-PSK AP with nl80211 control port in AP mode""" + run_ap_wpa2_psk_ap_control_port(dev, apdev, ctrl_val=1) + +def test_ap_wpa2_psk_ap_control_port_disabled(dev, apdev): + """WPA2-PSK AP with nl80211 control port in AP mode disabled""" + run_ap_wpa2_psk_ap_control_port(dev, apdev, ctrl_val=0) + +def run_ap_wpa2_psk_ap_control_port(dev, apdev, ctrl_val): + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + params['driver_params'] = "control_port_ap=%d" % ctrl_val + hapd = hostapd.add_ap(apdev[0], params) + + flags = hapd.request("DRIVER_FLAGS").splitlines()[1:] + flags2 = hapd.request("DRIVER_FLAGS2").splitlines()[1:] + logger.info("AP driver flags: " + str(flags)) + logger.info("AP driver flags2: " + str(flags2)) + if 'CONTROL_PORT' not in flags or 'CONTROL_PORT_RX' not in flags2: + raise HwsimSkip("No AP driver support for CONTROL_PORT") + + flags = dev[0].request("DRIVER_FLAGS").splitlines()[1:] + flags2 = dev[0].request("DRIVER_FLAGS2").splitlines()[1:] + logger.info("STA driver flags: " + str(flags)) + logger.info("STA driver flags2: " + str(flags2)) + if 'CONTROL_PORT' not in flags or 'CONTROL_PORT_RX' not in flags2: + raise HwsimSkip("No STA driver support for CONTROL_PORT") + + dev[0].connect(ssid, psk=passphrase, scan_freq="2412") + hapd.wait_sta() + hwsim_utils.test_connectivity(dev[0], hapd) + if "OK" not in dev[0].request("KEY_REQUEST 0 1"): + raise Exception("KEY_REQUEST failed") + ev = dev[0].wait_event(["WPA: Key negotiation completed"]) + if ev is None: + raise Exception("PTK rekey timed out") + hapd.wait_ptkinitdone(dev[0].own_addr()) + hwsim_utils.test_connectivity(dev[0], hapd) + +def test_ap_wpa2_psk_rsne_mismatch_ap(dev, apdev): + """RSNE mismatch in EAPOL-Key msg 3/4""" + ie = "30140100000fac040100000fac040100000fac020c80" + run_ap_wpa2_psk_rsne_mismatch_ap(dev, apdev, ie) + +def test_ap_wpa2_psk_rsne_mismatch_ap2(dev, apdev): + """RSNE mismatch in EAPOL-Key msg 3/4""" + ie = "30150100000fac040100000fac040100000fac020c0000" + run_ap_wpa2_psk_rsne_mismatch_ap(dev, apdev, ie) + +def test_ap_wpa2_psk_rsne_mismatch_ap3(dev, apdev): + """RSNE mismatch in EAPOL-Key msg 3/4""" + run_ap_wpa2_psk_rsne_mismatch_ap(dev, apdev, "") + +def run_ap_wpa2_psk_rsne_mismatch_ap(dev, apdev, rsne): + params = hostapd.wpa2_params(ssid="psk", passphrase="12345678") + params['rsne_override_eapol'] = rsne + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].connect("psk", psk="12345678", scan_freq="2412", wait_connect=False) + ev = dev[0].wait_event(["Associated with"], timeout=10) + if ev is None: + raise Exception("No indication of association seen") + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=5) + dev[0].request("REMOVE_NETWORK all") + if ev is None: + raise Exception("No disconnection seen") + if "CTRL-EVENT-DISCONNECTED" not in ev: + raise Exception("Unexpected connection") + if "reason=17 locally_generated=1" not in ev: + raise Exception("Unexpected disconnection reason: " + ev) + +def test_ap_wpa2_psk_rsnxe_mismatch_ap(dev, apdev): + """RSNXE mismatch in EAPOL-Key msg 3/4""" + params = hostapd.wpa2_params(ssid="psk", passphrase="12345678") + params['rsnxe_override_eapol'] = "F40100" + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].connect("psk", psk="12345678", scan_freq="2412", wait_connect=False) + ev = dev[0].wait_event(["Associated with"], timeout=10) + if ev is None: + raise Exception("No indication of association seen") + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=5) + dev[0].request("REMOVE_NETWORK all") + if ev is None: + raise Exception("No disconnection seen") + if "CTRL-EVENT-DISCONNECTED" not in ev: + raise Exception("Unexpected connection") + if "reason=17 locally_generated=1" not in ev: + raise Exception("Unexpected disconnection reason: " + ev) + +def test_ap_wpa2_psk_ext_key_id_ptk_rekey_ap0(dev, apdev): + """WPA2-PSK AP and PTK rekey by AP (disabled on STA)""" + run_ap_wpa2_psk_ext_key_id_ptk_rekey_ap(dev, apdev, 1, 0) + +def test_ap_wpa2_psk_ext_key_id_ptk_rekey_ap1(dev, apdev): + """WPA2-PSK AP and PTK rekey by AP (start with Key ID 0)""" + run_ap_wpa2_psk_ext_key_id_ptk_rekey_ap(dev, apdev, 1, 1) + +def test_ap_wpa2_psk_ext_key_id_ptk_rekey_ap2(dev, apdev): + """WPA2-PSK AP and PTK rekey by AP (start with Key ID 1)""" + run_ap_wpa2_psk_ext_key_id_ptk_rekey_ap(dev, apdev, 2, 1) + +def run_ap_wpa2_psk_ext_key_id_ptk_rekey_ap(dev, apdev, ap_ext_key_id, + sta_ext_key_id): + check_ext_key_id_capa(dev[0]) + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + params['wpa_ptk_rekey'] = '2' + params['extended_key_id'] = str(ap_ext_key_id) + hapd = hostapd.add_ap(apdev[0], params) + check_ext_key_id_capa(hapd) + try: + dev[0].set("extended_key_id", str(sta_ext_key_id)) + dev[0].connect(ssid, psk=passphrase, scan_freq="2412") + idx = int(dev[0].request("GET last_tk_key_idx")) + expect_idx = 1 if ap_ext_key_id == 2 and sta_ext_key_id else 0 + if idx != expect_idx: + raise Exception("Unexpected Key ID for the first TK: %d (expected %d)" % (idx, expect_idx)) + ev = dev[0].wait_event(["WPA: Key negotiation completed"]) + if ev is None: + raise Exception("PTK rekey timed out") + idx = int(dev[0].request("GET last_tk_key_idx")) + expect_idx = 1 if ap_ext_key_id == 1 and sta_ext_key_id else 0 + if idx != expect_idx: + raise Exception("Unexpected Key ID for the second TK: %d (expected %d)" % (idx, expect_idx)) + hwsim_utils.test_connectivity(dev[0], hapd) + finally: + dev[0].set("extended_key_id", "0") + +def test_ap_wpa2_psk_ext_key_id_ptk_rekey_sta0(dev, apdev): + """Extended Key ID and PTK rekey by station (Ext Key ID disabled on AP)""" + run_ap_wpa2_psk_ext_key_id_ptk_rekey_sta(dev, apdev, 0) + +def test_ap_wpa2_psk_ext_key_id_ptk_rekey_sta1(dev, apdev): + """Extended Key ID and PTK rekey by station (start with Key ID 0)""" + run_ap_wpa2_psk_ext_key_id_ptk_rekey_sta(dev, apdev, 1) + +def test_ap_wpa2_psk_ext_key_id_ptk_rekey_sta2(dev, apdev): + """Extended Key ID and PTK rekey by station (start with Key ID 1)""" + run_ap_wpa2_psk_ext_key_id_ptk_rekey_sta(dev, apdev, 2) + +def run_ap_wpa2_psk_ext_key_id_ptk_rekey_sta(dev, apdev, ext_key_id): + check_ext_key_id_capa(dev[0]) + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + params['extended_key_id'] = str(ext_key_id) + hapd = hostapd.add_ap(apdev[0], params) + check_ext_key_id_capa(hapd) + + Wlantest.setup(hapd) + wt = Wlantest() + wt.flush() + wt.add_passphrase(passphrase) + + try: + dev[0].set("extended_key_id", "1") + dev[0].connect(ssid, psk=passphrase, wpa_ptk_rekey="1", + scan_freq="2412") + idx = int(dev[0].request("GET last_tk_key_idx")) + expect_idx = 1 if ext_key_id == 2 else 0 + if idx != expect_idx: + raise Exception("Unexpected Key ID for the first TK: %d (expected %d)" % (idx, expect_idx)) + ev = dev[0].wait_event(["WPA: Key negotiation completed", + "CTRL-EVENT-DISCONNECTED"]) + if ev is None: + raise Exception("PTK rekey timed out") + if "CTRL-EVENT-DISCONNECTED" in ev: + raise Exception("Disconnect instead of rekey") + idx = int(dev[0].request("GET last_tk_key_idx")) + expect_idx = 1 if ext_key_id == 1 else 0 + if idx != expect_idx: + raise Exception("Unexpected Key ID for the second TK: %d (expected %d)" % (idx, expect_idx)) + hwsim_utils.test_connectivity(dev[0], hapd) + finally: + dev[0].set("extended_key_id", "0") diff --git a/tests/hwsim/test_ap_roam.py b/tests/hwsim/test_ap_roam.py index 9047c7a80..fca3b57c5 100644 --- a/tests/hwsim/test_ap_roam.py +++ b/tests/hwsim/test_ap_roam.py @@ -26,6 +26,34 @@ def test_ap_roam_open(dev, apdev): dev[0].roam(apdev[0]['bssid']) hwsim_utils.test_connectivity(dev[0], hapd0) +def test_ap_blacklist_all(dev, apdev, params): + """Ensure we clear the blacklist if all visible APs reject""" + hapd0 = hostapd.add_ap(apdev[0], {"ssid": "test-open", "max_num_sta": "0"}) + hapd1 = hostapd.add_ap(apdev[1], {"ssid": "test-open", "max_num_sta": "0"}) + bss0 = hapd0.own_addr() + bss1 = hapd1.own_addr() + + dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412", + wait_connect=False, bssid=bss0) + if not dev[0].wait_event(["CTRL-EVENT-AUTH-REJECT"], timeout=10): + raise Exception("AP 0 didn't reject us") + dev[0].request("REMOVE_NETWORK all") + dev[0].dump_monitor() + dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412", + wait_connect=False, bssid=bss1) + if not dev[0].wait_event(["CTRL-EVENT-AUTH-REJECT"], timeout=10): + raise Exception("AP 1 didn't reject us") + blacklist = get_blacklist(dev[0]) + logger.info("blacklist: " + str(blacklist)) + dev[0].request("REMOVE_NETWORK all") + dev[0].dump_monitor() + + hapd0.set("max_num_sta", "1") + # All visible APs were blacklisted; we should clear the blacklist and find + # the AP that now accepts us. + dev[0].scan_for_bss(bss0, freq=2412) + dev[0].connect("test-open", key_mgmt="NONE", scan_freq="2412", bssid=bss0) + @remote_compatible def test_ap_roam_open_failed(dev, apdev): """Roam failure due to rejected authentication""" diff --git a/tests/hwsim/test_ap_tdls.py b/tests/hwsim/test_ap_tdls.py index caba13df9..a2bf6d498 100644 --- a/tests/hwsim/test_ap_tdls.py +++ b/tests/hwsim/test_ap_tdls.py @@ -14,9 +14,8 @@ import hwsim_utils from hostapd import HostapdGlobal from hostapd import Hostapd import hostapd -from utils import HwsimSkip, skip_with_fips +from utils import * from wlantest import Wlantest -from test_ap_vht import vht_supported def start_ap_wpa2_psk(ap): params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") @@ -27,9 +26,13 @@ def connectivity(dev, hapd): hwsim_utils.test_connectivity(dev[0], hapd) hwsim_utils.test_connectivity(dev[1], hapd) -def connect_2sta(dev, ssid, hapd): - dev[0].connect(ssid, psk="12345678", scan_freq="2412") - dev[1].connect(ssid, psk="12345678", scan_freq="2412") +def connect_2sta(dev, ssid, hapd, sae=False): + key_mgmt = "SAE" if sae else "WPA-PSK" + ieee80211w = "2" if sae else "1" + dev[0].connect(ssid, key_mgmt=key_mgmt, psk="12345678", + ieee80211w=ieee80211w, scan_freq="2412") + dev[1].connect(ssid, key_mgmt=key_mgmt, psk="12345678", + ieee80211w=ieee80211w, scan_freq="2412") hapd.wait_sta() hapd.wait_sta() connectivity(dev, hapd) @@ -113,7 +116,7 @@ def check_connectivity(sta0, sta1, hapd): hwsim_utils.test_connectivity(sta0, hapd) hwsim_utils.test_connectivity(sta1, hapd) -def setup_tdls(sta0, sta1, hapd, reverse=False, expect_fail=False): +def setup_tdls(sta0, sta1, hapd, reverse=False, expect_fail=False, sae=False): logger.info("Setup TDLS") check_connectivity(sta0, sta1, hapd) bssid = hapd.own_addr() @@ -125,18 +128,20 @@ def setup_tdls(sta0, sta1, hapd, reverse=False, expect_fail=False): sta0.tdls_setup(addr1) time.sleep(1) if expect_fail: - tdls_check_ap(sta0, sta1, bssid, addr0, addr1) + if not sae: + tdls_check_ap(sta0, sta1, bssid, addr0, addr1) return if reverse: addr1 = sta0.p2p_interface_addr() addr0 = sta1.p2p_interface_addr() - conf = wt.get_tdls_counter("setup_conf_ok", bssid, addr0, addr1) - if conf == 0: - raise Exception("No TDLS Setup Confirm (success) seen") - tdls_check_dl(sta0, sta1, bssid, addr0, addr1) + if not sae: + conf = wt.get_tdls_counter("setup_conf_ok", bssid, addr0, addr1) + if conf == 0: + raise Exception("No TDLS Setup Confirm (success) seen") + tdls_check_dl(sta0, sta1, bssid, addr0, addr1) check_connectivity(sta0, sta1, hapd) -def teardown_tdls(sta0, sta1, hapd, responder=False, wildcard=False): +def teardown_tdls(sta0, sta1, hapd, responder=False, wildcard=False, sae=False): logger.info("Teardown TDLS") check_connectivity(sta0, sta1, hapd) bssid = hapd.own_addr() @@ -149,11 +154,12 @@ def teardown_tdls(sta0, sta1, hapd, responder=False, wildcard=False): else: sta0.tdls_teardown(addr1) time.sleep(1) - wt = Wlantest() - teardown = wt.get_tdls_counter("teardown", bssid, addr0, addr1) - if teardown == 0: - raise Exception("No TDLS Setup Teardown seen") - tdls_check_ap(sta0, sta1, bssid, addr0, addr1) + if not sae: + wt = Wlantest() + teardown = wt.get_tdls_counter("teardown", bssid, addr0, addr1) + if teardown == 0: + raise Exception("No TDLS Setup Teardown seen") + tdls_check_ap(sta0, sta1, bssid, addr0, addr1) check_connectivity(sta0, sta1, hapd) def check_tdls_link(sta0, sta1, connected=True): @@ -290,6 +296,8 @@ def test_ap_wpa2_tdls_double_tpk_m2(dev, apdev): def test_ap_wpa_tdls(dev, apdev): """WPA-PSK AP and two stations using TDLS""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) + skip_without_tkip(dev[1]) hapd = hostapd.add_ap(apdev[0], hostapd.wpa_params(ssid="test-wpa-psk", passphrase="12345678")) @@ -302,6 +310,7 @@ def test_ap_wpa_tdls(dev, apdev): def test_ap_wpa_mixed_tdls(dev, apdev): """WPA+WPA2-PSK AP and two stations using TDLS""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) hapd = hostapd.add_ap(apdev[0], hostapd.wpa_mixed_params(ssid="test-wpa-mixed-psk", passphrase="12345678")) @@ -313,6 +322,8 @@ def test_ap_wpa_mixed_tdls(dev, apdev): def test_ap_wep_tdls(dev, apdev): """WEP AP and two stations using TDLS""" + check_wep_capa(dev[0]) + check_wep_capa(dev[1]) hapd = hostapd.add_ap(apdev[0], {"ssid": "test-wep", "wep_key0": '"hello"'}) wlantest_setup(hapd) @@ -409,6 +420,7 @@ def test_ap_open_tdls_vht80(dev, apdev): "hw_mode": "a", "channel": "36", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_capab": "", @@ -448,7 +460,7 @@ def test_ap_open_tdls_vht80plus80(dev, apdev): "ht_capab": "[HT40+]", "ieee80211n": "1", "ieee80211ac": "1", - "vht_capab": "", + "vht_capab": "[VHT160-80PLUS80]", "vht_oper_chwidth": "3", "vht_oper_centr_freq_seg0_idx": "42", "vht_oper_centr_freq_seg1_idx": "155"} @@ -490,6 +502,7 @@ def test_ap_open_tdls_vht160(dev, apdev): "hw_mode": "a", "channel": "104", "ht_capab": "[HT40-]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "2", @@ -621,3 +634,17 @@ def _test_ap_open_tdls_external_control(dev, apdev): time.sleep(0.1) if connected: raise Exception("TDLS teardown did not complete") + +def test_ap_sae_tdls(dev, apdev): + """SAE AP and two stations using TDLS""" + check_sae_capab(dev[0]) + check_sae_capab(dev[1]) + params = hostapd.wpa2_params(ssid="test-wpa2-psk", passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + hapd = hostapd.add_ap(apdev[0], params) + wlantest_setup(hapd) + connect_2sta(dev, "test-wpa2-psk", hapd, sae=True) + setup_tdls(dev[0], dev[1], hapd, sae=True) + teardown_tdls(dev[0], dev[1], hapd, sae=True) + setup_tdls(dev[1], dev[0], hapd, sae=True) diff --git a/tests/hwsim/test_ap_vht.py b/tests/hwsim/test_ap_vht.py index ece0efda3..2b691ff71 100644 --- a/tests/hwsim/test_ap_vht.py +++ b/tests/hwsim/test_ap_vht.py @@ -15,15 +15,6 @@ import hostapd from wpasupplicant import WpaSupplicant from utils import * from test_dfs import wait_dfs_event -from test_ap_csa import csa_supported -from test_ap_ht import clear_scan_cache - -def vht_supported(): - cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) - reg = cmd.stdout.read() - if "@ 80)" in reg or "@ 160)" in reg: - return True - return False def test_ap_vht80(dev, apdev): """VHT with 80 MHz channel width""" @@ -75,6 +66,11 @@ def test_ap_vht80(dev, apdev): raise Exception("Missing STA flag: HT") if "[VHT]" not in sta['flags']: raise Exception("Missing STA flag: VHT") + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 128: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) except Exception as e: if isinstance(e, Exception) and str(e) == "AP startup failed": if not vht_supported(): @@ -290,6 +286,13 @@ def test_ap_vht_20(devs, apdevs): hapd = hostapd.add_ap(ap, params) dev.connect("test-vht20", scan_freq="5180", key_mgmt="NONE") hwsim_utils.test_connectivity(dev, hapd) + + sta = hapd.get_sta(dev.own_addr()) + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 115: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) finally: dev.request("DISCONNECT") clear_regdom(hapd, devs) @@ -313,6 +316,13 @@ def test_ap_vht_40(devs, apdevs): hapd = hostapd.add_ap(ap, params) dev.connect("test-vht40", scan_freq="5180", key_mgmt="NONE") hwsim_utils.test_connectivity(dev, hapd) + + sta = hapd.get_sta(dev.own_addr()) + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 116: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) finally: dev.request("DISCONNECT") clear_regdom(hapd, devs) @@ -320,6 +330,7 @@ def test_ap_vht_40(devs, apdevs): def test_ap_vht_capab_not_supported(dev, apdev): """VHT configuration with driver not supporting all vht_capab entries""" try: + hapd = None params = {"ssid": "vht", "country_code": "FI", "hw_mode": "a", @@ -350,6 +361,7 @@ def test_ap_vht160(dev, apdev): "hw_mode": "a", "channel": "36", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "2", @@ -395,6 +407,13 @@ def test_ap_vht160(dev, apdev): raise Exception("Unexpected SIGNAL_POLL value(1): " + str(sig)) if "WIDTH=160 MHz" not in sig: raise Exception("Unexpected SIGNAL_POLL value(2): " + str(sig)) + + sta = hapd.get_sta(dev[0].own_addr()) + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 129: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) except Exception as e: if isinstance(e, Exception) and str(e) == "AP startup failed": if not vht_supported(): @@ -418,6 +437,7 @@ def test_ap_vht160b(dev, apdev): "hw_mode": "a", "channel": "104", "ht_capab": "[HT40-]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "2", @@ -520,6 +540,7 @@ def run_ap_vht160_no_dfs(dev, apdev, channel, ht_capab): "hw_mode": "a", "channel": channel, "ht_capab": ht_capab, + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "2", @@ -532,7 +553,7 @@ def run_ap_vht160_no_dfs(dev, apdev, channel, ht_capab): cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) reg = cmd.stdout.readlines() for r in reg: - if "5490" in r and "DFS" in r: + if b"5490" in r and b"DFS" in r: raise HwsimSkip("ZA regulatory rule did not have DFS requirement removed") raise Exception("AP setup timed out") @@ -598,6 +619,7 @@ def test_ap_vht80plus80(dev, apdev): "hw_mode": "a", "channel": "52", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160-80PLUS80]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "3", @@ -615,6 +637,7 @@ def test_ap_vht80plus80(dev, apdev): "hw_mode": "a", "channel": "36", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160-80PLUS80]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "3", @@ -644,6 +667,13 @@ def test_ap_vht80plus80(dev, apdev): raise Exception("Unexpected SIGNAL_POLL value(3): " + str(sig)) if "CENTER_FRQ2=5775" not in sig: raise Exception("Unexpected SIGNAL_POLL value(4): " + str(sig)) + + sta = hapd2.get_sta(dev[1].own_addr()) + if 'supp_op_classes' not in sta or len(sta['supp_op_classes']) < 2: + raise Exception("No Supported Operating Classes information for STA") + opclass = int(sta['supp_op_classes'][0:2], 16) + if opclass != 130: + raise Exception("Unexpected Current Operating Class from STA: %d" % opclass) except Exception as e: if isinstance(e, Exception) and str(e) == "AP startup failed": if not vht_supported(): @@ -856,10 +886,10 @@ def test_ap_vht_csa_vht40_disable(dev, apdev): hapd = hostapd.add_ap(apdev[0], params) bssid = hapd.own_addr() - dev[0].connect("vht", key_mgmt="NONE", scan_freq="5745") + dev[0].connect("vht", key_mgmt="NONE", scan_freq="5200 5745") hwsim_utils.test_connectivity(dev[0], hapd) - hapd.request("CHAN_SWITCH 5 5200 center_freq1=5200 bandwidth=40 ht") + hapd.request("CHAN_SWITCH 5 5200 center_freq1=5210 sec_channel_offset=1 bandwidth=40 ht") ev = hapd.wait_event(["AP-CSA-FINISHED"], timeout=10) if ev is None: raise Exception("CSA finished event timed out") @@ -870,7 +900,14 @@ def test_ap_vht_csa_vht40_disable(dev, apdev): raise Exception("Channel switch event not seen") if "freq=5200" not in ev: raise Exception("Channel mismatch: " + ev) - time.sleep(0.5) + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5) + if ev: + # mac80211 does not support CSA to disable VHT, so the channel + # switch will be followed by disconnection and attempt to reconnect. + # Wait for that here to avoid failing the test case based on how + # example the connectivity test would get timed compared to getting + # disconnected or reconnected. + dev[0].wait_connected() hwsim_utils.test_connectivity(dev[0], hapd) dev[1].connect("vht", key_mgmt="NONE", scan_freq="5200") @@ -973,6 +1010,7 @@ def test_ap_vht_on_24ghz_2(dev, apdev): def test_prefer_vht40(dev, apdev): """Preference on VHT40 over HT40""" try: + hapd = None hapd2 = None params = {"ssid": "test", @@ -1008,7 +1046,7 @@ def test_prefer_vht40(dev, apdev): raise Exception("Unexpected BSS0 est_throughput: " + est) est = dev[0].get_bss(bssid2)['est_throughput'] - if est != "135001": + if est != "180001": raise Exception("Unexpected BSS1 est_throughput: " + est) finally: dev[0].request("DISCONNECT") @@ -1077,6 +1115,7 @@ def test_ap_vht_use_sta_nsts(dev, apdev): def test_ap_vht_tkip(dev, apdev): """VHT and TKIP""" + skip_without_tkip(dev[0]) try: hapd = None params = {"ssid": "vht", diff --git a/tests/hwsim/test_ap_vlan.py b/tests/hwsim/test_ap_vlan.py index 305889aa1..29f8f5322 100644 --- a/tests/hwsim/test_ap_vlan.py +++ b/tests/hwsim/test_ap_vlan.py @@ -26,9 +26,11 @@ from tshark import run_tshark def test_ap_vlan_open(dev, apdev): """AP VLAN with open network""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = {"ssid": "test-vlan-open", "dynamic_vlan": "1", - "accept_mac_file": "hostapd.accept"} + "accept_mac_file": filename} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") @@ -37,13 +39,17 @@ def test_ap_vlan_open(dev, apdev): hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") hwsim_utils.test_connectivity(dev[2], hapd) + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_vlan_file_open(dev, apdev): """AP VLAN with open network and vlan_file mapping""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = {"ssid": "test-vlan-open", "dynamic_vlan": "1", "vlan_file": "hostapd.vlan", - "accept_mac_file": "hostapd.accept"} + "accept_mac_file": filename} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") @@ -52,13 +58,17 @@ def test_ap_vlan_file_open(dev, apdev): hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") hwsim_utils.test_connectivity(dev[2], hapd) + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_vlan_file_open2(dev, apdev): """AP VLAN with open network and vlan_file mapping (2)""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept2') + hostapd.send_file(apdev[0], filename, filename) params = {"ssid": "test-vlan-open", "dynamic_vlan": "1", "vlan_file": "hostapd.vlan2", - "accept_mac_file": "hostapd.accept2"} + "accept_mac_file": filename} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") @@ -67,6 +77,8 @@ def test_ap_vlan_file_open2(dev, apdev): hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") hwsim_utils.test_connectivity_iface(dev[2], hapd, "hwsimbr3") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_vlan_file_parsing(dev, apdev, params): """hostapd vlan_file/mac_file parsing""" @@ -109,10 +121,12 @@ def test_ap_vlan_file_parsing(dev, apdev, params): def test_ap_vlan_wpa2(dev, apdev): """AP VLAN with WPA2-PSK""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = hostapd.wpa2_params(ssid="test-vlan", passphrase="12345678") params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-vlan", psk="12345678", scan_freq="2412") @@ -124,6 +138,8 @@ def test_ap_vlan_wpa2(dev, apdev): hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") hwsim_utils.test_connectivity_iface(dev[1], hapd, "brvlan2") hwsim_utils.test_connectivity(dev[2], hapd) + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_vlan_wpa2_radius(dev, apdev): """AP VLAN with WPA2-Enterprise and RADIUS attributes""" @@ -166,11 +182,13 @@ def test_ap_vlan_wpa2_radius_2(dev, apdev): def test_ap_vlan_wpa2_radius_local(dev, apdev): """AP VLAN with WPA2-Enterprise and local file setting VLAN IDs""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = hostapd.wpa2_eap_params(ssid="test-vlan") params['dynamic_vlan'] = "0" params['vlan_file'] = "hostapd.vlan" params['vlan_bridge'] = "test_br_vlan" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-vlan", key_mgmt="WPA-EAP", eap="PAX", @@ -191,6 +209,8 @@ def test_ap_vlan_wpa2_radius_local(dev, apdev): hwsim_utils.test_connectivity_iface(dev[0], hapd, "test_br_vlan1") hwsim_utils.test_connectivity_iface(dev[1], hapd, "test_br_vlan2") hwsim_utils.test_connectivity(dev[2], hapd) + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_vlan_wpa2_radius_id_change(dev, apdev): """AP VLAN with WPA2-Enterprise and RADIUS attributes changing VLANID""" @@ -340,10 +360,12 @@ def test_ap_vlan_wpa2_radius_required(dev, apdev): def test_ap_vlan_tagged(dev, apdev): """AP VLAN with tagged interface""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = {"ssid": "test-vlan-open", "dynamic_vlan": "1", "vlan_tagged_interface": "lo", - "accept_mac_file": "hostapd.accept"} + "accept_mac_file": filename} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect("test-vlan-open", key_mgmt="NONE", scan_freq="2412") @@ -352,6 +374,8 @@ def test_ap_vlan_tagged(dev, apdev): hwsim_utils.test_connectivity_iface(dev[0], hapd, "brlo.1") hwsim_utils.test_connectivity_iface(dev[1], hapd, "brlo.2") hwsim_utils.test_connectivity(dev[2], hapd) + if filename.startswith('/tmp/'): + os.unlink(filename) def ap_vlan_iface_cleanup_multibss_cleanup(): subprocess.call(['ifconfig', 'dummy0', 'down'], @@ -546,6 +570,8 @@ def test_ap_vlan_iface_cleanup_multibss_per_sta_vif(dev, apdev): def test_ap_vlan_without_station(dev, apdev, p): """AP VLAN with WPA2-PSK and no station""" try: + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) subprocess.call(['brctl', 'addbr', 'brvlan1']) subprocess.call(['brctl', 'setfd', 'brvlan1', '0']) subprocess.call(['ifconfig', 'brvlan1', 'up']) @@ -555,7 +581,7 @@ def test_ap_vlan_without_station(dev, apdev, p): passphrase="12345678x") params['dynamic_vlan'] = "1" params['vlan_file'] = 'hostapd.wlan3.vlan' - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) # inject some traffic @@ -618,6 +644,8 @@ def test_ap_vlan_without_station(dev, apdev, p): dev[0].request("DISCONNECT") dev[0].wait_disconnected() + if filename.startswith('/tmp/'): + os.unlink(filename) finally: subprocess.call(['ip', 'link', 'set', 'dev', 'brvlan1', 'down']) @@ -707,10 +735,12 @@ def test_ap_vlan_wpa2_radius_mixed(dev, apdev): def test_ap_vlan_reconnect(dev, apdev): """AP VLAN with WPA2-PSK connect, disconnect, connect""" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') + hostapd.send_file(apdev[0], filename, filename) params = hostapd.wpa2_params(ssid="test-vlan", passphrase="12345678") params['dynamic_vlan'] = "1" - params['accept_mac_file'] = "hostapd.accept" + params['accept_mac_file'] = filename hapd = hostapd.add_ap(apdev[0], params) logger.info("connect sta") @@ -725,6 +755,8 @@ def test_ap_vlan_reconnect(dev, apdev): dev[0].connect("test-vlan", psk="12345678", scan_freq="2412") hapd.wait_sta() hwsim_utils.test_connectivity_iface(dev[0], hapd, "brvlan1") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_ap_vlan_psk(dev, apdev, params): """AP VLAN based on PSK/passphrase""" diff --git a/tests/hwsim/test_ap_wps.py b/tests/hwsim/test_ap_wps.py index b7515937e..0ecf2961f 100644 --- a/tests/hwsim/test_ap_wps.py +++ b/tests/hwsim/test_ap_wps.py @@ -41,10 +41,8 @@ import xml.etree.ElementTree as ET import hwsim_utils import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, alloc_fail, fail_test, skip_with_fips -from utils import wait_fail_trigger, clear_regdom +from utils import * from test_ap_eap import int_eap_server_params -from test_sae import check_sae_capab def wps_start_ap(apdev, ssid="test-wps-conf"): params = {"ssid": ssid, "eap_server": "1", "wps_state": "2", @@ -55,6 +53,7 @@ def wps_start_ap(apdev, ssid="test-wps-conf"): @remote_compatible def test_ap_wps_init(dev, apdev): """Initial AP configuration with first WPS Enrollee""" + skip_without_tkip(dev[0]) ssid = "test-wps" hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, "eap_server": "1", "wps_state": "1"}) @@ -96,20 +95,27 @@ def test_ap_wps_init(dev, apdev): conf = hapd.request("GET_CONFIG") if "wps_state=configured" not in conf: raise Exception("AP not in WPS configured state") - if "wpa=3" not in conf: - raise Exception("AP not in WPA+WPA2 configuration") - if "rsn_pairwise_cipher=CCMP TKIP" not in conf: - raise Exception("Unexpected rsn_pairwise_cipher") - if "wpa_pairwise_cipher=CCMP TKIP" not in conf: - raise Exception("Unexpected wpa_pairwise_cipher") - if "group_cipher=TKIP" not in conf: - raise Exception("Unexpected group_cipher") + if "wpa=2" in conf: + if "rsn_pairwise_cipher=CCMP" not in conf: + raise Exception("Unexpected rsn_pairwise_cipher") + if "group_cipher=CCMP" not in conf: + raise Exception("Unexpected group_cipher") + else: + if "wpa=3" not in conf: + raise Exception("AP not in WPA+WPA2 configuration") + if "rsn_pairwise_cipher=CCMP TKIP" not in conf: + raise Exception("Unexpected rsn_pairwise_cipher") + if "wpa_pairwise_cipher=CCMP TKIP" not in conf: + raise Exception("Unexpected wpa_pairwise_cipher") + if "group_cipher=TKIP" not in conf: + raise Exception("Unexpected group_cipher") if len(dev[0].list_networks()) != 3: raise Exception("Unexpected number of network blocks") def test_ap_wps_init_2ap_pbc(dev, apdev): """Initial two-radio AP configuration with first WPS PBC Enrollee""" + skip_without_tkip(dev[0]) ssid = "test-wps" params = {"ssid": ssid, "eap_server": "1", "wps_state": "1"} hapd = hostapd.add_ap(apdev[0], params) @@ -146,6 +152,7 @@ def test_ap_wps_init_2ap_pbc(dev, apdev): def test_ap_wps_init_2ap_pin(dev, apdev): """Initial two-radio AP configuration with first WPS PIN Enrollee""" + skip_without_tkip(dev[0]) ssid = "test-wps" params = {"ssid": ssid, "eap_server": "1", "wps_state": "1"} hapd = hostapd.add_ap(apdev[0], params) @@ -229,6 +236,7 @@ def test_ap_wps_conf(dev, apdev): "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}) logger.info("WPS provisioning step") hapd.request("WPS_PBC") + dev[0].set("device_name", "Device A") dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") dev[0].dump_monitor() dev[0].request("WPS_PBC " + apdev[0]['bssid']) @@ -261,6 +269,7 @@ def test_ap_wps_conf_5ghz(dev, apdev): hapd = hostapd.add_ap(apdev[0], params) logger.info("WPS provisioning step") hapd.request("WPS_PBC") + dev[0].set("device_name", "Device A") dev[0].scan_for_bss(apdev[0]['bssid'], freq="5180") dev[0].request("WPS_PBC " + apdev[0]['bssid']) dev[0].wait_connected(timeout=30) @@ -284,6 +293,7 @@ def test_ap_wps_conf_chan14(dev, apdev): hapd = hostapd.add_ap(apdev[0], params) logger.info("WPS provisioning step") hapd.request("WPS_PBC") + dev[0].set("device_name", "Device A") dev[0].request("WPS_PBC") dev[0].wait_connected(timeout=30) @@ -407,6 +417,7 @@ def test_ap_wps_conf_pin(dev, apdev): def test_ap_wps_conf_pin_mixed_mode(dev, apdev): """WPS PIN provisioning with configured AP (WPA+WPA2)""" + skip_without_tkip(dev[0]) ssid = "test-wps-conf-pin-mixed" hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, "eap_server": "1", "wps_state": "2", @@ -584,6 +595,7 @@ def test_ap_wps_reg_connect_zero_len_ap_pin(dev, apdev): def test_ap_wps_reg_connect_mixed_mode(dev, apdev): """WPS registrar using AP PIN to connect (WPA+WPA2)""" + skip_without_tkip(dev[0]) ssid = "test-wps-reg-ap-pin" appin = "12345670" hostapd.add_ap(apdev[0], @@ -782,11 +794,12 @@ def test_ap_wps_reg_config_ext_processing(dev, apdev): def test_ap_wps_reg_config_tkip(dev, apdev): """WPS registrar configuring AP to use TKIP and AP upgrading to TKIP+CCMP""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) ssid = "test-wps-init-ap" appin = "12345670" - hostapd.add_ap(apdev[0], - {"ssid": ssid, "eap_server": "1", "wps_state": "1", - "ap_pin": appin}) + hapd = hostapd.add_ap(apdev[0], + {"ssid": ssid, "eap_server": "1", "wps_state": "1", + "ap_pin": appin}) logger.info("WPS configuration step") dev[0].flush_scan_cache() dev[0].request("SET wps_version_number 0x10") @@ -807,8 +820,12 @@ def test_ap_wps_reg_config_tkip(dev, apdev): raise Exception("Not fully connected: wpa_state={} bssid={}".format(status['wpa_state'], status['bssid'])) if status['ssid'] != new_ssid: raise Exception("Unexpected SSID") - if status['pairwise_cipher'] != 'CCMP' or status['group_cipher'] != 'TKIP': + if status['pairwise_cipher'] != 'CCMP': raise Exception("Unexpected encryption configuration") + if status['group_cipher'] != 'TKIP': + conf = hapd.request("GET_CONFIG") + if "group_cipher=CCMP" not in conf or status['group_cipher'] != 'CCMP': + raise Exception("Unexpected encryption configuration") if status['key_mgmt'] != 'WPA2-PSK': raise Exception("Unexpected key_mgmt") @@ -956,9 +973,7 @@ def test_ap_wps_setup_locked_2(dev, apdev): dev[0].request("WPS_CANCEL") dev[0].wait_disconnected() -@remote_compatible -def test_ap_wps_pbc_overlap_2ap(dev, apdev): - """WPS PBC session overlap with two active APs""" +def setup_ap_wps_pbc_overlap_2ap(apdev): params = {"ssid": "wps1", "eap_server": "1", "wps_state": "2", "wpa_passphrase": "12345678", "wpa": "2", "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP", @@ -971,16 +986,41 @@ def test_ap_wps_pbc_overlap_2ap(dev, apdev): hapd2 = hostapd.add_ap(apdev[1], params) hapd.request("WPS_PBC") hapd2.request("WPS_PBC") + return hapd, hapd2 + +@remote_compatible +def test_ap_wps_pbc_overlap_2ap(dev, apdev): + """WPS PBC session overlap with two active APs""" + hapd, hapd2 = setup_ap_wps_pbc_overlap_2ap(apdev) logger.info("WPS provisioning step") dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True) dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412") dev[0].request("WPS_PBC") ev = dev[0].wait_event(["WPS-OVERLAP-DETECTED"], timeout=15) - if ev is None: - raise Exception("PBC session overlap not detected") hapd.request("DISABLE") hapd2.request("DISABLE") dev[0].flush_scan_cache() + if ev is None: + raise Exception("PBC session overlap not detected") + +@remote_compatible +def test_ap_wps_pbc_overlap_2ap_specific_bssid(dev, apdev): + """WPS PBC session overlap with two active APs (specific BSSID selected)""" + hapd, hapd2 = setup_ap_wps_pbc_overlap_2ap(apdev) + logger.info("WPS provisioning step") + dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412", force_scan=True) + dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412") + dev[0].request("WPS_PBC " + apdev[0]['bssid']) + ev = dev[0].wait_event(["WPS-OVERLAP-DETECTED", + "CTRL-EVENT-CONNECTED"], timeout=15) + dev[0].request("DISCONNECT") + hapd.request("DISABLE") + hapd2.request("DISABLE") + dev[0].flush_scan_cache() + if ev is None: + raise Exception("PBC session overlap result not reported") + if "CTRL-EVENT-CONNECTED" not in ev: + raise Exception("Connection did not complete") @remote_compatible def test_ap_wps_pbc_overlap_2sta(dev, apdev): @@ -1958,6 +1998,7 @@ def _test_ap_wps_er_learn_oom(dev, apdev): def test_ap_wps_fragmentation(dev, apdev): """WPS with fragmentation in EAP-WSC and mixed mode WPA+WPA2""" + skip_without_tkip(dev[0]) ssid = "test-wps-fragmentation" appin = "12345670" hapd = hostapd.add_ap(apdev[0], @@ -2245,6 +2286,98 @@ def test_ap_wps_per_station_psk(dev, apdev): dev[1].flush_scan_cache() dev[2].flush_scan_cache() +def test_ap_wps_per_station_psk_preset(dev, apdev): + """WPS PIN provisioning with per-station PSK preset""" + addr0 = dev[0].own_addr() + addr1 = dev[1].own_addr() + addr2 = dev[2].own_addr() + ssid = "wps" + appin = "12345670" + pskfile = "/tmp/ap_wps_per_enrollee_psk_preset.psk_file" + try: + os.remove(pskfile) + except: + pass + + hapd = None + try: + with open(pskfile, "w") as f: + f.write("# WPA PSKs\n") + f.write("wps=1 " + addr0 + " preset-passphrase-0\n") + f.write("wps=1 " + addr2 + " preset-passphrase-2\n") + + params = {"ssid": ssid, "eap_server": "1", "wps_state": "2", + "wpa": "2", "wpa_key_mgmt": "WPA-PSK", + "rsn_pairwise": "CCMP", "ap_pin": appin, + "wpa_psk_file": pskfile} + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + logger.info("First enrollee") + pin = dev[0].wps_read_pin() + hapd.request("WPS_PIN any " + pin) + dev[0].scan_for_bss(bssid, freq=2412) + dev[0].request("WPS_PIN %s %s" % (bssid, pin)) + dev[0].wait_connected(timeout=30) + + logger.info("Second enrollee") + pin = dev[1].wps_read_pin() + hapd.request("WPS_PIN any " + pin) + dev[1].scan_for_bss(bssid, freq=2412) + dev[1].request("WPS_PIN %s %s" % (bssid, pin)) + dev[1].wait_connected(timeout=30) + + logger.info("External registrar") + dev[2].scan_for_bss(bssid, freq=2412) + dev[2].wps_reg(bssid, appin) + + logger.info("Verifying PSK results") + psks = get_psk(pskfile) + if addr0 not in psks: + raise Exception("No PSK recorded for sta0") + if addr1 not in psks: + raise Exception("No PSK recorded for sta1") + if addr2 not in psks: + raise Exception("No PSK recorded for sta2") + logger.info("PSK[0]: " + psks[addr0]) + logger.info("PSK[1]: " + psks[addr1]) + logger.info("PSK[2]: " + psks[addr2]) + if psks[addr0] == psks[addr1]: + raise Exception("Same PSK recorded for sta0 and sta1") + if psks[addr0] == psks[addr2]: + raise Exception("Same PSK recorded for sta0 and sta2") + if psks[addr1] == psks[addr2]: + raise Exception("Same PSK recorded for sta1 and sta2") + pmk0 = hapd.request("GET_PMK " + addr0) + pmk1 = hapd.request("GET_PMK " + addr1) + pmk2 = hapd.request("GET_PMK " + addr2) + logger.info("PMK[0]: " + pmk0) + logger.info("PMK[1]: " + pmk1) + logger.info("PMK[2]: " + pmk2) + if pmk0 != "565faec21ff04702d9d17c464e1301efd36c8a3ea46bb866b4bec7fed4384579": + raise Exception("PSK[0] mismatch") + if psks[addr1] != pmk1: + raise Exception("PSK[1] mismatch") + if psks[addr2] != pmk2: + raise Exception("PSK[2] mismatch") + + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + dev[0].dump_monitor() + logger.info("First enrollee again") + pin = dev[0].wps_read_pin() + hapd.request("WPS_PIN any " + pin) + dev[0].scan_for_bss(bssid, freq=2412) + dev[0].request("WPS_PIN %s %s" % (bssid, pin)) + dev[0].wait_connected(timeout=30) + psks2 = get_psk(pskfile) + if addr0 not in psks2: + raise Exception("No PSK recorded for sta0 (2)") + if psks[addr0] != psks2[addr0]: + raise Exception("Different PSK recorded for sta0(enrollee) and sta0(enrollee 2)") + finally: + os.remove(pskfile) + def test_ap_wps_per_station_psk_failure(dev, apdev): """WPS PBC provisioning with per-station PSK (file not writable)""" addr0 = dev[0].p2p_dev_addr() @@ -2339,6 +2472,7 @@ def test_ap_wps_pin_request_file(dev, apdev): def test_ap_wps_auto_setup_with_config_file(dev, apdev): """WPS auto-setup with configuration file""" + skip_without_tkip(dev[0]) conffile = "/tmp/ap_wps_auto_setup_with_config_file.conf" ifname = apdev[0]['ifname'] try: @@ -2377,10 +2511,9 @@ def test_ap_wps_auto_setup_with_config_file(dev, apdev): except: pass -def test_ap_wps_pbc_timeout(dev, apdev, params): - """wpa_supplicant PBC walk time and WPS ER SelReg timeout [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_ap_wps_pbc_timeout(dev, apdev): + """wpa_supplicant PBC walk time and WPS ER SelReg timeout""" ap_uuid = "27ea801a-9e5c-4e73-bd82-f89cbcd10d7e" hapd = add_ssdp_ap(apdev[0], ap_uuid) @@ -3523,6 +3656,7 @@ def test_ap_wps_disabled(dev, apdev): def test_ap_wps_mixed_cred(dev, apdev): """WPS 2.0 STA merging mixed mode WPA/WPA2 credentials""" + skip_without_tkip(dev[0]) ssid = "test-wps-wep" params = {"ssid": ssid, "eap_server": "1", "wps_state": "2", "skip_cred_build": "1", "extra_cred": "wps-mixed-cred"} @@ -9921,6 +10055,7 @@ def test_ap_wps_ignore_broadcast_ssid(dev, apdev): def test_ap_wps_wep(dev, apdev): """WPS AP trying to enable WEP""" + check_wep_capa(dev[0]) ssid = "test-wps" hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, "eap_server": "1", "wps_state": "1", @@ -10014,6 +10149,7 @@ def test_ap_wps_pbc_in_m1(dev, apdev): def test_ap_wps_pbc_mac_addr_change(dev, apdev, params): """WPS M1 with MAC address change""" + skip_without_tkip(dev[0]) ssid = "test-wps-mac-addr-change" hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, "eap_server": "1", "wps_state": "1"}) @@ -10164,6 +10300,8 @@ def run_ap_wps_conf_pin_cipher(dev, apdev, cipher): def test_ap_wps_and_sae(dev, apdev): """Initial AP configuration with first WPS Enrollee and adding SAE""" + skip_without_tkip(dev[0]) + skip_without_tkip(dev[1]) try: run_ap_wps_and_sae(dev, apdev) finally: @@ -10280,3 +10418,38 @@ def test_ap_wps_appl_ext(dev, apdev): dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412") dev[0].request("WPS_PIN %s %s" % (apdev[0]['bssid'], pin)) dev[0].wait_connected(timeout=30) + +@long_duration_test +def test_ap_wps_pbc_ap_timeout(dev, apdev): + """WPS PBC timeout on AP""" + run_ap_wps_ap_timeout(dev, apdev, "WPS_PBC") + +@long_duration_test +def test_ap_wps_pin_ap_timeout(dev, apdev): + """WPS PIN timeout on AP""" + run_ap_wps_ap_timeout(dev, apdev, "WPS_PIN any 12345670 10") + +def run_ap_wps_ap_timeout(dev, apdev, cmd): + ssid = "test-wps-conf" + hapd = hostapd.add_ap(apdev[0], + {"ssid": ssid, "eap_server": "1", "wps_state": "2", + "wpa_passphrase": "12345678", "wpa": "2", + "wpa_key_mgmt": "WPA-PSK", "rsn_pairwise": "CCMP"}) + bssid = hapd.own_addr() + hapd.request(cmd) + time.sleep(1) + dev[0].scan_for_bss(bssid, freq="2412") + bss = dev[0].get_bss(bssid) + logger.info("BSS during active Registrar: " + str(bss)) + if not bss['ie'].endswith("0106ffffffffffff"): + raise Exception("Authorized MAC not included") + ev = hapd.wait_event(["WPS-TIMEOUT"], timeout=130) + if ev is None and "PBC" in cmd: + raise Exception("WPS-TIMEOUT not reported") + time.sleep(5) + dev[0].flush_scan_cache() + dev[0].scan_for_bss(bssid, freq="2412", force_scan=True) + bss = dev[0].get_bss(bssid) + logger.info("BSS after timeout: " + str(bss)) + if bss['ie'].endswith("0106ffffffffffff"): + raise Exception("Authorized MAC not removed") diff --git a/tests/hwsim/test_bgscan.py b/tests/hwsim/test_bgscan.py index f418f56da..e3c1790ba 100644 --- a/tests/hwsim/test_bgscan.py +++ b/tests/hwsim/test_bgscan.py @@ -71,13 +71,22 @@ def test_bgscan_simple(dev, apdev): def test_bgscan_simple_beacon_loss(dev, apdev): """bgscan_simple and beacon loss""" - hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"}) + params = hostapd.wpa2_params(ssid="bgscan", passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412", - bgscan="simple:1:-20:2") + dev[0].set("disable_sa_query", "1") + dev[0].connect("bgscan", ieee80211w="2", key_mgmt="WPA-PSK-SHA256", + psk="12345678", scan_freq="2412", + bgscan="simple:100:-20:200") hapd.set("ext_mgmt_frame_handling", "1") if "OK" not in hapd.request("STOP_AP"): raise Exception("Failed to stop AP") + hapd.disable() + hapd.set("ssid", "foo") + hapd.set("beacon_int", "10000") + hapd.enable() ev = dev[0].wait_event(["CTRL-EVENT-BEACON-LOSS"], timeout=10) if ev is None: raise Exception("Beacon loss not reported") @@ -238,13 +247,21 @@ def test_bgscan_learn(dev, apdev): def test_bgscan_learn_beacon_loss(dev, apdev): """bgscan_simple and beacon loss""" - hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"}) + params = hostapd.wpa2_params(ssid="bgscan", passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + hapd = hostapd.add_ap(apdev[0], params) - dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412", - bgscan="learn:1:-20:2") + dev[0].set("disable_sa_query", "1") + dev[0].connect("bgscan", ieee80211w="2", key_mgmt="WPA-PSK-SHA256", + psk="12345678", scan_freq="2412", bgscan="learn:100:-20:200") hapd.set("ext_mgmt_frame_handling", "1") if "OK" not in hapd.request("STOP_AP"): raise Exception("Failed to stop AP") + hapd.disable() + hapd.set("ssid", "foo") + hapd.set("beacon_int", "10000") + hapd.enable() ev = dev[0].wait_event(["CTRL-EVENT-BEACON-LOSS"], timeout=10) if ev is None: raise Exception("Beacon loss not reported") @@ -285,3 +302,14 @@ def test_bgscan_unknown_module(dev, apdev): hapd = hostapd.add_ap(apdev[0], {"ssid": "bgscan"}) dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412", bgscan="unknown:-20:2") + +def test_bgscan_reconfig(dev, apdev): + """bgscan parameter update""" + hostapd.add_ap(apdev[0], {"ssid": "bgscan"}) + hostapd.add_ap(apdev[1], {"ssid": "bgscan"}) + + id = dev[0].connect("bgscan", key_mgmt="NONE", scan_freq="2412", + bgscan="simple:1:-20:2") + dev[0].set_network_quoted(id, "bgscan", "simple:1:-45:2") + dev[0].set_network_quoted(id, "bgscan", "learn:1:-20:2") + dev[0].set_network_quoted(id, "bgscan", "") diff --git a/tests/hwsim/test_cfg80211.py b/tests/hwsim/test_cfg80211.py index a461fe0ce..3ee7a909b 100644 --- a/tests/hwsim/test_cfg80211.py +++ b/tests/hwsim/test_cfg80211.py @@ -16,6 +16,7 @@ import hwsim_utils from tshark import run_tshark from nl80211 import * from wpasupplicant import WpaSupplicant +from utils import * def nl80211_command(dev, cmd, attr): res = dev.request("VENDOR ffffffff {} {}".format(nl80211_cmd[cmd], @@ -101,6 +102,7 @@ def test_cfg80211_tx_frame(dev, apdev, params): @remote_compatible def test_cfg80211_wep_key_idx_change(dev, apdev): """WEP Shared Key authentication and key index change without deauth""" + check_wep_capa(dev[0]) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-shared-key", "wep_key0": '"hello12345678"', diff --git a/tests/hwsim/test_connect_cmd.py b/tests/hwsim/test_connect_cmd.py index 87122aa32..3c0985137 100644 --- a/tests/hwsim/test_connect_cmd.py +++ b/tests/hwsim/test_connect_cmd.py @@ -12,6 +12,7 @@ import hwsim_utils import hostapd from wpasupplicant import WpaSupplicant from p2p_utils import * +from utils import * def test_connect_cmd_open(dev, apdev): """Open connection using cfg80211 connect command""" @@ -31,11 +32,13 @@ def test_connect_cmd_open(dev, apdev): def test_connect_cmd_wep(dev, apdev): """WEP Open System using cfg80211 connect command""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") + check_wep_capa(wpas) + params = {"ssid": "sta-connect-wep", "wep_key0": '"hello"'} hapd = hostapd.add_ap(apdev[0], params) - wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') - wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") wpas.connect("sta-connect-wep", key_mgmt="NONE", scan_freq="2412", wep_key0='"hello"') wpas.dump_monitor() @@ -46,12 +49,14 @@ def test_connect_cmd_wep(dev, apdev): def test_connect_cmd_wep_shared(dev, apdev): """WEP Shared key using cfg80211 connect command""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") + check_wep_capa(wpas) + params = {"ssid": "sta-connect-wep", "wep_key0": '"hello"', "auth_algs": "2"} hapd = hostapd.add_ap(apdev[0], params) - wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') - wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") id = wpas.connect("sta-connect-wep", key_mgmt="NONE", scan_freq="2412", auth_alg="SHARED", wep_key0='"hello"') wpas.dump_monitor() diff --git a/tests/hwsim/test_dbus.py b/tests/hwsim/test_dbus.py index 41661b8fb..1143802c6 100644 --- a/tests/hwsim/test_dbus.py +++ b/tests/hwsim/test_dbus.py @@ -9,6 +9,7 @@ import logging logger = logging.getLogger() import subprocess import time +import shutil import struct import sys @@ -24,7 +25,7 @@ except ImportError: import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, alloc_fail, fail_test +from utils import * from p2p_utils import * from test_ap_tdls import connect_2sta_open from test_ap_eap import check_altsubject_match_support @@ -1379,6 +1380,106 @@ def test_dbus_connect(dev, apdev): if not t.success(): raise Exception("Expected signals not seen") +def test_dbus_remove_connected(dev, apdev): + """D-Bus RemoveAllNetworks while connected""" + (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0]) + iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE) + + ssid = "test-open" + hapd = hostapd.add_ap(apdev[0], {"ssid": ssid}) + + class TestDbusConnect(TestDbus): + def __init__(self, bus): + TestDbus.__init__(self, bus) + self.network_added = False + self.network_selected = False + self.network_removed = False + self.state = 0 + + def __enter__(self): + gobject.timeout_add(1, self.run_connect) + gobject.timeout_add(15000, self.timeout) + self.add_signal(self.networkAdded, WPAS_DBUS_IFACE, "NetworkAdded") + self.add_signal(self.networkRemoved, WPAS_DBUS_IFACE, + "NetworkRemoved") + self.add_signal(self.networkSelected, WPAS_DBUS_IFACE, + "NetworkSelected") + self.add_signal(self.propertiesChanged, WPAS_DBUS_IFACE, + "PropertiesChanged") + self.loop.run() + return self + + def networkAdded(self, network, properties): + logger.debug("networkAdded: %s" % str(network)) + logger.debug(str(properties)) + self.network_added = True + + def networkRemoved(self, network): + logger.debug("networkRemoved: %s" % str(network)) + self.network_removed = True + + def networkSelected(self, network): + logger.debug("networkSelected: %s" % str(network)) + self.network_selected = True + + def propertiesChanged(self, properties): + logger.debug("propertiesChanged: %s" % str(properties)) + if 'State' in properties and properties['State'] == "completed": + if self.state == 0: + self.state = 1 + iface.Disconnect() + elif self.state == 2: + self.state = 3 + iface.Disconnect() + elif self.state == 4: + self.state = 5 + iface.Reattach() + elif self.state == 5: + self.state = 6 + iface.Disconnect() + elif self.state == 7: + self.state = 8 + res = iface.SignalPoll() + logger.debug("SignalPoll: " + str(res)) + if 'frequency' not in res or res['frequency'] != 2412: + self.state = -1 + logger.info("Unexpected SignalPoll result") + iface.RemoveAllNetworks() + if 'State' in properties and properties['State'] == "disconnected": + if self.state == 1: + self.state = 2 + iface.SelectNetwork(self.netw) + elif self.state == 3: + self.state = 4 + iface.Reassociate() + elif self.state == 6: + self.state = 7 + iface.Reconnect() + elif self.state == 8: + self.state = 9 + self.loop.quit() + + def run_connect(self, *args): + logger.debug("run_connect") + args = dbus.Dictionary({'ssid': ssid, + 'key_mgmt': 'NONE', + 'scan_freq': 2412}, + signature='sv') + self.netw = iface.AddNetwork(args) + iface.SelectNetwork(self.netw) + return False + + def success(self): + if not self.network_added or \ + not self.network_removed or \ + not self.network_selected: + return False + return self.state == 9 + + with TestDbusConnect(bus) as t: + if not t.success(): + raise Exception("Expected signals not seen") + def test_dbus_connect_psk_mem(dev, apdev): """D-Bus AddNetwork and connect with memory-only PSK""" (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0]) @@ -1812,8 +1913,7 @@ def test_dbus_network(dev, apdev): tests = [dbus.Dictionary({'psk': "1234567"}, signature='sv'), dbus.Dictionary({'identity': dbus.ByteArray()}, signature='sv'), - dbus.Dictionary({'identity': dbus.Byte(1)}, signature='sv'), - dbus.Dictionary({'identity': ""}, signature='sv')] + dbus.Dictionary({'identity': dbus.Byte(1)}, signature='sv')] for args in tests: try: iface.AddNetwork(args) @@ -5355,6 +5455,8 @@ def test_dbus_introspect(dev, apdev): raise Exception("Unexpected Introspect response") def run_busctl(service, obj): + if not shutil.which("busctl"): + raise HwsimSkip("No busctl available") logger.info("busctl introspect %s %s" % (service, obj)) cmd = subprocess.Popen(['busctl', 'introspect', service, obj], stdout=subprocess.PIPE, @@ -5490,8 +5592,70 @@ def test_dbus_ap(dev, apdev): if not t.success(): raise Exception("Expected signals not seen") +def test_dbus_ap_scan(dev, apdev): + """D-Bus AddNetwork for AP mode and scan""" + (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0]) + iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE) + + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + + hapd = hostapd.add_ap(apdev[0], {"ssid": "open"}) + bssid = hapd.own_addr() + + class TestDbusConnect(TestDbus): + def __init__(self, bus): + TestDbus.__init__(self, bus) + self.started = False + self.scan_completed = False + + def __enter__(self): + gobject.timeout_add(1, self.run_connect) + gobject.timeout_add(15000, self.timeout) + self.add_signal(self.propertiesChanged, WPAS_DBUS_IFACE, + "PropertiesChanged") + self.add_signal(self.scanDone, WPAS_DBUS_IFACE, "ScanDone") + self.loop.run() + return self + + def propertiesChanged(self, properties): + logger.debug("propertiesChanged: %s" % str(properties)) + if 'State' in properties and properties['State'] == "completed": + self.started = True + logger.info("Try to scan in AP mode") + iface.Scan({'Type': 'active', + 'Channels': [(dbus.UInt32(2412), dbus.UInt32(20))]}) + logger.info("Scan() returned") + + def scanDone(self, success): + logger.debug("scanDone: success=%s" % success) + if self.started: + self.scan_completed = True + self.loop.quit() + + def run_connect(self, *args): + logger.debug("run_connect") + args = dbus.Dictionary({'ssid': ssid, + 'key_mgmt': 'WPA-PSK', + 'psk': passphrase, + 'mode': 2, + 'frequency': 2412, + 'scan_freq': 2412}, + signature='sv') + self.netw = iface.AddNetwork(args) + iface.SelectNetwork(self.netw) + return False + + def success(self): + return self.started and self.scan_completed + + with TestDbusConnect(bus) as t: + if not t.success(): + raise Exception("Expected signals not seen") + def test_dbus_connect_wpa_eap(dev, apdev): """D-Bus AddNetwork and connection with WPA+WPA2-Enterprise AP""" + skip_without_tkip(dev[0]) (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0]) iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE) @@ -5859,3 +6023,71 @@ def test_dbus_mesh(dev, apdev): with TestDbusMesh(bus) as t: if not t.success(): raise Exception("Expected signals not seen") + +def test_dbus_roam(dev, apdev): + """D-Bus Roam""" + (bus, wpas_obj, path, if_obj) = prepare_dbus(dev[0]) + iface = dbus.Interface(if_obj, WPAS_DBUS_IFACE) + + ssid = "test-wpa2-psk" + passphrase = 'qwertyuiop' + params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase) + hapd = hostapd.add_ap(apdev[0], params) + hapd2 = hostapd.add_ap(apdev[1], params) + bssid = apdev[0]['bssid'] + dev[0].scan_for_bss(bssid, freq=2412) + bssid2 = apdev[1]['bssid'] + dev[0].scan_for_bss(bssid2, freq=2412) + + class TestDbusConnect(TestDbus): + def __init__(self, bus): + TestDbus.__init__(self, bus) + self.state = 0 + + def __enter__(self): + gobject.timeout_add(1, self.run_connect) + gobject.timeout_add(15000, self.timeout) + self.add_signal(self.propertiesChanged, WPAS_DBUS_IFACE, + "PropertiesChanged") + self.loop.run() + return self + + def propertiesChanged(self, properties): + logger.debug("propertiesChanged: %s" % str(properties)) + if 'State' in properties and properties['State'] == "completed": + if self.state == 0: + self.state = 1 + cur = properties["CurrentBSS"] + bss_obj = bus.get_object(WPAS_DBUS_SERVICE, cur) + res = bss_obj.Get(WPAS_DBUS_BSS, 'BSSID', + dbus_interface=dbus.PROPERTIES_IFACE) + bssid_str = '' + for item in res: + if len(bssid_str) > 0: + bssid_str += ':' + bssid_str += '%02x' % item + dst = bssid if bssid_str == bssid2 else bssid2 + iface.Roam(dst) + elif self.state == 1: + if "RoamComplete" in properties and \ + properties["RoamComplete"]: + self.state = 2 + self.loop.quit() + + def run_connect(self, *args): + logger.debug("run_connect") + args = dbus.Dictionary({'ssid': ssid, + 'key_mgmt': 'WPA-PSK', + 'psk': passphrase, + 'scan_freq': 2412}, + signature='sv') + self.netw = iface.AddNetwork(args) + iface.SelectNetwork(self.netw) + return False + + def success(self): + return self.state == 2 + + with TestDbusConnect(bus) as t: + if not t.success(): + raise Exception("Expected signals not seen") diff --git a/tests/hwsim/test_dfs.py b/tests/hwsim/test_dfs.py index a10d32b87..f1a1494bc 100644 --- a/tests/hwsim/test_dfs.py +++ b/tests/hwsim/test_dfs.py @@ -28,7 +28,8 @@ def wait_dfs_event(hapd, event, timeout): def start_dfs_ap(ap, ssid="dfs", ht=True, ht40=False, ht40minus=False, vht80=False, vht20=False, chanlist=None, - channel=None, country="FI", rrm_beacon_report=False): + channel=None, country="FI", rrm_beacon_report=False, + chan100=False): ifname = ap['ifname'] logger.info("Starting AP " + ifname + " on DFS channel") hapd = hostapd.add_ap(ap, {}, no_enable=True) @@ -37,7 +38,10 @@ def start_dfs_ap(ap, ssid="dfs", ht=True, ht40=False, hapd.set("ieee80211d", "1") hapd.set("ieee80211h", "1") hapd.set("hw_mode", "a") - hapd.set("channel", "52") + if chan100: + hapd.set("channel", "100") + else: + hapd.set("channel", "52") if not ht: hapd.set("ieee80211n", "0") if ht40: @@ -48,7 +52,10 @@ def start_dfs_ap(ap, ssid="dfs", ht=True, ht40=False, if vht80: hapd.set("ieee80211ac", "1") hapd.set("vht_oper_chwidth", "1") - hapd.set("vht_oper_centr_freq_seg0_idx", "58") + if chan100: + hapd.set("vht_oper_centr_freq_seg0_idx", "106") + else: + hapd.set("vht_oper_centr_freq_seg0_idx", "58") if vht20: hapd.set("ieee80211ac", "1") hapd.set("vht_oper_chwidth", "0") @@ -128,10 +135,9 @@ def test_dfs(dev, apdev): finally: clear_regdom(hapd, dev) -def test_dfs_etsi(dev, apdev, params): - """DFS and uniform spreading requirement for ETSI [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_dfs_etsi(dev, apdev): + """DFS and uniform spreading requirement for ETSI""" try: hapd = None hapd = start_dfs_ap(apdev[0]) @@ -443,10 +449,9 @@ def test_dfs_radar_ht40minus(dev, apdev): clear_regdom(hapd, dev) dev[0].request("STA_AUTOCONNECT 1") -def test_dfs_ht40_minus(dev, apdev, params): - """DFS CAC functionality on channel 104 HT40- [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_dfs_ht40_minus(dev, apdev): + """DFS CAC functionality on channel 104 HT40-""" try: hapd = None hapd = start_dfs_ap(apdev[0], ht40minus=True, channel=104) @@ -498,10 +503,9 @@ def test_dfs_cac_restart_on_enable(dev, apdev): finally: clear_regdom(hapd, dev) -def test_dfs_rrm(dev, apdev, params): - """DFS with RRM [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_dfs_rrm(dev, apdev): + """DFS with RRM""" try: hapd = None hapd = start_dfs_ap(apdev[0], country="US", rrm_beacon_report=True) @@ -526,3 +530,167 @@ def test_dfs_rrm(dev, apdev, params): raise Exception("Beacon report response not received") finally: clear_regdom(hapd, dev) + +@long_duration_test +def test_dfs_radar_vht80_downgrade(dev, apdev): + """DFS channel bandwidth downgrade from VHT80 to VHT40""" + try: + # Start with 80 MHz channel 100 (5500 MHz) to find a radar + hapd = None + hapd = start_dfs_ap(apdev[0], chanlist="100-140", + ht40=True, vht80=True, chan100=True) + time.sleep(1) + dfs_simulate_radar(hapd) + + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5) + if ev is None: + raise Exception("Timeout on DFS aborted event") + if "success=0 freq=5500" not in ev: + raise Exception("Unexpected DFS aborted event contents: " + ev) + + ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5) + if "freq=5500" not in ev: + raise Exception("Unexpected DFS radar detection freq: " + ev) + + # The only other available 80 MHz channel in the chanlist is + # 116 (5580 MHz), so that will be selected next. + ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5) + if "freq=5580 chan=116 sec_chan=1" not in ev: + raise Exception("Unexpected DFS new freq: " + ev) + + ev = wait_dfs_event(hapd, None, 5) + if "DFS-CAC-START" not in ev: + raise Exception("Unexpected DFS event: " + ev) + if "freq=5580" not in ev: + raise Exception("Unexpected DFS CAC freq: " + ev) + + time.sleep(1) + dfs_simulate_radar(hapd) + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 5) + if ev is None: + raise Exception("Timeout on DFS aborted event (2)") + if "success=0 freq=5580" not in ev: + raise Exception("Unexpected DFS aborted event (2) contents: " + ev) + + ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5) + if "freq=5580" not in ev: + raise Exception("Unexpected DFS radar detection (2) freq: " + ev) + + # No more 80 MHz channels are available, so have to downgrade to 40 MHz + # channels and the only remaining one is channel 132 (5660 MHz). + ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5) + if "freq=5660 chan=132 sec_chan=1" not in ev: + raise Exception("Unexpected DFS new freq (2): " + ev) + + ev = wait_dfs_event(hapd, None, 5) + if "DFS-CAC-START" not in ev: + raise Exception("Unexpected DFS event: " + ev) + if "freq=5660" not in ev: + raise Exception("Unexpected DFS CAC freq (2): " + ev) + + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) + if "success=1" not in ev: + raise Exception("CAC failed") + if "freq=5660" not in ev: + raise Exception("Unexpected DFS freq result: " + ev) + + ev = wait_dfs_event(hapd, None, 5) + if "AP-ENABLED" not in ev: + raise Exception("Unexpected DFS event: " + ev) + dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5660") + dev[0].wait_regdom(country_ie=True) + sig = dev[0].request("SIGNAL_POLL").splitlines() + if "FREQUENCY=5660" not in sig or "WIDTH=40 MHz" not in sig: + raise Exception("Unexpected SIGNAL_POLL value: " + str(sig)) + finally: + clear_regdom(hapd, dev) + +@long_duration_test +def test_dfs_chan_switch(dev, apdev): + """DFS channel switch""" + try: + hapd = None + hapd = start_dfs_ap(apdev[0], country="US") + + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) + if "success=1" not in ev: + raise Exception("CAC failed") + if "freq=5260" not in ev: + raise Exception("Unexpected DFS freq result") + ev = hapd.wait_event(["AP-ENABLED"], timeout=5) + if not ev: + raise Exception("AP setup timed out") + freq = hapd.get_status_field("freq") + if freq != "5260": + raise Exception("Unexpected frequency") + + dev[0].connect("dfs", key_mgmt="NONE", scan_freq="5260 5280") + dev[0].wait_regdom(country_ie=True) + hwsim_utils.test_connectivity(dev[0], hapd) + + if "OK" not in hapd.request("CHAN_SWITCH 5 5280 ht"): + raise Exception("CHAN_SWITCH failed") + # This results in BSS going down before restart, so the STA is expected + # to report disconnection. + dev[0].wait_disconnected() + ev = wait_dfs_event(hapd, "DFS-CAC-START", 5) + if "freq=5280" not in ev: + raise Exception("Unexpected channel: " + ev) + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) + if "success=1" not in ev: + raise Exception("CAC failed") + if "freq=5280" not in ev: + raise Exception("Unexpected DFS freq result") + ev = hapd.wait_event(["AP-ENABLED"], timeout=5) + if not ev: + raise Exception("AP setup timed out") + freq = hapd.get_status_field("freq") + if freq != "5280": + raise Exception("Unexpected frequency") + + dev[0].wait_connected(timeout=30) + hwsim_utils.test_connectivity(dev[0], hapd) + finally: + clear_regdom(hapd, dev) + +@long_duration_test +def test_dfs_no_available_channel(dev, apdev): + """DFS and no available channel after radar detection""" + try: + hapd = None + hapd = start_dfs_ap(apdev[0], chanlist="56") + + ev = hapd.wait_event(["AP-ENABLED"], timeout=70) + if not ev: + raise Exception("AP2 setup timed out") + + dfs_simulate_radar(hapd) + ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5) + if "freq=5260 ht_enabled=1 chan_offset=0 chan_width=1" not in ev: + raise Exception("Unexpected DFS radar detection freq from AP") + + ev = wait_dfs_event(hapd, "DFS-NEW-CHANNEL", 5) + if "freq=5280 chan=56" not in ev: + raise Exception("Unexpected DFS new freq: " + ev) + ev = wait_dfs_event(hapd, "DFS-CAC-START", 5) + if "freq=5280" not in ev: + raise Exception("Unexpected channel: " + ev) + ev = wait_dfs_event(hapd, "DFS-CAC-COMPLETED", 70) + if "success=1" not in ev: + raise Exception("CAC failed") + if "freq=5280" not in ev: + raise Exception("Unexpected DFS freq result") + ev = hapd.wait_event(["AP-ENABLED"], timeout=5) + if not ev: + raise Exception("AP setup timed out") + + dfs_simulate_radar(hapd) + ev = wait_dfs_event(hapd, "DFS-RADAR-DETECTED", 5) + if "freq=5280 ht_enabled=1 chan_offset=0 chan_width=1" not in ev: + raise Exception("Unexpected DFS radar detection freq from AP [2]") + + ev = hapd.wait_event(["AP-DISABLED"], timeout=10) + if ev is None: + raise Exception("AP was not disabled") + finally: + clear_regdom(hapd, dev) diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py index 46d29d4bd..5a9d1eeae 100644 --- a/tests/hwsim/test_dpp.py +++ b/tests/hwsim/test_dpp.py @@ -19,7 +19,7 @@ import time import hostapd import hwsim_utils from hwsim import HWSimRadio -from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger +from utils import * from wpasupplicant import WpaSupplicant from wlantest import WlantestCapture @@ -110,6 +110,33 @@ def test_dpp_qr_code_parsing(dev, apdev): dev[0].dpp_qr_code(uri) +def test_dpp_uri_version(dev, apdev): + """DPP URI version information""" + check_dpp_capab(dev[0], min_ver=2) + + id0 = dev[0].dpp_bootstrap_gen() + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + logger.info("Generated URI: " + uri) + + id1 = dev[0].dpp_qr_code(uri) + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1) + info = dev[0].request("DPP_BOOTSTRAP_INFO %d" % id1) + logger.info("Parsed URI info:\n" + info) + if "version=2" not in info.splitlines(): + raise Exception("Unexpected version information (v2)") + + dev[0].set("dpp_version_override", "1") + id0 = dev[0].dpp_bootstrap_gen() + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + logger.info("Generated URI: " + uri) + + id1 = dev[0].dpp_qr_code(uri) + uri = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id1) + info = dev[0].request("DPP_BOOTSTRAP_INFO %d" % id1) + logger.info("Parsed URI info:\n" + info) + if "version=0" not in info.splitlines(): + raise Exception("Unexpected version information (without indication)") + def test_dpp_qr_code_parsing_fail(dev, apdev): """DPP QR Code parsing local failure""" check_dpp_capab(dev[0]) @@ -276,6 +303,34 @@ def test_dpp_configurator_enrollee_brainpoolP512r1(dev, apdev): """DPP Configurator enrolling (brainpoolP512r1)""" run_dpp_configurator_enrollee(dev, apdev, conf_curve="brainpoolP512r1") +def test_dpp_configurator_enroll_conf(dev, apdev): + """DPP Configurator enrolling followed by use of the new Configurator""" + try: + dev[0].set("dpp_config_processing", "2") + run_dpp_configurator_enroll_conf(dev, apdev) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def run_dpp_configurator_enroll_conf(dev, apdev): + run_dpp_qr_code_auth_unicast(dev, apdev, None, netrole="configurator", + configurator=True, conf="configurator", + qr="mutual", stop_responder=False) + ev = dev[0].wait_event(["DPP-CONFIGURATOR-ID"], timeout=2) + if ev is None: + raise Exception("No Configurator instance added") + dev[1].reset() + dev[0].dump_monitor() + + ssid = "test-network" + passphrase = "test-passphrase" + dev[0].set("dpp_configurator_params", + "conf=sta-psk ssid=%s pass=%s" % (binascii.hexlify(ssid.encode()).decode(), binascii.hexlify(passphrase.encode()).decode())) + dev[0].dpp_listen(2412, role="configurator") + id0 = dev[0].dpp_bootstrap_gen(chan="81/1") + uri0 = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id0) + dev[1].dpp_auth_init(uri=uri0, role="enrollee") + wait_auth_success(dev[0], dev[1], configurator=dev[0], enrollee=dev[1]) + def test_dpp_qr_code_curve_prime256v1(dev, apdev): """DPP QR Code and curve prime256v1""" run_dpp_qr_code_auth_unicast(dev, apdev, "prime256v1") @@ -308,7 +363,7 @@ 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): + conf=None, qr=None, stop_responder=True): check_dpp_capab(dev[0], curve and "brainpool" in curve) check_dpp_capab(dev[1], curve and "brainpool" in curve) if configurator: @@ -316,19 +371,27 @@ def run_dpp_qr_code_auth_unicast(dev, apdev, curve, netrole=None, key=None, else: conf_id = None + if qr == "mutual": + logger.info("dev1 displays QR Code and dev0 scans it") + id1 = dev[1].dpp_bootstrap_gen(chan="81/1", mac=True, curve=curve) + uri1 = dev[1].request("DPP_BOOTSTRAP_GET_URI %d" % id1) + id1c = dev[0].dpp_qr_code(uri1) + else: + id1 = 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[0].dpp_listen(2412, netrole=netrole, qr=qr) dev[1].dpp_auth_init(uri=uri0, extra=init_extra, configurator=conf_id, - conf=conf) + conf=conf, own=id1) 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) + stop_responder=stop_responder) def test_dpp_qr_code_auth_mutual(dev, apdev): """DPP QR Code and authentication exchange (mutual)""" @@ -1420,7 +1483,7 @@ def run_dpp_akm(dev, apdev, pmk_len): raise HwsimSkip("DPP not supported") id = dev[0].connect("dpp", key_mgmt="DPP", ieee80211w="2", scan_freq="2412", - wait_connect=False) + 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") @@ -1770,7 +1833,36 @@ def test_dpp_auto_connect_2_connect_cmd(dev, apdev): finally: wpas.set("dpp_config_processing", "0", allow_fail=True) -def run_dpp_auto_connect(dev, apdev, processing): +def test_dpp_auto_connect_2_sta_ver1(dev, apdev): + """DPP and auto connect (2; STA using ver 1)""" + try: + run_dpp_auto_connect(dev, apdev, 2, sta_version=1) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def test_dpp_auto_connect_2_ap_ver1(dev, apdev): + """DPP and auto connect (2; AP using ver 1)""" + try: + run_dpp_auto_connect(dev, apdev, 2, ap_version=1) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def test_dpp_auto_connect_2_ver1(dev, apdev): + """DPP and auto connect (2; AP and STA using ver 1)""" + try: + run_dpp_auto_connect(dev, apdev, 2, ap_version=1, sta_version=1) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def test_dpp_auto_connect_2_conf_ver1(dev, apdev): + """DPP and auto connect (2; Configurator using ver 1)""" + try: + run_dpp_auto_connect(dev, apdev, 2, sta1_version=1) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def run_dpp_auto_connect(dev, apdev, processing, ap_version=0, sta_version=0, + sta1_version=0): check_dpp_capab(dev[0]) check_dpp_capab(dev[1]) @@ -1789,9 +1881,15 @@ def run_dpp_auto_connect(dev, apdev, processing): "dpp_netaccesskey": ap_netaccesskey} try: hapd = hostapd.add_ap(apdev[0], params) + if ap_version: + hapd.set("dpp_version_override", str(ap_version)) except: raise HwsimSkip("DPP not supported") + if sta_version: + dev[0].set("dpp_version_override", str(sta_version)) + if sta1_version: + dev[1].set("dpp_version_override", str(sta1_version)) 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) @@ -2465,6 +2563,30 @@ def test_dpp_hostapd_configurator_responder(dev, apdev): wait_auth_success(hapd, dev[0], configurator=hapd, enrollee=dev[0], stop_initiator=True) +def test_dpp_hostapd_configurator_fragmentation(dev, apdev): + """DPP with hostapd as configurator/initiator requiring fragmentation""" + 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) + conf = '{"wi-fi_tech":"infra", "discovery":{"ssid":"test"},"cred":{"akm":"psk","pass":"secret passphrase"}}' + 3000*' ' + hapd.set("dpp_config_obj_override", conf) + 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_own_config(dev, apdev): """DPP configurator signing own connector""" try: @@ -3657,8 +3779,8 @@ def test_dpp_pkex_test_fail(dev, apdev): (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_derive_bk_ke;dpp_auth_resp_rx"), + (1, "dpp_hkdf_expand;dpp_derive_bk_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"), @@ -3693,7 +3815,7 @@ def test_dpp_pkex_test_fail(dev, apdev): (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_derive_bk_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"), @@ -4152,7 +4274,7 @@ def test_dpp_peer_intro_local_failures(dev, apdev): 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_check_signed_connector;dpp_peer_intro"), (1, "dpp_parse_jwk")] for count, func in tests: with alloc_fail(dev[0], count, func): @@ -4571,10 +4693,20 @@ def test_dpp_controller_relay(dev, apdev, params): dev[0].set("dpp_config_processing", "0", allow_fail=True) dev[1].request("DPP_CONTROLLER_STOP") -def run_dpp_controller_relay(dev, apdev, params): - check_dpp_capab(dev[0]) - check_dpp_capab(dev[1]) +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], min_ver=2) + check_dpp_capab(dev[1], min_ver=2) prefix = "dpp_controller_relay" + if chirp: + prefix += "_chirp" cap_lo = os.path.join(params['logdir'], prefix + ".lo.pcap") wt = WlantestCapture('lo', cap_lo) @@ -4582,7 +4714,7 @@ def run_dpp_controller_relay(dev, apdev, params): # Controller conf_id = dev[1].dpp_configurator_add() dev[1].set("dpp_configurator_params", - " conf=sta-dpp configurator=%d" % conf_id) + "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) @@ -4601,23 +4733,61 @@ def run_dpp_controller_relay(dev, apdev, params): 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 - id_h = relay.dpp_bootstrap_gen(chan="81/6", mac=True) + 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 + # Initiate from Enrollee with broadcast DPP Authentication Request or + # using chirping dev[0].set("dpp_config_processing", "2") - dev[0].dpp_auth_init(uri=uri_c, role="enrollee") + 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) + ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1) + if ev is None: + raise Exception("DPP network id not reported") + network = int(ev.split(' ')[1]) + dev[0].wait_connected() + dev[0].dump_monitor() + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].dump_monitor() + + if "OK" not in dev[0].request("DPP_RECONFIG %s" % network): + raise Exception("Failed to start reconfiguration") + ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=15) + if ev is None: + raise Exception("DPP network id not reported for reconfiguration") + network2 = int(ev.split(' ')[1]) + if network == network2: + raise Exception("Network ID did not change") dev[0].wait_connected() time.sleep(0.5) @@ -4628,7 +4798,7 @@ def test_dpp_tcp(dev, apdev, params): prefix = "dpp_tcp" cap_lo = os.path.join(params['logdir'], prefix + ".lo.pcap") try: - run_dpp_tcp(dev, apdev, cap_lo) + run_dpp_tcp(dev[0], dev[1], cap_lo) finally: dev[1].request("DPP_CONTROLLER_STOP") @@ -4637,24 +4807,38 @@ def test_dpp_tcp_port(dev, apdev, params): prefix = "dpp_tcp_port" cap_lo = os.path.join(params['logdir'], prefix + ".lo.pcap") try: - run_dpp_tcp(dev, apdev, cap_lo, port="23456") + run_dpp_tcp(dev[0], dev[1], 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]) +def test_dpp_tcp_mutual(dev, apdev, params): + """DPP over TCP (mutual)""" + cap_lo = os.path.join(params['prefix'], ".lo.pcap") + try: + run_dpp_tcp(dev[0], dev[1], cap_lo, mutual=True) + finally: + dev[1].request("DPP_CONTROLLER_STOP") + +def test_dpp_tcp_mutual_hostapd_conf(dev, apdev, params): + """DPP over TCP (mutual, hostapd as Configurator)""" + cap_lo = os.path.join(params['prefix'], ".lo.pcap") + hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"}) + run_dpp_tcp(dev[0], hapd, cap_lo, mutual=True) + +def run_dpp_tcp(dev0, dev1, cap_lo, port=None, mutual=False): + check_dpp_capab(dev0) + check_dpp_capab(dev1) 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) + conf_id = dev1.dpp_configurator_add() + dev1.set("dpp_configurator_params", + " conf=sta-dpp configurator=%d" % conf_id) + id_c = dev1.dpp_bootstrap_gen() + uri_c = dev1.request("DPP_BOOTSTRAP_GET_URI %d" % id_c) + res = dev1.request("DPP_BOOTSTRAP_INFO %d" % id_c) pkhash = None for line in res.splitlines(): name, value = line.split('=') @@ -4666,13 +4850,77 @@ def run_dpp_tcp(dev, apdev, cap_lo, port=None): req = "DPP_CONTROLLER_START" if port: req += " tcp_port=" + port - if "OK" not in dev[1].request(req): + if mutual: + req += " qr=mutual" + id0 = dev0.dpp_bootstrap_gen() + uri0 = dev0.request("DPP_BOOTSTRAP_GET_URI %d" % id0) + own = id0 + else: + own = None + if "OK" not in dev1.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], + dev0.dpp_auth_init(uri=uri_c, own=own, role="enrollee", + tcp_addr="127.0.0.1", tcp_port=port) + + if mutual: + ev = dev0.wait_event(["DPP-RESPONSE-PENDING"], timeout=5) + if ev is None: + raise Exception("Pending response not reported") + ev = dev1.wait_event(["DPP-SCAN-PEER-QR-CODE"], timeout=5) + if ev is None: + raise Exception("QR Code scan for mutual authentication not requested") + + id1 = dev1.dpp_qr_code(uri0) + + ev = dev0.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(dev1, dev0, configurator=dev1, enrollee=dev0, + allow_enrollee_failure=True, + allow_configurator_failure=True) + time.sleep(0.5) + wt.close() + +def test_dpp_tcp_conf_init(dev, apdev, params): + """DPP over TCP (Configurator initiates)""" + cap_lo = os.path.join(params['prefix'], ".lo.pcap") + try: + run_dpp_tcp_conf_init(dev[0], dev[1], cap_lo) + finally: + dev[1].request("DPP_CONTROLLER_STOP") + +def test_dpp_tcp_conf_init_hostapd_enrollee(dev, apdev, params): + """DPP over TCP (Configurator initiates, hostapd as Enrollee)""" + cap_lo = os.path.join(params['prefix'], ".lo.pcap") + hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"}) + run_dpp_tcp_conf_init(dev[0], hapd, cap_lo, conf="ap-dpp") + +def run_dpp_tcp_conf_init(dev0, dev1, cap_lo, port=None, conf="sta-dpp"): + check_dpp_capab(dev0, min_ver=2) + check_dpp_capab(dev1, min_ver=2) + + wt = WlantestCapture('lo', cap_lo) + time.sleep(1) + + id_c = dev1.dpp_bootstrap_gen() + uri_c = dev1.request("DPP_BOOTSTRAP_GET_URI %d" % id_c) + res = dev1.request("DPP_BOOTSTRAP_INFO %d" % id_c) + req = "DPP_CONTROLLER_START role=enrollee" + if port: + req += " tcp_port=" + port + if "OK" not in dev1.request(req): + raise Exception("Failed to start Controller") + + conf_id = dev0.dpp_configurator_add() + dev0.dpp_auth_init(uri=uri_c, role="configurator", conf=conf, + configurator=conf_id, + tcp_addr="127.0.0.1", tcp_port=port) + wait_auth_success(dev1, dev0, configurator=dev0, enrollee=dev1, allow_enrollee_failure=True, allow_configurator_failure=True) time.sleep(0.5) @@ -4732,7 +4980,7 @@ def run_dpp_controller_rx_failure(dev, apdev): "eloop_sock_table_add_sock;?eloop_register_sock;dpp_controller_tcp_cb", "dpp_controller_rx", "dpp_controller_rx_auth_req", - "wpabuf_alloc;=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): @@ -4753,7 +5001,7 @@ 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) + addr = ("127.0.0.1", 8908) tests = [b"abc", b"abcd", @@ -5039,3 +5287,817 @@ def test_dpp_with_p2p_device(dev, apdev): 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)) + ev = hapd.wait_event(["DPP-CHIRP-RX"], timeout=1) + if ev is None: + raise Exception("No chirp received on the AP") + if "freq=2462" not in ev: + raise Exception("Chirp reception reported on unexpected channel: " + ev) + if "src=" + dev[0].own_addr() not in ev: + raise Exception("Unexpected chirp source reported: " + ev) + +@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 test_dpp_chirp_ap(dev, apdev): + """DPP chirp by an AP""" + check_dpp_capab(dev[0], min_ver=2) + + hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured", + "start_disabled": "1"}) + check_dpp_capab(hapd, min_ver=2) + + 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() + idc = dev[0].dpp_qr_code(uri) + dev[0].dpp_bootstrap_set(idc, conf="ap-dpp", configurator=conf_id) + dev[0].dpp_listen(2437) + if "OK" not in hapd.request("DPP_CHIRP own=%d iter=5" % id_h): + raise Exception("DPP_CHIRP failed") + wait_auth_success(hapd, dev[0], configurator=dev[0], enrollee=hapd, + timeout=20) + update_hapd_config(hapd) + +def start_dpp_pfs_ap(apdev, pfs, sae=False): + 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} + if sae: + params["wpa_key_mgmt"] = "DPP SAE" + params["sae_password"] = "sae-password" + 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, sae=False): + key_mgmt = "DPP SAE" if sae else "DPP" + psk = "sae-password" if sae else None + dev.connect("dpp", key_mgmt=key_mgmt, scan_freq="2412", + ieee80211w="2", dpp_pfs=str(pfs), + dpp_csign=params1_csign, + dpp_connector=params1_sta_connector, + dpp_netaccesskey=params1_sta_netaccesskey, + psk=psk, + 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_pfs_connect_cmd_ap_2(dev, apdev): + """DPP PFS and cfg80211 connect command (PFS not allowed by AP)""" + 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], 2) + run_dpp_pfs_sta(wpas, 0, pfs_expected=False) + run_dpp_pfs_sta(wpas, 1, fail=True) + run_dpp_pfs_sta(wpas, 2, pfs_expected=False) + +def test_dpp_pfs_connect_cmd_ap_2_sae(dev, apdev): + """DPP PFS and cfg80211 connect command (PFS not allowed by AP; SAE enabled)""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") + check_dpp_capab(wpas) + if "SAE" not in wpas.get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + hapd = start_dpp_pfs_ap(apdev[0], 2, sae=True) + run_dpp_pfs_sta(wpas, 0, pfs_expected=False, sae=True) + run_dpp_pfs_sta(wpas, 1, fail=True, sae=True) + run_dpp_pfs_sta(wpas, 2, pfs_expected=False, sae=True) + +def test_dpp_pfs_ap_0_sta_ver1(dev, apdev): + """DPP PFS AP default with version 1 STA""" + check_dpp_capab(dev[0]) + dev[0].set("dpp_version_override", "1") + hapd = start_dpp_pfs_ap(apdev[0], 0) + run_dpp_pfs_sta(dev[0], 0, 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 test_dpp_reconfig_connector_different_groups(dev, apdev): + """DPP reconfiguration connector with different groups""" + try: + run_dpp_reconfig_connector(dev, apdev, conf_curve="secp384r1") + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +@long_duration_test +def test_dpp_reconfig_retries(dev, apdev): + """DPP reconfiguration retries""" + try: + run_dpp_reconfig_connector(dev, apdev, test_retries=True) + for i in range(4): + ev = dev[0].wait_event(["DPP-TX "], timeout=120) + if ev is None or "type=14" not in ev: + raise Exception("Reconfig Announcement not sent") + dev[0].request("DPP_STOP_LISTEN") + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def run_dpp_reconfig_connector(dev, apdev, conf_curve=None, + test_retries=False): + check_dpp_capab(dev[0], min_ver=2) + check_dpp_capab(dev[1], min_ver=2) + + ssid = "reconfig" + passphrase = "secret passphrase" + passphrase2 = "another 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(curve=conf_curve) + conf = 'sta-psk' + dev[1].dpp_auth_init(uri=uri0, conf=conf, ssid=ssid, + 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") + ev = dev[1].wait_event(["DPP-CONN-STATUS-RESULT"], timeout=20) + if ev is None: + raise Exception("No connection status reported") + dev[1].dump_monitor() + + 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)) + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + + hapd.disable() + hapd.set("wpa_passphrase", passphrase2) + hapd.enable() + + time.sleep(0.1) + dev[0].dump_monitor() + dev[1].dump_monitor() + + if test_retries: + dev[1].request("DPP_STOP_LISTEN") + if "OK" not in dev[0].request("DPP_RECONFIG %s iter=10" % id): + raise Exception("Failed to start reconfiguration") + return + + dev[1].set("dpp_configurator_params", + "conf=sta-psk ssid=%s pass=%s conn_status=1" % (binascii.hexlify(ssid.encode()).decode(), binascii.hexlify(passphrase2.encode()).decode())) + dev[1].dpp_listen(2437) + + if "OK" not in dev[0].request("DPP_RECONFIG %s" % id): + raise Exception("Failed to start reconfiguration") + ev = dev[0].wait_event(["DPP-TX "], timeout=10) + if ev is None or "type=14" not in ev: + raise Exception("Reconfig Announcement not sent") + + ev = dev[1].wait_event(["DPP-RX"], timeout=5) + if ev is None: + raise Exception("DPP Reconfig Announcement not received") + if "freq=2437 type=14" not in ev: + raise Exception("Unexpected RX data for Reconfig Announcement: " + ev) + + ev = dev[0].wait_event(["DPP-RX"], timeout=5) + if ev is None or "freq=2437 type=15" not in ev: + raise Exception("DPP Reconfig Authentication Request not received") + + ev = dev[1].wait_event(["DPP-RX"], timeout=5) + if ev is None or "freq=2437 type=16" not in ev: + raise Exception("DPP Reconfig Authentication Response not received") + + ev = dev[0].wait_event(["DPP-RX"], timeout=5) + if ev is None or "freq=2437 type=17" not in ev: + raise Exception("DPP Reconfig Authentication Confirm not received") + + ev = dev[0].wait_event(["GAS-QUERY-START"], timeout=5) + if ev is None or "freq=2437" not in ev: + raise Exception("DPP Config Request (GAS) not transmitted") + + ev = dev[1].wait_event(["DPP-CONF-REQ-RX"], timeout=5) + if ev is None: + raise Exception("DPP Config Request (GAS) not received") + + ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=5) + if ev is None or "freq=2437" not in ev: + raise Exception("DPP Config Response (GAS) not received") + + ev = dev[1].wait_event(["DPP-RX"], timeout=5) + if ev is None or "freq=2437 type=11" not in ev: + raise Exception("DPP Config Result not received") + + ev = dev[1].wait_event(["DPP-CONF-SENT"], timeout=5) + if ev is None: + raise Exception("DPP Config Response (GAS) not transmitted") + + ev = dev[0].wait_event(["DPP-CONF-RECEIVED", "DPP-CONF-FAILED"], timeout=5) + if ev is None: + raise Exception("DPP config response reception result not indicated") + if "DPP-CONF-RECEIVED" not in ev: + raise Exception("Reconfiguration failed") + + dev[0].wait_connected() + + ev = dev[1].wait_event(["DPP-CONN-STATUS-RESULT"], timeout=20) + if ev is None: + raise Exception("No connection status reported") + +def test_dpp_reconfig_hostapd_configurator(dev, apdev): + """DPP reconfiguration with hostapd as configurator""" + try: + run_dpp_reconfig_hostapd_configurator(dev, apdev) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def run_dpp_reconfig_hostapd_configurator(dev, apdev): + ssid = "reconfig-ap" + check_dpp_capab(dev[0], min_ver=2) + hapd = hostapd.add_ap(apdev[0], {"ssid": "unconfigured"}) + check_dpp_capab(hapd, min_ver=2) + conf_id = hapd.dpp_configurator_add() + + cmd = "DPP_CONFIGURATOR_SIGN conf=ap-dpp configurator=%d ssid=%s" % (conf_id, binascii.hexlify(ssid.encode()).decode()) + res = hapd.request(cmd) + if "FAIL" in res: + raise Exception("Failed to generate own configuration") + hapd.set("dpp_configurator_connectivity", "1") + update_hapd_config(hapd) + + 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="expiry=%d" % (time.time() + 10), ssid=ssid) + wait_auth_success(dev[0], hapd, configurator=hapd, enrollee=dev[0]) + ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=1) + if ev is None: + raise Exception("DPP network id not reported") + network = int(ev.split(' ')[1]) + dev[0].wait_connected() + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].dump_monitor() + time.sleep(10) + if "FAIL" in dev[0].request("PMKSA_FLUSH"): + raise Exception("PMKSA_FLUSH failed") + dev[0].request("RECONNECT") + ev = dev[0].wait_event(["DPP-MISSING-CONNECTOR", "CTRL-EVENT-CONNECTED"], + timeout=15) + if ev is None or "DPP-MISSING-CONNECTOR" not in ev: + raise Exception("Missing Connector not reported") + if "netAccessKey expired" not in ev: + raise Exception("netAccessKey expiry not indicated") + dev[0].request("DISCONNECT") + dev[0].dump_monitor() + + hapd.set("dpp_configurator_params", + "conf=sta-dpp configurator=%d ssid=%s" % (conf_id, binascii.hexlify(ssid.encode()).decode())) + + if "OK" not in dev[0].request("DPP_RECONFIG %s" % network): + raise Exception("Failed to start reconfiguration") + ev = dev[0].wait_event(["DPP-NETWORK-ID"], timeout=15) + if ev is None: + raise Exception("DPP network id not reported for reconfiguration") + network2 = int(ev.split(' ')[1]) + if network == network2: + raise Exception("Network ID did not change") + dev[0].wait_connected() + +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") + +def dpp_sign_cert(cacert, cakey, csr_der): + csr = OpenSSL.crypto.load_certificate_request(OpenSSL.crypto.FILETYPE_ASN1, + csr_der) + cert = OpenSSL.crypto.X509() + cert.set_serial_number(12345) + cert.gmtime_adj_notBefore(-10) + cert.gmtime_adj_notAfter(100000) + cert.set_pubkey(csr.get_pubkey()) + dn = csr.get_subject() + cert.set_subject(dn) + cert.set_version(2) + cert.add_extensions([ + OpenSSL.crypto.X509Extension(b"basicConstraints", True, + b"CA:FALSE"), + OpenSSL.crypto.X509Extension(b"subjectKeyIdentifier", False, + b"hash", subject=cert), + OpenSSL.crypto.X509Extension(b"authorityKeyIdentifier", False, + b"keyid:always", issuer=cacert), + ]) + cert.set_issuer(cacert.get_subject()) + cert.sign(cakey, "sha256") + return cert + +def test_dpp_enterprise(dev, apdev, params): + """DPP and enterprise EAP-TLS provisioning""" + try: + dev[0].set("dpp_config_processing", "2") + run_dpp_enterprise(dev, apdev, params) + finally: + dev[0].set("dpp_config_processing", "0", allow_fail=True) + +def run_dpp_enterprise(dev, apdev, params): + if not openssl_imported: + raise HwsimSkip("OpenSSL python method not available") + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + + cert_file = params['prefix'] + ".cert.pem" + pkcs7_file = params['prefix'] + ".pkcs7.der" + + params = {"ssid": "dpp-ent", + "wpa": "2", + "wpa_key_mgmt": "WPA-EAP", + "rsn_pairwise": "CCMP", + "ieee8021x": "1", + "eap_server": "1", + "eap_user_file": "auth_serv/eap_user.conf", + "ca_cert": "auth_serv/ec-ca.pem", + "server_cert": "auth_serv/ec-server.pem", + "private_key": "auth_serv/ec-server.key"} + hapd = hostapd.add_ap(apdev[0], params) + + with open("auth_serv/ec-ca.pem", "rb") as f: + res = f.read() + cacert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, + res) + + with open("auth_serv/ec-ca.key", "rb") as f: + res = f.read() + cakey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, res) + + conf_id = dev[1].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].dpp_listen(2412) + csrattrs = "MAsGCSqGSIb3DQEJBw==" + id1 = dev[1].dpp_auth_init(uri=uri0, configurator=conf_id, conf="sta-dot1x", + csrattrs=csrattrs, ssid="dpp-ent") + + ev = dev[1].wait_event(["DPP-CSR"], timeout=10) + if ev is None: + raise Exception("Configurator did not receive CSR") + id1_csr = int(ev.split(' ')[1].split('=')[1]) + if id1 != id1_csr: + raise Exception("Peer bootstrapping ID mismatch in CSR event") + csr = ev.split(' ')[2] + if not csr.startswith("csr="): + raise Exception("Could not parse CSR event: " + ev) + csr = csr[4:] + csr = base64.b64decode(csr.encode()) + logger.info("CSR: " + binascii.hexlify(csr).decode()) + + cert = dpp_sign_cert(cacert, cakey, csr) + with open(cert_file, 'wb') as f: + f.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, + cert)) + subprocess.check_call(['openssl', 'crl2pkcs7', '-nocrl', + '-certfile', cert_file, + '-certfile', 'auth_serv/ec-ca.pem', + '-outform', 'DER', '-out', pkcs7_file]) + + #caCert = base64.b64encode(b"TODO").decode() + #res = dev[1].request("DPP_CA_SET peer=%d name=caCert value=%s" % (id1, caCert)) + #if "OK" not in res: + # raise Exception("Failed to set caCert") + + name = "server.w1.fi" + res = dev[1].request("DPP_CA_SET peer=%d name=trustedEapServerName value=%s" % (id1, name)) + if "OK" not in res: + raise Exception("Failed to set trustedEapServerName") + + with open(pkcs7_file, 'rb') as f: + pkcs7_der = f.read() + certbag = base64.b64encode(pkcs7_der).decode() + res = dev[1].request("DPP_CA_SET peer=%d name=certBag value=%s" % (id1, certbag)) + if "OK" not in res: + raise Exception("Failed to set certBag") + + ev = dev[1].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: + raise Exception("DPP configuration did not succeed (Configurator)") + + ev = dev[0].wait_event(["DPP-CONF-RECEIVED", "DPP-CONF-FAILED"], + timeout=1) + if ev is None: + raise Exception("DPP configuration not completed (Enrollee)") + if "DPP-CONF-FAILED" in ev: + raise Exception("DPP configuration did not succeed (Enrollee)") + + ev = dev[0].wait_event(["DPP-CERTBAG"], timeout=1) + if ev is None: + raise Exception("DPP-CERTBAG not reported") + certbag = base64.b64decode(ev.split(' ')[1].encode()) + if certbag != pkcs7_der: + raise Exception("DPP-CERTBAG mismatch") + + #ev = dev[0].wait_event(["DPP-CACERT"], timeout=1) + #if ev is None: + # raise Exception("DPP-CACERT not reported") + + ev = dev[0].wait_event(["DPP-SERVER-NAME"], timeout=1) + if ev is None: + raise Exception("DPP-SERVER-NAME not reported") + if ev.split(' ')[1] != name: + raise Exception("DPP-SERVER-NAME mismatch: " + 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_enterprise_reject(dev, apdev, params): + """DPP and enterprise EAP-TLS provisioning and CSR getting rejected""" + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + + conf_id = dev[1].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].dpp_listen(2412) + csrattrs = "MAsGCSqGSIb3DQEJBw==" + id1 = dev[1].dpp_auth_init(uri=uri0, configurator=conf_id, conf="sta-dot1x", + csrattrs=csrattrs, ssid="dpp-ent") + + ev = dev[1].wait_event(["DPP-CSR"], timeout=10) + if ev is None: + raise Exception("Configurator did not receive CSR") + + res = dev[1].request("DPP_CA_SET peer=%d name=status value=5" % id1) + if "OK" not in res: + raise Exception("Failed to set status") + + ev = dev[1].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: + raise Exception("DPP configuration did not succeed (Configurator)") + + ev = dev[0].wait_event(["DPP-CONF-RECEIVED", "DPP-CONF-FAILED"], + timeout=1) + if ev is None: + raise Exception("DPP configuration not completed (Enrollee)") + if "DPP-CONF-FAILED" not in ev: + raise Exception("DPP configuration did not fail (Enrollee)") + +def test_dpp_enterprise_tcp(dev, apdev, params): + """DPP over TCP for enterprise provisioning""" + if not openssl_imported: + raise HwsimSkip("OpenSSL python method not available") + + try: + run_dpp_enterprise_tcp(dev, apdev, params) + finally: + dev[1].request("DPP_CONTROLLER_STOP") + +def run_dpp_enterprise_tcp(dev, apdev, params): + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + + cap_lo = params['prefix'] + ".lo.pcap" + + wt = WlantestCapture('lo', cap_lo) + time.sleep(1) + + # Controller + conf_id = dev[1].dpp_configurator_add() + csrattrs = "MAsGCSqGSIb3DQEJBw==" + dev[1].set("dpp_configurator_params", + "conf=sta-dot1x configurator=%d csrattrs=%s" % (conf_id, csrattrs)) + 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) + req = "DPP_CONTROLLER_START" + if "OK" not in dev[1].request(req): + raise Exception("Failed to start Controller") + + dev[0].dpp_auth_init(uri=uri_c, role="enrollee", tcp_addr="127.0.0.1") + run_dpp_enterprise_tcp_end(params, dev, wt) + +def run_dpp_enterprise_tcp_end(params, dev, wt): + cert_file = params['prefix'] + ".cert.pem" + pkcs7_file = params['prefix'] + ".pkcs7.der" + + with open("auth_serv/ec-ca.pem", "rb") as f: + res = f.read() + cacert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, + res) + + with open("auth_serv/ec-ca.key", "rb") as f: + res = f.read() + cakey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, res) + + ev = dev[1].wait_event(["DPP-CSR"], timeout=10) + if ev is None: + raise Exception("Configurator did not receive CSR") + id1_csr = int(ev.split(' ')[1].split('=')[1]) + csr = ev.split(' ')[2] + if not csr.startswith("csr="): + raise Exception("Could not parse CSR event: " + ev) + csr = csr[4:] + csr = base64.b64decode(csr.encode()) + logger.info("CSR: " + binascii.hexlify(csr).decode()) + + cert = dpp_sign_cert(cacert, cakey, csr) + with open(cert_file, 'wb') as f: + f.write(OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, + cert)) + subprocess.check_call(['openssl', 'crl2pkcs7', '-nocrl', + '-certfile', cert_file, + '-certfile', 'auth_serv/ec-ca.pem', + '-outform', 'DER', '-out', pkcs7_file]) + + with open(pkcs7_file, 'rb') as f: + pkcs7_der = f.read() + certbag = base64.b64encode(pkcs7_der).decode() + res = dev[1].request("DPP_CA_SET peer=%d name=certBag value=%s" % (id1_csr, certbag)) + if "OK" not in res: + raise Exception("Failed to set certBag") + + ev = dev[1].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: + raise Exception("DPP configuration did not succeed (Configurator)") + + ev = dev[0].wait_event(["DPP-CONF-RECEIVED", "DPP-CONF-FAILED"], + timeout=1) + if ev is None: + raise Exception("DPP configuration not completed (Enrollee)") + if "DPP-CONF-RECEIVED" not in ev: + raise Exception("DPP configuration did not succeed (Enrollee)") + + time.sleep(0.5) + wt.close() + +def test_dpp_enterprise_tcp2(dev, apdev, params): + """DPP over TCP for enterprise provisioning (Controller initiating)""" + if not openssl_imported: + raise HwsimSkip("OpenSSL python method not available") + + try: + run_dpp_enterprise_tcp2(dev, apdev, params) + finally: + dev[0].request("DPP_CONTROLLER_STOP") + dev[1].request("DPP_CONTROLLER_STOP") + +def run_dpp_enterprise_tcp2(dev, apdev, params): + check_dpp_capab(dev[0]) + check_dpp_capab(dev[1]) + + cap_lo = params['prefix'] + ".lo.pcap" + cert_file = params['prefix'] + ".cert.pem" + pkcs7_file = params['prefix'] + ".pkcs7.der" + + with open("auth_serv/ec-ca.pem", "rb") as f: + res = f.read() + cacert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, + res) + + with open("auth_serv/ec-ca.key", "rb") as f: + res = f.read() + cakey = OpenSSL.crypto.load_privatekey(OpenSSL.crypto.FILETYPE_PEM, res) + + wt = WlantestCapture('lo', cap_lo) + time.sleep(1) + + # Client/Enrollee/Responder + id_e = dev[0].dpp_bootstrap_gen() + uri_e = dev[0].request("DPP_BOOTSTRAP_GET_URI %d" % id_e) + req = "DPP_CONTROLLER_START" + if "OK" not in dev[0].request(req): + raise Exception("Failed to start Client/Enrollee") + + # Controller/Configurator/Initiator + conf_id = dev[1].dpp_configurator_add() + csrattrs = "MAsGCSqGSIb3DQEJBw==" + dev[1].dpp_auth_init(uri=uri_e, role="configurator", configurator=conf_id, + conf="sta-dot1x", csrattrs=csrattrs, + tcp_addr="127.0.0.1") + + run_dpp_enterprise_tcp_end(params, dev, wt) diff --git a/tests/hwsim/test_eap.py b/tests/hwsim/test_eap.py index f1bf904bd..144e4d314 100644 --- a/tests/hwsim/test_eap.py +++ b/tests/hwsim/test_eap.py @@ -574,3 +574,29 @@ def test_eap_teap_eap_vendor(dev, apdev): anonymous_identity="TEAP", ca_cert="auth_serv/ca.pem", phase2="auth=VENDOR-TEST", pac_file="blob://teap_pac") + +def test_eap_teap_client_cert(dev, apdev): + """EAP-TEAP with client certificate in Phase 1""" + check_eap_capa(dev[0], "TEAP") + params = int_teap_server_params(eap_teap_auth="2") + hapd = hostapd.add_ap(apdev[0], params) + + # verify server accept a client with certificate, but no Phase 2 + # configuration + eap_connect(dev[0], hapd, "TEAP", "user", + anonymous_identity="TEAP", + phase1="teap_provisioning=2", + client_cert="auth_serv/user.pem", + private_key="auth_serv/user.key", + ca_cert="auth_serv/ca.pem", + pac_file="blob://teap_pac") + dev[0].dump_monitor() + res = eap_reauth(dev[0], "TEAP") + if res['tls_session_reused'] != '1': + raise Exception("EAP-TEAP could not use PAC session ticket") + + # verify server accepts a client without certificate + eap_connect(dev[1], hapd, "TEAP", "user", + anonymous_identity="TEAP", password="password", + ca_cert="auth_serv/ca.pem", phase2="auth=MSCHAPV2", + pac_file="blob://teap_pac") diff --git a/tests/hwsim/test_eap_proto.py b/tests/hwsim/test_eap_proto.py index 59519bd6b..7494b429a 100644 --- a/tests/hwsim/test_eap_proto.py +++ b/tests/hwsim/test_eap_proto.py @@ -106,7 +106,7 @@ def start_radius_server(eap_handler): logger.info("No EAP request available") reply.code = pyrad.packet.AccessChallenge - hmac_obj = hmac.new(reply.secret) + hmac_obj = hmac.new(reply.secret, digestmod=hashlib.md5) hmac_obj.update(struct.pack("B", reply.code)) hmac_obj.update(struct.pack("B", reply.id)) diff --git a/tests/hwsim/test_fils.py b/tests/hwsim/test_fils.py index 16fc03852..8e4df655e 100644 --- a/tests/hwsim/test_fils.py +++ b/tests/hwsim/test_fils.py @@ -17,7 +17,7 @@ import hostapd from tshark import run_tshark from wpasupplicant import WpaSupplicant import hwsim_utils -from utils import HwsimSkip, alloc_fail +from utils import * from test_erp import check_erp_capa, start_erp_as from test_ap_hs20 import ip_checksum @@ -1655,7 +1655,7 @@ def test_fils_sk_auth_mismatch(dev, apdev, params): hwsim_utils.test_connectivity(dev[0], hapd) def setup_fils_rekey(dev, apdev, params, wpa_ptk_rekey=0, wpa_group_rekey=0, - pmksa_caching=True): + pmksa_caching=True, ext_key_id=False): check_fils_capa(dev[0]) check_erp_capa(dev[0]) @@ -1673,6 +1673,8 @@ def setup_fils_rekey(dev, apdev, params, wpa_ptk_rekey=0, wpa_group_rekey=0, params['wpa_group_rekey'] = str(wpa_group_rekey) if not pmksa_caching: params['disable_pmksa_caching'] = '1' + if ext_key_id: + params['extended_key_id'] = '1' hapd = hostapd.add_ap(apdev[0]['ifname'], params) dev[0].scan_for_bss(bssid, freq=2412) @@ -2302,3 +2304,29 @@ def test_fils_sk_erp_roam_diff_akm(dev, apdev, params): raise Exception("Failed to connect to the second AP") hwsim_utils.test_connectivity(dev[0], hapd2) + +def test_fils_auth_ptk_rekey_ap_ext_key_id(dev, apdev, params): + """PTK rekeying after FILS authentication triggered by AP (Ext Key ID)""" + check_ext_key_id_capa(dev[0]) + try: + dev[0].set("extended_key_id", "1") + hapd = setup_fils_rekey(dev, apdev, params, wpa_ptk_rekey=2, + ext_key_id=True) + check_ext_key_id_capa(hapd) + idx = int(dev[0].request("GET last_tk_key_idx")) + if idx != 0: + raise Exception("Unexpected Key ID before TK rekey: %d" % idx) + ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=3) + if ev is None: + raise Exception("PTK rekey timed out") + idx = int(dev[0].request("GET last_tk_key_idx")) + if idx != 1: + raise Exception("Unexpected Key ID after TK rekey: %d" % idx) + hwsim_utils.test_connectivity(dev[0], hapd) + + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1) + if ev is not None: + raise Exception("Rekeying failed - disconnected") + hwsim_utils.test_connectivity(dev[0], hapd) + finally: + dev[0].set("extended_key_id", "0") diff --git a/tests/hwsim/test_gas.py b/tests/hwsim/test_gas.py index ec132f712..cb4a1a8d6 100644 --- a/tests/hwsim/test_gas.py +++ b/tests/hwsim/test_gas.py @@ -487,6 +487,25 @@ def test_gas_anqp_get(dev, apdev): if "FAIL" not in dev[0].request("HS20_ANQP_GET " + cmd): raise Exception("Invalid HS20_ANQP_GET accepted") +def test_gas_anqp_get_no_scan(dev, apdev): + """GAS/ANQP query without scan""" + hapd = start_ap(apdev[0]) + bssid = apdev[0]['bssid'] + if "OK" not in dev[0].request("ANQP_GET " + bssid + " freq=2412 258"): + raise Exception("ANQP_GET command failed") + ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) + if ev is None: + raise Exception("ANQP query timed out") + dev[0].dump_monitor() + + if "OK" not in dev[0].request("ANQP_GET 02:11:22:33:44:55 freq=2417 258"): + raise Exception("ANQP_GET command failed") + ev = dev[0].wait_event(["ANQP-QUERY-DONE"], timeout=10) + if ev is None: + raise Exception("ANQP query timed out [2]") + if "result=FAILURE" not in ev: + raise Exception("Unexpected result: " + ev) + def test_gas_anqp_get_oom(dev, apdev): """GAS/ANQP query OOM""" hapd = start_ap(apdev[0]) @@ -1651,6 +1670,11 @@ def test_gas_anqp_venue_url(dev, apdev): if not bss['anqp_capability_list'].startswith(binascii.hexlify(ids).decode()): raise Exception("Unexpected Capability List ANQP-element value: " + bss['anqp_capability_list']) + if "anqp[277]" not in bss: + raise Exception("Venue-URL ANQP info not available") + if "protected-anqp-info[277]" in bss: + raise Exception("Unexpected Venue-URL protection info") + def test_gas_anqp_venue_url2(dev, apdev): """GAS/ANQP and Venue URL (hostapd venue_url)""" venue_group = 1 @@ -1756,6 +1780,14 @@ def test_gas_anqp_venue_url_pmf(dev, apdev): if "2 " + url2 not in ev: raise Exception("Unexpected Venue URL information (2): " + ev) + bss = dev[0].get_bss(bssid) + if "anqp[277]" not in bss: + raise Exception("Venue-URL ANQP info not available") + if "protected-anqp-info[277]" not in bss: + raise Exception("Venue-URL protection info not available") + if bss["protected-anqp-info[277]"] != "1": + raise Exception("Venue-URL was not indicated to be protected") + def test_gas_anqp_capab_list(dev, apdev): """GAS/ANQP and Capability List ANQP-element""" params = {"ssid": "gas/anqp", diff --git a/tests/hwsim/test_hapd_ctrl.py b/tests/hwsim/test_hapd_ctrl.py index 5b802e478..0d8c10a1e 100644 --- a/tests/hwsim/test_hapd_ctrl.py +++ b/tests/hwsim/test_hapd_ctrl.py @@ -6,10 +6,11 @@ import logging logger = logging.getLogger() +import os from remotehost import remote_compatible import hostapd import hwsim_utils -from utils import skip_with_fips, alloc_fail, fail_test, HwsimSkip +from utils import * @remote_compatible def test_hapd_ctrl_status(dev, apdev): @@ -283,44 +284,56 @@ def test_hapd_ctrl_ess_disassoc(dev, apdev): def test_hapd_ctrl_set_deny_mac_file(dev, apdev): """hostapd and SET deny_mac_file ctrl_iface command""" ssid = "hapd-ctrl" + filename = hostapd.acl_file(dev, apdev, 'hostapd.macaddr') params = {"ssid": ssid} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412") dev[1].connect(ssid, key_mgmt="NONE", scan_freq="2412") - if "OK" not in hapd.request("SET deny_mac_file hostapd.macaddr"): + hapd.send_file(filename, filename) + if "OK" not in hapd.request("SET deny_mac_file " + filename): raise Exception("Unexpected SET failure") dev[0].wait_disconnected(timeout=15) ev = dev[1].wait_event(["CTRL-EVENT-DISCONNECTED"], 1) if ev is not None: raise Exception("Unexpected disconnection") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_hapd_ctrl_set_accept_mac_file(dev, apdev): """hostapd and SET accept_mac_file ctrl_iface command""" ssid = "hapd-ctrl" + filename = hostapd.acl_file(dev, apdev, 'hostapd.macaddr') params = {"ssid": ssid} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412") dev[1].connect(ssid, key_mgmt="NONE", scan_freq="2412") + hapd.send_file(filename, filename) hapd.request("SET macaddr_acl 1") - if "OK" not in hapd.request("SET accept_mac_file hostapd.macaddr"): + if "OK" not in hapd.request("SET accept_mac_file " + filename): raise Exception("Unexpected SET failure") dev[1].wait_disconnected(timeout=15) ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], 1) if ev is not None: raise Exception("Unexpected disconnection") + if filename.startswith('/tmp/'): + os.unlink(filename) def test_hapd_ctrl_set_accept_mac_file_vlan(dev, apdev): """hostapd and SET accept_mac_file ctrl_iface command (VLAN ID)""" ssid = "hapd-ctrl" + filename = hostapd.acl_file(dev, apdev, 'hostapd.accept') params = {"ssid": ssid} hapd = hostapd.add_ap(apdev[0], params) dev[0].connect(ssid, key_mgmt="NONE", scan_freq="2412") dev[1].connect(ssid, key_mgmt="NONE", scan_freq="2412") + hapd.send_file(filename, filename) hapd.request("SET macaddr_acl 1") - if "OK" not in hapd.request("SET accept_mac_file hostapd.accept"): + if "OK" not in hapd.request("SET accept_mac_file " + filename): raise Exception("Unexpected SET failure") dev[1].wait_disconnected(timeout=15) dev[0].wait_disconnected(timeout=15) + if filename.startswith('/tmp/'): + os.unlink(filename) @remote_compatible def test_hapd_ctrl_set_error_cases(dev, apdev): @@ -600,6 +613,7 @@ def test_hapd_dup_network_global_wpa2(dev, apdev): def test_hapd_dup_network_global_wpa(dev, apdev): """hostapd and DUP_NETWORK command (WPA)""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6' src_ssid = "hapd-ctrl-src" dst_ssid = "hapd-ctrl-dst" diff --git a/tests/hwsim/test_he.py b/tests/hwsim/test_he.py index d86e2423a..d062f512c 100644 --- a/tests/hwsim/test_he.py +++ b/tests/hwsim/test_he.py @@ -14,8 +14,6 @@ import hostapd from wpasupplicant import WpaSupplicant from utils import * from test_dfs import wait_dfs_event -from test_ap_csa import csa_supported -from test_ap_ht import clear_scan_cache def test_he_open(dev, apdev): """HE AP with open mode configuration""" @@ -156,27 +154,19 @@ def test_he80(dev, apdev): dev[0].request("DISCONNECT") clear_regdom(hapd, dev) -def test_he_wifi_generation(dev, apdev): +def _test_he_wifi_generation(dev, apdev, conf, scan_freq): """HE and wifi_generation""" try: hapd = None params = {"ssid": "he", "country_code": "FI", - "hw_mode": "a", - "channel": "36", - "ht_capab": "[HT40+]", "ieee80211n": "1", - "ieee80211ac": "1", - "ieee80211ax": "1", - "vht_oper_chwidth": "1", - "vht_capab": "[MAX-MPDU-11454]", - "vht_oper_centr_freq_seg0_idx": "42", - "he_oper_chwidth": "1", - "he_oper_centr_freq_seg0_idx": "42"} + "ieee80211ax": "1"} + params.update(conf) hapd = hostapd.add_ap(apdev[0], params) bssid = apdev[0]['bssid'] - dev[0].connect("he", key_mgmt="NONE", scan_freq="5180") + dev[0].connect("he", key_mgmt="NONE", scan_freq=scan_freq) status = dev[0].get_status() if 'wifi_generation' not in status: # For now, assume this is because of missing kernel support @@ -187,7 +177,7 @@ def test_he_wifi_generation(dev, apdev): wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") - wpas.connect("he", key_mgmt="NONE", scan_freq="5180") + wpas.connect("he", key_mgmt="NONE", scan_freq=scan_freq) status = wpas.get_status() if 'wifi_generation' not in status: # For now, assume this is because of missing kernel support @@ -204,6 +194,27 @@ def test_he_wifi_generation(dev, apdev): dev[0].request("DISCONNECT") clear_regdom(hapd, dev) +def test_he_wifi_generation(dev, apdev): + conf = { + "vht_oper_chwidth": "1", + "hw_mode": "a", + "channel": "36", + "ht_capab": "[HT40+]", + "vht_oper_centr_freq_seg0_idx": "42", + "he_oper_chwidth": "1", + "he_oper_centr_freq_seg0_idx": "42", + "vht_capab": "[MAX-MPDU-11454]", + "ieee80211ac": "1", + } + _test_he_wifi_generation(dev, apdev, conf, "5180") + +def test_he_wifi_generation_24(dev, apdev): + conf = { + "hw_mode": "g", + "channel": "1", + } + _test_he_wifi_generation(dev, apdev, conf, "2412") + def he80_test(apdev, dev, channel, ht_capab): clear_scan_cache(apdev) try: @@ -420,10 +431,9 @@ def test_he_40(devs, apdevs): dev.request("DISCONNECT") clear_regdom(hapd, devs) -def test_he160(dev, apdev, params): - """HE with 160 MHz channel width (1) [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_he160(dev, apdev): + """HE with 160 MHz channel width (1)""" try: hapd = None params = {"ssid": "he", @@ -431,6 +441,7 @@ def test_he160(dev, apdev, params): "hw_mode": "a", "channel": "36", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "ieee80211ax": "1", @@ -492,10 +503,9 @@ def test_he160(dev, apdev, params): dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5) dev[0].flush_scan_cache() -def test_he160b(dev, apdev, params): - """HE with 160 MHz channel width (2) [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_he160b(dev, apdev): + """HE with 160 MHz channel width (2)""" try: hapd = None @@ -504,6 +514,7 @@ def test_he160b(dev, apdev, params): "hw_mode": "a", "channel": "104", "ht_capab": "[HT40-]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "ieee80211ax": "1", @@ -609,6 +620,7 @@ def run_ap_he160_no_dfs(dev, apdev, channel, ht_capab): "hw_mode": "a", "channel": channel, "ht_capab": ht_capab, + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "ieee80211ax": "1", @@ -624,7 +636,7 @@ def run_ap_he160_no_dfs(dev, apdev, channel, ht_capab): cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) reg = cmd.stdout.readlines() for r in reg: - if "5490" in r and "DFS" in r: + if b"5490" in r and b"DFS" in r: raise HwsimSkip("ZA regulatory rule did not have DFS requirement removed") raise Exception("AP setup timed out") @@ -693,6 +705,7 @@ def test_he80plus80(dev, apdev): "hw_mode": "a", "channel": "52", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160-80PLUS80]", "ieee80211n": "1", "ieee80211ac": "1", "ieee80211ax": "1", @@ -714,6 +727,7 @@ def test_he80plus80(dev, apdev): "hw_mode": "a", "channel": "36", "ht_capab": "[HT40+]", + "vht_capab": "[VHT160-80PLUS80]", "ieee80211n": "1", "ieee80211ac": "1", "ieee80211ax": "1", @@ -956,6 +970,7 @@ def test_he_use_sta_nsts(dev, apdev): def test_he_tkip(dev, apdev): """HE and TKIP""" + skip_without_tkip(dev[0]) try: hapd = None params = {"ssid": "he", diff --git a/tests/hwsim/test_hostapd_oom.py b/tests/hwsim/test_hostapd_oom.py index a2cc59e2c..169ae015f 100644 --- a/tests/hwsim/test_hostapd_oom.py +++ b/tests/hwsim/test_hostapd_oom.py @@ -10,7 +10,7 @@ logger = logging.getLogger() import time import hostapd -from utils import HwsimSkip +from utils import * def hostapd_oom_loop(apdev, params, start_func="main"): hapd = hostapd.add_ap(apdev[0], {"ssid": "ctrl"}) @@ -125,10 +125,9 @@ def test_hostapd_oom_wpa2_psk_connect(dev, apdev): break dev[0].request("SCAN_INTERVAL 5") -def test_hostapd_oom_wpa2_eap_connect(dev, apdev, params): +@long_duration_test +def test_hostapd_oom_wpa2_eap_connect(dev, apdev): """hostapd failing during WPA2-EAP mode connection due to OOM""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") params['acct_server_addr'] = "127.0.0.1" params['acct_server_port'] = "1813" diff --git a/tests/hwsim/test_hs20_filter.py b/tests/hwsim/test_hs20_filter.py index 5194339c7..11cf34756 100644 --- a/tests/hwsim/test_hs20_filter.py +++ b/tests/hwsim/test_hs20_filter.py @@ -104,9 +104,11 @@ def _test_ip4_gtk_drop(devs, apdevs, params, dst): pass def test_ip4_gtk_drop_bcast(devs, apdevs, params): + """Hotspot 2.0 frame filtering - IPv4 GTK drop broadcast""" _test_ip4_gtk_drop(devs, apdevs, params, dst='ffffffffffff') def test_ip4_gtk_drop_mcast(devs, apdevs, params): + """Hotspot 2.0 frame filtering - IPv4 GTK drop multicast""" _test_ip4_gtk_drop(devs, apdevs, params, dst='ff0000000000') def _test_ip6_gtk_drop(devs, apdevs, params, dst): @@ -140,12 +142,15 @@ def _test_ip6_gtk_drop(devs, apdevs, params, dst): pass def test_ip6_gtk_drop_bcast(devs, apdevs, params): + """Hotspot 2.0 frame filtering - IPv6 GTK drop broadcast""" _test_ip6_gtk_drop(devs, apdevs, params, dst='ffffffffffff') def test_ip6_gtk_drop_mcast(devs, apdevs, params): + """Hotspot 2.0 frame filtering - IPv6 GTK drop multicast""" _test_ip6_gtk_drop(devs, apdevs, params, dst='ff0000000000') def test_ip4_drop_gratuitous_arp(devs, apdevs, params): + """Hotspot 2.0 frame filtering - IPv4 drop gratuitous ARP""" require_under_vm() procfile = '/proc/sys/net/ipv4/conf/%s/drop_gratuitous_arp' % devs[0].ifname if not os.path.exists(procfile): @@ -173,6 +178,7 @@ def test_ip4_drop_gratuitous_arp(devs, apdevs, params): subprocess.call(['ip', 'neigh', 'del', '10.0.0.1', 'dev', dev.ifname]) def test_ip6_drop_unsolicited_na(devs, apdevs, params): + """Hotspot 2.0 frame filtering - IPv6 drop unsolicited NA""" require_under_vm() procfile = '/proc/sys/net/ipv6/conf/%s/drop_unsolicited_na' % devs[0].ifname if not os.path.exists(procfile): diff --git a/tests/hwsim/test_ibss.py b/tests/hwsim/test_ibss.py index a9b7e11b0..29ebd8129 100644 --- a/tests/hwsim/test_ibss.py +++ b/tests/hwsim/test_ibss.py @@ -12,7 +12,7 @@ import re import subprocess import hwsim_utils -from utils import alloc_fail, wait_fail_trigger +from utils import * def connect_ibss_cmd(dev, id, freq=2412): dev.dump_monitor() @@ -189,6 +189,9 @@ def test_ibss_rsn_group_rekey(dev): def test_ibss_wpa_none(dev): """IBSS WPA-None""" + skip_without_tkip(dev[0]) + skip_without_tkip(dev[1]) + skip_without_tkip(dev[2]) ssid = "ibss-wpa-none" logger.info("Start IBSS on the first STA") @@ -257,6 +260,8 @@ def test_ibss_wpa_none(dev): def test_ibss_wpa_none_ccmp(dev): """IBSS WPA-None/CCMP""" + skip_without_tkip(dev[0]) + skip_without_tkip(dev[1]) ssid = "ibss-wpa-none" logger.info("Start IBSS on the first STA") @@ -377,6 +382,8 @@ def test_ibss_open_retry(dev): def test_ibss_rsn_tkip(dev): """IBSS RSN with TKIP as the cipher""" + skip_without_tkip(dev[0]) + skip_without_tkip(dev[1]) ssid = "ibss-rsn-tkip" id = add_ibss_rsn_tkip(dev[0], ssid) @@ -395,6 +402,9 @@ def test_ibss_rsn_tkip(dev): def test_ibss_wep(dev): """IBSS with WEP""" + check_wep_capa(dev[0]) + check_wep_capa(dev[1]) + ssid = "ibss-wep" id = add_ibss(dev[0], ssid, key_mgmt="NONE", wep_key0='"hello"') diff --git a/tests/hwsim/test_ieee8021x.py b/tests/hwsim/test_ieee8021x.py index bc1c3c939..89c282b39 100644 --- a/tests/hwsim/test_ieee8021x.py +++ b/tests/hwsim/test_ieee8021x.py @@ -13,13 +13,14 @@ import time import hostapd import hwsim_utils -from utils import skip_with_fips +from utils import * from tshark import run_tshark logger = logging.getLogger() def test_ieee8021x_wep104(dev, apdev): """IEEE 802.1X connection using dynamic WEP104""" + check_wep_capa(dev[0]) skip_with_fips(dev[0]) params = hostapd.radius_params() params["ssid"] = "ieee8021x-wep" @@ -36,6 +37,7 @@ def test_ieee8021x_wep104(dev, apdev): def test_ieee8021x_wep40(dev, apdev): """IEEE 802.1X connection using dynamic WEP40""" + check_wep_capa(dev[0]) skip_with_fips(dev[0]) params = hostapd.radius_params() params["ssid"] = "ieee8021x-wep" @@ -52,6 +54,7 @@ def test_ieee8021x_wep40(dev, apdev): def test_ieee8021x_wep_index_workaround(dev, apdev): """IEEE 802.1X and EAPOL-Key index workaround""" + check_wep_capa(dev[0]) skip_with_fips(dev[0]) params = hostapd.radius_params() params["ssid"] = "ieee8021x-wep" @@ -100,6 +103,7 @@ def test_ieee8021x_static_wep104(dev, apdev): run_static_wep(dev, apdev, '"hello-there-/"') def run_static_wep(dev, apdev, key): + check_wep_capa(dev[0]) params = hostapd.radius_params() params["ssid"] = "ieee8021x-wep" params["ieee8021x"] = "1" @@ -252,6 +256,7 @@ def send_eapol_key(dev, bssid, signkey, frame_start, frame_end): def test_ieee8021x_eapol_key(dev, apdev): """IEEE 802.1X connection and EAPOL-Key protocol tests""" + check_wep_capa(dev[0]) skip_with_fips(dev[0]) params = hostapd.radius_params() params["ssid"] = "ieee8021x-wep" @@ -317,6 +322,7 @@ def test_ieee8021x_reauth(dev, apdev): def test_ieee8021x_reauth_wep(dev, apdev, params): """IEEE 802.1X and EAPOL_REAUTH request with WEP""" + check_wep_capa(dev[0]) logdir = params['logdir'] params = hostapd.radius_params() @@ -492,6 +498,7 @@ def test_ieee8021x_open_leap(dev, apdev): def test_ieee8021x_and_wpa_enabled(dev, apdev): """IEEE 802.1X connection using dynamic WEP104 when WPA enabled""" + check_wep_capa(dev[0]) skip_with_fips(dev[0]) params = hostapd.radius_params() params["ssid"] = "ieee8021x-wep" diff --git a/tests/hwsim/test_monitor_interface.py b/tests/hwsim/test_monitor_interface.py index 62ce7383e..e1a48aeb0 100644 --- a/tests/hwsim/test_monitor_interface.py +++ b/tests/hwsim/test_monitor_interface.py @@ -4,6 +4,7 @@ # This software may be distributed under the terms of the BSD license. # See README for more details. +import binascii from remotehost import remote_compatible import logging logger = logging.getLogger() @@ -12,6 +13,7 @@ import time import hwsim_utils import hostapd from wpasupplicant import WpaSupplicant +from utils import radiotap_build, start_monitor, stop_monitor def test_monitor_iface_open(dev, apdev): """Open connection using cfg80211 monitor interface on AP""" @@ -72,9 +74,20 @@ def test_monitor_iface_unknown_sta(dev, apdev): hapd.request("DEAUTHENTICATE " + addr) # But the unprotected Deauth from TX frame-from-unassoc-STA will now be # processed - dev[0].request("DATA_TEST_CONFIG 1") - dev[0].request("DATA_TEST_TX " + bssid + " " + addr + " 0") - dev[0].request("DATA_TEST_CONFIG 0") + try: + sock = start_monitor(apdev[1]["ifname"]) + radiotap = radiotap_build() + + bssid = hapd.own_addr().replace(':', '') + addr = dev[0].own_addr().replace(':', '') + + # Inject Data frame from STA to AP since we not have SA in place + # anymore for normal data TX + frame = binascii.unhexlify("48010000" + bssid + addr + bssid + "0000") + sock.send(radiotap + frame) + finally: + stop_monitor(apdev[1]["ifname"]) + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5) if ev is None: raise Exception("No disconnection") diff --git a/tests/hwsim/test_multi_ap.py b/tests/hwsim/test_multi_ap.py index 5b28cf8da..4070d3ea7 100644 --- a/tests/hwsim/test_multi_ap.py +++ b/tests/hwsim/test_multi_ap.py @@ -5,6 +5,7 @@ # See README for more details. import hostapd +from utils import * def test_multi_ap_association(dev, apdev): """Multi-AP association in backhaul BSS""" @@ -183,6 +184,7 @@ def test_multi_ap_wps_split_psk(dev, apdev): def test_multi_ap_wps_split_mixed(dev, apdev): """WPS on split fronthaul and backhaul AP with mixed-mode fronthaul""" + skip_without_tkip(dev[0]) backhaul_ssid = "multi-ap-backhaul-wps" backhaul_passphrase = "87654321" params = hostapd.wpa_mixed_params(ssid="multi-ap-fronthaul-wps", diff --git a/tests/hwsim/test_nfc_wps.py b/tests/hwsim/test_nfc_wps.py index e98eb4113..a0e2d454f 100644 --- a/tests/hwsim/test_nfc_wps.py +++ b/tests/hwsim/test_nfc_wps.py @@ -13,7 +13,7 @@ logger = logging.getLogger() import hwsim_utils import hostapd -from utils import alloc_fail, fail_test, clear_regdom +from utils import * def check_wpa2_connection(sta, ap, hapd, ssid, mixed=False): status = sta.get_status() @@ -104,6 +104,7 @@ def test_nfc_wps_config_token(dev, apdev): def test_nfc_wps_config_token_init(dev, apdev): """NFC tag with configuration token from AP with auto configuration""" + skip_without_tkip(dev[0]) ssid = "test-wps-nfc-conf-token-init" hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, "eap_server": "1", "wps_state": "1"}) @@ -122,6 +123,7 @@ def test_nfc_wps_config_token_init(dev, apdev): @remote_compatible def test_nfc_wps_password_token_sta_init(dev, apdev): """Initial AP configuration with first WPS NFC Enrollee""" + skip_without_tkip(dev[0]) ssid = "test-wps-nfc-pw-token-init" hapd = hostapd.add_ap(apdev[0], {"ssid": ssid, "eap_server": "1", "wps_state": "1"}) @@ -216,6 +218,7 @@ def test_nfc_wps_password_token_ap_preconf(dev, apdev): def test_nfc_wps_handover_init(dev, apdev): """Connect to WPS AP with NFC connection handover and move to configured state""" + skip_without_tkip(dev[0]) try: _test_nfc_wps_handover_init(dev, apdev) finally: diff --git a/tests/hwsim/test_ocv.py b/tests/hwsim/test_ocv.py index df84e7124..802e67887 100644 --- a/tests/hwsim/test_ocv.py +++ b/tests/hwsim/test_ocv.py @@ -12,9 +12,8 @@ logger = logging.getLogger() import hostapd from wpasupplicant import WpaSupplicant import hwsim_utils -from utils import HwsimSkip +from utils import * -from test_ap_ht import set_world_reg from test_ap_psk import parse_eapol, build_eapol, pmk_to_ptk, eapol_key_mic, recv_eapol, send_eapol, reply_eapol, build_eapol_key_3_4, aes_wrap, pad_key_data #TODO: Refuse setting up AP with OCV but without MFP support @@ -260,6 +259,7 @@ def run_wpa2_ocv_vht160(dev, apdev): "channel": channel, "country_code": "ZA", "ht_capab": capab, + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "2", @@ -302,6 +302,7 @@ def run_wpa2_ocv_vht80plus80(dev, apdev): "channel": channel, "country_code": "US", "ht_capab": capab, + "vht_capab": "[VHT160-80PLUS80]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "3", @@ -904,3 +905,211 @@ def test_wpa2_ocv_auto_enable_pmf(dev, apdev): ieee80211w="2") dev[0].request("REMOVE_NETWORK all") dev[0].wait_disconnected() + +def test_wpa2_ocv_sta_override_eapol(dev, apdev): + """OCV on 2.4 GHz and STA override EAPOL-Key msg 2/4""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + dev[0].set("oci_freq_override_eapol", "2462") + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2", wait_connect=False) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=15) + dev[0].request("DISCONNECT") + if ev is None: + raise Exception("No connection result reported") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + if "reason=15" not in ev: + raise Exception("Unexpected disconnection reason: " + ev) + + check_ocv_failure(hapd, "EAPOL-Key msg 2/4", "eapol-key-m2", + dev[0].own_addr()) + +def test_wpa2_ocv_sta_override_sa_query_req(dev, apdev): + """OCV on 2.4 GHz and STA override SA Query Request""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2") + hapd.wait_sta() + dev[0].set("oci_freq_override_saquery_req", "2462") + if "OK" not in dev[0].request("UNPROT_DEAUTH"): + raise Exception("Triggering SA Query from the STA failed") + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=3) + if ev is None: + raise Exception("Disconnection after failed SA Query not reported") + dev[0].set("oci_freq_override_saquery_req", "0") + dev[0].wait_connected() + if "OK" not in dev[0].request("UNPROT_DEAUTH"): + raise Exception("Triggering SA Query from the STA failed") + check_ocv_failure(hapd, "SA Query Request", "saqueryreq", + dev[0].own_addr()) + ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=3) + if ev is not None: + raise Exception("SA Query from the STA failed") + +def test_wpa2_ocv_sta_override_sa_query_resp(dev, apdev): + """OCV on 2.4 GHz and STA override SA Query Response""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2") + dev[0].set("oci_freq_override_saquery_resp", "2462") + hapd.wait_sta() + if "OK" not in hapd.request("SA_QUERY " + dev[0].own_addr()): + raise Exception("SA_QUERY failed") + check_ocv_failure(hapd, "SA Query Response", "saqueryresp", + dev[0].own_addr()) + +def check_ocv_failure(dev, frame_txt, frame, addr): + ev = dev.wait_event(["OCV-FAILURE"], timeout=3) + if ev is None: + raise Exception("OCV failure for %s not reported" % frame_txt) + if "addr=" + addr not in ev: + raise Exception("Unexpected OCV failure addr: " + ev) + if "frame=" + frame not in ev: + raise Exception("Unexpected OCV failure frame: " + ev) + if "error=primary channel mismatch" not in ev: + raise Exception("Unexpected OCV failure error: " + ev) + +def test_wpa2_ocv_ap_override_eapol_m3(dev, apdev): + """OCV on 2.4 GHz and AP override EAPOL-Key msg 3/4""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1", + "oci_freq_override_eapol_m3": "2462"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + bssid = hapd.own_addr() + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2", wait_connect=False) + + check_ocv_failure(dev[0], "EAPOL-Key msg 3/4", "eapol-key-m3", bssid) + + ev = dev[0].wait_disconnected() + if "reason=15" not in ev: + raise Exception("Unexpected disconnection reason: " + ev) + +def test_wpa2_ocv_ap_override_eapol_g1(dev, apdev): + """OCV on 2.4 GHz and AP override EAPOL-Key group msg 1/2""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1", + "oci_freq_override_eapol_g1": "2462"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + bssid = hapd.own_addr() + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2") + + if "OK" not in hapd.request("REKEY_GTK"): + raise Exception("REKEY_GTK failed") + check_ocv_failure(dev[0], "EAPOL-Key group msg 1/2", "eapol-key-g1", bssid) + +def test_wpa2_ocv_ap_override_saquery_req(dev, apdev): + """OCV on 2.4 GHz and AP override SA Query Request""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1", + "oci_freq_override_saquery_req": "2462"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + bssid = hapd.own_addr() + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2") + + if "OK" not in hapd.request("SA_QUERY " + dev[0].own_addr()): + raise Exception("SA_QUERY failed") + check_ocv_failure(dev[0], "SA Query Request", "saqueryreq", bssid) + +def test_wpa2_ocv_ap_override_saquery_resp(dev, apdev): + """OCV on 2.4 GHz and AP override SA Query Response""" + params = {"channel": "1", + "ieee80211w": "2", + "ocv": "1", + "oci_freq_override_saquery_resp": "2462"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + bssid = hapd.own_addr() + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1", + ieee80211w="2") + + if "OK" not in dev[0].request("UNPROT_DEAUTH"): + raise Exception("Triggering SA Query from the STA failed") + check_ocv_failure(dev[0], "SA Query Response", "saqueryresp", bssid) + +@remote_compatible +def test_wpa2_ocv_no_pmf(dev, apdev): + """OCV on 2.4 GHz and no PMF on STA""" + params = {"channel": "1", + "ieee80211w": "1", + "ocv": "1"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + ie = "301a0100000fac040100000fac040100000fac0200400000000fac06" + if "OK" not in dev[0].request("TEST_ASSOC_IE " + ie): + raise Exception("Could not set TEST_ASSOC_IE") + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="0", + ieee80211w="0", wait_connect=False) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-ASSOC-REJECT"], + timeout=10) + dev[0].request("DISCONNECT") + if ev is None: + raise Exception("No connection result seen") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + if "status_code=31" not in ev: + raise Exception("Unexpected status code: " + ev) + +@remote_compatible +def test_wpa2_ocv_no_pmf_workaround(dev, apdev): + """OCV on 2.4 GHz and no PMF on STA with workaround""" + params = {"channel": "1", + "ieee80211w": "1", + "ocv": "2"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + ie = "301a0100000fac040100000fac040100000fac0200400000000fac06" + if "OK" not in dev[0].request("TEST_ASSOC_IE " + ie): + raise Exception("Could not set TEST_ASSOC_IE") + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="0", + ieee80211w="0") + +@remote_compatible +def test_wpa2_ocv_no_oci(dev, apdev): + """OCV on 2.4 GHz and no OCI from STA""" + params = {"channel": "1", + "ieee80211w": "1", + "ocv": "1"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + ie = "301a0100000fac040100000fac040100000fac0280400000000fac06" + if "OK" not in dev[0].request("TEST_ASSOC_IE " + ie): + raise Exception("Could not set TEST_ASSOC_IE") + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="0", + ieee80211w="1", wait_connect=False) + ev = hapd.wait_event(["OCV-FAILURE"], timeout=10) + if ev is None: + raise Exception("No OCV failure reported") + if "frame=eapol-key-m2 error=did not receive mandatory OCI" not in ev: + raise Exception("Unexpected error: " + ev) + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "WPA: 4-Way Handshake failed"], timeout=10) + dev[0].request("DISCONNECT") + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + if ev is None: + raise Exception("4-way handshake failure not reported") + +@remote_compatible +def test_wpa2_ocv_no_oci_workaround(dev, apdev): + """OCV on 2.4 GHz and no OCI from STA with workaround""" + params = {"channel": "1", + "ieee80211w": "1", + "ocv": "2"} + hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params) + ie = "301a0100000fac040100000fac040100000fac0280400000000fac06" + if "OK" not in dev[0].request("TEST_ASSOC_IE " + ie): + raise Exception("Could not set TEST_ASSOC_IE") + dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="0", + ieee80211w="1") diff --git a/tests/hwsim/test_owe.py b/tests/hwsim/test_owe.py index 645e8d4dc..95c6b19b8 100644 --- a/tests/hwsim/test_owe.py +++ b/tests/hwsim/test_owe.py @@ -16,6 +16,7 @@ from wpasupplicant import WpaSupplicant import hwsim_utils from tshark import run_tshark from utils import HwsimSkip, fail_test, alloc_fail, wait_fail_trigger +from test_ap_acs import wait_acs def test_owe(dev, apdev): """Opportunistic Wireless Encryption""" @@ -66,13 +67,19 @@ def test_owe_groups(dev, apdev): def test_owe_pmksa_caching(dev, apdev): """Opportunistic Wireless Encryption and PMKSA caching""" - run_owe_pmksa_caching(dev, apdev) + try: + run_owe_pmksa_caching(dev, apdev) + finally: + dev[0].set("reassoc_same_bss_optim", "0") def test_owe_pmksa_caching_connect_cmd(dev, apdev): """Opportunistic Wireless Encryption and PMKSA caching using cfg80211 connect command""" wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") - run_owe_pmksa_caching([wpas], apdev) + try: + run_owe_pmksa_caching([wpas], apdev) + finally: + wpas.set("reassoc_same_bss_optim", "0") def run_owe_pmksa_caching(dev, apdev): if "OWE" not in dev[0].get_capability("key_mgmt"): @@ -84,8 +91,10 @@ def run_owe_pmksa_caching(dev, apdev): hapd = hostapd.add_ap(apdev[0], params) bssid = hapd.own_addr() + dev[0].set("reassoc_same_bss_optim", "1") dev[0].scan_for_bss(bssid, freq="2412") id = dev[0].connect("owe", key_mgmt="OWE") + hapd.wait_sta() hwsim_utils.test_connectivity(dev[0], hapd) pmksa = dev[0].get_pmksa(bssid) dev[0].request("DISCONNECT") @@ -94,6 +103,7 @@ def run_owe_pmksa_caching(dev, apdev): dev[0].select_network(id, 2412) dev[0].wait_connected() + hapd.wait_sta() hwsim_utils.test_connectivity(dev[0], hapd) pmksa2 = dev[0].get_pmksa(bssid) dev[0].request("DISCONNECT") @@ -105,11 +115,9 @@ def run_owe_pmksa_caching(dev, apdev): dev[0].select_network(id, 2412) dev[0].wait_connected() + hapd.wait_sta() hwsim_utils.test_connectivity(dev[0], hapd) pmksa3 = dev[0].get_pmksa(bssid) - dev[0].request("DISCONNECT") - dev[0].wait_disconnected() - dev[0].dump_monitor() if pmksa is None or pmksa2 is None or pmksa3 is None: raise Exception("PMKSA entry missing") @@ -118,6 +126,12 @@ def run_owe_pmksa_caching(dev, apdev): if pmksa['pmkid'] == pmksa3['pmkid']: raise Exception("PMKID did not change after PMKSA cache flush") + dev[0].request("REASSOCIATE") + dev[0].wait_connected() + pmksa4 = dev[0].get_pmksa(bssid) + if pmksa3['pmkid'] != pmksa4['pmkid']: + raise Exception("Unexpected PMKID change when using PMKSA caching [2]") + def test_owe_and_psk(dev, apdev): """Opportunistic Wireless Encryption and WPA2-PSK enabled""" if "OWE" not in dev[0].get_capability("key_mgmt"): @@ -148,23 +162,38 @@ def test_owe_transition_mode_connect_cmd(dev, apdev): wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") run_owe_transition_mode([wpas], apdev) -def run_owe_transition_mode(dev, apdev): +def test_owe_transition_mode_mismatch1(dev, apdev): + """Opportunistic Wireless Encryption transition mode (mismatch 1)""" + run_owe_transition_mode(dev, apdev, adv_bssid0="02:11:22:33:44:55") + +def test_owe_transition_mode_mismatch2(dev, apdev): + """Opportunistic Wireless Encryption transition mode (mismatch 2)""" + run_owe_transition_mode(dev, apdev, adv_bssid1="02:11:22:33:44:66") + +def test_owe_transition_mode_mismatch3(dev, apdev): + """Opportunistic Wireless Encryption transition mode (mismatch 3)""" + run_owe_transition_mode(dev, apdev, adv_bssid0="02:11:22:33:44:55", + adv_bssid1="02:11:22:33:44:66") + +def run_owe_transition_mode(dev, apdev, adv_bssid0=None, adv_bssid1=None): if "OWE" not in dev[0].get_capability("key_mgmt"): raise HwsimSkip("OWE not supported") dev[0].flush_scan_cache() + adv_bssid = adv_bssid0 if adv_bssid0 else apdev[1]['bssid'] params = {"ssid": "owe-random", "wpa": "2", "wpa_key_mgmt": "OWE", "rsn_pairwise": "CCMP", "ieee80211w": "2", - "owe_transition_bssid": apdev[1]['bssid'], + "owe_transition_bssid": adv_bssid, "owe_transition_ssid": '"owe-test"', "ignore_broadcast_ssid": "1"} hapd = hostapd.add_ap(apdev[0], params) bssid = hapd.own_addr() + adv_bssid = adv_bssid1 if adv_bssid1 else apdev[0]['bssid'] params = {"ssid": "owe-test", - "owe_transition_bssid": apdev[0]['bssid'], + "owe_transition_bssid": adv_bssid, "owe_transition_ssid": '"owe-random"'} hapd2 = hostapd.add_ap(apdev[1], params) bssid2 = hapd2.own_addr() @@ -208,6 +237,88 @@ def run_owe_transition_mode(dev, apdev): dev[0].wait_connected() hwsim_utils.test_connectivity(dev[0], hapd) +def test_owe_transition_mode_ifname(dev, apdev): + """Opportunistic Wireless Encryption transition mode (ifname)""" + if "OWE" not in dev[0].get_capability("key_mgmt"): + raise HwsimSkip("OWE not supported") + dev[0].flush_scan_cache() + params = {"ssid": "owe-random", + "wpa": "2", + "wpa_key_mgmt": "OWE", + "rsn_pairwise": "CCMP", + "ieee80211w": "2", + "owe_transition_ifname": apdev[1]['ifname'], + "ignore_broadcast_ssid": "1"} + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + params = {"ssid": "owe-test", + "owe_transition_ifname": apdev[0]['ifname']} + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + dev[0].scan_for_bss(bssid, freq="2412") + dev[0].scan_for_bss(bssid2, freq="2412") + + id = dev[0].connect("owe-test", key_mgmt="OWE", ieee80211w="2", + scan_freq="2412") + val = dev[0].get_status_field("key_mgmt") + if val != "OWE": + raise Exception("Unexpected key_mgmt: " + val) + +def test_owe_transition_mode_ifname_acs(dev, apdev): + """Opportunistic Wireless Encryption transition mode (ifname, ACS)""" + run_owe_transition_mode_ifname_acs(dev, apdev, wait_first=False) + +def test_owe_transition_mode_ifname_acs2(dev, apdev): + """Opportunistic Wireless Encryption transition mode (ifname, ACS)""" + run_owe_transition_mode_ifname_acs(dev, apdev, wait_first=True) + +def run_owe_transition_mode_ifname_acs(dev, apdev, wait_first): + if "OWE" not in dev[0].get_capability("key_mgmt"): + raise HwsimSkip("OWE not supported") + dev[0].flush_scan_cache() + params = {"ssid": "owe-random", + "channel": "0", + "wpa": "2", + "wpa_key_mgmt": "OWE", + "rsn_pairwise": "CCMP", + "ieee80211w": "2", + "owe_transition_ifname": apdev[1]['ifname'], + "ignore_broadcast_ssid": "1"} + hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False) + bssid = hapd.own_addr() + + if wait_first: + wait_acs(hapd) + + params = {"ssid": "owe-test", + "channel": "0", + "owe_transition_ifname": apdev[0]['ifname']} + hapd2 = hostapd.add_ap(apdev[1], params, wait_enabled=False) + bssid2 = hapd2.own_addr() + + wait_acs(hapd2) + if not wait_first: + state = hapd.get_status_field("state") + if state == "ACS-STARTED": + time.sleep(5) + state = hapd.get_status_field("state") + if state != "ENABLED": + raise Exception("AP1 startup did not succeed") + + freq = hapd.get_status_field("freq") + freq2 = hapd2.get_status_field("freq") + + dev[0].scan_for_bss(bssid, freq=freq) + dev[0].scan_for_bss(bssid2, freq=freq2) + + id = dev[0].connect("owe-test", key_mgmt="OWE", ieee80211w="2", + scan_freq="%s %s" % (freq, freq2)) + val = dev[0].get_status_field("key_mgmt") + if val != "OWE": + raise Exception("Unexpected key_mgmt: " + val) + def test_owe_transition_mode_open_only_ap(dev, apdev): """Opportunistic Wireless Encryption transition mode connect to open-only AP""" if "OWE" not in dev[0].get_capability("key_mgmt"): @@ -329,6 +440,51 @@ def run_owe_transition_mode_multi_bss(dev, apdev): raise Exception("Unexpected key_mgmt: " + val) hwsim_utils.test_connectivity(dev[0], hapd2) +def test_owe_transition_mode_rsne_mismatch(dev, apdev): + """Opportunistic Wireless Encryption transition mode and RSNE mismatch""" + if "OWE" not in dev[0].get_capability("key_mgmt"): + raise HwsimSkip("OWE not supported") + dev[0].flush_scan_cache() + params = {"ssid": "owe-random", + "wpa": "2", + "wpa_key_mgmt": "OWE", + "rsn_pairwise": "CCMP", + "ieee80211w": "2", + "rsne_override_eapol": "30140100000fac040100000fac040100000fac020c00", + "owe_transition_bssid": apdev[1]['bssid'], + "owe_transition_ssid": '"owe-test"', + "ignore_broadcast_ssid": "1"} + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + params = {"ssid": "owe-test", + "owe_transition_bssid": apdev[0]['bssid'], + "owe_transition_ssid": '"owe-random"'} + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + dev[0].scan_for_bss(bssid, freq="2412") + dev[0].scan_for_bss(bssid2, freq="2412") + + id = dev[0].connect("owe-test", key_mgmt="OWE", ieee80211w="2", + scan_freq="2412", wait_connect=False) + ev = dev[0].wait_event(["PMKSA-CACHE-ADDED"], timeout=5) + if ev is None: + raise Exception("OWE PMKSA not created") + ev = dev[0].wait_event(["WPA: IE in 3/4 msg does not match with IE in Beacon/ProbeResp"], + timeout=5) + if ev is None: + raise Exception("RSNE mismatch not reported") + ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=5) + dev[0].request("REMOVE_NETWORK all") + if ev is None: + raise Exception("No disconnection seen") + if "CTRL-EVENT-DISCONNECTED" not in ev: + raise Exception("Unexpected connection") + if "reason=17 locally_generated=1" not in ev: + raise Exception("Unexpected disconnection reason: " + ev) + def test_owe_unsupported_group(dev, apdev): """Opportunistic Wireless Encryption and unsupported group""" try: @@ -716,3 +872,47 @@ def test_owe_ptk_hash(dev, apdev): if ev is None: raise Exception("No PMKSA cache removal event seen") dev[0].dump_monitor() + +def test_owe_transition_mode_disable(dev, apdev): + """Opportunistic Wireless Encryption transition mode disable""" + if "OWE" not in dev[0].get_capability("key_mgmt"): + raise HwsimSkip("OWE not supported") + dev[0].flush_scan_cache() + params = {"ssid": "owe-random", + "wpa": "2", + "wpa_key_mgmt": "OWE", + "rsn_pairwise": "CCMP", + "ieee80211w": "2", + "transition_disable": '0x08', + "owe_transition_bssid": apdev[1]['bssid'], + "owe_transition_ssid": '"owe-test"', + "ignore_broadcast_ssid": "1"} + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + params = {"ssid": "owe-test", + "owe_transition_bssid": apdev[0]['bssid'], + "owe_transition_ssid": '"owe-random"'} + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + dev[0].scan_for_bss(bssid, freq="2412") + dev[0].scan_for_bss(bssid2, freq="2412") + + id = dev[0].connect("owe-test", key_mgmt="OWE", ieee80211w="2", + scan_freq="2412") + + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "08": + raise Exception("Unexpected transition disable bitmap: " + ev) + + val = dev[0].get_network(id, "owe_only") + if val != "1": + raise Exception("Unexpected owe_only value: " + val) + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].request("RECONNECT") + dev[0].wait_connected() diff --git a/tests/hwsim/test_p2p_autogo.py b/tests/hwsim/test_p2p_autogo.py index e896323f1..91d68eaf2 100644 --- a/tests/hwsim/test_p2p_autogo.py +++ b/tests/hwsim/test_p2p_autogo.py @@ -10,6 +10,7 @@ import subprocess import logging logger = logging.getLogger() +import hostapd import hwsim_utils import utils from utils import HwsimSkip @@ -231,6 +232,28 @@ def test_autogo_pbc(dev): dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), "pbc", timeout=15, social=True) +def test_autogo_pbc_session_overlap(dev, apdev): + """P2P autonomous GO and PBC session overlap""" + params = {"ssid": "wps", "eap_server": "1", "wps_state": "1"} + hapd = hostapd.add_ap(apdev[0], params) + hapd.request("WPS_PBC") + bssid = hapd.own_addr() + time.sleep(0.1) + + dev[0].scan_for_bss(bssid, freq=2412) + dev[1].scan_for_bss(bssid, freq=2412) + + dev[1].global_request("SET p2p_no_group_iface 0") + autogo(dev[0], freq=2412) + if "OK" not in dev[0].group_request("WPS_PBC p2p_dev_addr=" + dev[1].p2p_dev_addr()): + raise Exception("WPS_PBC failed") + dev[1].p2p_connect_group(dev[0].p2p_dev_addr(), "pbc", timeout=15, + social=True) + hapd.disable() + remove_group(dev[0], dev[1]) + dev[0].flush_scan_cache() + dev[1].flush_scan_cache() + def test_autogo_tdls(dev): """P2P autonomous GO and two clients using TDLS""" go = dev[0] @@ -899,3 +922,15 @@ def run_autogo_interworking(dev): dev[0].remove_group() if '6b03110203' not in bss['ie']: raise Exception("Interworking element not seen") + +def test_autogo_remove_iface(dev): + """P2P autonomous GO and interface being removed""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5") + wpas.global_request("SET p2p_no_group_iface 1") + wpas.set("p2p_group_idle", "1") + autogo(wpas) + wpas.global_request("P2P_SET disallow_freq 5000") + time.sleep(0.1) + wpas.global_request("INTERFACE_REMOVE " + wpas.ifname) + time.sleep(1) diff --git a/tests/hwsim/test_p2p_channel.py b/tests/hwsim/test_p2p_channel.py index ad1d712d6..7bbc958b9 100644 --- a/tests/hwsim/test_p2p_channel.py +++ b/tests/hwsim/test_p2p_channel.py @@ -603,7 +603,7 @@ def test_p2p_autogo_pref_chan_not_in_regulatory(dev, apdev): raise Exception("Unexpected number of network blocks: " + str(netw)) id = netw[0]['id'] - set_country("SE", dev[0]) + set_country("JP", dev[0]) res = autogo(dev[0], persistent=id) if res['freq'] == "5745": raise Exception("Unexpected channel selected(2): " + res['freq']) @@ -1366,3 +1366,15 @@ def test_p2p_channel_drv_pref_autogo(dev): res_go = autogo(dev[0]) if res_go['freq'] != "2417": raise Exception("Unexpected operating frequency: " + res_go['freq']) + +def test_p2p_channel_disable_6ghz(dev): + """P2P with 6 GHz disabled""" + try: + dev[0].global_request("SET p2p_6ghz_disable 1") + dev[1].p2p_listen() + dev[0].discover_peer(dev[1].p2p_dev_addr(), social=False) + + autogo(dev[1]) + connect_cli(dev[1], dev[0]) + finally: + dev[0].global_request("SET p2p_6ghz_disable 0") diff --git a/tests/hwsim/test_p2p_concurrency.py b/tests/hwsim/test_p2p_concurrency.py index 512886ba4..8fb2bb929 100644 --- a/tests/hwsim/test_p2p_concurrency.py +++ b/tests/hwsim/test_p2p_concurrency.py @@ -13,8 +13,7 @@ import time import hwsim_utils import hostapd from p2p_utils import * -from test_ap_ht import clear_scan_cache -from utils import HwsimSkip +from utils import * @remote_compatible def test_concurrent_autogo(dev, apdev): diff --git a/tests/hwsim/test_p2p_grpform.py b/tests/hwsim/test_p2p_grpform.py index 47882cce2..88e253c0b 100644 --- a/tests/hwsim/test_p2p_grpform.py +++ b/tests/hwsim/test_p2p_grpform.py @@ -14,8 +14,7 @@ import os import hostapd import hwsim_utils -import utils -from utils import HwsimSkip +from utils import * from wpasupplicant import WpaSupplicant from p2p_utils import * from test_p2p_messages import parse_p2p_public_action, p2p_hdr, p2p_attr_capability, p2p_attr_go_intent, p2p_attr_config_timeout, p2p_attr_listen_channel, p2p_attr_intended_interface_addr, p2p_attr_channel_list, p2p_attr_device_info, p2p_attr_operating_channel, ie_p2p, ie_wsc, mgmt_tx, P2P_GO_NEG_REQ @@ -46,7 +45,7 @@ def test_grpform_a(dev): raise Exception("Unexpected group interface name") check_grpform_results(i_res, r_res) remove_group(dev[0], dev[1]) - if i_res['ifname'] in utils.get_ifnames(): + if i_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") def test_grpform_b(dev): @@ -67,7 +66,7 @@ def test_grpform_b(dev): if "FAIL" not in dev[0].group_request("P2P_GROUP_MEMBER 00:11:22:33:44:55"): raise Exception("P2P_GROUP_MEMBER for non-member accepted") remove_group(dev[0], dev[1]) - if r_res['ifname'] in utils.get_ifnames(): + if r_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") def test_grpform_c(dev): @@ -82,9 +81,9 @@ def test_grpform_c(dev): raise Exception("Unexpected group interface name") check_grpform_results(i_res, r_res) remove_group(dev[0], dev[1]) - if i_res['ifname'] in utils.get_ifnames(): + if i_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") - if r_res['ifname'] in utils.get_ifnames(): + if r_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") @remote_compatible @@ -99,9 +98,9 @@ def test_grpform2_c(dev): dev[1].global_request("SET p2p_no_group_iface 0") [i_res, r_res] = go_neg_pin_authorized(i_dev=dev[0], i_intent=0, r_dev=dev[1], r_intent=15) remove_group(dev[0], dev[1]) - if i_res['ifname'] in utils.get_ifnames(): + if i_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") - if r_res['ifname'] in utils.get_ifnames(): + if r_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") @remote_compatible @@ -116,9 +115,9 @@ def test_grpform3_c(dev): dev[1].global_request("SET p2p_no_group_iface 0") [i_res, r_res] = go_neg_pin(i_dev=dev[0], i_intent=15, r_dev=dev[1], r_intent=0) remove_group(dev[0], dev[1]) - if i_res['ifname'] in utils.get_ifnames(): + if i_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") - if r_res['ifname'] in utils.get_ifnames(): + if r_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") @remote_compatible @@ -638,6 +637,7 @@ def clear_pbc_overlap(dev, ap): dev[1].request("P2P_CANCEL") dev[0].p2p_stop_find() dev[1].p2p_stop_find() + remove_group(dev[0], dev[1], allow_failure=True) dev[0].dump_monitor() dev[1].dump_monitor() time.sleep(0.1) @@ -653,9 +653,9 @@ def test_grpform_pbc_overlap(dev, apdev): hapd.request("WPS_PBC") time.sleep(0.1) - # Since P2P Client scan case is now optimzied to use a specific SSID, the + # Since P2P Client scan case is now optimized to use a specific SSID, the # WPS AP will not reply to that and the scan after GO Negotiation can quite - # likely miss the AP due to dwell time being short enoguh to miss the Beacon + # likely miss the AP due to dwell time being short enough to miss the Beacon # frame. This has made the test case somewhat pointless, but keep it here # for now with an additional scan to confirm that PBC detection works if # there is a BSS entry for a overlapping AP. @@ -677,11 +677,11 @@ def test_grpform_pbc_overlap(dev, apdev): raise Exception("Failed to authorize GO Neg") if "OK" not in dev[1].global_request("P2P_CONNECT " + addr0 + " pbc go_intent=15 freq=2412"): raise Exception("Failed to initiate GO Neg") - ev = dev[0].wait_global_event(["WPS-OVERLAP-DETECTED"], timeout=15) - if ev is None: - raise Exception("PBC overlap not reported") - + ev = dev[0].wait_global_event(["WPS-OVERLAP-DETECTED", + "P2P-GROUP-FORMATION-SUCCESS"], timeout=15) clear_pbc_overlap(dev, apdev[0]) + if ev is None or "P2P-GROUP-FORMATION-SUCCESS" not in ev: + raise Exception("P2P group formation did not complete") @remote_compatible def test_grpform_pbc_overlap_group_iface(dev, apdev): @@ -713,14 +713,9 @@ def test_grpform_pbc_overlap_group_iface(dev, apdev): raise Exception("Failed to initiate GO Neg") ev = dev[0].wait_global_event(["WPS-OVERLAP-DETECTED", "P2P-GROUP-FORMATION-SUCCESS"], timeout=15) - if ev is None or "WPS-OVERLAP-DETECTED" not in ev: - # Do not report this as failure since the P2P group formation case - # using a separate group interface has limited chances of "seeing" the - # overlapping AP due to a per-SSID scan and no prior scan operations on - # the group interface. - logger.info("PBC overlap not reported") - clear_pbc_overlap(dev, apdev[0]) + if ev is None or "P2P-GROUP-FORMATION-SUCCESS" not in ev: + raise Exception("P2P group formation did not complete") @remote_compatible def test_grpform_goneg_fail_with_group_iface(dev): @@ -738,11 +733,9 @@ def test_grpform_goneg_fail_with_group_iface(dev): if ev is None: raise Exception("GO Negotiation failure timed out") -def test_grpform_cred_ready_timeout(dev, apdev, params): - """P2P GO Negotiation wait for credentials to become ready [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") - +@long_duration_test +def test_grpform_cred_ready_timeout(dev): + """P2P GO Negotiation wait for credentials to become ready""" dev[1].p2p_listen() addr1 = dev[1].p2p_dev_addr() if not dev[0].discover_peer(addr1): @@ -1185,7 +1178,7 @@ def test_grpform_random_addr(dev): check_grpform_results(i_res, r_res) hwsim_utils.test_connectivity_p2p(dev[0], dev[1]) remove_group(dev[0], dev[1]) - if i_res['ifname'] in utils.get_ifnames(): + if i_res['ifname'] in get_ifnames(): raise Exception("Group interface netdev was not removed") finally: dev[0].global_request("SET p2p_interface_random_mac_addr 0") diff --git a/tests/hwsim/test_pmksa_cache.py b/tests/hwsim/test_pmksa_cache.py index 11daaaa67..526f7f455 100644 --- a/tests/hwsim/test_pmksa_cache.py +++ b/tests/hwsim/test_pmksa_cache.py @@ -662,6 +662,9 @@ def test_pmksa_cache_ap_expiration(dev, apdev): params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache") hapd = hostapd.add_ap(apdev[0], params) bssid = apdev[0]['bssid'] + + dev[0].cmd_execute(['iw', 'dev', dev[0].ifname, + 'set', 'power_save', 'off']) dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="WPA-EAP", eap="GPSK", identity="gpsk-user-session-timeout", password="abcdefghijklmnop0123456789abcdef", @@ -669,20 +672,44 @@ def test_pmksa_cache_ap_expiration(dev, apdev): ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5) if ev is None: raise Exception("No connection event received from hostapd") + hapd.dump_monitor() + dev[0].request("DISCONNECT") + ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=5) + if ev is None: + raise Exception("No disconnection event received from hostapd") + dev[0].wait_disconnected() + + # Wait for session timeout to remove PMKSA cache entry time.sleep(5) dev[0].dump_monitor() + hapd.dump_monitor() + dev[0].request("RECONNECT") ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", "CTRL-EVENT-CONNECTED"], timeout=20) if ev is None: - raise Exception("Roaming with the AP timed out") + raise Exception("Reconnection with the AP timed out") if "CTRL-EVENT-CONNECTED" in ev: raise Exception("EAP exchange missing") dev[0].wait_connected(timeout=20, error="Reconnect timed out") dev[0].dump_monitor() + ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5) + if ev is None: + raise Exception("No connection event received from hostapd [2]") + hapd.dump_monitor() + + # Wait for session timeout + ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=10) + if ev is None: + raise Exception("No disconnection event received from hostapd [2]") dev[0].wait_disconnected(timeout=20) dev[0].wait_connected(timeout=20, error="Reassociation timed out") + ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5) + if ev is None: + raise Exception("No connection event received from hostapd [3]") + hapd.dump_monitor() + dev[0].dump_monitor() def test_pmksa_cache_multiple_sta(dev, apdev): """PMKSA cache with multiple stations""" @@ -1071,6 +1098,66 @@ def test_pmksa_cache_ctrl_ext(dev, apdev): if "CTRL-EVENT-EAP-STARTED" in ev: raise Exception("Unexpected EAP exchange after external PMKSA cache restore") +def test_pmksa_cache_ctrl_ext_ft(dev, apdev): + """PMKSA cache control interface for external management (FT)""" + params = hostapd.wpa2_eap_params(ssid="test-pmksa-cache") + params['wpa_key_mgmt'] = "FT-EAP" + params['nas_identifier'] = "nas.w1.fi" + params['r1_key_holder'] = "000102030406" + params["mobility_domain"] = "a1b2" + hapd = hostapd.add_ap(apdev[0], params) + bssid = apdev[0]['bssid'] + + id = dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="FT-EAP", + eap="GPSK", identity="gpsk user", + password="abcdefghijklmnop0123456789abcdef", + scan_freq="2412") + + res1 = dev[0].request("PMKSA_GET %d" % id) + logger.info("PMKSA_GET: " + res1) + if "UNKNOWN COMMAND" in res1: + raise HwsimSkip("PMKSA_GET not supported in the build") + if bssid not in res1: + raise Exception("PMKSA cache entry missing") + + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + dev[0].dump_monitor() + dev[0].request("PMKSA_FLUSH") + + id = dev[0].connect("test-pmksa-cache", proto="RSN", key_mgmt="FT-EAP", + eap="GPSK", identity="gpsk user", + password="abcdefghijklmnop0123456789abcdef", + ft_eap_pmksa_caching="1", + scan_freq="2412", only_add_network=True) + res3 = dev[0].request("PMKSA_GET %d" % id) + if res3 != '': + raise Exception("Unexpected PMKSA cache entry remains: " + res3) + + for entry in res1.splitlines(): + if "OK" not in dev[0].request("PMKSA_ADD %d %s" % (id, entry)): + raise Exception("Failed to add PMKSA entry") + + dev[0].select_network(id) + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "CTRL-EVENT-CONNECTED"], timeout=15) + if ev is None: + raise Exception("Connection with the AP timed out") + if "CTRL-EVENT-EAP-STARTED" in ev: + raise Exception("Unexpected EAP exchange after external PMKSA cache restore") + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].dump_monitor() + dev[0].request("PMKSA_FLUSH") + # Add a PMKSA cache entry for FT-EAP with PMKSA caching disabled to confirm + # that the PMKID is not configured to the driver (this part requires manual + # check of the debug log currently). + dev[0].set_network(id, "ft_eap_pmksa_caching", "0") + for entry in res1.splitlines(): + if "OK" not in dev[0].request("PMKSA_ADD %d %s" % (id, entry)): + raise Exception("Failed to add PMKSA entry") + def test_rsn_preauth_processing(dev, apdev): """RSN pre-authentication processing on AP""" params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap") diff --git a/tests/hwsim/test_radius.py b/tests/hwsim/test_radius.py index fde5650de..16a29ec85 100644 --- a/tests/hwsim/test_radius.py +++ b/tests/hwsim/test_radius.py @@ -18,7 +18,7 @@ import threading import time import hostapd -from utils import HwsimSkip, require_under_vm, skip_with_fips, alloc_fail, fail_test, wait_fail_trigger +from utils import * from test_ap_hs20 import build_dhcp_ack from test_ap_ft import ft_params1 @@ -442,6 +442,7 @@ def test_radius_acct_ft_psk(dev, apdev): def test_radius_acct_ieee8021x(dev, apdev): """RADIUS Accounting - IEEE 802.1X""" + check_wep_capa(dev[0]) skip_with_fips(dev[0]) as_hapd = hostapd.Hostapd("as") params = hostapd.radius_params() @@ -759,7 +760,7 @@ def test_radius_das_disconnect(dev, apdev): def add_message_auth_req(req): req.authenticator = req.CreateAuthenticator() - hmac_obj = hmac.new(req.secret) + hmac_obj = hmac.new(req.secret, digestmod=hashlib.md5) hmac_obj.update(struct.pack("B", req.code)) hmac_obj.update(struct.pack("B", req.id)) @@ -961,7 +962,7 @@ def test_radius_macacl_unreachable(dev, apdev): hapd.set("auth_server_port", "1812") hapd.disable() hapd.enable() - dev[0].wait_connected() + dev[0].wait_connected(timeout=20) dev[0].request("DISCONNECT") dev[0].wait_disconnected() @@ -1045,7 +1046,7 @@ def test_radius_protocol(dev, apdev): pw = b"incorrect" else: pw = reply.secret - hmac_obj = hmac.new(pw) + hmac_obj = hmac.new(pw, digestmod=hashlib.md5) hmac_obj.update(struct.pack("B", reply.code)) hmac_obj.update(struct.pack("B", reply.id)) @@ -1388,7 +1389,7 @@ def test_radius_auth_force_invalid_client_addr(dev, apdev): def add_message_auth(req): req.authenticator = req.CreateAuthenticator() - hmac_obj = hmac.new(req.secret) + hmac_obj = hmac.new(req.secret, digestmod=hashlib.md5) hmac_obj.update(struct.pack("B", req.code)) hmac_obj.update(struct.pack("B", req.id)) diff --git a/tests/hwsim/test_rrm.py b/tests/hwsim/test_rrm.py index dde98932b..73782c995 100644 --- a/tests/hwsim/test_rrm.py +++ b/tests/hwsim/test_rrm.py @@ -16,11 +16,8 @@ import time import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger -from utils import disable_hapd, clear_regdom_dev, clear_regdom -from test_ap_ht import clear_scan_cache +from utils import * from remotehost import remote_compatible -from test_ap_vht import vht_supported def check_rrm_support(dev): rrm = int(dev.get_driver_status_field("capa.rrm_flags"), 16) @@ -1119,7 +1116,7 @@ def test_rrm_beacon_req_table_bssid(dev, apdev): report = BeaconReport(binascii.unhexlify(fields[4])) logger.info("Received beacon report: " + str(report)) if "bssid=" + bssid2 not in str(report): - raise Exception("Report for unexpect BSS") + raise Exception("Report for unexpected BSS") ev = hapd.wait_event(["BEACON-RESP-RX"], timeout=0.1) if ev is not None: raise Exception("Unexpected beacon report response") @@ -1143,7 +1140,7 @@ def test_rrm_beacon_req_table_ssid(dev, apdev): report = BeaconReport(binascii.unhexlify(fields[4])) logger.info("Received beacon report: " + str(report)) if "bssid=" + bssid2 not in str(report): - raise Exception("Report for unexpect BSS") + raise Exception("Report for unexpected BSS") ev = hapd.wait_event(["BEACON-RESP-RX"], timeout=0.1) if ev is not None: raise Exception("Unexpected beacon report response") @@ -1732,6 +1729,7 @@ def test_rrm_beacon_req_passive_scan_vht160(dev, apdev): "hw_mode": "a", "channel": "104", "ht_capab": "[HT40-]", + "vht_capab": "[VHT160]", "ieee80211n": "1", "ieee80211ac": "1", "vht_oper_chwidth": "2", diff --git a/tests/hwsim/test_sae.py b/tests/hwsim/test_sae.py index a55bd07ef..9276e513e 100644 --- a/tests/hwsim/test_sae.py +++ b/tests/hwsim/test_sae.py @@ -17,13 +17,9 @@ import subprocess import hwsim_utils import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger, start_monitor, stop_monitor, radiotap_build +from utils import * from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations -def check_sae_capab(dev): - if "SAE" not in dev.get_capability("auth_alg"): - raise HwsimSkip("SAE not supported") - @remote_compatible def test_sae(dev, apdev): """SAE with default group""" @@ -363,6 +359,42 @@ def test_sae_mixed_mfp(dev, apdev): dev[2].connect("test-sae", psk="12345678", ieee80211w="0", scan_freq="2412") dev[2].dump_monitor() +def test_sae_and_psk_transition_disable(dev, apdev): + """SAE and PSK transition disable indication""" + check_sae_capab(dev[0]) + params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") + params["ieee80211w"] = "1" + params['wpa_key_mgmt'] = 'SAE WPA-PSK' + params['transition_disable'] = '0x01' + hapd = hostapd.add_ap(apdev[0], params) + + dev[0].request("SET sae_groups ") + id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE WPA-PSK", + ieee80211w="1", scan_freq="2412") + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "01": + raise Exception("Unexpected transition disable bitmap: " + ev) + + val = dev[0].get_network(id, "ieee80211w") + if val != "2": + raise Exception("Unexpected ieee80211w value: " + val) + val = dev[0].get_network(id, "key_mgmt") + if val != "SAE": + raise Exception("Unexpected key_mgmt value: " + val) + val = dev[0].get_network(id, "group") + if val != "CCMP": + raise Exception("Unexpected group value: " + val) + val = dev[0].get_network(id, "proto") + if val != "RSN": + raise Exception("Unexpected proto value: " + val) + + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].request("RECONNECT") + dev[0].wait_connected() + def test_sae_mfp(dev, apdev): """SAE and MFP enabled without sae_require_mfp""" check_sae_capab(dev[0]) @@ -1044,6 +1076,47 @@ def test_sae_proto_hostapd_ffc(dev, apdev): # Unexpected continuation of the connection attempt with confirm hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030002000000" + "0000" + "fd7b081ff4e8676f03612a4140eedcd3c179ab3a13b93863c6f7ca451340b9ae") +def sae_start_ap(apdev, sae_pwe): + params = hostapd.wpa2_params(ssid="test-sae", passphrase="foofoofoo") + params['wpa_key_mgmt'] = 'SAE' + params['sae_groups'] = "19" + params['sae_pwe'] = str(sae_pwe) + return hostapd.add_ap(apdev, params) + +def check_commit_status(hapd, use_status, expect_status): + hapd.set("ext_mgmt_frame_handling", "1") + bssid = hapd.own_addr().replace(':', '') + addr = "020000000000" + addr2 = "020000000001" + hdr = "b0003a01" + bssid + addr + bssid + "1000" + hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" + group = "1300" + scalar = "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + element_x = "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d" + element_y = "d3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8" + status = binascii.hexlify(struct.pack('L', binascii.crc32(ssid.encode())) + val = binascii.hexlify(payload).decode() + sigma = start_sigma_dut(dev[0].ifname) + found = False + try: + cmd = "sta_scan,Interface,%s,ChnlFreq,2412,ShortSSID,%s" % (dev[0].ifname, val) + for i in range(10): + sigma_dut_cmd_check(cmd, timeout=5) + ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS"]) + if ev is None: + raise Exception("Scan did not complete") + if bssid in dev[0].request("SCAN_RESULTS"): + found = True + break + finally: + stop_sigma_dut(sigma) + dev[0].request("VENDOR_ELEM_REMOVE 14 *") + + if not found: + raise Exception("AP not found in scan results") + +def test_sigma_dut_sta_scan_wait_completion(dev, apdev): + """sigma_dut sta_scan WaitCompletion,1""" + sigma = start_sigma_dut(dev[0].ifname) + try: + cmd = "sta_scan,Interface,%s,ChnlFreq,2412,WaitCompletion,1" % dev[0].ifname + res = sigma_dut_cmd(cmd, timeout=10) + finally: + stop_sigma_dut(sigma) + def test_sigma_dut_ap_osen(dev, apdev, params): """sigma_dut controlled AP with OSEN""" logdir = os.path.join(params['logdir'], @@ -3077,14 +3775,9 @@ def test_sigma_dut_ap_ent_ft_eap(dev, apdev, params): finally: stop_sigma_dut(sigma) +@reset_ignore_old_scan_res def test_sigma_dut_venue_url(dev, apdev): """sigma_dut controlled Venue URL fetch""" - try: - run_sigma_dut_venue_url(dev, apdev) - finally: - dev[0].set("ignore_old_scan_res", "0") - -def run_sigma_dut_venue_url(dev, apdev): ifname = dev[0].ifname sigma = start_sigma_dut(ifname) @@ -3282,6 +3975,7 @@ def test_sigma_dut_eap_ttls_uosc_tod_tofu(dev, apdev, params): run_sigma_dut_eap_ttls_uosc_tod(dev, apdev, params, True) def run_sigma_dut_eap_ttls_uosc_tod(dev, apdev, params, tofu): + check_tls_tod(dev[0]) logdir = params['logdir'] name = "sigma_dut_eap_ttls_uosc_tod" @@ -3360,21 +4054,19 @@ def test_sigma_dut_eap_ttls_uosc_initial_tod_tofu(dev, apdev, params): run_sigma_dut_eap_ttls_uosc_initial_tod(dev, apdev, params, True) def run_sigma_dut_eap_ttls_uosc_initial_tod(dev, apdev, params, tofu): + check_tls_tod(dev[0]) logdir = params['logdir'] - - name = "sigma_dut_eap_ttls_uosc_initial_tod" - if tofu: - name += "_tofu" + name = params['name'] with open("auth_serv/rsa3072-ca.pem", "r") as f: - with open(os.path.join(logdir, name + ".ca.pem"), "w") as f2: + with open(params['prefix'] + ".ca.pem", "w") as f2: f2.write(f.read()) if tofu: src = "auth_serv/server-certpol2.pem" else: src = "auth_serv/server-certpol.pem" - dst = os.path.join(logdir, name + ".server.der") - hashdst = os.path.join(logdir, name + ".server.pem.sha256") + dst = params['prefix'] + ".server.der" + hashdst = params['prefix'] + ".server.pem.sha256" subprocess.check_call(["openssl", "x509", "-in", src, "-out", dst, "-outform", "DER"], stderr=open('/dev/null', 'w')) @@ -3716,6 +4408,7 @@ def test_sigma_dut_sae_h2e_enabled_group_rejected(dev, apdev): raise Exception("Unexpected connection reported") finally: stop_sigma_dut(sigma) + dev[0].set("sae_pwe", "0") def test_sigma_dut_sae_h2e_rsnxe_mismatch(dev, apdev): """sigma_dut controlled SAE H2E misbehavior with RSNXE""" @@ -3809,3 +4502,759 @@ def test_sigma_dut_ap_sae_h2e_group_rejection(dev, apdev, params): finally: stop_sigma_dut(sigma) dev[0].set("sae_pwe", "0") + +def test_sigma_dut_ap_sae_h2e_anti_clogging(dev, apdev, params): + """sigma_dut controlled AP with SAE H2E and anti-clogging token""" + logdir = os.path.join(params['logdir'], + "sigma_dut_ap_sae_h2e_anti_clogging.sigma-hostapd") + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, sae_h2e=True, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,SAE,PSK,12345678,AntiCloggingThreshold,0") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + + dev[0].set("sae_groups", "") + dev[0].set("sae_pwe", "2") + dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", + ieee80211w="2", scan_freq="2412") + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) + dev[0].set("sae_pwe", "0") + +def test_sigma_dut_ap_5ghz(dev, apdev, params): + """sigma_dut controlled AP on 5 GHz""" + run_sigma_dut_ap_channel(dev, apdev, params, 36, '11na', 5180, + check_signal="WIDTH=20 MHz") + +def test_sigma_dut_ap_ht40plus(dev, apdev, params): + """sigma_dut controlled AP and HT40+""" + run_sigma_dut_ap_channel(dev, apdev, params, 36, '11na', 5180, + extra="width,40", check_signal="WIDTH=40 MHz") + +def test_sigma_dut_ap_ht40minus(dev, apdev, params): + """sigma_dut controlled AP and HT40-""" + run_sigma_dut_ap_channel(dev, apdev, params, 40, '11na', 5200, + extra="width,40", check_signal="WIDTH=40 MHz") + +def test_sigma_dut_ap_vht40(dev, apdev, params): + """sigma_dut controlled AP and VHT40""" + run_sigma_dut_ap_channel(dev, apdev, params, 36, '11ac', 5180, + extra="width,40", check_signal="WIDTH=40 MHz", + program="VHT") + +def test_sigma_dut_ap_vht80(dev, apdev, params): + """sigma_dut controlled AP and VHT80""" + run_sigma_dut_ap_channel(dev, apdev, params, 36, '11ac', 5180, + extra="width,80", check_signal="WIDTH=80 MHz", + program="VHT") + +def run_sigma_dut_ap_channel(dev, apdev, params, channel, mode, scan_freq, + extra=None, check_signal=None, program=None): + logdir = params['prefix'] + ".sigma-hostapd" + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + subprocess.call(['iw', 'reg', 'set', 'US']) + cmd = "ap_reset_default" + if program: + cmd += ",program," + program + sigma_dut_cmd_check(cmd) + cmd = "ap_set_wireless,NAME,AP,CHANNEL,%d,SSID,test-psk,MODE,%s" % (channel, mode) + if extra: + cmd += "," + extra + sigma_dut_cmd_check(cmd) + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-PSK,PSK,12345678") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + + with open("/tmp/sigma_dut-ap.conf", "rb") as f: + with open(params['prefix'] + ".sigma-conf", "wb") as f2: + f2.write(f.read()) + + dev[0].connect("test-psk", psk="12345678", scan_freq=str(scan_freq)) + sig = dev[0].request("SIGNAL_POLL") + logger.info("SIGNAL_POLL:\n" + sig.strip()) + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + + sigma_dut_cmd_check("ap_reset_default") + + if check_signal and check_signal not in sig: + raise Exception("Unexpected SIGNAL_POLL data") + finally: + stop_sigma_dut(sigma) + subprocess.call(['iw', 'reg', 'set', '00']) + dev[0].flush_scan_cache() + +@reset_ignore_old_scan_res +def test_sigma_dut_beacon_prot(dev, apdev): + """sigma_dut controlled STA and beacon protection""" + ssid = "test-pmf-required" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params["wpa_key_mgmt"] = "WPA-PSK-SHA256" + params["ieee80211w"] = "2" + params["beacon_prot"] = "1" + try: + hapd = hostapd.add_ap(apdev[0], params) + except Exception as e: + if "Failed to enable hostapd interface" in str(e): + raise HwsimSkip("Beacon protection not supported") + raise + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + try: + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,PMF" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,type,PSK,passphrase,%s,encpType,aes-ccmp,keymgmttype,wpa2,PMF,Required,BeaconProtection,1" % (ifname, "test-pmf-required", "12345678")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-pmf-required"), + timeout=10) + sigma_dut_wait_connected(ifname) + + time.sleep(1) + check_mac80211_bigtk(dev[0], hapd) + + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) + +def test_sigma_dut_ap_beacon_prot(dev, apdev, params): + """sigma_dut controlled AP and beacon protection""" + logdir = params['prefix'] + ".sigma-hostapd" + + Wlantest.setup(None) + wt = Wlantest() + wt.flush() + wt.add_passphrase("12345678") + + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-psk,MODE,11ng") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-PSK,PSK,12345678,PMF,Required,BeaconProtection,1") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + bssid = sigma_dut_cmd_check("ap_get_mac_address,NAME,AP") + bssid = bssid.split(',')[3] + + dev[0].connect("test-psk", key_mgmt="WPA-PSK-SHA256", + psk="12345678", scan_freq="2412", + ieee80211w="2", beacon_prot="1") + time.sleep(1) + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) + + valid_bip = wt.get_bss_counter('valid_bip_mmie', bssid) + invalid_bip = wt.get_bss_counter('invalid_bip_mmie', bssid) + missing_bip = wt.get_bss_counter('missing_bip_mmie', bssid) + logger.info("wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip)) + if valid_bip < 0 or invalid_bip > 0 or missing_bip > 0: + raise Exception("Unexpected wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip)) + +def test_sigma_dut_ap_transition_disable(dev, apdev, params): + """sigma_dut controlled AP and transition disabled indication""" + logdir = params['prefix'] + ".sigma-hostapd" + + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678,PMF,Required,Transition_Disable,1,Transition_Disable_Index,0") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + + dev[0].set("sae_groups", "") + dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", + ieee80211w="2", scan_freq="2412") + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "01": + raise Exception("Unexpected transition disable bitmap: " + ev) + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) + +def test_sigma_dut_ap_transition_disable_change(dev, apdev, params): + """sigma_dut controlled AP and transition disabled indication change""" + logdir = params['prefix'] + ".sigma-hostapd" + + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678,PMF,Required") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + dev[0].set("sae_groups", "") + dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", + ieee80211w="2", scan_freq="2412") + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is not None: + raise Exception("Unexpected transition disable indication") + dev[0].request("DISCONNECT") + dev[0].wait_disconnected() + dev[0].dump_monitor() + + sigma_dut_cmd_check("ap_set_rfeature,NAME,AP,Transition_Disable,1,Transition_Disable_Index,0") + dev[0].request("RECONNECT") + dev[0].wait_connected() + ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "01": + raise Exception("Unexpected transition disable bitmap: " + ev) + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) + +def test_sigma_dut_ft_rsnxe_used_mismatch(dev, apdev): + """sigma_dut controlled FT protocol with RSNXE Used mismatch""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + try: + ssid = "test-sae" + params = hostapd.wpa2_params(ssid=ssid) + params['wpa_key_mgmt'] = 'SAE FT-SAE' + params["ieee80211w"] = "2" + params['sae_password'] = "hello" + params['sae_pwe'] = "2" + params['mobility_domain'] = 'aabb' + bssid = apdev[0]['bssid'].replace(':', '') + params['nas_identifier'] = bssid + '.nas.example.com' + params['r1_key_holder'] = bssid + params['pmk_r1_push'] = '0' + params['r0kh'] = 'ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff' + params['r1kh'] = '00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff' + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + sigma_dut_cmd_check("sta_reset_default,interface,%s" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,AKMSuiteType,8;9" % (ifname, "test-sae", "hello")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"), + timeout=10) + sigma_dut_wait_connected(ifname) + dev[0].dump_monitor() + + bssid2 = apdev[1]['bssid'].replace(':', '') + params['nas_identifier'] = bssid2 + '.nas.example.com' + params['r1_key_holder'] = bssid2 + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + + sigma_dut_cmd_check("sta_reassoc,interface,%s,Channel,1,bssid,%s" % (ifname, bssid2)) + count = 0 + for i in range(5): + ev = dev[0].wait_event(["Trying to associate", + "CTRL-EVENT-CONNECTED"], timeout=10) + if ev is None: + raise Exception("Connection timed out") + if "CTRL-EVENT-CONNECTED" in ev: + break + count += 1 + dev[0].dump_monitor() + if count != 1: + raise Exception("Unexpected number of association attempts for the first FT protocol exchange (expecting success)") + + sigma_dut_cmd_check("sta_set_rfeature,interface,%s,prog,WPA3,ReassocReq_RSNXE_Used,1" % ifname) + sigma_dut_cmd_check("sta_reassoc,interface,%s,Channel,1,bssid,%s" % (ifname, bssid)) + count = 0 + for i in range(5): + ev = dev[0].wait_event(["Trying to associate", + "CTRL-EVENT-CONNECTED"], timeout=10) + if ev is None: + raise Exception("Connection timed out") + if "CTRL-EVENT-CONNECTED" in ev: + break + count += 1 + dev[0].dump_monitor() + if count != 2: + raise Exception("Unexpected number of association attempts for the second FT protocol exchange (expecting failure)") + + sigma_dut_cmd_check("sta_disconnect,interface," + ifname) + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) + +def test_sigma_dut_ap_ft_rsnxe_used_mismatch(dev, apdev, params): + """sigma_dut controlled AP with FT and RSNXE Used mismatch""" + logdir = params['prefix'] + ".sigma-hostapd" + conffile = params['prefix'] + ".sigma-conf" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng,DOMAIN,aabb") + sigma_dut_cmd_check("ap_set_security,NAME,AP,AKMSuiteType,8;9,SAEPasswords,hello,PMF,Required") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + + with open("/tmp/sigma_dut-ap.conf", "rb") as f: + with open(conffile, "wb") as f2: + f2.write(f.read()) + + dev[0].connect("test-sae", key_mgmt="FT-SAE", sae_password="hello", + ieee80211w="2", scan_freq="2412") + + sigma_dut_cmd_check("ap_set_rfeature,NAME,AP,type,WPA3,ReassocResp_RSNXE_Used,1") + # This would need to be followed by FT protocol roaming test, but + # that is not currently convenient to implement, so for now, this + # test is based on manual inspection of hostapd getting configured + # properly. + + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) + +def test_sigma_dut_ocv(dev, apdev): + """sigma_dut controlled STA using OCV""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + try: + ssid = "test-sae" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + params['sae_groups'] = '19' + params['ocv'] = '1' + hapd = hostapd.add_ap(apdev[0], params) + + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_wireless,interface,%s,program,WPA3,ocvc,1" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2" % (ifname, "test-sae", "12345678")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"), + timeout=10) + sigma_dut_wait_connected(ifname) + + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_wireless,interface,%s,program,WPA3,ocvc,1" % ifname) + sigma_dut_cmd_check("sta_set_rfeature,interface,%s,prog,WPA3,OCIFrameType,eapolM2,OCIChannel,11" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2" % (ifname, "test-sae", "12345678")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae")) + ev = hapd.wait_event(["OCV-FAILURE"], timeout=1) + if ev is None: + raise Exception("OCV failure for EAPOL-Key msg 2/4 not reported") + if "addr=" + dev[0].own_addr() not in ev: + raise Exception("Unexpected OCV failure addr: " + ev) + if "frame=eapol-key-m2" not in ev: + raise Exception("Unexpected OCV failure frame: " + ev) + if "error=primary channel mismatch" not in ev: + raise Exception("Unexpected OCV failure error: " + ev) + + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) + +def test_sigma_dut_ap_ocv(dev, apdev, params): + """sigma_dut controlled AP using OCV""" + logdir = params['prefix'] + ".sigma-hostapd" + conffile = params['prefix'] + ".sigma-conf" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,ocvc,1") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + bssid = sigma_dut_cmd_check("ap_get_mac_address,NAME,AP") + bssid = bssid.split(',')[3] + + with open("/tmp/sigma_dut-ap.conf", "rb") as f: + with open(conffile, "wb") as f2: + f2.write(f.read()) + + dev[0].set("sae_groups", "") + dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", + ieee80211w="2", ocv="1", scan_freq="2412") + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + dev[0].dump_monitor() + + sigma_dut_cmd_check("ap_set_rfeature,NAME,AP,type,WPA3,OCIFrameType,eapolM3,OCIChannel,3") + dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", + ieee80211w="2", ocv="1", scan_freq="2412", + wait_connect=False) + check_ocv_failure(dev[0], "EAPOL-Key msg 3/4", "eapol-key-m3", + bssid) + dev[0].request("REMOVE_NETWORK all") + dev[0].wait_disconnected() + dev[0].dump_monitor() + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) + +def test_sigma_dut_gtk_rekey(dev, apdev): + """sigma_dut controlled STA requesting GTK rekeying""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + try: + ssid = "test-sae" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + params['sae_groups'] = '19' + hapd = hostapd.add_ap(apdev[0], params) + + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_wireless,interface,%s,program,WPA3,ocvc,1" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2" % (ifname, "test-sae", "12345678")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"), + timeout=10) + sigma_dut_wait_connected(ifname) + + dev[0].dump_monitor() + sigma_dut_cmd_check("dev_exec_action,interface,%s,program,WPA3,KeyRotation,1" % ifname) + ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=5) + if ev is None: + raise Exception("GTK rekeying not seen") + + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) + +def test_sigma_dut_ap_gtk_rekey(dev, apdev, params): + """sigma_dut controlled AP and requested GTK rekeying""" + logdir = params['prefix'] + ".sigma-hostapd" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,test-sae,MODE,11ng") + sigma_dut_cmd_check("ap_set_security,NAME,AP,KEYMGNT,WPA2-SAE,PSK,12345678") + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + + dev[0].set("sae_groups", "") + dev[0].connect("test-sae", key_mgmt="SAE", psk="12345678", + ieee80211w="2", scan_freq="2412") + dev[0].dump_monitor() + + sigma_dut_cmd_check("dev_exec_action,name,AP,interface,%s,program,WPA3,KeyRotation,1" % iface) + + ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=5) + if ev is None: + raise Exception("GTK rekeying not seen") + + sigma_dut_cmd_check("ap_reset_default") + finally: + stop_sigma_dut(sigma) + +def test_sigma_dut_sae_pk(dev, apdev): + """sigma_dut controlled STA using SAE-PK""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + ssid = "SAE-PK test" + pw = "hbbi-f4xq-b45g" + m = "d2e5fa27d1be8897f987f2d480d2af6b" + pk = "MHcCAQEEIAJIGlfnteonDb7rQyP/SGQjwzrZAnfrXIm4280VWajYoAoGCCqGSM49AwEHoUQDQgAEeRkstKQV+FSAMqBayqFknn2nAQsdsh/MhdX6tiHOTAFin/sUMFRMyspPtIu7YvlKdsexhI0jPVhaYZn1jKWhZg==" + + try: + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + params['sae_groups'] = '19' + params['sae_password'] = ['%s|pk=%s:%s' % (pw, m, pk)] + hapd = hostapd.add_ap(apdev[0], params) + + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_wireless,interface,%s,program,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2,sae_pk,1" % (ifname, ssid, pw)) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, ssid), + timeout=10) + sigma_dut_wait_connected(ifname) + dev[0].dump_monitor() + + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) + +def run_sigma_dut_ap_sae_pk(conffile, dev, ssid, pw, keypair, m, failure, + status=None, omit=False, immediate=False, sig=None): + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,%s,MODE,11ng" % ssid) + cmd = "ap_set_security,NAME,AP,AKMSuiteType,8,PairwiseCipher,AES-CCMP-128,GroupCipher,AES-CCMP-128,GroupMgntCipher,BIP-CMAC-128,PMF,Required,PSK,%s,sae_pk,1,Transition_Disable,1,Transition_Disable_Index,0,SAE_PK_KeyPair,%s,SAE_PK_Modifier,%s" % (pw, keypair, m) + if status is not None: + cmd += ",SAE_Commit_StatusCode,%d" % status + if omit: + cmd += ",SAE_PK_Omit,1" + if immediate: + cmd += ",SAE_Confirm_Immediate,1" + if sig: + cmd += ",SAE_PK_KeyPairSigOverride," + sig + sigma_dut_cmd_check(cmd) + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + bssid = sigma_dut_cmd_check("ap_get_mac_address,NAME,AP") + bssid = bssid.split(',')[3] + + with open("/tmp/sigma_dut-ap.conf", "rb") as f: + with open(conffile, "ab") as f2: + f2.write(f.read()) + f2.write('\n'.encode()) + + dev.set("sae_groups", "") + dev.connect(ssid, key_mgmt="SAE", sae_password=pw, ieee80211w="2", + scan_freq="2412", wait_connect=False) + + ev = dev.wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=15) + if ev is None: + raise Exception("No connection result reported") + + bss = dev.get_bss(bssid) + if 'flags' not in bss: + raise Exception("Could not get BSS flags from BSS table") + if "[SAE-H2E]" not in bss['flags'] or "[SAE-PK]" not in bss['flags']: + raise Exception("Unexpected BSS flags: " + bss['flags']) + + if failure: + if "CTRL-EVENT-CONNECTED" in ev: + raise Exception("Unexpected connection") + dev.request("REMOVE_NETWORK all") + else: + if "CTRL-EVENT-CONNECTED" not in ev: + raise Exception("Connection failed") + dev.request("REMOVE_NETWORK all") + dev.wait_disconnected() + dev.dump_monitor() + + sigma_dut_cmd_check("ap_reset_default") + +def test_sigma_dut_ap_sae_pk(dev, apdev, params): + """sigma_dut controlled AP using SAE-PK""" + logdir = params['prefix'] + ".sigma-hostapd" + conffile = params['prefix'] + ".sigma-conf" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + tests = [("SAEPK-4.7.1.1", "ya3o-zvm2-r4so", "saepk1.pem", + "faa1ef5094bdb4cb2836332ca2c09839", False), + ("SAEPK-4.7.1.2", "xcc2-qwru-yg23", "saepk1.pem", + "b1b30107eb74de2f25afd079bb4196c1", False), + ("SAEPK-4.7.1.3", "skqz-6scq-zcqv", "saepk1.pem", + "4c0ff61465e0f298510254ff54916c71", False), + ("SAEPK-4.7.1.4", "r6em-rya4-tqfa", "saepkP384.pem", + "fb811655209e9edf347a675ddd3e9c82", False), + ("SAEPK-4.7.1.5", "6kjo-umvi-7x3w", "saepkP521.pem", + "cccb76bc0f113ab754826ba9538d66f5", False), + ("SAEPK-5.7.1.1", "sw4h-re63-wgqg", "saepk1.pem", + "0d126f302d85ac809a6a4229dbbe3c75", False), + ("SAEPK-5.7.1.2", "wewq-r4kg-4ioz-xb2p", "saepk1.pem", + "d6b1d8924b1a462677e67b3bbfe73977", False), + ("SAEPK-5.7.1.3", "vb3v-5skk-5eft-v4hu-w2c5", "saepk1.pem", + "41f8cfceb96ebc5c8af9677d22749fad", False), + ("SAEPK-5.7.1.4", "2qsw-6tgy-xnwa-s7lo-75tq-qggr", "saepk1.pem", + "089e8d4a3a79ec637c54dd7bd61972f2", False), + ("SAE-PK test", "hbbi-f4xq-b45g", "saepkP256.pem", + "d2e5fa27d1be8897f987f2d480d2af6b", False), + ("SAE-PK test", "hbbi-f4xq-b457-jje4", "saepkP256.pem", + "d2e5fa27d1be8897f987f2d480d2af6b", False), + ("SAE-PK test", "hbbi-f4xq-b457-jjew-muei", "saepkP256.pem", + "d2e5fa27d1be8897f987f2d480d2af6b", False), + ("SAE-PK test", "hbbi-f4xq-b457-jjew-muey-fod3", "saepkP256.pem", + "d2e5fa27d1be8897f987f2d480d2af6b", False), + ("SAEPK-5.7.1.1", "sw4h-re63-wgqg", "saepk1.pem", + "0d126f302d85ac809a6a4229dbbe3c75", False), + ("SAEPK-5.7.1.10", "tkor-7nb3-r7tv", "saepkP384.pem", + "af1a3df913fc0103f65f105ed1472277", False), + ("SAEPK-5.7.1.11", "yjl3-vfvu-w6r3", "saepkP521.pem", + "24dadf9d253c4169c9647a21cb54fc57", False), + ("SAEPK-5.7.2.1", "rntm-tkrp-xgke", "saepk1.pem", + "cd38ccce3baff627d09bee7b9530d6ce", False), + ("SAEPK-5.7.2.2", "7lt7-7dqt-6abk", "saepk1.pem", + "a22fc8489932597c9e83de62dec02b21", False), + ("SAEPK-5.7.2.3", "sw4h-re63-wgqg", "saepk2.pem", + "1f4a4c7d290d97e0b6ab0cbbbfa0726d", True), + ("SAEPK-5.7.2.4", "rmj3-ya7b-42k4", "saepk1.pem", + "5f65e2bc37f8494de7a605ff615c8b6a", False), + ("SAEPK-5.7.2.4", "rmj3-ya7b-42k4", "saepk2.pem", + "5f65e2bc37f8494de7a605ff615c8b6a", True), + ("SAEPK-5.7.3", "4322-ufus-4bhm", "saepk1.pem", + "21ede99abc46679646693cafe4677d4e", False)] + + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + for ssid, pw, keypair, m, failure in tests: + run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m, + failure) + finally: + stop_sigma_dut(sigma) + +def test_sigma_dut_ap_sae_pk_misbehavior(dev, apdev, params): + """sigma_dut controlled AP using SAE-PK misbehavior""" + logdir = params['prefix'] + ".sigma-hostapd" + conffile = params['prefix'] + ".sigma-conf" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + ssid = "SAEPK-4.7.1.1" + pw = "rmj3-ya7b-42k4" + keypair = "saepk1.pem" + m = "faa1ef5094bdb4cb2836332ca2c09839" + + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m, + True, status=126) + run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m, + True, omit=True) + run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m, + True, status=126, omit=True, immediate=True) + run_sigma_dut_ap_sae_pk(conffile, dev[0], ssid, pw, keypair, m, + True, sig="saepk2.pem") + finally: + stop_sigma_dut(sigma) + +def run_sigma_dut_ap_sae_pk_mixed(conffile, dev, ssid, pw, keypair, m, failure): + sigma_dut_cmd_check("ap_reset_default") + sigma_dut_cmd_check("ap_set_wireless,NAME,AP,CHANNEL,1,SSID,%s,MODE,11ng" % ssid) + cmd = "ap_set_security,NAME,AP,AKMSuiteType,2;8,PairwiseCipher,AES-CCMP-128,GroupCipher,AES-CCMP-128,GroupMgntCipher,BIP-CMAC-128,PMF,Required,PSK,%s,sae_pk,0,Transition_Disable,0" % (pw) + sigma_dut_cmd_check(cmd) + sigma_dut_cmd_check("ap_config_commit,NAME,AP") + bssid = sigma_dut_cmd_check("ap_get_mac_address,NAME,AP") + bssid = bssid.split(',')[3] + + with open("/tmp/sigma_dut-ap.conf", "rb") as f: + with open(conffile, "ab") as f2: + f2.write(f.read()) + f2.write('\n'.encode()) + + sigma_dut_cmd_check("ap_set_rfeature,NAME,AP,type,WPA3,Transition_Disable,1,Transition_Disable_Index,0") + + dev[0].set("sae_groups", "") + dev[0].connect(ssid, key_mgmt="SAE", sae_password=pw, ieee80211w="2", + scan_freq="2412") + dev[1].connect(ssid, key_mgmt="WPA-PSK", psk=pw, ieee80211w="2", + scan_freq="2412") + + sigma_dut_cmd_check("ap_reset_default") + +def test_sigma_dut_ap_sae_pk_mixed(dev, apdev, params): + """sigma_dut controlled AP using SAE-PK(disabled) and PSK""" + logdir = params['prefix'] + ".sigma-hostapd" + conffile = params['prefix'] + ".sigma-conf" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + ssid = "SAEPK-5.7.3" + pw = "4322-ufus-4bhm" + keypair = "saepk1.pem" + m = "21ede99abc46679646693cafe4677d4e" + + with HWSimRadio() as (radio, iface): + sigma = start_sigma_dut(iface, hostapd_logdir=logdir) + try: + run_sigma_dut_ap_sae_pk_mixed(conffile, dev, ssid, pw, keypair, + m, False) + finally: + stop_sigma_dut(sigma) + +def test_sigma_dut_client_privacy(dev, apdev, params): + """sigma_dut client privacy""" + logdir = params['logdir'] + + ssid = "test" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + hapd = hostapd.add_ap(apdev[0], params) + + ifname = dev[0].ifname + addr = dev[0].own_addr() + sigma = start_sigma_dut(ifname) + try: + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_wireless,interface,%s,program,WPA3,ClientPrivacy,1" % ifname) + cmd = "sta_scan,Interface,%s,ChnlFreq,2412,WaitCompletion,1" % dev[0].ifname + sigma_dut_cmd_check(cmd, timeout=10) + time.sleep(2) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_psk,interface,%s,ssid,%s,passphrase,%s,encpType,aes-ccmp,keymgmttype,wpa2" % (ifname, ssid, "12345678")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, ssid), + timeout=10) + sigma_dut_wait_connected(ifname) + sigma_dut_cmd_check("sta_get_ip_config,interface," + ifname) + sigma_dut_cmd_check("sta_disconnect,interface," + ifname) + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) + dev[1].set("mac_addr", "0", allow_fail=True) + dev[1].set("rand_addr_lifetime", "60", allow_fail=True) + dev[1].set("preassoc_mac_addr", "0", allow_fail=True) + dev[1].set("gas_rand_mac_addr", "0", allow_fail=True) + dev[1].set("gas_rand_addr_lifetime", "60", allow_fail=True) + + out = run_tshark(os.path.join(logdir, "hwsim0.pcapng"), + "wlan.addr == " + addr, + display=["wlan.ta"]) + res = out.splitlines() + if len(res) > 0: + raise Exception("Permanent address used unexpectedly") + +def test_sigma_dut_wpa3_inject_frame(dev, apdev): + """sigma_dut and WPA3 frame inject""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + + ifname = dev[0].ifname + sigma = start_sigma_dut(ifname) + + try: + ssid = "test-sae" + params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678") + params['wpa_key_mgmt'] = 'SAE' + params["ieee80211w"] = "2" + params["ocv"] = "1" + params['sae_groups'] = '19 20 21' + hapd = hostapd.add_ap(apdev[0], params) + + sigma_dut_cmd_check("sta_reset_default,interface,%s,prog,WPA3" % ifname) + sigma_dut_cmd_check("sta_set_ip_config,interface,%s,dhcp,0,ip,127.0.0.11,mask,255.255.255.0" % ifname) + sigma_dut_cmd_check("sta_set_wireless,interface,%s,program,WPA3,ocvc,1" % ifname) + sigma_dut_cmd_check("sta_set_security,interface,%s,ssid,%s,passphrase,%s,type,SAE,encpType,aes-ccmp,keymgmttype,wpa2" % (ifname, "test-sae", "12345678")) + sigma_dut_cmd_check("sta_associate,interface,%s,ssid,%s,channel,1" % (ifname, "test-sae"), + timeout=10) + sigma_dut_wait_connected(ifname) + sigma_dut_cmd("dev_send_frame,interface,%s,program,WPA3,framename,SAQueryReq,OCIChannel,2" % ifname) + sigma_dut_cmd("dev_send_frame,interface,%s,program,WPA3,framename,SAQueryReq,OCIChannel,1" % ifname) + sigma_dut_cmd("dev_send_frame,interface,%s,program,WPA3,framename,ReassocReq" % ifname) + hwsim_utils.test_connectivity(dev[0], hapd) + sigma_dut_cmd_check("sta_reset_default,interface," + ifname) + finally: + stop_sigma_dut(sigma) diff --git a/tests/hwsim/test_ssid.py b/tests/hwsim/test_ssid.py index d4ee4e370..faee75d5f 100644 --- a/tests/hwsim/test_ssid.py +++ b/tests/hwsim/test_ssid.py @@ -77,7 +77,7 @@ def test_ssid_utf8(dev, apdev): if "[UTF-8]" not in dev[0].request("SCAN_RESULTS"): raise Exception("[UTF-8] flag not included in SCAN_RESULTS") -def clear_scan_cache(hapd, dev): +def clear_scan_cache2(hapd, dev): # clear BSS table to avoid issues in following test cases dev[0].request("REMOVE_NETWORK all") dev[1].request("REMOVE_NETWORK all") @@ -97,7 +97,7 @@ def test_ssid_hidden(dev, apdev): ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) if ev is not None: raise Exception("Unexpected connection") - clear_scan_cache(hapd, dev) + clear_scan_cache2(hapd, dev) @remote_compatible def test_ssid_hidden2(dev, apdev): @@ -110,7 +110,7 @@ def test_ssid_hidden2(dev, apdev): ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) if ev is not None: raise Exception("Unexpected connection") - clear_scan_cache(hapd, dev) + clear_scan_cache2(hapd, dev) @remote_compatible def test_ssid_hidden_wpa2(dev, apdev): @@ -124,4 +124,4 @@ def test_ssid_hidden_wpa2(dev, apdev): ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) if ev is not None: raise Exception("Unexpected connection") - clear_scan_cache(hapd, dev) + clear_scan_cache2(hapd, dev) diff --git a/tests/hwsim/test_suite_b.py b/tests/hwsim/test_suite_b.py index f61947251..7065b18bd 100644 --- a/tests/hwsim/test_suite_b.py +++ b/tests/hwsim/test_suite_b.py @@ -672,3 +672,68 @@ def test_openssl_ecdh_curves(dev, apdev): raise Exception("EAP failure not reported") dev[0].request("REMOVE_NETWORK all") dev[0].wait_disconnected() + +def test_suite_b_192_pmksa_caching_roam(dev, apdev): + """WPA2/GCMP-256 connection at Suite B 192-bit level using PMKSA caching and roaming""" + check_suite_b_192_capa(dev) + dev[0].flush_scan_cache() + params = suite_b_192_ap_params() + hapd = hostapd.add_ap(apdev[0], params) + bssid = hapd.own_addr() + + dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B-192", + ieee80211w="2", + openssl_ciphers="SUITEB192", + eap="TLS", identity="tls user", + ca_cert="auth_serv/ec2-ca.pem", + client_cert="auth_serv/ec2-user.pem", + private_key="auth_serv/ec2-user.key", + pairwise="GCMP-256", group="GCMP-256", scan_freq="2412") + ev = dev[0].wait_event(["PMKSA-CACHE-ADDED"], timeout=5) + if ev is None: + raise Exception("PMKSA cache entry not added for AP1") + hapd.wait_sta() + dev[0].dump_monitor() + + hapd2 = hostapd.add_ap(apdev[1], params) + bssid2 = hapd2.own_addr() + dev[0].scan_for_bss(bssid2, freq=2412) + dev[0].request("ROAM " + bssid2) + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "CTRL-EVENT-CONNECTED"], timeout=20) + if ev is None: + raise Exception("Roaming with the AP timed out") + if "CTRL-EVENT-EAP-STARTED" not in ev: + raise Exception("EAP exchange not seen") + ev = dev[0].wait_connected() + if bssid2 not in ev: + raise Exception("Roam to AP2 connected back to AP1") + ev = dev[0].wait_event(["PMKSA-CACHE-ADDED"], timeout=5) + if ev is None: + raise Exception("PMKSA cache entry not added for AP2") + hapd2.wait_sta() + dev[0].dump_monitor() + + dev[0].request("ROAM " + bssid) + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "CTRL-EVENT-CONNECTED"], timeout=20) + if ev is None: + raise Exception("Roaming with the AP timed out") + if "CTRL-EVENT-EAP-STARTED" in ev: + raise Exception("Unexpected EAP exchange") + if bssid not in ev: + raise Exception("Roam to AP1 connected back to AP2") + hapd.wait_sta() + dev[0].dump_monitor() + + dev[0].request("ROAM " + bssid2) + ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED", + "CTRL-EVENT-CONNECTED"], timeout=20) + if ev is None: + raise Exception("Roaming with the AP timed out") + if "CTRL-EVENT-EAP-STARTED" in ev: + raise Exception("Unexpected EAP exchange") + if bssid2 not in ev: + raise Exception("Second roam to AP2 connected back to AP1") + hapd2.wait_sta() + dev[0].dump_monitor() diff --git a/tests/hwsim/test_wep.py b/tests/hwsim/test_wep.py index d6af730ae..6df9ef899 100644 --- a/tests/hwsim/test_wep.py +++ b/tests/hwsim/test_wep.py @@ -11,11 +11,12 @@ import subprocess from remotehost import remote_compatible import hostapd import hwsim_utils -from utils import clear_regdom +from utils import * @remote_compatible def test_wep_open_auth(dev, apdev): """WEP Open System authentication""" + check_wep_capa(dev[0]) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-open", "wep_key0": '"hello"'}) @@ -35,6 +36,8 @@ def test_wep_open_auth(dev, apdev): @remote_compatible def test_wep_shared_key_auth(dev, apdev): """WEP Shared Key authentication""" + check_wep_capa(dev[0]) + check_wep_capa(dev[1]) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-shared-key", "wep_key0": '"hello12345678"', @@ -50,6 +53,7 @@ def test_wep_shared_key_auth(dev, apdev): @remote_compatible def test_wep_shared_key_auth_not_allowed(dev, apdev): """WEP Shared Key authentication not allowed""" + check_wep_capa(dev[0]) hostapd.add_ap(apdev[0], {"ssid": "wep-shared-key", "wep_key0": '"hello12345678"', @@ -63,6 +67,9 @@ def test_wep_shared_key_auth_not_allowed(dev, apdev): def test_wep_shared_key_auth_multi_key(dev, apdev): """WEP Shared Key authentication with multiple keys""" + check_wep_capa(dev[0]) + check_wep_capa(dev[1]) + check_wep_capa(dev[2]) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-shared-key", "wep_key0": '"hello12345678"', @@ -92,6 +99,7 @@ def test_wep_shared_key_auth_multi_key(dev, apdev): def test_wep_ht_vht(dev, apdev): """WEP and HT/VHT""" + check_wep_capa(dev[0]) dev[0].flush_scan_cache() try: hapd = None @@ -124,6 +132,7 @@ def test_wep_ht_vht(dev, apdev): def test_wep_ifdown(dev, apdev): """AP with WEP and external ifconfig down""" + check_wep_capa(dev[0]) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-open", "wep_key0": '"hello"'}) diff --git a/tests/hwsim/test_wext.py b/tests/hwsim/test_wext.py index 1668ccd69..e14eecede 100644 --- a/tests/hwsim/test_wext.py +++ b/tests/hwsim/test_wext.py @@ -11,7 +11,7 @@ import os import hostapd import hwsim_utils from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, skip_with_fips +from utils import * from test_rfkill import get_rfkill def get_wext_interface(): @@ -55,6 +55,7 @@ def test_wext_wpa2_psk(dev, apdev): def test_wext_wpa_psk(dev, apdev): """WEXT driver interface with WPA-PSK""" skip_with_fips(dev[0]) + skip_without_tkip(dev[0]) wpas = get_wext_interface() params = hostapd.wpa_params(ssid="wext-wpa-psk", passphrase="12345678") @@ -149,6 +150,7 @@ def test_wext_pmksa_cache(dev, apdev): def test_wext_wep_open_auth(dev, apdev): """WEP Open System authentication""" wpas = get_wext_interface() + check_wep_capa(wpas) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-open", @@ -162,6 +164,7 @@ def test_wext_wep_open_auth(dev, apdev): def test_wext_wep_shared_key_auth(dev, apdev): """WEP Shared Key authentication""" wpas = get_wext_interface() + check_wep_capa(wpas) hapd = hostapd.add_ap(apdev[0], {"ssid": "wep-shared-key", diff --git a/tests/hwsim/test_wpas_ap.py b/tests/hwsim/test_wpas_ap.py index 5d6dfedde..b5b43114a 100644 --- a/tests/hwsim/test_wpas_ap.py +++ b/tests/hwsim/test_wpas_ap.py @@ -4,13 +4,14 @@ # This software may be distributed under the terms of the BSD license. # See README for more details. +import hostapd from remotehost import remote_compatible import time import logging logger = logging.getLogger() import hwsim_utils -from utils import HwsimSkip, alloc_fail, clear_regdom_dev +from utils import * from wpasupplicant import WpaSupplicant from test_p2p_channel import set_country @@ -103,6 +104,7 @@ def test_wpas_ap_open_isolate(dev): @remote_compatible def test_wpas_ap_wep(dev): """wpa_supplicant AP mode - WEP""" + check_wep_capa(dev[0]) id = dev[0].add_network() dev[0].set_network(id, "mode", "2") dev[0].set_network_quoted(id, "ssid", "wpas-ap-wep") @@ -540,17 +542,18 @@ def test_wpas_ap_oom(dev): dev[0].wait_disconnected() dev[0].request("REMOVE_NETWORK all") - id = dev[0].add_network() - dev[0].set_network(id, "mode", "2") - dev[0].set_network_quoted(id, "ssid", "wpas-ap") - dev[0].set_network(id, "key_mgmt", "NONE") - dev[0].set_network_quoted(id, "wep_key0", "hello") - dev[0].set_network(id, "frequency", "2412") - dev[0].set_network(id, "scan_freq", "2412") - with alloc_fail(dev[0], 1, "=wpa_supplicant_conf_ap"): - dev[0].select_network(id) - dev[0].wait_disconnected() - dev[0].request("REMOVE_NETWORK all") + if "WEP40" in dev[0].get_capability("group"): + id = dev[0].add_network() + dev[0].set_network(id, "mode", "2") + dev[0].set_network_quoted(id, "ssid", "wpas-ap") + dev[0].set_network(id, "key_mgmt", "NONE") + dev[0].set_network_quoted(id, "wep_key0", "hello") + dev[0].set_network(id, "frequency", "2412") + dev[0].set_network(id, "scan_freq", "2412") + with alloc_fail(dev[0], 1, "=wpa_supplicant_conf_ap"): + dev[0].select_network(id) + dev[0].wait_disconnected() + dev[0].request("REMOVE_NETWORK all") wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') wpas.interface_add("wlan5") @@ -812,3 +815,91 @@ def run_wpas_ap_sae(dev, sae_password, sae_password_id=False): dev[1].request("SET sae_groups ") dev[1].connect("wpas-ap-sae", key_mgmt="SAE", sae_password="12345678", sae_password_id=pw_id, scan_freq="2412") + +def test_wpas_ap_scan(dev, apdev): + """wpa_supplicant AP mode and scanning""" + dev[0].flush_scan_cache() + + hapd = hostapd.add_ap(apdev[0], {"ssid": "open"}) + bssid = hapd.own_addr() + + id = dev[0].add_network() + dev[0].set_network(id, "mode", "2") + dev[0].set_network_quoted(id, "ssid", "wpas-ap-open") + dev[0].set_network(id, "key_mgmt", "NONE") + dev[0].set_network(id, "frequency", "2412") + dev[0].set_network(id, "scan_freq", "2412") + dev[0].select_network(id) + wait_ap_ready(dev[0]) + dev[0].dump_monitor() + + if "OK" not in dev[0].request("SCAN freq=2412"): + raise Exception("SCAN command not accepted") + ev = dev[0].wait_event(["CTRL-EVENT-SCAN-RESULTS", + "CTRL-EVENT-SCAN-FAILED"], 15) + if ev is None: + raise Exception("Scan result timed out") + if "CTRL-EVENT-SCAN-FAILED ret=-95" in ev: + # Scanning in AP mode not supported + return + if "CTRL-EVENT-SCAN-FAILED" in ev: + raise Exception("Unexpected scan failure reason: " + ev) + if "CTRL-EVENT-SCAN-RESULTS" in ev: + bss = dev[0].get_bss(bssid) + if not bss: + raise Exception("AP not found in scan") + +def test_wpas_ap_sae(dev): + """wpa_supplicant AP mode - SAE using psk""" + run_wpas_ap_sae(dev, False) + +def test_wpas_ap_sae_and_psk_transition_disable(dev): + """wpa_supplicant AP mode - SAE+PSK transition disable indication""" + if "SAE" not in dev[0].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + if "SAE" not in dev[1].get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + dev[0].set("sae_groups", "") + id = dev[0].add_network() + dev[0].set_network(id, "mode", "2") + dev[0].set_network_quoted(id, "ssid", "wpas-ap-sae") + dev[0].set_network(id, "proto", "WPA2") + dev[0].set_network(id, "key_mgmt", "SAE") + dev[0].set_network(id, "transition_disable", "1") + dev[0].set_network(id, "ieee80211w", "1") + dev[0].set_network(id, "pairwise", "CCMP") + dev[0].set_network(id, "group", "CCMP") + dev[0].set_network_quoted(id, "psk", "12345678") + dev[0].set_network(id, "frequency", "2412") + dev[0].set_network(id, "scan_freq", "2412") + dev[0].set_network(id, "wps_disabled", "1") + dev[0].select_network(id) + wait_ap_ready(dev[0]) + + dev[1].set("sae_groups", "") + dev[1].connect("wpas-ap-sae", key_mgmt="SAE WPA-PSK", + psk="12345678", ieee80211w="1", + scan_freq="2412") + ev = dev[1].wait_event(["TRANSITION-DISABLE"], timeout=1) + if ev is None: + raise Exception("Transition disable not indicated") + if ev.split(' ')[1] != "01": + raise Exception("Unexpected transition disable bitmap: " + ev) + + val = dev[1].get_network(id, "ieee80211w") + if val != "2": + raise Exception("Unexpected ieee80211w value: " + val) + val = dev[1].get_network(id, "key_mgmt") + if val != "SAE": + raise Exception("Unexpected key_mgmt value: " + val) + val = dev[1].get_network(id, "group") + if val != "CCMP": + raise Exception("Unexpected group value: " + val) + val = dev[1].get_network(id, "proto") + if val != "RSN": + raise Exception("Unexpected proto value: " + val) + + dev[1].request("DISCONNECT") + dev[1].wait_disconnected() + dev[1].request("RECONNECT") + dev[1].wait_connected() diff --git a/tests/hwsim/test_wpas_config.py b/tests/hwsim/test_wpas_config.py index ba408252a..6bf62d0b7 100644 --- a/tests/hwsim/test_wpas_config.py +++ b/tests/hwsim/test_wpas_config.py @@ -10,6 +10,7 @@ import os from wpasupplicant import WpaSupplicant import hostapd +from utils import * config_checks = [("ap_scan", "0"), ("update_config", "1"), @@ -594,3 +595,60 @@ def test_wpas_config_file_key_mgmt(dev, apdev, params): wpas.interface_remove("wlan5") wpas.interface_add("wlan5", config=config) + +def check_network_config(config, network_expected, check=None): + with open(config, "r") as f: + data = f.read() + logger.info("Configuration file contents:\n" + data.rstrip()) + if network_expected and "network=" not in data: + raise Exception("Missing network block in configuration data") + if not network_expected and "network=" in data: + raise Exception("Unexpected network block in configuration data") + if check and check not in data: + raise Exception("Missing " + check) + +def test_wpas_config_file_sae(dev, apdev, params): + """wpa_supplicant config file writing with SAE""" + config = os.path.join(params['logdir'], 'wpas_config_file_sae.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_sae_capab(wpas) + + # Valid SAE configuration with sae_password + wpas.connect("test-sae", sae_password="sae-password", key_mgmt="SAE", + only_add_network=True) + wpas.save_config() + check_network_config(config, True, check="key_mgmt=SAE") + + wpas.request("REMOVE_NETWORK all") + wpas.save_config() + check_network_config(config, False) + + # Valid SAE configuration with psk + wpas.connect("test-sae", psk="sae-password", key_mgmt="SAE", + only_add_network=True) + wpas.save_config() + check_network_config(config, True, check="key_mgmt=SAE") + wpas.request("REMOVE_NETWORK all") + + # Invalid PSK configuration with sae_password + wpas.connect("test-psk", sae_password="sae-password", key_mgmt="WPA-PSK", + only_add_network=True) + wpas.save_config() + check_network_config(config, False) + + # Invalid SAE configuration with raw_psk + wpas.connect("test-sae", raw_psk=32*"00", key_mgmt="SAE", + only_add_network=True) + wpas.save_config() + check_network_config(config, False) + +def test_wpas_config_update_without_file(dev, apdev): + """wpa_supplicant SAVE_CONFIG without config file""" + wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') + wpas.interface_add("wlan5") + wpas.set("update_config", "1") + if "FAIL" not in wpas.request("SAVE_CONFIG"): + raise Exception("SAVE_CONFIG accepted unexpectedly") diff --git a/tests/hwsim/test_wpas_ctrl.py b/tests/hwsim/test_wpas_ctrl.py index bac373f2f..04418f093 100644 --- a/tests/hwsim/test_wpas_ctrl.py +++ b/tests/hwsim/test_wpas_ctrl.py @@ -17,12 +17,13 @@ import hostapd import hwsim_utils from hwsim import HWSimRadio from wpasupplicant import WpaSupplicant -from utils import alloc_fail, fail_test +from utils import * from test_wpas_ap import wait_ap_ready @remote_compatible def test_wpas_ctrl_network(dev): """wpa_supplicant ctrl_iface network set/get""" + skip_without_tkip(dev[0]) id = dev[0].add_network() if "FAIL" not in dev[0].request("SET_NETWORK " + str(id)): @@ -145,11 +146,12 @@ def test_wpas_ctrl_network(dev): if "FAIL" not in dev[0].request("SET_NETWORK " + str(id) + ' identity 12x3'): raise Exception("Unexpected success for invalid identity string") - for i in range(0, 4): - if "FAIL" in dev[0].request("SET_NETWORK " + str(id) + ' wep_key' + str(i) + ' aabbccddee'): - raise Exception("Unexpected wep_key set failure") - if dev[0].get_network(id, "wep_key" + str(i)) != '*': - raise Exception("Unexpected wep_key get failure") + if "WEP40" in dev[0].get_capability("group"): + for i in range(0, 4): + if "FAIL" in dev[0].request("SET_NETWORK " + str(id) + ' wep_key' + str(i) + ' aabbccddee'): + raise Exception("Unexpected wep_key set failure") + if dev[0].get_network(id, "wep_key" + str(i)) != '*': + raise Exception("Unexpected wep_key get failure") if "FAIL" in dev[0].request("SET_NETWORK " + str(id) + ' psk_list P2P-00:11:22:33:44:55-0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'): raise Exception("Unexpected failure for psk_list string") @@ -205,11 +207,12 @@ def test_wpas_ctrl_network(dev): raise Exception("Invalid WEP key accepted") if "FAIL" not in dev[0].request('SET_NETWORK ' + str(id) + ' wep_key0 "12345678901234567"'): raise Exception("Too long WEP key accepted") - # too short WEP key is ignored - dev[0].set_network_quoted(id, "wep_key0", "1234") - dev[0].set_network_quoted(id, "wep_key1", "12345") - dev[0].set_network_quoted(id, "wep_key2", "1234567890123") - dev[0].set_network_quoted(id, "wep_key3", "1234567890123456") + if "WEP40" in dev[0].get_capability("group"): + # too short WEP key is ignored + dev[0].set_network_quoted(id, "wep_key0", "1234") + dev[0].set_network_quoted(id, "wep_key1", "12345") + dev[0].set_network_quoted(id, "wep_key2", "1234567890123") + dev[0].set_network_quoted(id, "wep_key3", "1234567890123456") dev[0].set_network(id, "go_p2p_dev_addr", "any") if dev[0].get_network(id, "go_p2p_dev_addr") is not None: @@ -802,6 +805,7 @@ def test_wpas_ctrl_level(dev): finally: dev[2].mon.request("LEVEL 3") +@remote_compatible def test_wpas_ctrl_bssid_filter(dev, apdev): """wpa_supplicant bssid_filter""" try: @@ -818,7 +822,8 @@ def test_wpas_ctrl_bssid_filter(dev, apdev): bss = dev[2].get_bss(apdev[1]['bssid']) if bss and len(bss) != 0: raise Exception("Unexpected BSS data") - dev[2].request("SET bssid_filter ") + dev[2].request("SET bssid_filter " + apdev[0]['bssid'] + " " + \ + apdev[1]['bssid']) dev[2].scan(freq="2412") bss = dev[2].get_bss(apdev[0]['bssid']) if bss is None or len(bss) == 0: @@ -982,6 +987,16 @@ def test_wpas_ctrl_get_capability(dev): if "WPA-PSK" not in res or "WPA-EAP" not in res: raise Exception("Unexpected GET_CAPABILITY key_mgmt response: " + str(res)) + res = dev[0].get_capability("key_mgmt iftype=STATION") + if "WPA-PSK" not in res or "WPA-EAP" not in res: + raise Exception("Unexpected GET_CAPABILITY key_mgmt iftype=STATION response: " + str(res)) + + iftypes = [ "STATION", "AP_VLAN", "AP", "P2P_GO", "P2P_CLIENT", + "P2P_DEVICE", "MESH", "IBSS", "NAN", "UNKNOWN" ] + for i in iftypes: + res = dev[0].get_capability("key_mgmt iftype=" + i) + logger.info("GET_CAPABILITY key_mgmt iftype=%s: %s" % (i, res)) + res = dev[0].get_capability("proto") if "WPA" not in res or "RSN" not in res: raise Exception("Unexpected GET_CAPABILITY proto response: " + str(res)) diff --git a/tests/hwsim/test_wpas_mesh.py b/tests/hwsim/test_wpas_mesh.py index 85dd384e2..75bc02146 100644 --- a/tests/hwsim/test_wpas_mesh.py +++ b/tests/hwsim/test_wpas_mesh.py @@ -16,10 +16,8 @@ import binascii import hwsim_utils import hostapd from wpasupplicant import WpaSupplicant -from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger, \ - radiotap_build, start_monitor, stop_monitor +from utils import * from tshark import run_tshark, run_tshark_json -from test_ap_ht import set_world_reg from test_sae import build_sae_commit, sae_rx_commit_token_req from hwsim_utils import set_group_map @@ -82,8 +80,24 @@ def check_mesh_scan(dev, params, other_started=False, beacon_int=0): if '[MESH]' not in bss['flags']: raise Exception("BSS output did not include MESH flag") -def check_mesh_group_added(dev): - ev = dev.wait_event(["MESH-GROUP-STARTED"]) +def check_dfs_started(dev, timeout=10): + ev = dev.wait_event(["DFS-CAC-START"], timeout=timeout) + if ev is None: + raise Exception("Test exception: CAC did not start") + +def check_dfs_finished(dev, timeout=70): + ev = dev.wait_event(["DFS-CAC-COMPLETED"], timeout=timeout) + if ev is None: + raise Exception("Test exception: CAC did not finish") + +def check_mesh_radar_handling_finished(dev, timeout=75): + ev = dev.wait_event(["CTRL-EVENT-CHANNEL-SWITCH", "MESH-GROUP-STARTED"], + timeout=timeout) + if ev is None: + raise Exception("Test exception: Couldn't join mesh") + +def check_mesh_group_added(dev, timeout=10): + ev = dev.wait_event(["MESH-GROUP-STARTED"], timeout=timeout) if ev is None: raise Exception("Test exception: Couldn't join mesh") @@ -93,6 +107,10 @@ def check_mesh_group_removed(dev): if ev is None: raise Exception("Test exception: Couldn't leave mesh") +def check_regdom_change(dev, timeout=10): + ev = dev.wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=timeout) + if ev is None: + raise Exception("Test exception: No regdom change happened.") def check_mesh_peer_connected(dev, timeout=10): ev = dev.wait_event(["MESH-PEER-CONNECTED"], timeout=timeout) @@ -169,6 +187,39 @@ def test_wpas_mesh_group_remove(dev): check_mesh_group_removed(dev[0]) dev[0].mesh_group_remove() +def dfs_simulate_radar(dev): + logger.info("Trigger a simulated radar event") + phyname = dev.get_driver_status_field("phyname") + radar_file = '/sys/kernel/debug/ieee80211/' + phyname + '/hwsim/dfs_simulate_radar' + with open(radar_file, 'w') as f: + f.write('1') + +@long_duration_test +def test_mesh_peer_connected_dfs(dev): + """Mesh peer connected (DFS)""" + dev[0].set("country", "DE") + dev[1].set("country", "DE") + + check_regdom_change(dev[0]) + check_regdom_change(dev[1]) + + check_mesh_support(dev[0]) + add_open_mesh_network(dev[0], freq="5500", beacon_int=160) + add_open_mesh_network(dev[1], freq="5500", beacon_int=160) + check_dfs_started(dev[0]) + check_dfs_finished(dev[0]) + check_mesh_joined_connected(dev, timeout0=10) + + dfs_simulate_radar(dev[0]) + + check_mesh_radar_handling_finished(dev[0], timeout=75) + + dev[0].set("country", "00") + dev[1].set("country", "00") + + check_regdom_change(dev[0]) + check_regdom_change(dev[1]) + def test_wpas_mesh_peer_connected(dev): """wpa_supplicant MESH peer connected""" check_mesh_support(dev[0]) @@ -219,6 +270,16 @@ def test_wpas_mesh_open(dev, apdev): if mode != "mesh": raise Exception("Unexpected mode: " + mode) + dev[0].scan(freq="2462") + bss = dev[0].get_bss(dev[1].own_addr()) + if bss and 'ie' in bss and "ff0724" in bss['ie']: + sta = dev[0].request("STA " + dev[1].own_addr()) + logger.info("STA info:\n" + sta.rstrip()) + if "[HE]" not in sta: + raise Exception("Missing STA HE flag") + if "[VHT]" in sta: + raise Exception("Unexpected STA VHT flag") + def test_wpas_mesh_open_no_auto(dev, apdev): """wpa_supplicant open MESH network connectivity""" check_mesh_support(dev[0]) @@ -398,7 +459,7 @@ def set_reg(dev, country): def clear_reg_setting(dev): dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) + clear_regdom_dev(dev) dev[0].flush_scan_cache() dev[1].flush_scan_cache() @@ -504,6 +565,7 @@ def test_mesh_secure_gcmp_256_gmac_256(dev, apdev): def test_mesh_secure_invalid_pairwise_cipher(dev, apdev): """Secure mesh and invalid group cipher""" check_mesh_support(dev[0], secure=True) + skip_without_tkip(dev[0]) dev[0].request("SET sae_groups ") id = add_mesh_secure_net(dev[0], pairwise="TKIP", group="CCMP") if dev[0].mesh_group_add(id) != None: @@ -514,6 +576,7 @@ def test_mesh_secure_invalid_pairwise_cipher(dev, apdev): def test_mesh_secure_invalid_group_cipher(dev, apdev): """Secure mesh and invalid group cipher""" + skip_without_tkip(dev[0]) check_mesh_support(dev[0], secure=True) dev[0].request("SET sae_groups ") id = add_mesh_secure_net(dev[0], pairwise="CCMP", group="TKIP") @@ -896,11 +959,7 @@ def test_wpas_mesh_open_5ghz(dev, apdev): try: _test_wpas_mesh_open_5ghz(dev, apdev) finally: - dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) - dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) - dev[0].flush_scan_cache() - dev[1].flush_scan_cache() + clear_reg_setting(dev) def _test_wpas_mesh_open_5ghz(dev, apdev): check_mesh_support(dev[0]) @@ -923,56 +982,6 @@ def _test_wpas_mesh_open_5ghz(dev, apdev): dev[0].dump_monitor() dev[1].dump_monitor() -def test_wpas_mesh_open_5ghz_coex(dev, apdev): - """Mesh network on 5 GHz band and 20/40 coex change""" - try: - _test_wpas_mesh_open_5ghz_coex(dev, apdev) - finally: - dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) - dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - set_world_reg(apdev0=apdev[0], dev0=dev[0]) - dev[0].flush_scan_cache() - dev[1].flush_scan_cache() - -def _test_wpas_mesh_open_5ghz_coex(dev, apdev): - check_mesh_support(dev[0]) - subprocess.call(['iw', 'reg', 'set', 'US']) - - # Start a 20 MHz BSS on channel 40 that would be the secondary channel of - # HT40+ mesh on channel 36. - params = {"ssid": "test-ht40", - "hw_mode": "a", - "channel": "40", - "country_code": "US"} - hapd = hostapd.add_ap(apdev[0], params) - bssid = hapd.own_addr() - - for i in range(2): - for j in range(5): - ev = dev[i].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=5) - if ev is None: - raise Exception("No regdom change event") - if "alpha2=US" in ev: - break - dev[i].scan_for_bss(bssid, freq=5200) - add_open_mesh_network(dev[i], freq="5180") - - check_mesh_joined_connected(dev) - - freq = dev[0].get_status_field("freq") - if freq != "5200": - raise Exception("Unexpected STATUS freq=" + freq) - sig = dev[0].request("SIGNAL_POLL").splitlines() - if "FREQUENCY=5200" not in sig: - raise Exception("Unexpected SIGNAL_POLL output: " + str(sig)) - - hapd.disable() - dev[0].mesh_group_remove() - dev[1].mesh_group_remove() - check_mesh_group_removed(dev[0]) - check_mesh_group_removed(dev[1]) - dev[0].dump_monitor() - dev[1].dump_monitor() def test_wpas_mesh_open_ht40(dev, apdev): """Mesh and HT40 support difference""" @@ -982,7 +991,7 @@ def test_wpas_mesh_open_ht40(dev, apdev): dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) dev[2].request("MESH_GROUP_REMOVE " + dev[2].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) + clear_regdom_dev(dev) dev[0].flush_scan_cache() dev[1].flush_scan_cache() dev[2].flush_scan_cache() @@ -1027,11 +1036,7 @@ def test_wpas_mesh_open_vht40(dev, apdev): try: _test_wpas_mesh_open_vht40(dev, apdev) finally: - dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) - dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) - dev[0].flush_scan_cache() - dev[1].flush_scan_cache() + clear_reg_setting(dev) def _test_wpas_mesh_open_vht40(dev, apdev): check_mesh_support(dev[0]) @@ -1059,6 +1064,14 @@ def _test_wpas_mesh_open_vht40(dev, apdev): if "CENTER_FRQ1=5190" not in sig: raise Exception("Unexpected SIGNAL_POLL value(3b): " + str(sig)) + dev[0].scan(freq="5180") + bss = dev[0].get_bss(dev[1].own_addr()) + if bss and 'ie' in bss and "ff0724" in bss['ie']: + sta = dev[0].request("STA " + dev[1].own_addr()) + logger.info("STA info:\n" + sta.rstrip()) + if "[HT][VHT][HE]" not in sta: + raise Exception("Missing STA flags") + dev[0].mesh_group_remove() dev[1].mesh_group_remove() check_mesh_group_removed(dev[0]) @@ -1071,11 +1084,7 @@ def test_wpas_mesh_open_vht20(dev, apdev): try: _test_wpas_mesh_open_vht20(dev, apdev) finally: - dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) - dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) - dev[0].flush_scan_cache() - dev[1].flush_scan_cache() + clear_reg_setting(dev) def _test_wpas_mesh_open_vht20(dev, apdev): check_mesh_support(dev[0]) @@ -1115,11 +1124,7 @@ def test_wpas_mesh_open_vht_80p80(dev, apdev): try: _test_wpas_mesh_open_vht_80p80(dev, apdev) finally: - dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) - dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) - dev[0].flush_scan_cache() - dev[1].flush_scan_cache() + clear_reg_setting(dev) def _test_wpas_mesh_open_vht_80p80(dev, apdev): check_mesh_support(dev[0]) @@ -1163,11 +1168,7 @@ def test_mesh_open_vht_160(dev, apdev): try: _test_mesh_open_vht_160(dev, apdev) finally: - dev[0].request("MESH_GROUP_REMOVE " + dev[0].ifname) - dev[1].request("MESH_GROUP_REMOVE " + dev[1].ifname) - subprocess.call(['iw', 'reg', 'set', '00']) - dev[0].flush_scan_cache() - dev[1].flush_scan_cache() + clear_reg_setting(dev) def _test_mesh_open_vht_160(dev, apdev): check_mesh_support(dev[0]) @@ -1275,10 +1276,9 @@ def test_wpas_mesh_password_mismatch(dev, apdev): if count == 0: raise Exception("Neither dev0 nor dev1 reported auth failure") -def test_wpas_mesh_password_mismatch_retry(dev, apdev, params): - """Mesh password mismatch and retry [long]""" - if not params['long']: - raise HwsimSkip("Skip test case with long duration due to --long not specified") +@long_duration_test +def test_wpas_mesh_password_mismatch_retry(dev, apdev): + """Mesh password mismatch and retry""" check_mesh_support(dev[0], secure=True) dev[0].request("SET sae_groups ") id = add_mesh_secure_net(dev[0]) diff --git a/tests/hwsim/tshark.py b/tests/hwsim/tshark.py index d6a57f0a3..32cdf4701 100644 --- a/tests/hwsim/tshark.py +++ b/tests/hwsim/tshark.py @@ -12,6 +12,8 @@ import subprocess import logging logger = logging.getLogger() +from utils import * + class UnknownFieldsException(Exception): def __init__(self, fields): Exception.__init__(self, "unknown tshark fields %s" % ','.join(fields)) @@ -41,6 +43,8 @@ def _run_tshark(filename, filter, display=None, wait=True): stderr=subprocess.PIPE) except Exception as e: logger.info("Could run run tshark check: " + str(e)) + if "No such file or directory: 'tshark'" in str(e): + raise HwsimSkip("No tshark available") cmd = None return None @@ -111,6 +115,8 @@ def run_tshark_json(filename, filter): stderr=subprocess.PIPE) except Exception as e: logger.info("Could run run tshark: " + str(e)) + if "No such file or directory: 'tshark'" in str(e): + raise HwsimSkip("No tshark available") return None output = cmd.communicate() out = output[0].decode() diff --git a/tests/hwsim/utils.py b/tests/hwsim/utils.py index b3a883131..3aa7c4497 100644 --- a/tests/hwsim/utils.py +++ b/tests/hwsim/utils.py @@ -13,6 +13,7 @@ import time import remotehost import logging logger = logging.getLogger() +import hostapd def get_ifnames(): ifnames = [] @@ -30,6 +31,10 @@ class HwsimSkip(Exception): def __str__(self): return self.reason +def long_duration_test(func): + func.long_duration_test = True + return func + class alloc_fail(object): def __init__(self, dev, count, funcs): self._dev = dev @@ -89,6 +94,48 @@ def skip_with_fips(dev, reason="Not supported in FIPS mode"): if res and 'FIPS' in res: raise HwsimSkip(reason) +def check_ext_key_id_capa(dev): + res = dev.get_driver_status_field('capa.flags') + if (int(res, 0) & 0x8000000000000000) == 0: + raise HwsimSkip("Extended Key ID not supported") + +def skip_without_tkip(dev): + res = dev.get_capability("fips") + if "TKIP" not in dev.get_capability("pairwise") or \ + "TKIP" not in dev.get_capability("group"): + raise HwsimSkip("Cipher TKIP not supported") + +def check_wep_capa(dev): + if "WEP40" not in dev.get_capability("group"): + raise HwsimSkip("WEP not supported") + +def check_sae_capab(dev): + if "SAE" not in dev.get_capability("auth_alg"): + raise HwsimSkip("SAE not supported") + +def check_sae_pk_capab(dev): + if "PK" not in dev.get_capability("sae"): + raise HwsimSkip("SAE-PK not supported") + +def check_tls_tod(dev): + tls = dev.request("GET tls_library") + if not tls.startswith("OpenSSL") and not tls.startswith("internal"): + raise HwsimSkip("TLS TOD-TOFU/STRICT not supported with this TLS library: " + tls) + +def vht_supported(): + cmd = subprocess.Popen(["iw", "reg", "get"], stdout=subprocess.PIPE) + reg = cmd.stdout.read() + if "@ 80)" in reg or "@ 160)" in reg: + return True + return False + +# This function checks whether the provided dev, which may be either +# WpaSupplicant or Hostapd supports CSA. +def csa_supported(dev): + res = dev.get_driver_status() + if (int(res['capa.flags'], 0) & 0x80000000) == 0: + raise HwsimSkip("CSA not supported") + def get_phy(ap, ifname=None): phy = "phy3" try: @@ -162,7 +209,7 @@ def clear_regdom_dev(dev, count=1): dev[i].request("DISCONNECT") for i in range(count): dev[i].disconnect_and_stop_scan() - subprocess.call(['iw', 'reg', 'set', '00']) + dev[0].cmd_execute(['iw', 'reg', 'set', '00']) wait_regdom_changes(dev[0]) country = dev[0].get_driver_status_field("country") logger.info("Country code at the end: " + country) @@ -194,3 +241,58 @@ def start_monitor(ifname, freq=2412): def stop_monitor(ifname): subprocess.call(["ip", "link", "set", "dev", ifname, "down"]) subprocess.call(["iw", ifname, "set", "type", "managed"]) + +def clear_scan_cache(apdev): + ifname = apdev['ifname'] + hostapd.cmd_execute(apdev, ['ifconfig', ifname, 'up']) + hostapd.cmd_execute(apdev, ['iw', ifname, 'scan', 'trigger', 'freq', '2412', + 'flush']) + time.sleep(0.1) + hostapd.cmd_execute(apdev, ['ifconfig', ifname, 'down']) + +def set_world_reg(apdev0=None, apdev1=None, dev0=None): + if apdev0: + hostapd.cmd_execute(apdev0, ['iw', 'reg', 'set', '00']) + if apdev1: + hostapd.cmd_execute(apdev1, ['iw', 'reg', 'set', '00']) + if dev0: + dev0.cmd_execute(['iw', 'reg', 'set', '00']) + time.sleep(0.1) + +def sysctl_write(val): + subprocess.call(['sysctl', '-w', val], stdout=open('/dev/null', 'w')) + +def var_arg_call(fn, dev, apdev, params): + if fn.__code__.co_argcount > 2: + return fn(dev, apdev, params) + elif fn.__code__.co_argcount > 1: + return fn(dev, apdev) + return fn(dev) + +def cloned_wrapper(wrapper, fn): + # we need the name set right for selecting / printing etc. + wrapper.__name__ = fn.__name__ + wrapper.__doc__ = fn.__doc__ + # reparent to the right module for module filtering + wrapper.__module__ = fn.__module__ + return wrapper + +def disable_ipv6(fn): + def wrapper(dev, apdev, params): + require_under_vm() + try: + sysctl_write('net.ipv6.conf.all.disable_ipv6=1') + sysctl_write('net.ipv6.conf.default.disable_ipv6=1') + var_arg_call(fn, dev, apdev, params) + finally: + sysctl_write('net.ipv6.conf.all.disable_ipv6=0') + sysctl_write('net.ipv6.conf.default.disable_ipv6=0') + return cloned_wrapper(wrapper, fn) + +def reset_ignore_old_scan_res(fn): + def wrapper(dev, apdev, params): + try: + var_arg_call(fn, dev, apdev, params) + finally: + dev[0].set("ignore_old_scan_res", "0") + return cloned_wrapper(wrapper, fn) diff --git a/tests/hwsim/vm/README b/tests/hwsim/vm/README index 4cea85b98..224d65a26 100644 --- a/tests/hwsim/vm/README +++ b/tests/hwsim/vm/README @@ -1,9 +1,23 @@ -These scripts allow you to run the hwsim tests inside a KVM virtual machine. +These scripts allow you to run the hwsim tests inside a KVM virtual machine or +as a UML (User Mode Linux) program. -To set it up, first compile a kernel with the kernel-config file as the -.config. You can adjust it as needed, the configuration is for a 64-bit -x86 system and should be close to minimal. The architecture must be the -same as your host since the host's filesystem is used. +To set it up, first compile a kernel with the kernel-config[.uml] file as the +.config. You can adjust it as needed, the configuration is for a 64-bit x86 +system and should be close to minimal. The architecture must be the same as +your host since the host's filesystem is used. + +To build the regular x86_64 kernel, simply issue + +yes "" | make -j + +or to build UML: + +yes "" | ARCH=um make -j + +Running a UML kernel is recommended as it can optimize out any sleep()s or +kernel timers by taking advantage of UML time travel mode, greatly increasing +test efficiency (~3200 tests can be run in under 5 minutes using parallel-vm.py +on a 24 core CPU). Install the required tools: at least 'kvm', if you want tracing trace-cmd, valgrind if you want, etc. diff --git a/tests/hwsim/vm/kernel-config b/tests/hwsim/vm/kernel-config index e41d69823..2aff20af4 100644 --- a/tests/hwsim/vm/kernel-config +++ b/tests/hwsim/vm/kernel-config @@ -1,905 +1,82 @@ -# -# Automatically generated file; DO NOT EDIT. -# Linux/x86 4.10.0-rc5 Kernel Configuration -# -CONFIG_64BIT=y -CONFIG_X86_64=y -CONFIG_X86=y -CONFIG_INSTRUCTION_DECODER=y -CONFIG_OUTPUT_FORMAT="elf64-x86-64" -CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig" -CONFIG_LOCKDEP_SUPPORT=y -CONFIG_STACKTRACE_SUPPORT=y -CONFIG_MMU=y -CONFIG_ARCH_MMAP_RND_BITS_MIN=28 -CONFIG_ARCH_MMAP_RND_BITS_MAX=32 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=8 -CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=16 -CONFIG_NEED_DMA_MAP_STATE=y -CONFIG_NEED_SG_DMA_LENGTH=y -CONFIG_GENERIC_BUG=y -CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_RWSEM_XCHGADD_ALGORITHM=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ARCH_HAS_CPU_RELAX=y -CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y -CONFIG_HAVE_SETUP_PER_CPU_AREA=y -CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y -CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y -CONFIG_ARCH_HIBERNATION_POSSIBLE=y -CONFIG_ARCH_SUSPEND_POSSIBLE=y -CONFIG_ARCH_WANT_HUGE_PMD_SHARE=y -CONFIG_ARCH_WANT_GENERAL_HUGETLB=y -CONFIG_ZONE_DMA32=y -CONFIG_AUDIT_ARCH=y -CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y -CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y -CONFIG_X86_64_SMP=y -CONFIG_ARCH_SUPPORTS_UPROBES=y -CONFIG_FIX_EARLYCON_MEM=y -CONFIG_DEBUG_RODATA=y -CONFIG_PGTABLE_LEVELS=4 -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" -CONFIG_IRQ_WORK=y -CONFIG_BUILDTIME_EXTABLE_SORT=y -CONFIG_THREAD_INFO_IN_TASK=y - -# -# General setup -# -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_CROSS_COMPILE="" -# CONFIG_COMPILE_TEST is not set -CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set -CONFIG_HAVE_KERNEL_GZIP=y -CONFIG_HAVE_KERNEL_BZIP2=y -CONFIG_HAVE_KERNEL_LZMA=y -CONFIG_HAVE_KERNEL_XZ=y -CONFIG_HAVE_KERNEL_LZO=y -CONFIG_HAVE_KERNEL_LZ4=y -# CONFIG_KERNEL_GZIP is not set CONFIG_KERNEL_BZIP2=y -# CONFIG_KERNEL_LZMA is not set -# CONFIG_KERNEL_XZ is not set -# CONFIG_KERNEL_LZO is not set -# CONFIG_KERNEL_LZ4 is not set -CONFIG_DEFAULT_HOSTNAME="(none)" # CONFIG_SWAP is not set CONFIG_SYSVIPC=y -CONFIG_SYSVIPC_SYSCTL=y -# CONFIG_POSIX_MQUEUE is not set # CONFIG_CROSS_MEMORY_ATTACH is not set -# CONFIG_FHANDLE is not set -# CONFIG_USELIB is not set -# CONFIG_AUDIT is not set -CONFIG_HAVE_ARCH_AUDITSYSCALL=y - -# -# IRQ subsystem -# -CONFIG_GENERIC_IRQ_PROBE=y -CONFIG_GENERIC_IRQ_SHOW=y -CONFIG_GENERIC_PENDING_IRQ=y -CONFIG_IRQ_DOMAIN=y -CONFIG_IRQ_DOMAIN_HIERARCHY=y -# CONFIG_IRQ_DOMAIN_DEBUG is not set -CONFIG_IRQ_FORCED_THREADING=y -CONFIG_SPARSE_IRQ=y -CONFIG_CLOCKSOURCE_WATCHDOG=y -CONFIG_ARCH_CLOCKSOURCE_DATA=y -CONFIG_CLOCKSOURCE_VALIDATE_LAST_CYCLE=y -CONFIG_GENERIC_TIME_VSYSCALL=y -CONFIG_GENERIC_CLOCKEVENTS=y -CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y -CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST=y -CONFIG_GENERIC_CMOS_UPDATE=y - -# -# Timers subsystem -# -CONFIG_TICK_ONESHOT=y -CONFIG_NO_HZ_COMMON=y -# CONFIG_HZ_PERIODIC is not set -CONFIG_NO_HZ_IDLE=y -# CONFIG_NO_HZ_FULL is not set CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y - -# -# CPU/Task time and stats accounting -# -CONFIG_TICK_CPU_ACCOUNTING=y -# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set -# CONFIG_IRQ_TIME_ACCOUNTING is not set +CONFIG_PREEMPT=y CONFIG_BSD_PROCESS_ACCT=y -# CONFIG_BSD_PROCESS_ACCT_V3 is not set CONFIG_TASKSTATS=y CONFIG_TASK_DELAY_ACCT=y CONFIG_TASK_XACCT=y CONFIG_TASK_IO_ACCOUNTING=y - -# -# RCU Subsystem -# -CONFIG_PREEMPT_RCU=y -# CONFIG_RCU_EXPERT is not set -CONFIG_SRCU=y -# CONFIG_TASKS_RCU is not set -CONFIG_RCU_STALL_COMMON=y -# CONFIG_TREE_RCU_TRACE is not set -# CONFIG_RCU_EXPEDITE_BOOT is not set -# CONFIG_BUILD_BIN2C is not set -# CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=21 -CONFIG_LOG_CPU_MAX_BUF_SHIFT=12 -CONFIG_NMI_LOG_BUF_SHIFT=13 -CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y -CONFIG_ARCH_SUPPORTS_NUMA_BALANCING=y -CONFIG_ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH=y -CONFIG_ARCH_SUPPORTS_INT128=y -# CONFIG_CGROUPS is not set -# CONFIG_CHECKPOINT_RESTORE is not set -# CONFIG_NAMESPACES is not set -# CONFIG_SCHED_AUTOGROUP is not set -# CONFIG_SYSFS_DEPRECATED is not set -# CONFIG_RELAY is not set -# CONFIG_BLK_DEV_INITRD is not set -CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y -CONFIG_ANON_INODES=y -CONFIG_SYSCTL_EXCEPTION_TRACE=y -CONFIG_HAVE_PCSPKR_PLATFORM=y -CONFIG_BPF=y -CONFIG_EXPERT=y -CONFIG_MULTIUSER=y -CONFIG_SGETMASK_SYSCALL=y -CONFIG_SYSFS_SYSCALL=y -# CONFIG_SYSCTL_SYSCALL is not set -CONFIG_POSIX_TIMERS=y -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y -CONFIG_KALLSYMS_ABSOLUTE_PERCPU=y -CONFIG_KALLSYMS_BASE_RELATIVE=y -CONFIG_PRINTK=y -CONFIG_PRINTK_NMI=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_PCSPKR_PLATFORM=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_TIMERFD=y -CONFIG_EVENTFD=y -# CONFIG_BPF_SYSCALL is not set -CONFIG_SHMEM=y -CONFIG_AIO=y -CONFIG_ADVISE_SYSCALLS=y -# CONFIG_USERFAULTFD is not set -CONFIG_PCI_QUIRKS=y -CONFIG_MEMBARRIER=y +CONFIG_NAMESPACES=y +# CONFIG_FHANDLE is not set CONFIG_EMBEDDED=y -CONFIG_HAVE_PERF_EVENTS=y - -# -# Kernel Performance Events And Counters -# -CONFIG_PERF_EVENTS=y -# CONFIG_DEBUG_PERF_USE_VMALLOC is not set -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLUB_DEBUG=y # CONFIG_COMPAT_BRK is not set -# CONFIG_SLAB is not set -CONFIG_SLUB=y -# CONFIG_SLOB is not set -# CONFIG_SLAB_FREELIST_RANDOM is not set -CONFIG_SLUB_CPU_PARTIAL=y -# CONFIG_SYSTEM_DATA_VERIFICATION is not set -# CONFIG_PROFILING is not set -CONFIG_TRACEPOINTS=y -CONFIG_HAVE_OPROFILE=y -CONFIG_OPROFILE_NMI_TIMER=y -CONFIG_JUMP_LABEL=y -# CONFIG_STATIC_KEYS_SELFTEST is not set -# CONFIG_UPROBES is not set -# CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set -CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y -CONFIG_ARCH_USE_BUILTIN_BSWAP=y -CONFIG_HAVE_IOREMAP_PROT=y -CONFIG_HAVE_KPROBES=y -CONFIG_HAVE_KRETPROBES=y -CONFIG_HAVE_OPTPROBES=y -CONFIG_HAVE_KPROBES_ON_FTRACE=y -CONFIG_HAVE_NMI=y -CONFIG_HAVE_ARCH_TRACEHOOK=y -CONFIG_HAVE_DMA_CONTIGUOUS=y -CONFIG_GENERIC_SMP_IDLE_THREAD=y -CONFIG_ARCH_WANTS_DYNAMIC_TASK_STRUCT=y -CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y -CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_HW_BREAKPOINT=y -CONFIG_HAVE_MIXED_BREAKPOINTS_REGS=y -CONFIG_HAVE_USER_RETURN_NOTIFIER=y -CONFIG_HAVE_PERF_EVENTS_NMI=y -CONFIG_HAVE_PERF_REGS=y -CONFIG_HAVE_PERF_USER_STACK_DUMP=y -CONFIG_HAVE_ARCH_JUMP_LABEL=y -CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG=y -CONFIG_HAVE_ALIGNED_STRUCT_PAGE=y -CONFIG_HAVE_CMPXCHG_LOCAL=y -CONFIG_HAVE_CMPXCHG_DOUBLE=y -CONFIG_HAVE_ARCH_SECCOMP_FILTER=y -CONFIG_HAVE_GCC_PLUGINS=y -# CONFIG_GCC_PLUGINS is not set -CONFIG_HAVE_CC_STACKPROTECTOR=y -# CONFIG_CC_STACKPROTECTOR is not set -CONFIG_CC_STACKPROTECTOR_NONE=y -# CONFIG_CC_STACKPROTECTOR_REGULAR is not set -# CONFIG_CC_STACKPROTECTOR_STRONG is not set -CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES=y -CONFIG_HAVE_CONTEXT_TRACKING=y -CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y -CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y -CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y -CONFIG_HAVE_ARCH_HUGE_VMAP=y -CONFIG_HAVE_ARCH_SOFT_DIRTY=y -CONFIG_MODULES_USE_ELF_RELA=y -CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y -CONFIG_ARCH_HAS_ELF_RANDOMIZE=y -CONFIG_HAVE_ARCH_MMAP_RND_BITS=y -CONFIG_HAVE_EXIT_THREAD=y -CONFIG_ARCH_MMAP_RND_BITS=28 -CONFIG_HAVE_COPY_THREAD_TLS=y -CONFIG_HAVE_STACK_VALIDATION=y -# CONFIG_HAVE_ARCH_HASH is not set -# CONFIG_ISA_BUS_API is not set -# CONFIG_CPU_NO_EFFICIENT_FFS is not set -CONFIG_HAVE_ARCH_VMAP_STACK=y -CONFIG_VMAP_STACK=y - -# -# GCOV-based kernel profiling -# -# CONFIG_GCOV_KERNEL is not set -CONFIG_ARCH_HAS_GCOV_PROFILE_ALL=y -# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set -CONFIG_SLABINFO=y -CONFIG_RT_MUTEXES=y -CONFIG_BASE_SMALL=0 -# CONFIG_MODULES is not set -CONFIG_MODULES_TREE_LOOKUP=y -CONFIG_BLOCK=y -# CONFIG_BLK_DEV_BSG is not set -# CONFIG_BLK_DEV_BSGLIB is not set -# CONFIG_BLK_DEV_INTEGRITY is not set -# CONFIG_BLK_DEV_ZONED is not set -# CONFIG_BLK_CMDLINE_PARSER is not set -# CONFIG_BLK_WBT is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_AIX_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -CONFIG_MAC_PARTITION=y -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_KARMA_PARTITION is not set -CONFIG_EFI_PARTITION=y -# CONFIG_SYSV68_PARTITION is not set -# CONFIG_CMDLINE_PARTITION is not set -CONFIG_BLK_MQ_PCI=y - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -# CONFIG_IOSCHED_DEADLINE is not set -# CONFIG_IOSCHED_CFQ is not set -CONFIG_DEFAULT_NOOP=y -CONFIG_DEFAULT_IOSCHED="noop" -CONFIG_UNINLINE_SPIN_UNLOCK=y -CONFIG_ARCH_SUPPORTS_ATOMIC_RMW=y -CONFIG_MUTEX_SPIN_ON_OWNER=y -CONFIG_RWSEM_SPIN_ON_OWNER=y -CONFIG_LOCK_SPIN_ON_OWNER=y -CONFIG_ARCH_USE_QUEUED_SPINLOCKS=y -CONFIG_QUEUED_SPINLOCKS=y -CONFIG_ARCH_USE_QUEUED_RWLOCKS=y -CONFIG_QUEUED_RWLOCKS=y -# CONFIG_FREEZER is not set - -# -# Processor type and features -# -CONFIG_ZONE_DMA=y CONFIG_SMP=y -CONFIG_X86_FEATURE_NAMES=y -CONFIG_X86_FAST_FEATURE_TESTS=y -# CONFIG_X86_X2APIC is not set -CONFIG_X86_MPPARSE=y -# CONFIG_GOLDFISH is not set -# CONFIG_INTEL_RDT_A is not set # CONFIG_X86_EXTENDED_PLATFORM is not set -# CONFIG_X86_INTEL_LPSS is not set -# CONFIG_X86_AMD_PLATFORM_DEVICE is not set -# CONFIG_IOSF_MBI is not set -CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_HYPERVISOR_GUEST=y CONFIG_PARAVIRT=y -# CONFIG_PARAVIRT_DEBUG is not set CONFIG_PARAVIRT_SPINLOCKS=y -# CONFIG_QUEUED_LOCK_STAT is not set -# CONFIG_XEN is not set -CONFIG_KVM_GUEST=y -# CONFIG_KVM_DEBUG_FS is not set -# CONFIG_PARAVIRT_TIME_ACCOUNTING is not set -CONFIG_PARAVIRT_CLOCK=y -CONFIG_NO_BOOTMEM=y -# CONFIG_MK8 is not set -# CONFIG_MPSC is not set CONFIG_MCORE2=y -# CONFIG_MATOM is not set -# CONFIG_GENERIC_CPU is not set -CONFIG_X86_INTERNODE_CACHE_SHIFT=6 -CONFIG_X86_L1_CACHE_SHIFT=6 -CONFIG_X86_INTEL_USERCOPY=y -CONFIG_X86_USE_PPRO_CHECKSUM=y -CONFIG_X86_P6_NOP=y -CONFIG_X86_TSC=y -CONFIG_X86_CMPXCHG64=y -CONFIG_X86_CMOV=y -CONFIG_X86_MINIMUM_CPU_FAMILY=64 -CONFIG_X86_DEBUGCTLMSR=y -# CONFIG_PROCESSOR_SELECT is not set -CONFIG_CPU_SUP_INTEL=y -CONFIG_CPU_SUP_AMD=y -CONFIG_CPU_SUP_CENTAUR=y -CONFIG_HPET_TIMER=y -CONFIG_DMI=y CONFIG_GART_IOMMU=y -# CONFIG_CALGARY_IOMMU is not set -CONFIG_SWIOTLB=y -CONFIG_IOMMU_HELPER=y -# CONFIG_MAXSMP is not set CONFIG_NR_CPUS=4 -# CONFIG_SCHED_SMT is not set -CONFIG_SCHED_MC=y -CONFIG_SCHED_MC_PRIO=y -# CONFIG_PREEMPT_NONE is not set -# CONFIG_PREEMPT_VOLUNTARY is not set -CONFIG_PREEMPT=y -CONFIG_PREEMPT_COUNT=y -CONFIG_X86_LOCAL_APIC=y -CONFIG_X86_IO_APIC=y -# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set # CONFIG_X86_MCE is not set - -# -# Performance monitoring -# -CONFIG_PERF_EVENTS_INTEL_UNCORE=y -CONFIG_PERF_EVENTS_INTEL_RAPL=y -CONFIG_PERF_EVENTS_INTEL_CSTATE=y -# CONFIG_PERF_EVENTS_AMD_POWER is not set -# CONFIG_VM86 is not set -CONFIG_X86_16BIT=y -CONFIG_X86_ESPFIX64=y -CONFIG_X86_VSYSCALL_EMULATION=y -# CONFIG_I8K is not set -CONFIG_MICROCODE=y -CONFIG_MICROCODE_INTEL=y -# CONFIG_MICROCODE_AMD is not set CONFIG_MICROCODE_OLD_INTERFACE=y -# CONFIG_X86_MSR is not set -# CONFIG_X86_CPUID is not set -CONFIG_ARCH_PHYS_ADDR_T_64BIT=y -CONFIG_ARCH_DMA_ADDR_T_64BIT=y -# CONFIG_NUMA is not set -CONFIG_ARCH_SPARSEMEM_ENABLE=y -CONFIG_ARCH_SPARSEMEM_DEFAULT=y -CONFIG_ARCH_SELECT_MEMORY_MODEL=y -CONFIG_ARCH_PROC_KCORE_TEXT=y -CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_SPARSEMEM_MANUAL=y -CONFIG_SPARSEMEM=y -CONFIG_HAVE_MEMORY_PRESENT=y -CONFIG_SPARSEMEM_EXTREME=y -CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y -CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y -CONFIG_SPARSEMEM_VMEMMAP=y -CONFIG_HAVE_MEMBLOCK=y -CONFIG_HAVE_MEMBLOCK_NODE_MAP=y -CONFIG_ARCH_DISCARD_MEMBLOCK=y -# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set -# CONFIG_MEMORY_HOTPLUG is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -CONFIG_ARCH_ENABLE_SPLIT_PMD_PTLOCK=y -# CONFIG_COMPACTION is not set -CONFIG_PHYS_ADDR_T_64BIT=y -# CONFIG_BOUNCE is not set -CONFIG_VIRT_TO_BUS=y -# CONFIG_KSM is not set -CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 -# CONFIG_TRANSPARENT_HUGEPAGE is not set -# CONFIG_CLEANCACHE is not set -# CONFIG_CMA is not set -# CONFIG_ZPOOL is not set -# CONFIG_ZBUD is not set -# CONFIG_ZSMALLOC is not set -CONFIG_GENERIC_EARLY_IOREMAP=y -CONFIG_ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT=y -# CONFIG_IDLE_PAGE_TRACKING is not set -CONFIG_ARCH_USES_HIGH_VMA_FLAGS=y -CONFIG_ARCH_HAS_PKEYS=y -# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set -CONFIG_X86_RESERVE_LOW=64 -CONFIG_MTRR=y # CONFIG_MTRR_SANITIZER is not set -CONFIG_X86_PAT=y -CONFIG_ARCH_USES_PG_UNCACHED=y -CONFIG_ARCH_RANDOM=y -CONFIG_X86_SMAP=y -# CONFIG_X86_INTEL_MPX is not set -CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS=y -# CONFIG_EFI is not set # CONFIG_SECCOMP is not set CONFIG_HZ_100=y -# CONFIG_HZ_250 is not set -# CONFIG_HZ_300 is not set -# CONFIG_HZ_1000 is not set -CONFIG_HZ=100 -CONFIG_SCHED_HRTICK=y -# CONFIG_KEXEC is not set -# CONFIG_KEXEC_FILE is not set -# CONFIG_CRASH_DUMP is not set -CONFIG_PHYSICAL_START=0x1000000 # CONFIG_RELOCATABLE is not set CONFIG_PHYSICAL_ALIGN=0x1000000 -# CONFIG_HOTPLUG_CPU is not set -# CONFIG_LEGACY_VSYSCALL_NATIVE is not set CONFIG_LEGACY_VSYSCALL_EMULATE=y -# CONFIG_LEGACY_VSYSCALL_NONE is not set -# CONFIG_CMDLINE_BOOL is not set -CONFIG_MODIFY_LDT_SYSCALL=y -CONFIG_HAVE_LIVEPATCH=y -CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y - -# -# Power management and ACPI options -# # CONFIG_SUSPEND is not set -# CONFIG_PM is not set -CONFIG_ACPI=y -CONFIG_ACPI_LEGACY_TABLES_LOOKUP=y -CONFIG_ARCH_MIGHT_HAVE_ACPI_PDC=y -CONFIG_ACPI_SYSTEM_POWER_STATES_SUPPORT=y -# CONFIG_ACPI_DEBUGGER is not set -# CONFIG_ACPI_PROCFS_POWER is not set -CONFIG_ACPI_REV_OVERRIDE_POSSIBLE=y -# CONFIG_ACPI_EC_DEBUGFS is not set # CONFIG_ACPI_AC is not set # CONFIG_ACPI_BATTERY is not set # CONFIG_ACPI_BUTTON is not set # CONFIG_ACPI_FAN is not set -# CONFIG_ACPI_DOCK is not set -CONFIG_ACPI_CPU_FREQ_PSS=y -CONFIG_ACPI_PROCESSOR_CSTATE=y -CONFIG_ACPI_PROCESSOR_IDLE=y -CONFIG_ACPI_CPPC_LIB=y -CONFIG_ACPI_PROCESSOR=y -# CONFIG_ACPI_PROCESSOR_AGGREGATOR is not set -CONFIG_ACPI_THERMAL=y -# CONFIG_ACPI_CUSTOM_DSDT is not set -CONFIG_ARCH_HAS_ACPI_TABLE_UPGRADE=y -# CONFIG_ACPI_DEBUG is not set -# CONFIG_ACPI_PCI_SLOT is not set -CONFIG_X86_PM_TIMER=y -# CONFIG_ACPI_CONTAINER is not set -CONFIG_ACPI_HOTPLUG_IOAPIC=y -# CONFIG_ACPI_SBS is not set -# CONFIG_ACPI_HED is not set -# CONFIG_ACPI_CUSTOM_METHOD is not set -# CONFIG_ACPI_REDUCED_HARDWARE_ONLY is not set -CONFIG_HAVE_ACPI_APEI=y -CONFIG_HAVE_ACPI_APEI_NMI=y -# CONFIG_ACPI_APEI is not set -# CONFIG_DPTF_POWER is not set -# CONFIG_PMIC_OPREGION is not set -# CONFIG_ACPI_CONFIGFS is not set -# CONFIG_SFI is not set - -# -# CPU Frequency scaling -# -CONFIG_CPU_FREQ=y -# CONFIG_CPU_FREQ_STAT is not set -CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set -CONFIG_CPU_FREQ_GOV_PERFORMANCE=y -# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set -# CONFIG_CPU_FREQ_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set -# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set -# CONFIG_CPU_FREQ_GOV_SCHEDUTIL is not set - -# -# CPU frequency scaling drivers -# -CONFIG_X86_INTEL_PSTATE=y -# CONFIG_X86_PCC_CPUFREQ is not set -# CONFIG_X86_ACPI_CPUFREQ is not set -# CONFIG_X86_SPEEDSTEP_CENTRINO is not set -# CONFIG_X86_P4_CLOCKMOD is not set - -# -# shared options -# -# CONFIG_X86_SPEEDSTEP_LIB is not set - -# -# CPU Idle -# -CONFIG_CPU_IDLE=y CONFIG_CPU_IDLE_GOV_LADDER=y -CONFIG_CPU_IDLE_GOV_MENU=y -# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set -# CONFIG_INTEL_IDLE is not set - -# -# Bus options (PCI etc.) -# -CONFIG_PCI=y -CONFIG_PCI_DIRECT=y # CONFIG_PCI_MMCONFIG is not set -CONFIG_PCI_DOMAINS=y -# CONFIG_PCI_CNB20LE_QUIRK is not set -# CONFIG_PCIEPORTBUS is not set -CONFIG_PCI_BUS_ADDR_T_64BIT=y -# CONFIG_PCI_MSI is not set -# CONFIG_PCI_DEBUG is not set -# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set -# CONFIG_PCI_STUB is not set -# CONFIG_HT_IRQ is not set -# CONFIG_PCI_IOV is not set -# CONFIG_PCI_PRI is not set -# CONFIG_PCI_PASID is not set -CONFIG_PCI_LABEL=y -# CONFIG_HOTPLUG_PCI is not set - -# -# PCI host controller drivers -# -# CONFIG_ISA_BUS is not set # CONFIG_ISA_DMA_API is not set -CONFIG_AMD_NB=y -# CONFIG_PCCARD is not set -# CONFIG_RAPIDIO is not set -# CONFIG_X86_SYSFB is not set - -# -# Executable file formats / Emulations -# -CONFIG_BINFMT_ELF=y -CONFIG_ELFCORE=y -CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y -CONFIG_BINFMT_SCRIPT=y -# CONFIG_HAVE_AOUT is not set -# CONFIG_BINFMT_MISC is not set -CONFIG_COREDUMP=y -# CONFIG_IA32_EMULATION is not set -# CONFIG_X86_X32 is not set -CONFIG_X86_DEV_DMA_OPS=y -CONFIG_PMC_ATOM=y +# CONFIG_DMIID is not set +# CONFIG_VIRTUALIZATION is not set +CONFIG_JUMP_LABEL=y +# CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +CONFIG_MAC_PARTITION=y +# CONFIG_COMPACTION is not set +# CONFIG_BOUNCE is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 CONFIG_NET=y -CONFIG_NET_INGRESS=y - -# -# Networking options -# CONFIG_PACKET=y -# CONFIG_PACKET_DIAG is not set CONFIG_UNIX=y -# CONFIG_UNIX_DIAG is not set -CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set -# CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set -# CONFIG_XFRM_STATISTICS is not set -# CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y -# CONFIG_IP_FIB_TRIE_STATS is not set CONFIG_IP_MULTIPLE_TABLES=y -# CONFIG_IP_ROUTE_MULTIPATH is not set -# CONFIG_IP_ROUTE_VERBOSE is not set -# CONFIG_IP_PNP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE_DEMUX is not set -CONFIG_NET_IP_TUNNEL=y -# CONFIG_IP_MROUTE is not set -# CONFIG_SYN_COOKIES is not set -# CONFIG_NET_UDP_TUNNEL is not set -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_INET_AH is not set -# CONFIG_INET_ESP is not set -# CONFIG_INET_IPCOMP is not set -# CONFIG_INET_XFRM_TUNNEL is not set -CONFIG_INET_TUNNEL=y -# CONFIG_INET_XFRM_MODE_TRANSPORT is not set -# CONFIG_INET_XFRM_MODE_TUNNEL is not set -# CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_DIAG is not set -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -CONFIG_IPV6=y -# CONFIG_IPV6_ROUTER_PREF is not set -# CONFIG_IPV6_OPTIMISTIC_DAD is not set -# CONFIG_INET6_AH is not set -# CONFIG_INET6_ESP is not set -# CONFIG_INET6_IPCOMP is not set -# CONFIG_IPV6_MIP6 is not set -# CONFIG_IPV6_ILA is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -CONFIG_INET6_XFRM_MODE_TRANSPORT=y -CONFIG_INET6_XFRM_MODE_TUNNEL=y -CONFIG_INET6_XFRM_MODE_BEET=y -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -# CONFIG_IPV6_VTI is not set -CONFIG_IPV6_SIT=y -# CONFIG_IPV6_SIT_6RD is not set -CONFIG_IPV6_NDISC_NODETYPE=y -# CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_FOU is not set -# CONFIG_IPV6_FOU_TUNNEL is not set -# CONFIG_IPV6_MULTIPLE_TABLES is not set -# CONFIG_IPV6_MROUTE is not set -# CONFIG_IPV6_SEG6_LWTUNNEL is not set -# CONFIG_IPV6_SEG6_HMAC is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NET_PTP_CLASSIFY is not set -# CONFIG_NETWORK_PHY_TIMESTAMPING is not set CONFIG_NETFILTER=y -# CONFIG_NETFILTER_DEBUG is not set -CONFIG_NETFILTER_ADVANCED=y CONFIG_BRIDGE_NETFILTER=y - -# -# Core Netfilter Configuration -# -CONFIG_NETFILTER_INGRESS=y -CONFIG_NETFILTER_NETLINK=y -# CONFIG_NETFILTER_NETLINK_ACCT is not set -# CONFIG_NETFILTER_NETLINK_QUEUE is not set -# CONFIG_NETFILTER_NETLINK_LOG is not set -# CONFIG_NF_CONNTRACK is not set -# CONFIG_NF_LOG_NETDEV is not set CONFIG_NF_TABLES=y -# CONFIG_NF_TABLES_INET is not set -# CONFIG_NF_TABLES_NETDEV is not set -# CONFIG_NFT_EXTHDR is not set -# CONFIG_NFT_META is not set -# CONFIG_NFT_RT is not set -# CONFIG_NFT_NUMGEN is not set -# CONFIG_NFT_SET_RBTREE is not set -# CONFIG_NFT_SET_HASH is not set -# CONFIG_NFT_COUNTER is not set -# CONFIG_NFT_LOG is not set -# CONFIG_NFT_LIMIT is not set -# CONFIG_NFT_OBJREF is not set -# CONFIG_NFT_QUOTA is not set -# CONFIG_NFT_REJECT is not set -# CONFIG_NFT_COMPAT is not set -# CONFIG_NFT_HASH is not set CONFIG_NETFILTER_XTABLES=y - -# -# Xtables combined modules -# -# CONFIG_NETFILTER_XT_MARK is not set - -# -# Xtables targets -# -# CONFIG_NETFILTER_XT_TARGET_CLASSIFY is not set -# CONFIG_NETFILTER_XT_TARGET_HMARK is not set -# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set -# CONFIG_NETFILTER_XT_TARGET_LOG is not set -# CONFIG_NETFILTER_XT_TARGET_MARK is not set -# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set -# CONFIG_NETFILTER_XT_TARGET_NFQUEUE is not set -# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set -# CONFIG_NETFILTER_XT_TARGET_TEE is not set -# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set - -# -# Xtables matches -# -# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set -# CONFIG_NETFILTER_XT_MATCH_BPF is not set -# CONFIG_NETFILTER_XT_MATCH_COMMENT is not set -# CONFIG_NETFILTER_XT_MATCH_CPU is not set -# CONFIG_NETFILTER_XT_MATCH_DCCP is not set -# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set -# CONFIG_NETFILTER_XT_MATCH_DSCP is not set -# CONFIG_NETFILTER_XT_MATCH_ECN is not set -# CONFIG_NETFILTER_XT_MATCH_ESP is not set -# CONFIG_NETFILTER_XT_MATCH_HASHLIMIT is not set -# CONFIG_NETFILTER_XT_MATCH_HL is not set -# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set -# CONFIG_NETFILTER_XT_MATCH_IPRANGE is not set -# CONFIG_NETFILTER_XT_MATCH_L2TP is not set -# CONFIG_NETFILTER_XT_MATCH_LENGTH is not set -# CONFIG_NETFILTER_XT_MATCH_LIMIT is not set -# CONFIG_NETFILTER_XT_MATCH_MAC is not set -# CONFIG_NETFILTER_XT_MATCH_MARK is not set -# CONFIG_NETFILTER_XT_MATCH_MULTIPORT is not set -# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set -# CONFIG_NETFILTER_XT_MATCH_OSF is not set -# CONFIG_NETFILTER_XT_MATCH_OWNER is not set -# CONFIG_NETFILTER_XT_MATCH_POLICY is not set -# CONFIG_NETFILTER_XT_MATCH_PHYSDEV is not set CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y -# CONFIG_NETFILTER_XT_MATCH_QUOTA is not set -# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set -# CONFIG_NETFILTER_XT_MATCH_REALM is not set -# CONFIG_NETFILTER_XT_MATCH_RECENT is not set -# CONFIG_NETFILTER_XT_MATCH_SCTP is not set -# CONFIG_NETFILTER_XT_MATCH_STATISTIC is not set -# CONFIG_NETFILTER_XT_MATCH_STRING is not set -# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set -# CONFIG_NETFILTER_XT_MATCH_TIME is not set -# CONFIG_NETFILTER_XT_MATCH_U32 is not set -# CONFIG_IP_SET is not set -# CONFIG_IP_VS is not set - -# -# IP: Netfilter Configuration -# -# CONFIG_NF_DEFRAG_IPV4 is not set -# CONFIG_NF_SOCKET_IPV4 is not set -# CONFIG_NF_TABLES_IPV4 is not set -# CONFIG_NF_TABLES_ARP is not set -# CONFIG_NF_DUP_IPV4 is not set -# CONFIG_NF_LOG_ARP is not set -# CONFIG_NF_LOG_IPV4 is not set -# CONFIG_NF_REJECT_IPV4 is not set -# CONFIG_IP_NF_IPTABLES is not set -# CONFIG_IP_NF_ARPTABLES is not set - -# -# IPv6: Netfilter Configuration -# -# CONFIG_NF_DEFRAG_IPV6 is not set -# CONFIG_NF_SOCKET_IPV6 is not set -# CONFIG_NF_TABLES_IPV6 is not set -# CONFIG_NF_DUP_IPV6 is not set -# CONFIG_NF_REJECT_IPV6 is not set -# CONFIG_NF_LOG_IPV6 is not set -# CONFIG_IP6_NF_IPTABLES is not set CONFIG_NF_TABLES_BRIDGE=y -# CONFIG_NF_LOG_BRIDGE is not set CONFIG_BRIDGE_NF_EBTABLES=y -# CONFIG_BRIDGE_EBT_BROUTE is not set CONFIG_BRIDGE_EBT_T_FILTER=y -# CONFIG_BRIDGE_EBT_T_NAT is not set -# CONFIG_BRIDGE_EBT_802_3 is not set -# CONFIG_BRIDGE_EBT_AMONG is not set CONFIG_BRIDGE_EBT_ARP=y CONFIG_BRIDGE_EBT_IP=y CONFIG_BRIDGE_EBT_IP6=y -# CONFIG_BRIDGE_EBT_LIMIT is not set -# CONFIG_BRIDGE_EBT_MARK is not set CONFIG_BRIDGE_EBT_PKTTYPE=y -# CONFIG_BRIDGE_EBT_STP is not set -# CONFIG_BRIDGE_EBT_VLAN is not set CONFIG_BRIDGE_EBT_ARPREPLY=y -# CONFIG_BRIDGE_EBT_DNAT is not set -# CONFIG_BRIDGE_EBT_MARK_T is not set -# CONFIG_BRIDGE_EBT_REDIRECT is not set -# CONFIG_BRIDGE_EBT_SNAT is not set -# CONFIG_BRIDGE_EBT_LOG is not set -# CONFIG_BRIDGE_EBT_NFLOG is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_RDS is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_L2TP is not set -CONFIG_STP=y CONFIG_BRIDGE=y -CONFIG_BRIDGE_IGMP_SNOOPING=y -# CONFIG_BRIDGE_VLAN_FILTERING is not set -CONFIG_HAVE_NET_DSA=y -# CONFIG_NET_DSA is not set CONFIG_VLAN_8021Q=y -# CONFIG_VLAN_8021Q_GVRP is not set -# CONFIG_VLAN_8021Q_MVRP is not set -# CONFIG_DECNET is not set -CONFIG_LLC=y -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_PHONET is not set -# CONFIG_6LOWPAN is not set -# CONFIG_IEEE802154 is not set -# CONFIG_NET_SCHED is not set -# CONFIG_DCB is not set -# CONFIG_BATMAN_ADV is not set -# CONFIG_OPENVSWITCH is not set -# CONFIG_VSOCKETS is not set -# CONFIG_NETLINK_DIAG is not set -# CONFIG_MPLS is not set -# CONFIG_HSR is not set -# CONFIG_NET_SWITCHDEV is not set -# CONFIG_NET_L3_MASTER_DEV is not set -# CONFIG_NET_NCSI is not set -CONFIG_RPS=y -CONFIG_RFS_ACCEL=y -CONFIG_XPS=y -CONFIG_NET_RX_BUSY_POLL=y -CONFIG_BQL=y -CONFIG_NET_FLOW_LIMIT=y - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_NET_DROP_MONITOR is not set -# CONFIG_HAMRADIO is not set -# CONFIG_CAN is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set -# CONFIG_AF_KCM is not set -# CONFIG_STREAM_PARSER is not set -CONFIG_FIB_RULES=y -CONFIG_WIRELESS=y -CONFIG_WEXT_CORE=y -CONFIG_WEXT_PROC=y CONFIG_CFG80211=y -# CONFIG_NL80211_TESTMODE is not set CONFIG_CFG80211_DEVELOPER_WARNINGS=y -# CONFIG_CFG80211_CERTIFICATION_ONUS is not set -CONFIG_CFG80211_DEFAULT_PS=y CONFIG_CFG80211_DEBUGFS=y -# CONFIG_CFG80211_INTERNAL_REGDB is not set -CONFIG_CFG80211_CRDA_SUPPORT=y CONFIG_CFG80211_WEXT=y -# CONFIG_LIB80211 is not set CONFIG_MAC80211=y -CONFIG_MAC80211_HAS_RC=y -CONFIG_MAC80211_RC_MINSTREL=y -CONFIG_MAC80211_RC_MINSTREL_HT=y -# CONFIG_MAC80211_RC_MINSTREL_VHT is not set -CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y -CONFIG_MAC80211_RC_DEFAULT="minstrel_ht" CONFIG_MAC80211_MESH=y CONFIG_MAC80211_DEBUGFS=y CONFIG_MAC80211_MESSAGE_TRACING=y @@ -909,978 +86,68 @@ CONFIG_MAC80211_VERBOSE_DEBUG=y CONFIG_MAC80211_MLME_DEBUG=y CONFIG_MAC80211_STA_DEBUG=y CONFIG_MAC80211_HT_DEBUG=y -# CONFIG_MAC80211_OCB_DEBUG is not set CONFIG_MAC80211_IBSS_DEBUG=y CONFIG_MAC80211_PS_DEBUG=y -# CONFIG_MAC80211_MPL_DEBUG is not set -# CONFIG_MAC80211_MPATH_DEBUG is not set -# CONFIG_MAC80211_MHWMP_DEBUG is not set -# CONFIG_MAC80211_MESH_SYNC_DEBUG is not set -# CONFIG_MAC80211_MESH_CSA_DEBUG is not set -# CONFIG_MAC80211_MESH_PS_DEBUG is not set CONFIG_MAC80211_TDLS_DEBUG=y -# CONFIG_MAC80211_DEBUG_COUNTERS is not set -CONFIG_MAC80211_STA_HASH_MAX_SIZE=0 -# CONFIG_WIMAX is not set CONFIG_RFKILL=y -# CONFIG_RFKILL_INPUT is not set CONFIG_NET_9P=y CONFIG_NET_9P_VIRTIO=y -# CONFIG_NET_9P_DEBUG is not set -# CONFIG_CAIF is not set -# CONFIG_CEPH_LIB is not set -# CONFIG_NFC is not set -# CONFIG_LWTUNNEL is not set -CONFIG_DST_CACHE=y -# CONFIG_NET_DEVLINK is not set -CONFIG_MAY_USE_DEVLINK=y -CONFIG_HAVE_EBPF_JIT=y - -# -# Device Drivers -# - -# -# Generic Driver Options -# +CONFIG_PCI=y CONFIG_UEVENT_HELPER=y CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_DEVTMPFS is not set -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -CONFIG_FW_LOADER=y -CONFIG_FIRMWARE_IN_KERNEL=y -CONFIG_EXTRA_FIRMWARE="" -# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set -CONFIG_ALLOW_DEV_COREDUMP=y -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_DEBUG_TEST_DRIVER_REMOVE is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_GENERIC_CPU_DEVICES is not set -CONFIG_GENERIC_CPU_AUTOPROBE=y -# CONFIG_DMA_SHARED_BUFFER is not set - -# -# Bus devices -# -# CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set -# CONFIG_OF is not set -CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y -# CONFIG_PARPORT is not set -CONFIG_PNP=y # CONFIG_PNP_DEBUG_MESSAGES is not set - -# -# Protocols -# -CONFIG_PNPACPI=y # CONFIG_BLK_DEV is not set -# CONFIG_BLK_DEV_NVME is not set -# CONFIG_NVME_FC is not set -# CONFIG_NVME_TARGET is not set - -# -# Misc devices -# -# CONFIG_SENSORS_LIS3LV02D is not set -# CONFIG_DUMMY_IRQ is not set -# CONFIG_IBM_ASM is not set -# CONFIG_PHANTOM is not set -# CONFIG_SGI_IOC4 is not set -# CONFIG_TIFM_CORE is not set -# CONFIG_ENCLOSURE_SERVICES is not set -# CONFIG_HP_ILO is not set -# CONFIG_SRAM is not set -# CONFIG_C2PORT is not set - -# -# EEPROM support -# -# CONFIG_EEPROM_93CX6 is not set -# CONFIG_CB710_CORE is not set - -# -# Texas Instruments shared transport line discipline -# - -# -# Altera FPGA firmware download module -# -# CONFIG_INTEL_MEI is not set -# CONFIG_INTEL_MEI_ME is not set -# CONFIG_INTEL_MEI_TXE is not set -# CONFIG_VMWARE_VMCI is not set - -# -# Intel MIC Bus Driver -# -# CONFIG_INTEL_MIC_BUS is not set - -# -# SCIF Bus Driver -# -# CONFIG_SCIF_BUS is not set - -# -# VOP Bus Driver -# -# CONFIG_VOP_BUS is not set - -# -# Intel MIC Host Driver -# - -# -# Intel MIC Card Driver -# - -# -# SCIF Driver -# - -# -# Intel MIC Coprocessor State Management (COSM) Drivers -# - -# -# VOP Driver -# -# CONFIG_GENWQE is not set -# CONFIG_ECHO is not set -# CONFIG_CXL_BASE is not set -# CONFIG_CXL_AFU_DRIVER_OPS is not set -CONFIG_HAVE_IDE=y -# CONFIG_IDE is not set - -# -# SCSI device support -# -CONFIG_SCSI_MOD=y -# CONFIG_RAID_ATTRS is not set -# CONFIG_SCSI is not set -# CONFIG_SCSI_DMA is not set -# CONFIG_SCSI_NETLINK is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_FIREWIRE is not set -# CONFIG_FIREWIRE_NOSY is not set -# CONFIG_MACINTOSH_DRIVERS is not set CONFIG_NETDEVICES=y -CONFIG_NET_CORE=y -# CONFIG_BONDING is not set CONFIG_DUMMY=y -# CONFIG_EQUALIZER is not set -# CONFIG_NET_TEAM is not set -# CONFIG_MACVLAN is not set -# CONFIG_VXLAN is not set -# CONFIG_MACSEC is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_TUN is not set -# CONFIG_TUN_VNET_CROSS_LE is not set -# CONFIG_VETH is not set -# CONFIG_VIRTIO_NET is not set -# CONFIG_NLMON is not set -# CONFIG_ARCNET is not set - -# -# CAIF transport drivers -# - -# -# Distributed Switch Architecture drivers -# +CONFIG_MACSEC=y +CONFIG_VETH=y # CONFIG_ETHERNET is not set -# CONFIG_FDDI is not set -# CONFIG_HIPPI is not set -# CONFIG_NET_SB1000 is not set -# CONFIG_PHYLIB is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set - -# -# Host-side USB support is needed for USB Network Adapter support -# -CONFIG_WLAN=y -# CONFIG_WIRELESS_WDS is not set -CONFIG_WLAN_VENDOR_ADMTEK=y -# CONFIG_ADM8211 is not set -CONFIG_WLAN_VENDOR_ATH=y -# CONFIG_ATH_DEBUG is not set -# CONFIG_ATH5K is not set -# CONFIG_ATH5K_PCI is not set -# CONFIG_ATH9K is not set -# CONFIG_ATH6KL is not set -# CONFIG_WIL6210 is not set -# CONFIG_ATH10K is not set -# CONFIG_WCN36XX is not set -CONFIG_WLAN_VENDOR_ATMEL=y -# CONFIG_ATMEL is not set -CONFIG_WLAN_VENDOR_BROADCOM=y -# CONFIG_B43 is not set -# CONFIG_B43LEGACY is not set -# CONFIG_BRCMSMAC is not set -# CONFIG_BRCMFMAC is not set -CONFIG_WLAN_VENDOR_CISCO=y -CONFIG_WLAN_VENDOR_INTEL=y -# CONFIG_IPW2100 is not set -# CONFIG_IPW2200 is not set -# CONFIG_IWL4965 is not set -# CONFIG_IWL3945 is not set -# CONFIG_IWLWIFI is not set -CONFIG_WLAN_VENDOR_INTERSIL=y -# CONFIG_HOSTAP is not set -# CONFIG_HERMES is not set -# CONFIG_P54_COMMON is not set -# CONFIG_PRISM54 is not set -CONFIG_WLAN_VENDOR_MARVELL=y -# CONFIG_LIBERTAS is not set -# CONFIG_LIBERTAS_THINFIRM is not set -# CONFIG_MWIFIEX is not set -# CONFIG_MWL8K is not set -CONFIG_WLAN_VENDOR_MEDIATEK=y -CONFIG_WLAN_VENDOR_RALINK=y -# CONFIG_RT2X00 is not set -CONFIG_WLAN_VENDOR_REALTEK=y -# CONFIG_RTL8180 is not set -CONFIG_RTL_CARDS=y -# CONFIG_RTL8192CE is not set -# CONFIG_RTL8192SE is not set -# CONFIG_RTL8192DE is not set -# CONFIG_RTL8723AE is not set -# CONFIG_RTL8723BE is not set -# CONFIG_RTL8188EE is not set -# CONFIG_RTL8192EE is not set -# CONFIG_RTL8821AE is not set -CONFIG_WLAN_VENDOR_RSI=y -# CONFIG_RSI_91X is not set -CONFIG_WLAN_VENDOR_ST=y -# CONFIG_CW1200 is not set -CONFIG_WLAN_VENDOR_TI=y -# CONFIG_WL1251 is not set -# CONFIG_WL12XX is not set -# CONFIG_WL18XX is not set -# CONFIG_WLCORE is not set -CONFIG_WLAN_VENDOR_ZYDAS=y CONFIG_MAC80211_HWSIM=y - -# -# Enable WiMAX (Networking options) to see the WiMAX drivers -# -# CONFIG_WAN is not set -# CONFIG_VMXNET3 is not set -# CONFIG_FUJITSU_ES is not set -# CONFIG_ISDN is not set -# CONFIG_NVM is not set - -# -# Input device support -# -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT_POLLDEV is not set -# CONFIG_INPUT_SPARSEKMAP is not set -# CONFIG_INPUT_MATRIXKMAP is not set - -# -# Userland interfaces -# -# CONFIG_INPUT_MOUSEDEV is not set -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set -# CONFIG_RMI4_CORE is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_CT82C710 is not set -# CONFIG_SERIO_PCIPS2 is not set -# CONFIG_SERIO_LIBPS2 is not set -# CONFIG_SERIO_RAW is not set -# CONFIG_SERIO_ALTERA_PS2 is not set -# CONFIG_SERIO_PS2MULT is not set -# CONFIG_SERIO_ARC_PS2 is not set -# CONFIG_USERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_TTY=y -CONFIG_VT=y -CONFIG_CONSOLE_TRANSLATIONS=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -CONFIG_VT_HW_CONSOLE_BINDING=y -CONFIG_UNIX98_PTYS=y # CONFIG_LEGACY_PTYS is not set -# CONFIG_SERIAL_NONSTANDARD is not set -# CONFIG_NOZOMI is not set -# CONFIG_N_GSM is not set -# CONFIG_TRACE_SINK is not set -CONFIG_DEVMEM=y -# CONFIG_DEVKMEM is not set - -# -# Serial drivers -# -CONFIG_SERIAL_EARLYCON=y CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y # CONFIG_SERIAL_8250_PNP is not set -# CONFIG_SERIAL_8250_FINTEK is not set CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_PCI=y -CONFIG_SERIAL_8250_NR_UARTS=4 -CONFIG_SERIAL_8250_RUNTIME_UARTS=4 -# CONFIG_SERIAL_8250_EXTENDED is not set -# CONFIG_SERIAL_8250_FSL is not set -# CONFIG_SERIAL_8250_DW is not set -# CONFIG_SERIAL_8250_RT288X is not set -CONFIG_SERIAL_8250_LPSS=y # CONFIG_SERIAL_8250_MID is not set -# CONFIG_SERIAL_8250_MOXA is not set - -# -# Non-8250 serial port support -# -# CONFIG_SERIAL_UARTLITE is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set -# CONFIG_SERIAL_SCCNXP is not set -# CONFIG_SERIAL_ALTERA_JTAGUART is not set -# CONFIG_SERIAL_ALTERA_UART is not set -# CONFIG_SERIAL_ARC is not set -# CONFIG_SERIAL_RP2 is not set -# CONFIG_SERIAL_FSL_LPUART is not set -# CONFIG_TTY_PRINTK is not set -# CONFIG_VIRTIO_CONSOLE is not set -# CONFIG_IPMI_HANDLER is not set # CONFIG_HW_RANDOM is not set -# CONFIG_NVRAM is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set -# CONFIG_MWAVE is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_HPET is not set -# CONFIG_HANGCHECK_TIMER is not set -# CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set -CONFIG_DEVPORT=y -# CONFIG_XILLYBUS is not set - -# -# I2C support -# -# CONFIG_I2C is not set -# CONFIG_SPI is not set -# CONFIG_SPMI is not set -# CONFIG_HSI is not set - -# -# PPS support -# -# CONFIG_PPS is not set - -# -# PPS generators support -# - -# -# PTP clock support -# -# CONFIG_PTP_1588_CLOCK is not set - -# -# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks. -# -# CONFIG_GPIOLIB is not set -# CONFIG_W1 is not set -# CONFIG_POWER_AVS is not set -# CONFIG_POWER_RESET is not set CONFIG_POWER_SUPPLY=y -# CONFIG_POWER_SUPPLY_DEBUG is not set -# CONFIG_PDA_POWER is not set -# CONFIG_TEST_POWER is not set -# CONFIG_BATTERY_DS2780 is not set -# CONFIG_BATTERY_DS2781 is not set -# CONFIG_BATTERY_BQ27XXX is not set -# CONFIG_CHARGER_MAX8903 is not set # CONFIG_HWMON is not set -CONFIG_THERMAL=y -# CONFIG_THERMAL_WRITABLE_TRIPS is not set -CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y -# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set -# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set -# CONFIG_THERMAL_DEFAULT_GOV_POWER_ALLOCATOR is not set -# CONFIG_THERMAL_GOV_FAIR_SHARE is not set -CONFIG_THERMAL_GOV_STEP_WISE=y -# CONFIG_THERMAL_GOV_BANG_BANG is not set -# CONFIG_THERMAL_GOV_USER_SPACE is not set -# CONFIG_THERMAL_GOV_POWER_ALLOCATOR is not set -# CONFIG_THERMAL_EMULATION is not set -# CONFIG_INTEL_POWERCLAMP is not set -# CONFIG_INTEL_SOC_DTS_THERMAL is not set - -# -# ACPI INT340X thermal drivers -# -# CONFIG_INT340X_THERMAL is not set -# CONFIG_INTEL_PCH_THERMAL is not set -# CONFIG_WATCHDOG is not set -CONFIG_SSB_POSSIBLE=y - -# -# Sonics Silicon Backplane -# -# CONFIG_SSB is not set -CONFIG_BCMA_POSSIBLE=y - -# -# Broadcom specific AMBA -# -# CONFIG_BCMA is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_CORE is not set -# CONFIG_MFD_CROS_EC is not set -# CONFIG_HTC_PASIC3 is not set -# CONFIG_LPC_ICH is not set -# CONFIG_LPC_SCH is not set -# CONFIG_MFD_INTEL_LPSS_ACPI is not set -# CONFIG_MFD_INTEL_LPSS_PCI is not set -# CONFIG_MFD_JANZ_CMODIO is not set -# CONFIG_MFD_KEMPLD is not set -# CONFIG_MFD_MT6397 is not set -# CONFIG_MFD_RDC321X is not set -# CONFIG_MFD_RTSX_PCI is not set -# CONFIG_MFD_SM501 is not set -# CONFIG_ABX500_CORE is not set -# CONFIG_MFD_SYSCON is not set -# CONFIG_MFD_TI_AM335X_TSCADC is not set -# CONFIG_MFD_TMIO is not set -# CONFIG_MFD_VX855 is not set -# CONFIG_REGULATOR is not set -# CONFIG_MEDIA_SUPPORT is not set - -# -# Graphics support -# -# CONFIG_AGP is not set -CONFIG_VGA_ARB=y -CONFIG_VGA_ARB_MAX_GPUS=16 -# CONFIG_VGA_SWITCHEROO is not set -# CONFIG_DRM is not set - -# -# ACP (Audio CoProcessor) Configuration -# - -# -# Frame buffer Devices -# CONFIG_FB=y -# CONFIG_FIRMWARE_EDID is not set -CONFIG_FB_CMDLINE=y -CONFIG_FB_NOTIFY=y -# CONFIG_FB_DDC is not set -CONFIG_FB_BOOT_VESA_SUPPORT=y -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -# CONFIG_FB_SYS_FILLRECT is not set -# CONFIG_FB_SYS_COPYAREA is not set -# CONFIG_FB_SYS_IMAGEBLIT is not set -# CONFIG_FB_FOREIGN_ENDIAN is not set -# CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y -# CONFIG_FB_TILEBLITTING is not set - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_ARC is not set -# CONFIG_FB_ASILIANT is not set -# CONFIG_FB_IMSTT is not set -# CONFIG_FB_VGA16 is not set CONFIG_FB_VESA=y -# CONFIG_FB_N411 is not set -# CONFIG_FB_HGA is not set -# CONFIG_FB_OPENCORES is not set -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_NVIDIA is not set -# CONFIG_FB_RIVA is not set -# CONFIG_FB_I740 is not set -# CONFIG_FB_LE80578 is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_S3 is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -# CONFIG_FB_KYRO is not set -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_VT8623 is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_ARK is not set -# CONFIG_FB_PM3 is not set -# CONFIG_FB_CARMINE is not set -# CONFIG_FB_IBM_GXT4500 is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FB_METRONOME is not set -# CONFIG_FB_MB862XX is not set -# CONFIG_FB_BROADSHEET is not set -# CONFIG_FB_AUO_K190X is not set -# CONFIG_FB_SIMPLE is not set -# CONFIG_FB_SM712 is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set -# CONFIG_VGASTATE is not set - -# -# Console display driver support -# -CONFIG_VGA_CONSOLE=y CONFIG_VGACON_SOFT_SCROLLBACK=y -CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64 -CONFIG_DUMMY_CONSOLE=y -CONFIG_DUMMY_CONSOLE_COLUMNS=80 -CONFIG_DUMMY_CONSOLE_ROWS=25 CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -# CONFIG_LOGO is not set -# CONFIG_SOUND is not set - -# -# HID support -# -CONFIG_HID=y -# CONFIG_HID_BATTERY_STRENGTH is not set CONFIG_HIDRAW=y -# CONFIG_UHID is not set -CONFIG_HID_GENERIC=y - -# -# Special HID drivers -# -# CONFIG_HID_A4TECH is not set -# CONFIG_HID_ACRUX is not set -# CONFIG_HID_APPLE is not set -# CONFIG_HID_AUREAL is not set -# CONFIG_HID_BELKIN is not set -# CONFIG_HID_CHERRY is not set -# CONFIG_HID_CHICONY is not set -# CONFIG_HID_CMEDIA is not set -# CONFIG_HID_CYPRESS is not set -# CONFIG_HID_DRAGONRISE is not set -# CONFIG_HID_EMS_FF is not set -# CONFIG_HID_ELECOM is not set -# CONFIG_HID_EZKEY is not set -# CONFIG_HID_GEMBIRD is not set -# CONFIG_HID_GFRM is not set -# CONFIG_HID_KEYTOUCH is not set -# CONFIG_HID_KYE is not set -# CONFIG_HID_WALTOP is not set -# CONFIG_HID_GYRATION is not set -# CONFIG_HID_ICADE is not set -# CONFIG_HID_TWINHAN is not set -# CONFIG_HID_KENSINGTON is not set -# CONFIG_HID_LCPOWER is not set -# CONFIG_HID_LENOVO is not set -# CONFIG_HID_LOGITECH is not set -# CONFIG_HID_MAGICMOUSE is not set -# CONFIG_HID_MAYFLASH is not set -# CONFIG_HID_MICROSOFT is not set -# CONFIG_HID_MONTEREY is not set -# CONFIG_HID_MULTITOUCH is not set -# CONFIG_HID_ORTEK is not set -# CONFIG_HID_PANTHERLORD is not set -# CONFIG_HID_PETALYNX is not set -# CONFIG_HID_PICOLCD is not set -# CONFIG_HID_PLANTRONICS is not set -# CONFIG_HID_PRIMAX is not set -# CONFIG_HID_SAITEK is not set -# CONFIG_HID_SAMSUNG is not set -# CONFIG_HID_SPEEDLINK is not set -# CONFIG_HID_STEELSERIES is not set -# CONFIG_HID_SUNPLUS is not set -# CONFIG_HID_RMI is not set -# CONFIG_HID_GREENASIA is not set -# CONFIG_HID_SMARTJOYPLUS is not set -# CONFIG_HID_TIVO is not set -# CONFIG_HID_TOPSEED is not set -# CONFIG_HID_THRUSTMASTER is not set -# CONFIG_HID_UDRAW_PS3 is not set -# CONFIG_HID_WACOM is not set -# CONFIG_HID_XINMO is not set -# CONFIG_HID_ZEROPLUS is not set -# CONFIG_HID_ZYDACRON is not set -# CONFIG_HID_SENSOR_HUB is not set -# CONFIG_HID_ALPS is not set - -# -# Intel ISH HID support -# -# CONFIG_INTEL_ISH_HID is not set -CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_SUPPORT is not set -# CONFIG_UWB is not set -# CONFIG_MMC is not set -# CONFIG_MEMSTICK is not set -# CONFIG_NEW_LEDS is not set -# CONFIG_ACCESSIBILITY is not set -# CONFIG_INFINIBAND is not set -CONFIG_EDAC_ATOMIC_SCRUB=y -CONFIG_EDAC_SUPPORT=y -# CONFIG_EDAC is not set -CONFIG_RTC_LIB=y -CONFIG_RTC_MC146818_LIB=y -# CONFIG_RTC_CLASS is not set -# CONFIG_DMADEVICES is not set - -# -# DMABUF options -# -# CONFIG_SYNC_FILE is not set -# CONFIG_AUXDISPLAY is not set -# CONFIG_UIO is not set CONFIG_VIRT_DRIVERS=y -CONFIG_VIRTIO=y - -# -# Virtio drivers -# CONFIG_VIRTIO_PCI=y -CONFIG_VIRTIO_PCI_LEGACY=y -# CONFIG_VIRTIO_BALLOON is not set -# CONFIG_VIRTIO_INPUT is not set -# CONFIG_VIRTIO_MMIO is not set - -# -# Microsoft Hyper-V guest support -# -# CONFIG_HYPERV is not set -# CONFIG_STAGING is not set # CONFIG_X86_PLATFORM_DEVICES is not set -# CONFIG_CHROME_PLATFORMS is not set - -# -# Hardware Spinlock drivers -# - -# -# Clock Source drivers -# -CONFIG_CLKEVT_I8253=y -CONFIG_I8253_LOCK=y -CONFIG_CLKBLD_I8253=y -# CONFIG_ATMEL_PIT is not set -# CONFIG_SH_TIMER_CMT is not set -# CONFIG_SH_TIMER_MTU2 is not set -# CONFIG_SH_TIMER_TMU is not set -# CONFIG_EM_TIMER_STI is not set -CONFIG_MAILBOX=y -CONFIG_PCC=y -# CONFIG_ALTERA_MBOX is not set # CONFIG_IOMMU_SUPPORT is not set - -# -# Remoteproc drivers -# -# CONFIG_REMOTEPROC is not set - -# -# Rpmsg drivers -# - -# -# SOC (System On Chip) specific Drivers -# - -# -# Broadcom SoC drivers -# -# CONFIG_SUNXI_SRAM is not set -# CONFIG_SOC_TI is not set -# CONFIG_PM_DEVFREQ is not set -# CONFIG_EXTCON is not set -# CONFIG_MEMORY is not set -# CONFIG_IIO is not set -# CONFIG_NTB is not set -# CONFIG_VME_BUS is not set -# CONFIG_PWM is not set -CONFIG_ARM_GIC_MAX_NR=1 -# CONFIG_IPACK_BUS is not set -# CONFIG_RESET_CONTROLLER is not set -# CONFIG_FMC is not set - -# -# PHY Subsystem -# -# CONFIG_GENERIC_PHY is not set -# CONFIG_PHY_PXA_28NM_HSIC is not set -# CONFIG_PHY_PXA_28NM_USB2 is not set -# CONFIG_BCM_KONA_USB2_PHY is not set -# CONFIG_POWERCAP is not set -# CONFIG_MCB is not set - -# -# Performance monitor support -# -# CONFIG_RAS is not set -# CONFIG_THUNDERBOLT is not set - -# -# Android -# -# CONFIG_ANDROID is not set -# CONFIG_NVMEM is not set -# CONFIG_STM is not set -# CONFIG_INTEL_TH is not set - -# -# FPGA Configuration Support -# -# CONFIG_FPGA is not set - -# -# Firmware Drivers -# -# CONFIG_ARM_SCPI_PROTOCOL is not set -# CONFIG_EDD is not set -CONFIG_FIRMWARE_MEMMAP=y -# CONFIG_DELL_RBU is not set -# CONFIG_DCDBAS is not set -# CONFIG_DMIID is not set -# CONFIG_DMI_SYSFS is not set -CONFIG_DMI_SCAN_MACHINE_NON_EFI_FALLBACK=y -# CONFIG_ISCSI_IBFT_FIND is not set -# CONFIG_FW_CFG_SYSFS is not set -# CONFIG_GOOGLE_FIRMWARE is not set -# CONFIG_EFI_DEV_PATH_PARSER is not set - -# -# Tegra firmware driver -# - -# -# File systems -# -CONFIG_DCACHE_WORD_ACCESS=y -# CONFIG_EXT2_FS is not set -# CONFIG_EXT3_FS is not set -# CONFIG_EXT4_FS is not set -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set -# CONFIG_BTRFS_FS is not set -# CONFIG_NILFS2_FS is not set -# CONFIG_F2FS_FS is not set -# CONFIG_FS_DAX is not set -CONFIG_FS_POSIX_ACL=y -# CONFIG_EXPORTFS_BLOCK_OPS is not set -CONFIG_FILE_LOCKING=y -CONFIG_MANDATORY_FILE_LOCKING=y -# CONFIG_FS_ENCRYPTION is not set -# CONFIG_FSNOTIFY is not set # CONFIG_DNOTIFY is not set # CONFIG_INOTIFY_USER is not set -# CONFIG_FANOTIFY is not set -# CONFIG_QUOTA is not set -# CONFIG_QUOTACTL is not set -# CONFIG_AUTOFS4_FS is not set -# CONFIG_FUSE_FS is not set -# CONFIG_OVERLAY_FS is not set - -# -# Caches -# -# CONFIG_FSCACHE is not set - -# -# CD-ROM/DVD Filesystems -# CONFIG_ISO9660_FS=y -# CONFIG_JOLIET is not set -# CONFIG_ZISOFS is not set -# CONFIG_UDF_FS is not set - -# -# DOS/FAT/NT Filesystems -# -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_NTFS_FS is not set - -# -# Pseudo filesystems -# -CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y -CONFIG_PROC_SYSCTL=y -CONFIG_PROC_PAGE_MONITOR=y -# CONFIG_PROC_CHILDREN is not set -CONFIG_KERNFS=y -CONFIG_SYSFS=y CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y -CONFIG_TMPFS_XATTR=y -# CONFIG_HUGETLBFS is not set -# CONFIG_HUGETLB_PAGE is not set -CONFIG_ARCH_HAS_GIGANTIC_PAGE=y CONFIG_CONFIGFS_FS=y # CONFIG_MISC_FILESYSTEMS is not set -CONFIG_NETWORK_FILESYSTEMS=y -# CONFIG_NFS_FS is not set -# CONFIG_NFSD is not set -# CONFIG_CEPH_FS is not set -# CONFIG_CIFS is not set -# CONFIG_NCP_FS is not set -# CONFIG_CODA_FS is not set -# CONFIG_AFS_FS is not set CONFIG_9P_FS=y CONFIG_9P_FS_POSIX_ACL=y -# CONFIG_9P_FS_SECURITY is not set -CONFIG_NLS=y -CONFIG_NLS_DEFAULT="iso8859-1" -# CONFIG_NLS_CODEPAGE_437 is not set -# CONFIG_NLS_CODEPAGE_737 is not set -# CONFIG_NLS_CODEPAGE_775 is not set -# CONFIG_NLS_CODEPAGE_850 is not set -# CONFIG_NLS_CODEPAGE_852 is not set -# CONFIG_NLS_CODEPAGE_855 is not set -# CONFIG_NLS_CODEPAGE_857 is not set -# CONFIG_NLS_CODEPAGE_860 is not set -# CONFIG_NLS_CODEPAGE_861 is not set -# CONFIG_NLS_CODEPAGE_862 is not set -# CONFIG_NLS_CODEPAGE_863 is not set -# CONFIG_NLS_CODEPAGE_864 is not set -# CONFIG_NLS_CODEPAGE_865 is not set -# CONFIG_NLS_CODEPAGE_866 is not set -# CONFIG_NLS_CODEPAGE_869 is not set -# CONFIG_NLS_CODEPAGE_936 is not set -# CONFIG_NLS_CODEPAGE_950 is not set -# CONFIG_NLS_CODEPAGE_932 is not set -# CONFIG_NLS_CODEPAGE_949 is not set -# CONFIG_NLS_CODEPAGE_874 is not set -# CONFIG_NLS_ISO8859_8 is not set -# CONFIG_NLS_CODEPAGE_1250 is not set -# CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set -# CONFIG_NLS_ISO8859_1 is not set -# CONFIG_NLS_ISO8859_2 is not set -# CONFIG_NLS_ISO8859_3 is not set -# CONFIG_NLS_ISO8859_4 is not set -# CONFIG_NLS_ISO8859_5 is not set -# CONFIG_NLS_ISO8859_6 is not set -# CONFIG_NLS_ISO8859_7 is not set -# CONFIG_NLS_ISO8859_9 is not set -# CONFIG_NLS_ISO8859_13 is not set -# CONFIG_NLS_ISO8859_14 is not set -# CONFIG_NLS_ISO8859_15 is not set -# CONFIG_NLS_KOI8_R is not set -# CONFIG_NLS_KOI8_U is not set -# CONFIG_NLS_MAC_ROMAN is not set -# CONFIG_NLS_MAC_CELTIC is not set -# CONFIG_NLS_MAC_CENTEURO is not set -# CONFIG_NLS_MAC_CROATIAN is not set -# CONFIG_NLS_MAC_CYRILLIC is not set -# CONFIG_NLS_MAC_GAELIC is not set -# CONFIG_NLS_MAC_GREEK is not set -# CONFIG_NLS_MAC_ICELAND is not set -# CONFIG_NLS_MAC_INUIT is not set -# CONFIG_NLS_MAC_ROMANIAN is not set -# CONFIG_NLS_MAC_TURKISH is not set -# CONFIG_NLS_UTF8 is not set -# CONFIG_DLM is not set - -# -# Kernel hacking -# -CONFIG_TRACE_IRQFLAGS_SUPPORT=y - -# -# printk and dmesg options -# +CONFIG_CRYPTO_ECHAINIV=y +CONFIG_CRYPTO_CRCT10DIF=y +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_HW is not set CONFIG_PRINTK_TIME=y -CONFIG_CONSOLE_LOGLEVEL_DEFAULT=7 -CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4 -# CONFIG_BOOT_PRINTK_DELAY is not set CONFIG_DYNAMIC_DEBUG=y - -# -# Compile-time checks and compiler options -# CONFIG_DEBUG_INFO=y CONFIG_DEBUG_INFO_REDUCED=y -# CONFIG_DEBUG_INFO_SPLIT is not set -# CONFIG_DEBUG_INFO_DWARF4 is not set -# CONFIG_GDB_SCRIPTS is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y CONFIG_FRAME_WARN=1024 -# CONFIG_STRIP_ASM_SYMS is not set -# CONFIG_READABLE_ASM is not set -# CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_PAGE_OWNER is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_SECTION_MISMATCH=y -CONFIG_SECTION_MISMATCH_WARN_ONLY=y -CONFIG_ARCH_WANT_FRAME_POINTERS=y -CONFIG_FRAME_POINTER=y -# CONFIG_STACK_VALIDATION is not set -# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set CONFIG_MAGIC_SYSRQ=y -CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1 -CONFIG_DEBUG_KERNEL=y - -# -# Memory Debugging -# CONFIG_PAGE_EXTENSION=y CONFIG_DEBUG_PAGEALLOC=y -# CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT is not set -# CONFIG_PAGE_POISONING is not set -# CONFIG_DEBUG_PAGE_REF is not set +CONFIG_DEBUG_RODATA_TEST=y CONFIG_DEBUG_OBJECTS=y CONFIG_DEBUG_OBJECTS_SELFTEST=y CONFIG_DEBUG_OBJECTS_FREE=y @@ -1888,426 +155,21 @@ CONFIG_DEBUG_OBJECTS_TIMERS=y CONFIG_DEBUG_OBJECTS_WORK=y CONFIG_DEBUG_OBJECTS_RCU_HEAD=y CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y -CONFIG_DEBUG_OBJECTS_ENABLE_DEFAULT=1 CONFIG_SLUB_DEBUG_ON=y -# CONFIG_SLUB_STATS is not set -CONFIG_HAVE_DEBUG_KMEMLEAK=y CONFIG_DEBUG_KMEMLEAK=y -CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=400 -# CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF is not set CONFIG_DEBUG_STACK_USAGE=y -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_VIRTUAL is not set -# CONFIG_DEBUG_MEMORY_INIT is not set -# CONFIG_DEBUG_PER_CPU_MAPS is not set -CONFIG_HAVE_DEBUG_STACKOVERFLOW=y -# CONFIG_DEBUG_STACKOVERFLOW is not set -CONFIG_HAVE_ARCH_KMEMCHECK=y -CONFIG_HAVE_ARCH_KASAN=y -# CONFIG_KASAN is not set -CONFIG_ARCH_HAS_KCOV=y -# CONFIG_KCOV is not set -# CONFIG_DEBUG_SHIRQ is not set - -# -# Debug Lockups and Hangs -# -CONFIG_LOCKUP_DETECTOR=y -CONFIG_HARDLOCKUP_DETECTOR=y -# CONFIG_BOOTPARAM_HARDLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_HARDLOCKUP_PANIC_VALUE=0 -# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set -CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 -CONFIG_DETECT_HUNG_TASK=y -CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120 -# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set -CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 -# CONFIG_WQ_WATCHDOG is not set CONFIG_PANIC_ON_OOPS=y -CONFIG_PANIC_ON_OOPS_VALUE=1 -CONFIG_PANIC_TIMEOUT=0 -CONFIG_SCHED_DEBUG=y -CONFIG_SCHED_INFO=y -CONFIG_SCHEDSTATS=y -# CONFIG_SCHED_STACK_END_CHECK is not set -# CONFIG_DEBUG_TIMEKEEPING is not set -CONFIG_TIMER_STATS=y -CONFIG_DEBUG_PREEMPT=y - -# -# Lock Debugging (spinlocks, mutexes, etc...) -# -CONFIG_DEBUG_RT_MUTEXES=y -CONFIG_DEBUG_SPINLOCK=y -CONFIG_DEBUG_MUTEXES=y -# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set -CONFIG_DEBUG_LOCK_ALLOC=y +CONFIG_HARDLOCKUP_DETECTOR=y CONFIG_PROVE_LOCKING=y -CONFIG_LOCKDEP=y CONFIG_LOCK_STAT=y CONFIG_DEBUG_LOCKDEP=y CONFIG_DEBUG_ATOMIC_SLEEP=y -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_LOCK_TORTURE_TEST is not set -CONFIG_TRACE_IRQFLAGS=y -CONFIG_STACKTRACE=y CONFIG_DEBUG_KOBJECT=y -# CONFIG_DEBUG_KOBJECT_RELEASE is not set -CONFIG_DEBUG_BUGVERBOSE=y CONFIG_DEBUG_LIST=y -CONFIG_DEBUG_PI_LIST=y -# CONFIG_DEBUG_SG is not set CONFIG_DEBUG_NOTIFIERS=y -# CONFIG_DEBUG_CREDENTIALS is not set - -# -# RCU Debugging -# -CONFIG_PROVE_RCU=y -CONFIG_PROVE_RCU_REPEATEDLY=y -CONFIG_SPARSE_RCU_POINTER=y -# CONFIG_TORTURE_TEST is not set -# CONFIG_RCU_PERF_TEST is not set -# CONFIG_RCU_TORTURE_TEST is not set CONFIG_RCU_CPU_STALL_TIMEOUT=60 # CONFIG_RCU_TRACE is not set -# CONFIG_RCU_EQS_DEBUG is not set -# CONFIG_DEBUG_WQ_FORCE_RR_CPU is not set -# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -# CONFIG_NOTIFIER_ERROR_INJECTION is not set -# CONFIG_FAULT_INJECTION is not set CONFIG_LATENCYTOP=y -CONFIG_USER_STACKTRACE_SUPPORT=y -CONFIG_NOP_TRACER=y -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_DYNAMIC_FTRACE_WITH_REGS=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y -CONFIG_HAVE_SYSCALL_TRACEPOINTS=y -CONFIG_HAVE_FENTRY=y -CONFIG_HAVE_C_RECORDMCOUNT=y -CONFIG_TRACE_CLOCK=y -CONFIG_RING_BUFFER=y -CONFIG_EVENT_TRACING=y -CONFIG_CONTEXT_SWITCH_TRACER=y -CONFIG_TRACING=y -CONFIG_GENERIC_TRACER=y -CONFIG_TRACING_SUPPORT=y -CONFIG_FTRACE=y CONFIG_FUNCTION_TRACER=y -CONFIG_FUNCTION_GRAPH_TRACER=y -# CONFIG_IRQSOFF_TRACER is not set -# CONFIG_PREEMPT_TRACER is not set -# CONFIG_SCHED_TRACER is not set -# CONFIG_HWLAT_TRACER is not set -# CONFIG_FTRACE_SYSCALLS is not set -# CONFIG_TRACER_SNAPSHOT is not set -CONFIG_BRANCH_PROFILE_NONE=y -# CONFIG_PROFILE_ANNOTATED_BRANCHES is not set -# CONFIG_PROFILE_ALL_BRANCHES is not set -# CONFIG_STACK_TRACER is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_UPROBE_EVENT is not set -# CONFIG_PROBE_EVENTS is not set -CONFIG_DYNAMIC_FTRACE=y -CONFIG_DYNAMIC_FTRACE_WITH_REGS=y -# CONFIG_FUNCTION_PROFILER is not set -CONFIG_FTRACE_MCOUNT_RECORD=y -# CONFIG_FTRACE_STARTUP_TEST is not set -# CONFIG_MMIOTRACE is not set -# CONFIG_HIST_TRIGGERS is not set -# CONFIG_TRACEPOINT_BENCHMARK is not set -# CONFIG_RING_BUFFER_BENCHMARK is not set -# CONFIG_RING_BUFFER_STARTUP_TEST is not set -# CONFIG_TRACE_ENUM_MAP_FILE is not set - -# -# Runtime Testing -# -# CONFIG_LKDTM is not set -# CONFIG_TEST_LIST_SORT is not set -# CONFIG_BACKTRACE_SELF_TEST is not set -# CONFIG_RBTREE_TEST is not set -# CONFIG_ATOMIC64_SELFTEST is not set -# CONFIG_TEST_HEXDUMP is not set -# CONFIG_TEST_STRING_HELPERS is not set -# CONFIG_TEST_KSTRTOX is not set -# CONFIG_TEST_PRINTF is not set -# CONFIG_TEST_BITMAP is not set -# CONFIG_TEST_UUID is not set -# CONFIG_TEST_RHASHTABLE is not set -# CONFIG_TEST_HASH is not set -# CONFIG_PROVIDE_OHCI1394_DMA_INIT is not set -# CONFIG_DMA_API_DEBUG is not set -# CONFIG_TEST_FIRMWARE is not set -# CONFIG_TEST_UDELAY is not set -# CONFIG_MEMTEST is not set -# CONFIG_BUG_ON_DATA_CORRUPTION is not set -# CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_KGDB is not set -CONFIG_ARCH_HAS_UBSAN_SANITIZE_ALL=y -# CONFIG_ARCH_WANTS_UBSAN_NO_NULL is not set -# CONFIG_UBSAN is not set -CONFIG_ARCH_HAS_DEVMEM_IS_ALLOWED=y # CONFIG_STRICT_DEVMEM is not set # CONFIG_X86_VERBOSE_BOOTUP is not set -CONFIG_EARLY_PRINTK=y -# CONFIG_EARLY_PRINTK_DBGP is not set -# CONFIG_X86_PTDUMP_CORE is not set -# CONFIG_X86_PTDUMP is not set -CONFIG_DEBUG_RODATA_TEST=y -# CONFIG_DEBUG_WX is not set -CONFIG_DOUBLEFAULT=y -# CONFIG_DEBUG_TLBFLUSH is not set -# CONFIG_IOMMU_DEBUG is not set -# CONFIG_IOMMU_STRESS is not set -CONFIG_HAVE_MMIOTRACE_SUPPORT=y -CONFIG_IO_DELAY_TYPE_0X80=0 -CONFIG_IO_DELAY_TYPE_0XED=1 -CONFIG_IO_DELAY_TYPE_UDELAY=2 -CONFIG_IO_DELAY_TYPE_NONE=3 -CONFIG_IO_DELAY_0X80=y -# CONFIG_IO_DELAY_0XED is not set -# CONFIG_IO_DELAY_UDELAY is not set -# CONFIG_IO_DELAY_NONE is not set -CONFIG_DEFAULT_IO_DELAY_TYPE=0 -# CONFIG_DEBUG_BOOT_PARAMS is not set -# CONFIG_CPA_DEBUG is not set -# CONFIG_OPTIMIZE_INLINING is not set -# CONFIG_DEBUG_ENTRY is not set -# CONFIG_DEBUG_NMI_SELFTEST is not set -CONFIG_X86_DEBUG_FPU=y -# CONFIG_PUNIT_ATOM_DEBUG is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY_DMESG_RESTRICT is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITYFS is not set -CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y -CONFIG_HAVE_ARCH_HARDENED_USERCOPY=y -# CONFIG_HARDENED_USERCOPY is not set -CONFIG_DEFAULT_SECURITY_DAC=y -CONFIG_DEFAULT_SECURITY="" -CONFIG_CRYPTO=y - -# -# Crypto core or helper -# -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_ALGAPI2=y -CONFIG_CRYPTO_AEAD=y -CONFIG_CRYPTO_AEAD2=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_BLKCIPHER2=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_HASH2=y -CONFIG_CRYPTO_RNG=y -CONFIG_CRYPTO_RNG2=y -CONFIG_CRYPTO_RNG_DEFAULT=y -CONFIG_CRYPTO_AKCIPHER2=y -CONFIG_CRYPTO_KPP2=y -CONFIG_CRYPTO_ACOMP2=y -# CONFIG_CRYPTO_RSA is not set -# CONFIG_CRYPTO_DH is not set -# CONFIG_CRYPTO_ECDH is not set -CONFIG_CRYPTO_MANAGER=y -CONFIG_CRYPTO_MANAGER2=y -# CONFIG_CRYPTO_USER is not set -CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y -CONFIG_CRYPTO_GF128MUL=y -CONFIG_CRYPTO_NULL=y -CONFIG_CRYPTO_NULL2=y -# CONFIG_CRYPTO_PCRYPT is not set -CONFIG_CRYPTO_WORKQUEUE=y -# CONFIG_CRYPTO_CRYPTD is not set -# CONFIG_CRYPTO_MCRYPTD is not set -# CONFIG_CRYPTO_AUTHENC is not set - -# -# Authenticated Encryption with Associated Data -# -CONFIG_CRYPTO_CCM=y -CONFIG_CRYPTO_GCM=y -# CONFIG_CRYPTO_CHACHA20POLY1305 is not set -CONFIG_CRYPTO_SEQIV=y -CONFIG_CRYPTO_ECHAINIV=y - -# -# Block modes -# -# CONFIG_CRYPTO_CBC is not set -CONFIG_CRYPTO_CTR=y -# CONFIG_CRYPTO_CTS is not set -# CONFIG_CRYPTO_ECB is not set -# CONFIG_CRYPTO_LRW is not set -# CONFIG_CRYPTO_PCBC is not set -# CONFIG_CRYPTO_XTS is not set -# CONFIG_CRYPTO_KEYWRAP is not set - -# -# Hash modes -# -# CONFIG_CRYPTO_CMAC is not set -CONFIG_CRYPTO_HMAC=y -# CONFIG_CRYPTO_XCBC is not set -# CONFIG_CRYPTO_VMAC is not set - -# -# Digest -# -# CONFIG_CRYPTO_CRC32C is not set -# CONFIG_CRYPTO_CRC32C_INTEL is not set -# CONFIG_CRYPTO_CRC32 is not set -# CONFIG_CRYPTO_CRC32_PCLMUL is not set -CONFIG_CRYPTO_CRCT10DIF=y -CONFIG_CRYPTO_GHASH=y -# CONFIG_CRYPTO_POLY1305 is not set -# CONFIG_CRYPTO_POLY1305_X86_64 is not set -# CONFIG_CRYPTO_MD4 is not set -# CONFIG_CRYPTO_MD5 is not set -# CONFIG_CRYPTO_MICHAEL_MIC is not set -# CONFIG_CRYPTO_RMD128 is not set -# CONFIG_CRYPTO_RMD160 is not set -# CONFIG_CRYPTO_RMD256 is not set -# CONFIG_CRYPTO_RMD320 is not set -# CONFIG_CRYPTO_SHA1 is not set -# CONFIG_CRYPTO_SHA1_SSSE3 is not set -# CONFIG_CRYPTO_SHA256_SSSE3 is not set -# CONFIG_CRYPTO_SHA512_SSSE3 is not set -# CONFIG_CRYPTO_SHA1_MB is not set -# CONFIG_CRYPTO_SHA256_MB is not set -# CONFIG_CRYPTO_SHA512_MB is not set -CONFIG_CRYPTO_SHA256=y -# CONFIG_CRYPTO_SHA512 is not set -# CONFIG_CRYPTO_SHA3 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_WP512 is not set -# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set - -# -# Ciphers -# -CONFIG_CRYPTO_AES=y -# CONFIG_CRYPTO_AES_X86_64 is not set -# CONFIG_CRYPTO_AES_NI_INTEL is not set -# CONFIG_CRYPTO_ANUBIS is not set -CONFIG_CRYPTO_ARC4=y -# CONFIG_CRYPTO_BLOWFISH is not set -# CONFIG_CRYPTO_BLOWFISH_X86_64 is not set -# CONFIG_CRYPTO_CAMELLIA is not set -# CONFIG_CRYPTO_CAMELLIA_X86_64 is not set -# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX_X86_64 is not set -# CONFIG_CRYPTO_CAMELLIA_AESNI_AVX2_X86_64 is not set -# CONFIG_CRYPTO_CAST5 is not set -# CONFIG_CRYPTO_CAST5_AVX_X86_64 is not set -# CONFIG_CRYPTO_CAST6 is not set -# CONFIG_CRYPTO_CAST6_AVX_X86_64 is not set -# CONFIG_CRYPTO_DES is not set -# CONFIG_CRYPTO_DES3_EDE_X86_64 is not set -# CONFIG_CRYPTO_FCRYPT is not set -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_SALSA20 is not set -# CONFIG_CRYPTO_SALSA20_X86_64 is not set -# CONFIG_CRYPTO_CHACHA20 is not set -# CONFIG_CRYPTO_CHACHA20_X86_64 is not set -# CONFIG_CRYPTO_SEED is not set -# CONFIG_CRYPTO_SERPENT is not set -# CONFIG_CRYPTO_SERPENT_SSE2_X86_64 is not set -# CONFIG_CRYPTO_SERPENT_AVX_X86_64 is not set -# CONFIG_CRYPTO_SERPENT_AVX2_X86_64 is not set -# CONFIG_CRYPTO_TEA is not set -# CONFIG_CRYPTO_TWOFISH is not set -# CONFIG_CRYPTO_TWOFISH_X86_64 is not set -# CONFIG_CRYPTO_TWOFISH_X86_64_3WAY is not set -# CONFIG_CRYPTO_TWOFISH_AVX_X86_64 is not set - -# -# Compression -# -# CONFIG_CRYPTO_DEFLATE is not set -# CONFIG_CRYPTO_LZO is not set -# CONFIG_CRYPTO_842 is not set -# CONFIG_CRYPTO_LZ4 is not set -# CONFIG_CRYPTO_LZ4HC is not set - -# -# Random Number Generation -# -# CONFIG_CRYPTO_ANSI_CPRNG is not set -CONFIG_CRYPTO_DRBG_MENU=y -CONFIG_CRYPTO_DRBG_HMAC=y -# CONFIG_CRYPTO_DRBG_HASH is not set -# CONFIG_CRYPTO_DRBG_CTR is not set -CONFIG_CRYPTO_DRBG=y -CONFIG_CRYPTO_JITTERENTROPY=y -# CONFIG_CRYPTO_USER_API_HASH is not set -# CONFIG_CRYPTO_USER_API_SKCIPHER is not set -# CONFIG_CRYPTO_USER_API_RNG is not set -# CONFIG_CRYPTO_USER_API_AEAD is not set -# CONFIG_CRYPTO_HW is not set - -# -# Certificates for signature checking -# -CONFIG_HAVE_KVM=y -# CONFIG_VIRTUALIZATION is not set -CONFIG_BINARY_PRINTF=y - -# -# Library routines -# -CONFIG_BITREVERSE=y -# CONFIG_HAVE_ARCH_BITREVERSE is not set -CONFIG_RATIONAL=y -CONFIG_GENERIC_STRNCPY_FROM_USER=y -CONFIG_GENERIC_STRNLEN_USER=y -CONFIG_GENERIC_NET_UTILS=y -CONFIG_GENERIC_FIND_FIRST_BIT=y -CONFIG_GENERIC_PCI_IOMAP=y -CONFIG_GENERIC_IOMAP=y -CONFIG_GENERIC_IO=y -CONFIG_ARCH_USE_CMPXCHG_LOCKREF=y -CONFIG_ARCH_HAS_FAST_MULTIPLIER=y -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -# CONFIG_CRC_T10DIF is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC32_SELFTEST is not set -CONFIG_CRC32_SLICEBY8=y -# CONFIG_CRC32_SLICEBY4 is not set -# CONFIG_CRC32_SARWATE is not set -# CONFIG_CRC32_BIT is not set -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -# CONFIG_CRC8 is not set -# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set -# CONFIG_RANDOM32_SELFTEST is not set -# CONFIG_XZ_DEC is not set -# CONFIG_XZ_DEC_BCJ is not set -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT_MAP=y -CONFIG_HAS_DMA=y -CONFIG_CPU_RMAP=y -CONFIG_DQL=y -CONFIG_GLOB=y -# CONFIG_GLOB_SELFTEST is not set -CONFIG_NLATTR=y -# CONFIG_CORDIC is not set -# CONFIG_DDR is not set -# CONFIG_IRQ_POLL is not set -CONFIG_FONT_SUPPORT=y -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_SG_SPLIT is not set -# CONFIG_SG_POOL is not set -CONFIG_ARCH_HAS_SG_CHAIN=y -CONFIG_ARCH_HAS_PMEM_API=y -CONFIG_ARCH_HAS_MMIO_FLUSH=y -CONFIG_SBITMAP=y diff --git a/tests/hwsim/vm/kernel-config.uml b/tests/hwsim/vm/kernel-config.uml new file mode 100644 index 000000000..b0f2f65ac --- /dev/null +++ b/tests/hwsim/vm/kernel-config.uml @@ -0,0 +1,131 @@ +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_LOG_BUF_SHIFT=14 +CONFIG_CGROUPS=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_SCHED=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +# CONFIG_PID_NS is not set +CONFIG_SYSFS_DEPRECATED=y +CONFIG_CC_OPTIMIZE_FOR_SIZE=y +CONFIG_SLAB=y +CONFIG_HOSTFS=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MMAPPER=y +# CONFIG_SECCOMP is not set +CONFIG_UML_TIME_TRAVEL_SUPPORT=y +CONFIG_SSL=y +CONFIG_NULL_CHAN=y +CONFIG_PORT_CHAN=y +CONFIG_PTY_CHAN=y +CONFIG_TTY_CHAN=y +CONFIG_XTERM_CHAN=y +CONFIG_CON_CHAN="pts" +CONFIG_SSL_CHAN="pts" +CONFIG_UML_NET=y +CONFIG_UML_NET_TUNTAP=y +CONFIG_UML_NET_VECTOR=y +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_MQ_IOSCHED_DEADLINE is not set +# CONFIG_MQ_IOSCHED_KYBER is not set +CONFIG_BINFMT_MISC=y +# CONFIG_COMPACTION is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_NETFILTER=y +CONFIG_BRIDGE_NETFILTER=y +CONFIG_NF_TABLES=y +CONFIG_NETFILTER_XTABLES=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NF_TABLES_BRIDGE=y +CONFIG_BRIDGE_NF_EBTABLES=y +CONFIG_BRIDGE_EBT_T_FILTER=y +CONFIG_BRIDGE_EBT_ARP=y +CONFIG_BRIDGE_EBT_IP=y +CONFIG_BRIDGE_EBT_IP6=y +CONFIG_BRIDGE_EBT_PKTTYPE=y +CONFIG_BRIDGE_EBT_ARPREPLY=y +CONFIG_BRIDGE=y +CONFIG_BRIDGE_VLAN_FILTERING=y +CONFIG_VLAN_8021Q=y +CONFIG_CFG80211=y +CONFIG_CFG80211_DEBUGFS=y +CONFIG_CFG80211_WEXT=y +CONFIG_MAC80211=y +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_DEBUGFS=y +CONFIG_MAC80211_MESSAGE_TRACING=y +CONFIG_MAC80211_DEBUG_MENU=y +CONFIG_MAC80211_VERBOSE_DEBUG=y +CONFIG_MAC80211_MLME_DEBUG=y +CONFIG_MAC80211_STA_DEBUG=y +CONFIG_MAC80211_HT_DEBUG=y +CONFIG_MAC80211_OCB_DEBUG=y +CONFIG_MAC80211_IBSS_DEBUG=y +CONFIG_MAC80211_PS_DEBUG=y +CONFIG_MAC80211_TDLS_DEBUG=y +CONFIG_MAC80211_DEBUG_COUNTERS=y +CONFIG_RFKILL=y +CONFIG_UEVENT_HELPER=y +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_BLK_DEV_UBD=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_DUMMY=y +CONFIG_MACSEC=y +CONFIG_VETH=y +# CONFIG_ETHERNET is not set +# CONFIG_WLAN_VENDOR_ADMTEK is not set +# CONFIG_WLAN_VENDOR_ATH is not set +# CONFIG_WLAN_VENDOR_ATMEL is not set +# CONFIG_WLAN_VENDOR_BROADCOM is not set +# CONFIG_WLAN_VENDOR_CISCO is not set +# CONFIG_WLAN_VENDOR_INTEL is not set +# CONFIG_WLAN_VENDOR_INTERSIL is not set +# CONFIG_WLAN_VENDOR_MARVELL is not set +# CONFIG_WLAN_VENDOR_MEDIATEK is not set +# CONFIG_WLAN_VENDOR_RALINK is not set +# CONFIG_WLAN_VENDOR_REALTEK is not set +# CONFIG_WLAN_VENDOR_RSI is not set +# CONFIG_WLAN_VENDOR_ST is not set +# CONFIG_WLAN_VENDOR_TI is not set +# CONFIG_WLAN_VENDOR_ZYDAS is not set +# CONFIG_WLAN_VENDOR_QUANTENNA is not set +CONFIG_MAC80211_HWSIM=y +CONFIG_LEGACY_PTY_COUNT=32 +# CONFIG_HW_RANDOM is not set +CONFIG_UML_RANDOM=y +# CONFIG_IOMMU_SUPPORT is not set +# CONFIG_DNOTIFY is not set +# CONFIG_INOTIFY_USER is not set +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +# CONFIG_MISC_FILESYSTEMS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS=y +CONFIG_LSM="yama,loadpin,safesetid,integrity" +CONFIG_CRYPTO_CRC32C=y +CONFIG_CRYPTO_ARC4=y +CONFIG_CRC16=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_FRAME_WARN=1024 +CONFIG_DEBUG_FS=y +CONFIG_DEBUG_KERNEL=y +CONFIG_PANIC_ON_OOPS=y +CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y +CONFIG_PREEMPTIRQ_EVENTS=y +# CONFIG_RUNTIME_TESTING_MENU is not set diff --git a/tests/hwsim/vm/parallel-vm.py b/tests/hwsim/vm/parallel-vm.py index 714b8746c..c451e8ab6 100755 --- a/tests/hwsim/vm/parallel-vm.py +++ b/tests/hwsim/vm/parallel-vm.py @@ -58,6 +58,7 @@ long_tests = ["ap_roam_open", "dfs", "dfs_ht40_minus", "dfs_etsi", + "dfs_radar_vht80_downgrade", "ap_acs_dfs", "grpform_cred_ready_timeout", "hostapd_oom_wpa2_eap_connect", @@ -75,6 +76,8 @@ long_tests = ["ap_roam_open", "ap_wps_iteration", "ap_wps_iteration_error", "ap_wps_pbc_timeout", + "ap_wps_pbc_ap_timeout", + "ap_wps_pin_ap_timeout", "ap_wps_http_timeout", "p2p_go_move_reg_change", "p2p_go_move_active", diff --git a/tests/hwsim/vm/vm-run.sh b/tests/hwsim/vm/vm-run.sh index b31beb139..06dee0689 100755 --- a/tests/hwsim/vm/vm-run.sh +++ b/tests/hwsim/vm/vm-run.sh @@ -136,6 +136,9 @@ function finish { } trap finish EXIT +if [ -z $KVM ]; then + RUN_TEST_ARGS="--long $RUN_TEST_ARGS" +fi echo "$RUN_TEST_ARGS" > $argsfile A="mac80211_hwsim.support_p2p_device=0 " diff --git a/tests/hwsim/wlantest.py b/tests/hwsim/wlantest.py index b0e817913..16765d27a 100644 --- a/tests/hwsim/wlantest.py +++ b/tests/hwsim/wlantest.py @@ -29,7 +29,7 @@ class Wlantest: return cls.remote_host.execute(["killall", "-9", "wlantest"]) - cls.remote_host.wait_execute_complete(cls.exe_thread, 5) + cls.remote_host.thread_wait(cls.exe_thread, 5) cls.exe_thread = None cls.exe_res = [] @@ -64,7 +64,7 @@ class Wlantest: pcap_file, log_file) cls.remote_host.add_log(log_file) cls.remote_host.add_log(pcap_file) - cls.exe_thread = cls.remote_host.execute_run(cmd.split(), cls.exe_res) + cls.exe_thread = cls.remote_host.thread_run(cmd.split(), cls.exe_res) # Give wlantest a chance to start working time.sleep(1) @@ -91,7 +91,8 @@ class Wlantest: @classmethod def setup(cls, wpa, is_p2p=False): - cls.chan_from_wpa(wpa, is_p2p) + if wpa: + cls.chan_from_wpa(wpa, is_p2p) cls.start_remote_wlantest() cls.setup_done = True diff --git a/tests/hwsim/wpasupplicant.py b/tests/hwsim/wpasupplicant.py index 2283fa99c..92c855227 100644 --- a/tests/hwsim/wpasupplicant.py +++ b/tests/hwsim/wpasupplicant.py @@ -1099,16 +1099,27 @@ class WpaSupplicant: "bssid_whitelist", "mem_only_psk", "eap_workaround", "engine", "fils_dh_group", "bssid_hint", "dpp_csign", "dpp_csign_expiry", - "dpp_netaccesskey", "dpp_netaccesskey_expiry", + "dpp_netaccesskey", "dpp_netaccesskey_expiry", "dpp_pfs", "group_mgmt", "owe_group", "owe_only", "owe_ptk_workaround", + "transition_disable", "sae_pk", "roaming_consortium_selection", "ocv", "multi_ap_backhaul_sta", "rx_stbc", "tx_stbc", - "ft_eap_pmksa_caching"] + "ft_eap_pmksa_caching", "beacon_prot", + "wpa_deny_ptk0_rekey"] for field in not_quoted: if field in kwargs and kwargs[field]: self.set_network(id, field, kwargs[field]) + known_args = {"raw_psk", "password_hex", "peerkey", "okc", "ocsp", + "only_add_network", "wait_connect"} + unknown = set(kwargs.keys()) + unknown -= set(quoted) + unknown -= set(not_quoted) + unknown -= known_args + if unknown: + raise Exception("Unknown WpaSupplicant::connect() arguments: " + str(unknown)) + if "raw_psk" in kwargs and kwargs['raw_psk']: self.set_network(id, "psk", kwargs['raw_psk']) if "password_hex" in kwargs and kwargs['password_hex']: @@ -1190,27 +1201,42 @@ class WpaSupplicant: "CTRL-EVENT-SCAN-RESULTS"], timeout=0.5) self.dump_monitor() - def roam(self, bssid, fail_test=False, assoc_reject_ok=False): + def roam(self, bssid, fail_test=False, assoc_reject_ok=False, + check_bssid=True): self.dump_monitor() if "OK" not in self.request("ROAM " + bssid): raise Exception("ROAM failed") if fail_test: if assoc_reject_ok: ev = self.wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED", "CTRL-EVENT-ASSOC-REJECT"], timeout=1) else: - ev = self.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) + ev = self.wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=1) + if ev and "CTRL-EVENT-DISCONNECTED" in ev: + self.dump_monitor() + return if ev is not None and "CTRL-EVENT-ASSOC-REJECT" not in ev: raise Exception("Unexpected connection") self.dump_monitor() return - ev = self.wait_event(["CTRL-EVENT-CONNECTED", - "CTRL-EVENT-ASSOC-REJECT"], timeout=10) + if assoc_reject_ok: + ev = self.wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED"], timeout=10) + else: + ev = self.wait_event(["CTRL-EVENT-CONNECTED", + "CTRL-EVENT-DISCONNECTED", + "CTRL-EVENT-ASSOC-REJECT"], timeout=10) if ev is None: raise Exception("Roaming with the AP timed out") if "CTRL-EVENT-ASSOC-REJECT" in ev: raise Exception("Roaming association rejected") + if "CTRL-EVENT-DISCONNECTED" in ev: + raise Exception("Unexpected disconnection when waiting for roam to complete") self.dump_monitor() + if check_bssid and self.get_status_field('bssid') != bssid: + raise Exception("Did not roam to correct BSSID") def roam_over_ds(self, bssid, fail_test=False): self.dump_monitor() @@ -1427,6 +1453,10 @@ class WpaSupplicant: def note(self, txt): self.request("NOTE " + txt) + def save_config(self): + if "OK" not in self.request("SAVE_CONFIG"): + raise Exception("Failed to save configuration file") + def wait_regdom(self, country_ie=False): for i in range(5): ev = self.wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=1) @@ -1470,6 +1500,20 @@ class WpaSupplicant: raise Exception("Failed to generate bootstrapping info") return int(res) + def dpp_bootstrap_set(self, id, conf=None, configurator=None, ssid=None, + extra=None): + cmd = "DPP_BOOTSTRAP_SET %d" % id + if ssid: + cmd += " ssid=" + binascii.hexlify(ssid.encode()).decode() + if extra: + cmd += " " + extra + if conf: + cmd += " conf=" + conf + if configurator is not None: + cmd += " configurator=%d" % configurator + if "OK" not in self.request(cmd): + raise Exception("Failed to set bootstrapping parameters") + def dpp_listen(self, freq, netrole=None, qr=None, role=None): cmd = "DPP_LISTEN " + str(freq) if netrole: @@ -1485,7 +1529,8 @@ class WpaSupplicant: extra=None, own=None, role=None, neg_freq=None, ssid=None, passphrase=None, expect_fail=False, tcp_addr=None, tcp_port=None, conn_status=False, - ssid_charset=None, nfc_uri=None, netrole=None): + ssid_charset=None, nfc_uri=None, netrole=None, + csrattrs=None): cmd = "DPP_AUTH_INIT" if peer is None: if nfc_uri: @@ -1519,6 +1564,8 @@ class WpaSupplicant: cmd += " conn_status=1" if netrole: cmd += " netrole=" + netrole + if csrattrs: + cmd += " csrattrs=" + csrattrs res = self.request(cmd) if expect_fail: if "FAIL" not in res: @@ -1526,6 +1573,7 @@ class WpaSupplicant: return if "OK" not in res: raise Exception("Failed to initiate DPP Authentication") + return int(peer) def dpp_pkex_init(self, identifier, code, role=None, key=None, curve=None, extra=None, use_id=None, allow_fail=False): diff --git a/tests/p2p-fuzzer/Makefile b/tests/p2p-fuzzer/Makefile deleted file mode 100644 index 4f81ef158..000000000 --- a/tests/p2p-fuzzer/Makefile +++ /dev/null @@ -1,51 +0,0 @@ -all: p2p-fuzzer - -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -SRC=../../src - -CFLAGS += -I$(SRC) - -$(SRC)/utils/libutils.a: - $(MAKE) -C $(SRC)/utils - -$(SRC)/common/libcommon.a: - $(MAKE) -C $(SRC)/common - -$(SRC)/crypto/libcrypto.a: - $(MAKE) -C $(SRC)/crypto - -$(SRC)/tls/libtls.a: - $(MAKE) -C $(SRC)/tls - -$(SRC)/p2p/libp2p.a: - $(MAKE) -C $(SRC)/p2p - -$(SRC)/wps/libwps.a: - $(MAKE) -C $(SRC)/wps - -LIBS += $(SRC)/utils/libutils.a -LIBS += $(SRC)/common/libcommon.a -LIBS += $(SRC)/crypto/libcrypto.a -LIBS += $(SRC)/p2p/libp2p.a -LIBS += $(SRC)/tls/libtls.a -LIBS += $(SRC)/wps/libwps.a - -p2p-fuzzer: p2p-fuzzer.o $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) - -clean: - $(MAKE) -C $(SRC) clean - rm -f p2p-fuzzer *~ *.o *.d - --include $(OBJS:%.o=%.d) diff --git a/tests/p2p-fuzzer/go-neg-req.dat b/tests/p2p-fuzzer/go-neg-req.dat deleted file mode 100644 index ed06834d7..000000000 Binary files a/tests/p2p-fuzzer/go-neg-req.dat and /dev/null differ diff --git a/tests/p2p-fuzzer/invitation-req.dat b/tests/p2p-fuzzer/invitation-req.dat deleted file mode 100644 index 5991f3e6e..000000000 Binary files a/tests/p2p-fuzzer/invitation-req.dat and /dev/null differ diff --git a/tests/p2p-fuzzer/p2p-fuzzer.c b/tests/p2p-fuzzer/p2p-fuzzer.c deleted file mode 100644 index 8e9559294..000000000 --- a/tests/p2p-fuzzer/p2p-fuzzer.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * wpa_supplicant - P2P fuzzer - * Copyright (c) 2015, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "common/ieee802_11_defs.h" -#include "p2p/p2p.h" - - -static void debug_print(void *ctx, int level, const char *msg) -{ - wpa_printf(level, "P2P: %s", msg); -} - - -static void find_stopped(void *ctx) -{ -} - - -static int start_listen(void *ctx, unsigned int freq, - unsigned int duration, - const struct wpabuf *probe_resp_ie) -{ - return 0; -} - - -static void stop_listen(void *ctx) -{ -} - - -static void dev_found(void *ctx, const u8 *addr, - const struct p2p_peer_info *info, - int new_device) -{ -} - - -static void dev_lost(void *ctx, const u8 *dev_addr) -{ -} - - -static int send_action(void *ctx, unsigned int freq, const u8 *dst, - const u8 *src, const u8 *bssid, const u8 *buf, - size_t len, unsigned int wait_time, int *scheduled) -{ - *scheduled = 0; - return 0; -} - - -static void send_action_done(void *ctx) -{ -} - - -static void go_neg_req_rx(void *ctx, const u8 *src, u16 dev_passwd_id, - u8 go_intent) -{ -} - - -static struct p2p_data * init_p2p(void) -{ - struct p2p_config p2p; - - os_memset(&p2p, 0, sizeof(p2p)); - p2p.max_peers = 100; - p2p.passphrase_len = 8; - p2p.channels.reg_classes = 1; - p2p.channels.reg_class[0].reg_class = 81; - p2p.channels.reg_class[0].channel[0] = 1; - p2p.channels.reg_class[0].channel[1] = 2; - p2p.channels.reg_class[0].channels = 2; - p2p.debug_print = debug_print; - p2p.find_stopped = find_stopped; - p2p.start_listen = start_listen; - p2p.stop_listen = stop_listen; - p2p.dev_found = dev_found; - p2p.dev_lost = dev_lost; - p2p.send_action = send_action; - p2p.send_action_done = send_action_done; - p2p.go_neg_req_rx = go_neg_req_rx; - - return p2p_init(&p2p); -} - - -struct arg_ctx { - struct p2p_data *p2p; - const char *fname; -}; - - -static void test_send_proberesp(void *eloop_data, void *user_ctx) -{ - struct arg_ctx *ctx = eloop_data; - char *data; - size_t len; - struct os_reltime rx_time; - - wpa_printf(MSG_INFO, "p2p-fuzzer: Send proberesp '%s'", ctx->fname); - - data = os_readfile(ctx->fname, &len); - if (!data) { - wpa_printf(MSG_ERROR, "Could not read '%s'", ctx->fname); - return; - } - - wpa_hexdump(MSG_MSGDUMP, "fuzzer - IEs", data, len); - - os_memset(&rx_time, 0, sizeof(rx_time)); - p2p_scan_res_handler(ctx->p2p, (u8 *) "\x02\x00\x00\x00\x01\x00", 2412, - &rx_time, 0, (u8 *) data, len); - p2p_scan_res_handled(ctx->p2p); - - os_free(data); - eloop_terminate(); -} - - -static void test_send_action(void *eloop_data, void *user_ctx) -{ - struct arg_ctx *ctx = eloop_data; - char *data; - size_t len; - struct os_reltime rx_time; - struct ieee80211_mgmt *mgmt; - - wpa_printf(MSG_INFO, "p2p-fuzzer: Send action '%s'", ctx->fname); - - data = os_readfile(ctx->fname, &len); - if (!data) { - wpa_printf(MSG_ERROR, "Could not read '%s'", ctx->fname); - return; - } - if (len < IEEE80211_HDRLEN + 1) - goto out; - - wpa_hexdump(MSG_MSGDUMP, "fuzzer - action", data, len); - - mgmt = (struct ieee80211_mgmt *) data; - os_memset(&rx_time, 0, sizeof(rx_time)); - p2p_rx_action(ctx->p2p, mgmt->da, mgmt->sa, mgmt->bssid, - mgmt->u.action.category, - (u8 *) data + IEEE80211_HDRLEN + 1, - len - IEEE80211_HDRLEN - 1, 2412); - -out: - os_free(data); - eloop_terminate(); -} - - -int main(int argc, char *argv[]) -{ - struct p2p_data *p2p; - struct arg_ctx ctx; - - /* TODO: probreq and wpas_p2p_probe_req_rx() */ - - if (argc < 3) { - printf("usage: %s \n", argv[0]); - return -1; - } - - if (os_program_init()) - return -1; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (eloop_init()) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - - p2p = init_p2p(); - if (!p2p) { - wpa_printf(MSG_ERROR, "P2P init failed"); - return -1; - } - - ctx.p2p = p2p; - ctx.fname = argv[2]; - - if (os_strcmp(argv[1], "proberesp") == 0) { - eloop_register_timeout(0, 0, test_send_proberesp, &ctx, NULL); - } else if (os_strcmp(argv[1], "action") == 0) { - eloop_register_timeout(0, 0, test_send_action, &ctx, NULL); - } else { - wpa_printf(MSG_ERROR, "Unsupported test type '%s'", argv[1]); - return -1; - } - - wpa_printf(MSG_DEBUG, "Starting eloop"); - eloop_run(); - wpa_printf(MSG_DEBUG, "eloop done"); - - p2p_deinit(p2p); - eloop_destroy(); - os_program_deinit(); - - return 0; -} diff --git a/tests/p2p-fuzzer/p2ps-pd-req.dat b/tests/p2p-fuzzer/p2ps-pd-req.dat deleted file mode 100644 index 7e1b6d91d..000000000 Binary files a/tests/p2p-fuzzer/p2ps-pd-req.dat and /dev/null differ diff --git a/tests/p2p-fuzzer/proberesp-go.dat b/tests/p2p-fuzzer/proberesp-go.dat deleted file mode 100644 index 8541652ff..000000000 Binary files a/tests/p2p-fuzzer/proberesp-go.dat and /dev/null differ diff --git a/tests/p2p-fuzzer/proberesp.dat b/tests/p2p-fuzzer/proberesp.dat deleted file mode 100644 index 8d997d1c5..000000000 Binary files a/tests/p2p-fuzzer/proberesp.dat and /dev/null differ diff --git a/tests/remote/config.py b/tests/remote/config.py index 55c601316..1ac362ead 100644 --- a/tests/remote/config.py +++ b/tests/remote/config.py @@ -17,8 +17,8 @@ logger = logging.getLogger() # definitions in the format as below. In other case HWSIM cfg will be used. # setup_params = {"setup_hw" : "./tests/setup_hw.sh", - "hostapd" : "./tests/hostapd", - "wpa_supplicant" : "./tests/wpa_supplicant", + "hostapd" : "./tests/hostapd-rt", + "wpa_supplicant" : "./tests/wpa_supplicant-rt", "iperf" : "iperf", "wlantest" : "./tests/wlantest", "wlantest_cli" : "./tests/wlantest_cli", @@ -69,6 +69,8 @@ def get_devices(filename="cfg.py"): def get_device(devices, name=None, flags=None, lock=False): if name is None and flags is None: raise Exception("Failed to get device") + word = name.split(":") + name = word[0] for device in devices: if device['name'] == name: return device diff --git a/tests/remote/hwsim_wrapper.py b/tests/remote/hwsim_wrapper.py index c1bbb27d7..38f927f6e 100644 --- a/tests/remote/hwsim_wrapper.py +++ b/tests/remote/hwsim_wrapper.py @@ -67,13 +67,15 @@ def run_hwsim_test(devices, setup_params, refs, duts, monitors, hwsim_test): dut_host.dev['bssid'] = rutils.get_mac_addr(dut_host) apdev.append(dut_host.dev) - # run hwsim test/currently only 2 params tests if hwsim_test.__code__.co_argcount == 1: hwsim_test(dev) elif hwsim_test.__code__.co_argcount == 2: hwsim_test(dev, apdev) else: - raise Exception("more than 2 arguments required") + params = {} + params['long'] = 1 + params['logdir'] = local_log_dir + hwsim_test(dev, apdev, params) # hostapd/wpa_supplicant cleanup for wpas in dev: @@ -88,10 +90,10 @@ def run_hwsim_test(devices, setup_params, refs, duts, monitors, hwsim_test): monitor.remove(dut_host) for ref_host in ref_hosts: - ref_host.execute(["killall", "wpa_supplicant"]) + rutils.kill_wpasupplicant(ref_host, setup_params) ref_host.get_logs(local_log_dir) for dut_host in dut_hosts: - dut_host.execute(["killall", "hostapd"]) + rutils.kill_hostapd(dut_host, setup_params) dut_host.get_logs(local_log_dir) if mon is not None: wlantest.Wlantest.reset_remote_wlantest() @@ -113,10 +115,10 @@ def run_hwsim_test(devices, setup_params, refs, duts, monitors, hwsim_test): monitor.remove(dut_host) for ref_host in ref_hosts: - ref_host.execute(["killall", "wpa_supplicant"]) + rutils.kill_wpasupplicant(ref_host, setup_params) ref_host.get_logs(local_log_dir) for dut_host in dut_hosts: - dut_host.execute(["killall", "hostapd"]) + rutils.kill_hostapd(dut_host, setup_params) dut_host.get_logs(local_log_dir) if mon is not None: wlantest.Wlantest.reset_remote_wlantest() diff --git a/tests/remote/monitor.py b/tests/remote/monitor.py index 47b5e3bbd..0f77d500b 100644 --- a/tests/remote/monitor.py +++ b/tests/remote/monitor.py @@ -26,7 +26,8 @@ def create(devices, setup_params, refs, duts, monitors): mons.append(monitor) for mon in mons: - dev = config.get_device(devices, mon) + word = mon.split(":") + dev = config.get_device(devices, word[0]) if dev is None: continue @@ -35,6 +36,15 @@ def create(devices, setup_params, refs, duts, monitors): port=dev['port'], name=dev['name']) + for iface_param in word[1:]: + params = iface_param.split(",") + if len(params) > 3: + monitor_param = { "freq" : rutils.c2f(params[0]), + "bw" : params[1], + "center_freq1" : rutils.c2f(params[2]), + "center_freq2" : rutils.c2f(params[3]) } + host.monitor_params.append(monitor_param) + try: host.execute(["iw", "reg", "set", setup_params['country']]) rutils.setup_hw_host(host, setup_params, True) @@ -49,11 +59,15 @@ def destroy(devices, hosts): stop(host) for monitor in host.monitors: host.execute(["ifconfig", monitor, "down"]) + host.monitor_params = [] -def setup(host, monitor_params): +def setup(host, monitor_params=None): if host is None: return + if monitor_params == None: + monitor_params = host.monitor_params + ifaces = re.split('; | |, ', host.ifname) count = 0 for param in monitor_params: @@ -63,6 +77,7 @@ def setup(host, monitor_params): logger.debug(traceback.format_exc()) break host.execute(["ifconfig", iface, " down"]) + host.execute(["rfkill", "unblock", "wifi"]) host.execute(["iw", iface, "set type monitor"]) host.execute(["ifconfig", iface, "up"]) status, buf = host.execute(["iw", iface, "set", "freq", param['freq'], @@ -95,7 +110,7 @@ def run(host, setup_params): log = log_dir + tc_name + "_" + host.name + log_monitor + ".pcap" host.add_log(log) - thread = host.execute_run([tshark, "-w", log], monitor_res) + thread = host.thread_run([tshark, "-w", log], monitor_res) host.thread = thread @@ -107,10 +122,7 @@ def stop(host): if host.thread is None: return - host.execute(["killall", "-s", "INT", "tshark"]) - host.wait_execute_complete(host.thread, 5) - if host.thread.isAlive(): - raise Exception("tshark still alive") + host.thread_stop(host.thread) host.thread = None # Add monitor to existing interface diff --git a/tests/remote/run-tests.py b/tests/remote/run-tests.py index 550071253..e26e3483a 100755 --- a/tests/remote/run-tests.py +++ b/tests/remote/run-tests.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 # # Remote test case executor # Copyright (c) 2016, Tieto Corporation @@ -32,7 +32,7 @@ from hwsim_wrapper import run_hwsim_test def usage(): print("USAGE: " + sys.argv[0] + " -t devices") print("USAGE: " + sys.argv[0] + " -t check_devices") - print("USAGE: " + sys.argv[0] + " -d -t [-r ] [-c ] [-m ] [-h hwsim_tests][-R][-T][-P][-v]") + print("USAGE: " + sys.argv[0] + " -d -t [-r ] [-c ] [-m ] [-h hwsim_tests] [-f hwsim_modules][-R][-T][-P][-v]") print("USAGE: " + sys.argv[0]) def get_devices(devices, duts, refs, monitors): @@ -71,6 +71,8 @@ def main(): requested_tests = ["help"] requested_hwsim_tests = [] hwsim_tests = [] + requested_modules = [] + modules_tests = [] cfg_file = "cfg.py" log_dir = "./logs/" verbose = False @@ -80,8 +82,9 @@ def main(): # parse input parameters try: - opts, args = getopt.getopt(sys.argv[1:], "d:r:t:l:k:c:m:h:vRPT", - ["dut=", "ref=", "tests=", "log-dir=", + opts, args = getopt.getopt(sys.argv[1:], "d:f:r:t:l:k:c:m:h:vRPT", + ["dut=", "modules=", "ref=", "tests=", + "log-dir=", "cfg=", "key=", "monitor=", "hwsim="]) except getopt.GetoptError as err: print(err) @@ -113,6 +116,8 @@ def main(): cfg_file = argument elif option in ("-h", "--hwsim"): requested_hwsim_tests = re.split('; | |, ', argument) + elif option in ("-f", "--modules"): + requested_modules = re.split('; | |, ', argument) else: assert False, "unhandled option" @@ -200,7 +205,7 @@ def main(): t = None for tt in hwsim_tests: name = tt.__name__.replace('test_', '', 1) - if name == test and tt.__code__.co_argcount <= 2: + if name == test: t = tt break if not t: @@ -208,9 +213,25 @@ def main(): continue hwsim_tests_to_run.append(t) + # import test_* from modules + files = os.listdir("../hwsim/") + for t in files: + m = re.match(r'(test_.*)\.py$', t) + if m: + mod = __import__(m.group(1)) + if mod.__name__.replace('test_', '', 1) not in requested_modules: + continue + for key, val in mod.__dict__.items(): + if key.startswith("test_"): + modules_tests.append(val) + + if len(requested_modules) > 0: + requested_hwsim_tests = modules_tests + hwsim_tests_to_run = modules_tests + # sort the list test_names.sort() - tests.sort() + tests.sort(key=lambda t: t.__name__) # print help if requested_tests[0] == "help" and len(requested_hwsim_tests) == 0: @@ -278,13 +299,19 @@ def main(): # now run test cases for dut in duts: - logger.warning("DUT: " + str(dut)) + if len(requested_hwsim_tests) > 0: + logger.warning("DUT (apdev): " + str(dut)) + else: + logger.warning("DUT: " + str(dut)) for ref in refs: - logger.warning("REF: " + str(ref)) + if len(requested_hwsim_tests) > 0: + logger.warning("REF (dev): " + str(ref)) + else: + logger.warning("REF: " + str(ref)) for monitor in monitors: logger.warning("MON: " + str(monitor)) - # run check_devices at begining + # run check_devices at beginning logger.warning("RUN check_devices") try: check_devices(devices, setup_params, refs, duts, monitors) diff --git a/tests/remote/rutils.py b/tests/remote/rutils.py index e80d7dc0e..0585480a2 100644 --- a/tests/remote/rutils.py +++ b/tests/remote/rutils.py @@ -117,7 +117,8 @@ def run_hostapd(host, setup_params): if log_file: host.add_log(log_file) - status, buf = host.execute([setup_params['hostapd'], "-B", "-ddt", "-g", "udp:" + host.port, log]) + pidfile = setup_params['log_dir'] + "hostapd_" + host.ifname + "_" + setup_params['tc_name'] + ".pid" + status, buf = host.execute([setup_params['hostapd'], "-B", "-ddt", "-g", "udp:" + host.port, "-P", pidfile, log]) if status != 0: raise Exception("Could not run hostapd: " + buf) @@ -134,10 +135,19 @@ def run_wpasupplicant(host, setup_params): if log_file: host.add_log(log_file) - status, buf = host.execute([setup_params['wpa_supplicant'], "-B", "-ddt", "-g", "udp:" + host.port, log]) + pidfile = setup_params['log_dir'] + "wpa_supplicant_" + host.ifname + "_" + setup_params['tc_name'] + ".pid" + status, buf = host.execute([setup_params['wpa_supplicant'], "-B", "-ddt", "-g", "udp:" + host.port, "-P", pidfile, log]) if status != 0: raise Exception("Could not run wpa_supplicant: " + buf) +def kill_wpasupplicant(host, setup_params): + pidfile = setup_params['log_dir'] + "wpa_supplicant_" + host.ifname + "_" + setup_params['tc_name'] + ".pid" + host.execute(["kill `cat " + pidfile + "`"]) + +def kill_hostapd(host, setup_params): + pidfile = setup_params['log_dir'] + "hostapd_" + host.ifname + "_" + setup_params['tc_name'] + ".pid" + host.execute(["kill `cat " + pidfile + "`"]) + def get_ap_params(channel="1", bw="HT20", country="US", security="open", ht_capab=None, vht_capab=None): ssid = "test_" + channel + "_" + security + "_" + bw @@ -233,6 +243,8 @@ def get_ipv6(client, ifname=None): for line in lines: res = line.find("Scope:Link") + if res == -1: + res = line.find("") if res != -1: break @@ -242,6 +254,8 @@ def get_ipv6(client, ifname=None): addr_mask = words[2] addr = addr_mask.split("/") return addr[0] + if words[0] == "inet6": + return words[1] return "unknown" @@ -275,7 +289,7 @@ def get_mac_addr(host, iface=None): for word in words: if found == 1: return word - if word == "HWaddr": + if word == "HWaddr" or word == "ether": found = 1 raise Exception("Could not find HWaddr") @@ -328,11 +342,11 @@ def ping_run(host, ip, result, ifname=None, addr_type="ipv4", deadline="5", qos= flush_arp_cache(host) - thread = host.execute_run(ping, result) + thread = host.thread_run(ping, result) return thread def ping_wait(host, thread, timeout=None): - host.wait_execute_complete(thread, timeout) + host.thread_wait(thread, timeout) if thread.isAlive(): raise Exception("ping thread still alive") @@ -482,23 +496,23 @@ def iperf_run(server, client, server_ip, client_res, server_res, flush_arp_cache(server) flush_arp_cache(client) - server_thread = server.execute_run(iperf_server, server_res) + server_thread = server.thread_run(iperf_server, server_res) time.sleep(1) - client_thread = client.execute_run(iperf_client, client_res) + client_thread = client.thread_run(iperf_client, client_res) return server_thread, client_thread def iperf_wait(server, client, server_thread, client_thread, timeout=None, iperf="iperf"): - client.wait_execute_complete(client_thread, timeout) + client.thread_wait(client_thread, timeout) if client_thread.isAlive(): raise Exception("iperf client thread still alive") - server.wait_execute_complete(server_thread, 5) + server.thread_wait(server_thread, 5) if server_thread.isAlive(): server.execute(["killall", "-s", "INT", iperf]) time.sleep(1) - server.wait_execute_complete(server_thread, 5) + server.thread_wait(server_thread, 5) if server_thread.isAlive(): raise Exception("iperf server thread still alive") diff --git a/tests/remote/test_monitor.py b/tests/remote/test_monitor.py new file mode 100644 index 000000000..c8b88d4be --- /dev/null +++ b/tests/remote/test_monitor.py @@ -0,0 +1,52 @@ +# Monitor support +# +# This software may be distributed under the terms of the BSD license. +# See README for more details. + +import remotehost +import config +import rutils +import monitor +import time +import os + +import logging +logger = logging.getLogger() + +def run_monitor(devices, setup_params, refs, duts, monitors, seconds=None): + try: + air_monitor = [] + output = "\n\tPCAP files:\n" + # setup log dir + local_log_dir = setup_params['local_log_dir'] + + # add/run monitors if requested + air_monitors = monitor.create(devices, setup_params, refs, duts, + monitors) + for air_monitor in air_monitors: + monitor.setup(air_monitor) + monitor.run(air_monitor, setup_params) + logger.warning(air_monitor.name + " - monitor started ...") + + if seconds != None: + time.sleep(int(seconds)) + else: + input("\tPress Enter to end capturing...") + + # destroy monitor / get pcap + monitor.destroy(devices, air_monitors) + for air_monitor in air_monitors: + for log in air_monitor.logs: + head, tail = os.path.split(log) + output = output + "\t" + local_log_dir + "/" + tail + "\n" + air_monitor.get_logs(local_log_dir) + return output + except: + for air_monitor in air_monitors: + monitor.destroy(devices, air_monitors) + air_monitor.get_logs(local_log_dir) + raise + +def test_run_monitor(devices, setup_params, refs, duts, monitors): + """TC run standalone monitor""" + return run_monitor(devices, setup_params, refs, duts, monitors) diff --git a/tests/test-asn1.c b/tests/test-asn1.c deleted file mode 100644 index c6957fd25..000000000 --- a/tests/test-asn1.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Testing tool for ASN.1 routines - * Copyright (c) 2006-2009, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "tls/asn1.h" - - -static const char * asn1_class_str(int class) -{ - switch (class) { - case ASN1_CLASS_UNIVERSAL: - return "Universal"; - case ASN1_CLASS_APPLICATION: - return "Application"; - case ASN1_CLASS_CONTEXT_SPECIFIC: - return "Context-specific"; - case ASN1_CLASS_PRIVATE: - return "Private"; - default: - return "?"; - } -} - - -int asn1_parse(const u8 *buf, size_t len, int level) -{ - const u8 *pos, *prev, *end; - char prefix[10], str[100]; - int _level; - struct asn1_hdr hdr; - struct asn1_oid oid; - u8 tmp; - - _level = level; - if ((size_t) _level > sizeof(prefix) - 1) - _level = sizeof(prefix) - 1; - memset(prefix, ' ', _level); - prefix[_level] = '\0'; - - pos = buf; - end = buf + len; - - while (pos < end) { - if (asn1_get_next(pos, end - pos, &hdr) < 0) - return -1; - - prev = pos; - pos = hdr.payload; - - wpa_printf(MSG_MSGDUMP, "ASN.1:%s Class %d(%s) P/C %d(%s) " - "Tag %u Length %u", - prefix, hdr.class, asn1_class_str(hdr.class), - hdr.constructed, - hdr.constructed ? "Constructed" : "Primitive", - hdr.tag, hdr.length); - - if (hdr.class == ASN1_CLASS_CONTEXT_SPECIFIC && - hdr.constructed) { - if (asn1_parse(pos, hdr.length, level + 1) < 0) - return -1; - pos += hdr.length; - } - - if (hdr.class != ASN1_CLASS_UNIVERSAL) - continue; - - switch (hdr.tag) { - case ASN1_TAG_EOC: - if (hdr.length) { - wpa_printf(MSG_DEBUG, "ASN.1: Non-zero " - "end-of-contents length (%u)", - hdr.length); - return -1; - } - wpa_printf(MSG_MSGDUMP, "ASN.1:%s EOC", prefix); - break; - case ASN1_TAG_BOOLEAN: - if (hdr.length != 1) { - wpa_printf(MSG_DEBUG, "ASN.1: Unexpected " - "Boolean length (%u)", hdr.length); - return -1; - } - tmp = *pos++; - wpa_printf(MSG_MSGDUMP, "ASN.1:%s Boolean %s", - prefix, tmp ? "TRUE" : "FALSE"); - break; - case ASN1_TAG_INTEGER: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: INTEGER", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_BITSTRING: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: BitString", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_OCTETSTRING: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: OctetString", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_NULL: - if (hdr.length) { - wpa_printf(MSG_DEBUG, "ASN.1: Non-zero Null " - "length (%u)", hdr.length); - return -1; - } - wpa_printf(MSG_MSGDUMP, "ASN.1:%s Null", prefix); - break; - case ASN1_TAG_OID: - if (asn1_get_oid(prev, end - prev, &oid, &prev) < 0) { - wpa_printf(MSG_DEBUG, "ASN.1: Invalid OID"); - return -1; - } - asn1_oid_to_str(&oid, str, sizeof(str)); - wpa_printf(MSG_DEBUG, "ASN.1:%s OID %s", prefix, str); - pos += hdr.length; - break; - case ANS1_TAG_RELATIVE_OID: - wpa_hexdump(MSG_MSGDUMP, "ASN.1: Relative OID", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_SEQUENCE: - wpa_printf(MSG_MSGDUMP, "ASN.1:%s SEQUENCE", prefix); - if (asn1_parse(pos, hdr.length, level + 1) < 0) - return -1; - pos += hdr.length; - break; - case ASN1_TAG_SET: - wpa_printf(MSG_MSGDUMP, "ASN.1:%s SET", prefix); - if (asn1_parse(pos, hdr.length, level + 1) < 0) - return -1; - pos += hdr.length; - break; - case ASN1_TAG_PRINTABLESTRING: - wpa_hexdump_ascii(MSG_MSGDUMP, - "ASN.1: PrintableString", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_IA5STRING: - wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: IA5String", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_UTCTIME: - wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: UTCTIME", - pos, hdr.length); - pos += hdr.length; - break; - case ASN1_TAG_VISIBLESTRING: - wpa_hexdump_ascii(MSG_MSGDUMP, "ASN.1: VisibleString", - pos, hdr.length); - pos += hdr.length; - break; - default: - wpa_printf(MSG_DEBUG, "ASN.1: Unknown tag %d", - hdr.tag); - return -1; - } - } - - return 0; -} - - -int main(int argc, char *argv[]) -{ - FILE *f; - u8 buf[3000]; - size_t len; - - wpa_debug_level = 0; - - f = fopen(argv[1], "rb"); - if (f == NULL) - return -1; - len = fread(buf, 1, sizeof(buf), f); - fclose(f); - - if (asn1_parse(buf, len, 0) < 0) - printf("Failed to parse DER ASN.1\n"); - - printf("\n\n"); - - return 0; -} diff --git a/tests/test-base64.c b/tests/test-base64.c index 980febf9e..99943f0db 100644 --- a/tests/test-base64.c +++ b/tests/test-base64.c @@ -26,9 +26,9 @@ int main(int argc, char *argv[]) return -1; if (strcmp(argv[1], "encode") == 0) - e = base64_encode(buf, len, &elen); + e = (unsigned char *) base64_encode(buf, len, &elen); else - e = base64_decode(buf, len, &elen); + e = base64_decode((const char *) buf, len, &elen); if (e == NULL) return -2; f = fopen(argv[3], "w"); diff --git a/tests/test-eapol.c b/tests/test-eapol.c deleted file mode 100644 index 944e4cfb9..000000000 --- a/tests/test-eapol.c +++ /dev/null @@ -1,608 +0,0 @@ -/* - * Testing tool for EAPOL-Key Supplicant/Authenticator routines - * Copyright (c) 2006-2019, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "rsn_supp/wpa.h" -#include "ap/wpa_auth.h" - - -struct wpa { - enum { AUTH, SUPP } test_peer; - enum { READ, WRITE } test_oper; - FILE *f; - int wpa1; - - u8 auth_addr[ETH_ALEN]; - u8 supp_addr[ETH_ALEN]; - u8 psk[PMK_LEN]; - - /* from authenticator */ - u8 *auth_eapol; - size_t auth_eapol_len; - - /* from supplicant */ - u8 *supp_eapol; - size_t supp_eapol_len; - - struct wpa_sm *supp; - struct wpa_authenticator *auth_group; - struct wpa_state_machine *auth; - - u8 supp_ie[80]; - size_t supp_ie_len; - - int key_request_done; - int key_request_done1; - int auth_sent; -}; - - -const struct wpa_driver_ops *const wpa_drivers[] = { NULL }; - - -static int auth_read_msg(struct wpa *wpa); -static void supp_eapol_key_request(void *eloop_data, void *user_ctx); - - -static void usage(void) { - wpa_printf(MSG_INFO, - "usage: test-eapol "); - exit(-1); -} - - -static void write_msg(FILE *f, const u8 *msg, size_t msg_len) -{ - u8 len[2]; - - wpa_printf(MSG_DEBUG, "TEST: Write message to file (msg_len=%u)", - (unsigned int) msg_len); - WPA_PUT_BE16(len, msg_len); - fwrite(len, 2, 1, f); - fwrite(msg, msg_len, 1, f); -} - - -static u8 * read_msg(FILE *f, size_t *ret_len) -{ - u8 len[2]; - u16 msg_len; - u8 *msg; - - if (fread(len, 2, 1, f) != 1) { - wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len"); - eloop_terminate(); - return NULL; - } - msg_len = WPA_GET_BE16(len); - - msg = os_malloc(msg_len); - if (!msg) - return NULL; - if (msg_len > 0 && fread(msg, msg_len, 1, f) != 1) { - wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)", - msg_len); - os_free(msg); - eloop_terminate(); - return NULL; - } - wpa_hexdump(MSG_DEBUG, "TEST: Read message from file", msg, msg_len); - - *ret_len = msg_len; - return msg; -} - - -static int supp_get_bssid(void *ctx, u8 *bssid) -{ - struct wpa *wpa = ctx; - wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); - os_memcpy(bssid, wpa->auth_addr, ETH_ALEN); - return 0; -} - - -static void supp_set_state(void *ctx, enum wpa_states state) -{ - wpa_printf(MSG_DEBUG, "SUPP: %s(state=%d)", __func__, state); -} - - -static void auth_eapol_rx(void *eloop_data, void *user_ctx) -{ - struct wpa *wpa = eloop_data; - - wpa_printf(MSG_DEBUG, "AUTH: RX EAPOL frame"); - wpa->auth_sent = 0; - wpa_receive(wpa->auth_group, wpa->auth, wpa->supp_eapol, - wpa->supp_eapol_len); - if (!wpa->auth_sent && wpa->test_peer == SUPP && - wpa->test_oper == READ) { - /* Speed up process by not going through retransmit timeout */ - wpa_printf(MSG_DEBUG, - "AUTH: No response was sent - process next message"); - auth_read_msg(wpa); - } - if (wpa->wpa1 && wpa->key_request_done && !wpa->key_request_done1) { - wpa->key_request_done1 = 1; - eloop_register_timeout(0, 0, supp_eapol_key_request, - wpa, NULL); - } - -} - - -static void supp_eapol_rx(void *eloop_data, void *user_ctx) -{ - struct wpa *wpa = eloop_data; - - wpa_printf(MSG_DEBUG, "SUPP: RX EAPOL frame"); - wpa_sm_rx_eapol(wpa->supp, wpa->auth_addr, wpa->auth_eapol, - wpa->auth_eapol_len); -} - - -static int supp_read_msg(struct wpa *wpa) -{ - os_free(wpa->auth_eapol); - wpa->auth_eapol = read_msg(wpa->f, &wpa->auth_eapol_len); - if (!wpa->auth_eapol) - return -1; - eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL); - return 0; -} - - -static int supp_ether_send(void *ctx, const u8 *dest, u16 proto, const u8 *buf, - size_t len) -{ - struct wpa *wpa = ctx; - - wpa_printf(MSG_DEBUG, "SUPP: %s(dest=" MACSTR " proto=0x%04x " - "len=%lu)", - __func__, MAC2STR(dest), proto, (unsigned long) len); - - if (wpa->test_peer == SUPP && wpa->test_oper == WRITE) - write_msg(wpa->f, buf, len); - - if (wpa->test_peer == AUTH && wpa->test_oper == READ) - return supp_read_msg(wpa); - - os_free(wpa->supp_eapol); - wpa->supp_eapol = os_malloc(len); - if (!wpa->supp_eapol) - return -1; - os_memcpy(wpa->supp_eapol, buf, len); - wpa->supp_eapol_len = len; - eloop_register_timeout(0, 0, auth_eapol_rx, wpa, NULL); - - return 0; -} - - -static u8 * supp_alloc_eapol(void *ctx, u8 type, const void *data, - u16 data_len, size_t *msg_len, void **data_pos) -{ - struct ieee802_1x_hdr *hdr; - - wpa_printf(MSG_DEBUG, "SUPP: %s(type=%d data_len=%d)", - __func__, type, data_len); - - *msg_len = sizeof(*hdr) + data_len; - hdr = os_malloc(*msg_len); - if (hdr == NULL) - return NULL; - - hdr->version = 2; - hdr->type = type; - hdr->length = host_to_be16(data_len); - - if (data) - os_memcpy(hdr + 1, data, data_len); - else - os_memset(hdr + 1, 0, data_len); - - if (data_pos) - *data_pos = hdr + 1; - - return (u8 *) hdr; -} - - -static int supp_get_beacon_ie(void *ctx) -{ - struct wpa *wpa = ctx; - const u8 *ie; - size_t ielen; - - wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); - - ie = wpa_auth_get_wpa_ie(wpa->auth_group, &ielen); - if (ie == NULL || ielen < 1) - return -1; - if (ie[0] == WLAN_EID_RSN) - return wpa_sm_set_ap_rsn_ie(wpa->supp, ie, 2 + ie[1]); - return wpa_sm_set_ap_wpa_ie(wpa->supp, ie, 2 + ie[1]); -} - - -static int supp_set_key(void *ctx, enum wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, - const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) -{ - wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d " - "set_tx=%d)", - __func__, alg, MAC2STR(addr), key_idx, set_tx); - wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len); - wpa_hexdump(MSG_DEBUG, "SUPP: set_key - key", key, key_len); - return 0; -} - - -static int supp_mlme_setprotection(void *ctx, const u8 *addr, - int protection_type, int key_type) -{ - wpa_printf(MSG_DEBUG, "SUPP: %s(addr=" MACSTR " protection_type=%d " - "key_type=%d)", - __func__, MAC2STR(addr), protection_type, key_type); - return 0; -} - - -static void supp_cancel_auth_timeout(void *ctx) -{ - wpa_printf(MSG_DEBUG, "SUPP: %s", __func__); -} - - -static void * supp_get_network_ctx(void *ctx) -{ - return (void *) 1; -} - - -static void supp_deauthenticate(void *ctx, u16 reason_code) -{ - wpa_printf(MSG_DEBUG, "SUPP: %s(%d)", __func__, reason_code); -} - - -static enum wpa_states supp_get_state(void *ctx) -{ - return WPA_COMPLETED; -} - - -static int supp_init(struct wpa *wpa) -{ - struct wpa_sm_ctx *ctx = os_zalloc(sizeof(*ctx)); - - if (!ctx) - return -1; - - ctx->ctx = wpa; - ctx->msg_ctx = wpa; - ctx->set_state = supp_set_state; - ctx->get_bssid = supp_get_bssid; - ctx->ether_send = supp_ether_send; - ctx->get_beacon_ie = supp_get_beacon_ie; - ctx->alloc_eapol = supp_alloc_eapol; - ctx->set_key = supp_set_key; - ctx->mlme_setprotection = supp_mlme_setprotection; - ctx->cancel_auth_timeout = supp_cancel_auth_timeout; - ctx->get_network_ctx = supp_get_network_ctx; - ctx->deauthenticate = supp_deauthenticate; - ctx->get_state = supp_get_state; - wpa->supp = wpa_sm_init(ctx); - if (!wpa->supp) { - wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed"); - return -1; - } - - wpa_sm_set_own_addr(wpa->supp, wpa->supp_addr); - if (wpa->wpa1) { - wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 0); - wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_WPA); - wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE, - WPA_CIPHER_TKIP); - wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_TKIP); - wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT, - WPA_KEY_MGMT_PSK); - } else { - wpa_sm_set_param(wpa->supp, WPA_PARAM_RSN_ENABLED, 1); - wpa_sm_set_param(wpa->supp, WPA_PARAM_PROTO, WPA_PROTO_RSN); - wpa_sm_set_param(wpa->supp, WPA_PARAM_PAIRWISE, - WPA_CIPHER_CCMP); - wpa_sm_set_param(wpa->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); - wpa_sm_set_param(wpa->supp, WPA_PARAM_KEY_MGMT, - WPA_KEY_MGMT_PSK); - wpa_sm_set_param(wpa->supp, WPA_PARAM_MFP, - MGMT_FRAME_PROTECTION_OPTIONAL); - } - wpa_sm_set_pmk(wpa->supp, wpa->psk, PMK_LEN, NULL, NULL); - - wpa->supp_ie_len = sizeof(wpa->supp_ie); - if (wpa_sm_set_assoc_wpa_ie_default(wpa->supp, wpa->supp_ie, - &wpa->supp_ie_len) < 0) { - wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_set_assoc_wpa_ie_default()" - " failed"); - return -1; - } - - wpa_sm_notify_assoc(wpa->supp, wpa->auth_addr); - - return 0; -} - - -static void auth_logger(void *ctx, const u8 *addr, logger_level level, - const char *txt) -{ - if (addr) - wpa_printf(MSG_DEBUG, "AUTH: " MACSTR " - %s", - MAC2STR(addr), txt); - else - wpa_printf(MSG_DEBUG, "AUTH: %s", txt); -} - - -static int auth_read_msg(struct wpa *wpa) -{ - os_free(wpa->supp_eapol); - wpa->supp_eapol = read_msg(wpa->f, &wpa->supp_eapol_len); - if (!wpa->supp_eapol) - return -1; - eloop_register_timeout(0, 0, auth_eapol_rx, wpa, NULL); - return 0; -} - - -static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data, - size_t data_len, int encrypt) -{ - struct wpa *wpa = ctx; - - wpa_printf(MSG_DEBUG, "AUTH: %s(addr=" MACSTR " data_len=%lu " - "encrypt=%d)", - __func__, MAC2STR(addr), (unsigned long) data_len, encrypt); - wpa->auth_sent = 1; - - if (wpa->test_peer == AUTH && wpa->test_oper == WRITE) - write_msg(wpa->f, data, data_len); - - if (wpa->test_peer == SUPP && wpa->test_oper == READ) - return auth_read_msg(wpa); - - os_free(wpa->auth_eapol); - wpa->auth_eapol = os_malloc(data_len); - if (!wpa->auth_eapol) - return -1; - os_memcpy(wpa->auth_eapol, data, data_len); - wpa->auth_eapol_len = data_len; - eloop_register_timeout(0, 0, supp_eapol_rx, wpa, NULL); - - return 0; -} - - -static const u8 * auth_get_psk(void *ctx, const u8 *addr, - const u8 *p2p_dev_addr, const u8 *prev_psk, - size_t *psk_len, int *vlan_id) -{ - struct wpa *wpa = ctx; - - wpa_printf(MSG_DEBUG, "AUTH: %s (addr=" MACSTR " prev_psk=%p)", - __func__, MAC2STR(addr), prev_psk); - if (vlan_id) - *vlan_id = 0; - if (psk_len) - *psk_len = PMK_LEN; - if (prev_psk) - return NULL; - return wpa->psk; -} - - -static void supp_eapol_key_request(void *eloop_data, void *user_ctx) -{ - struct wpa *wpa = eloop_data; - - wpa_printf(MSG_DEBUG, "SUPP: EAPOL-Key Request trigger"); - if (wpa->test_peer == SUPP && wpa->test_oper == READ) { - if (!eloop_is_timeout_registered(auth_eapol_rx, wpa, NULL)) - auth_read_msg(wpa); - } else { - wpa_sm_key_request(wpa->supp, 0, 1); - } -} - - -static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, - const u8 *addr, int idx, u8 *key, - size_t key_len) -{ - struct wpa *wpa = ctx; - - wpa_printf(MSG_DEBUG, "AUTH: %s (vlan_id=%d alg=%d idx=%d key_len=%d)", - __func__, vlan_id, alg, idx, (int) key_len); - if (addr) - wpa_printf(MSG_DEBUG, "AUTH: addr=" MACSTR, MAC2STR(addr)); - - if (alg != WPA_ALG_NONE && idx == 0 && key_len > 0 && - !wpa->key_request_done) { - wpa_printf(MSG_DEBUG, "Test EAPOL-Key Request"); - wpa->key_request_done = 1; - if (!wpa->wpa1) - eloop_register_timeout(0, 0, supp_eapol_key_request, - wpa, NULL); - } - - return 0; -} - - -static int auth_init_group(struct wpa *wpa) -{ - struct wpa_auth_config conf; - struct wpa_auth_callbacks cb; - - wpa_printf(MSG_DEBUG, "AUTH: Initializing group state machine"); - - os_memset(&conf, 0, sizeof(conf)); - if (wpa->wpa1) { - conf.wpa = 1; - conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK; - conf.wpa_pairwise = WPA_CIPHER_TKIP; - conf.wpa_group = WPA_CIPHER_TKIP; - } else { - conf.wpa = 2; - conf.wpa_key_mgmt = WPA_KEY_MGMT_PSK; - conf.wpa_pairwise = WPA_CIPHER_CCMP; - conf.rsn_pairwise = WPA_CIPHER_CCMP; - conf.wpa_group = WPA_CIPHER_CCMP; - conf.ieee80211w = 2; - conf.group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC; - } - conf.eapol_version = 2; - conf.wpa_group_update_count = 4; - conf.wpa_pairwise_update_count = 4; - - os_memset(&cb, 0, sizeof(cb)); - cb.logger = auth_logger; - cb.send_eapol = auth_send_eapol; - cb.get_psk = auth_get_psk; - cb.set_key = auth_set_key, - - wpa->auth_group = wpa_init(wpa->auth_addr, &conf, &cb, wpa); - if (!wpa->auth_group) { - wpa_printf(MSG_DEBUG, "AUTH: wpa_init() failed"); - return -1; - } - - return 0; -} - - -static int auth_init(struct wpa *wpa) -{ - if (wpa->test_peer == AUTH && wpa->test_oper == READ) - return supp_read_msg(wpa); - - wpa->auth = wpa_auth_sta_init(wpa->auth_group, wpa->supp_addr, NULL); - if (!wpa->auth) { - wpa_printf(MSG_DEBUG, "AUTH: wpa_auth_sta_init() failed"); - return -1; - } - - if (wpa_validate_wpa_ie(wpa->auth_group, wpa->auth, 2412, wpa->supp_ie, - wpa->supp_ie_len, NULL, 0, NULL, 0, NULL, 0) != - WPA_IE_OK) { - wpa_printf(MSG_DEBUG, "AUTH: wpa_validate_wpa_ie() failed"); - return -1; - } - - wpa_auth_sm_event(wpa->auth, WPA_ASSOC); - - wpa_auth_sta_associated(wpa->auth_group, wpa->auth); - - return 0; -} - - -static void deinit(struct wpa *wpa) -{ - wpa_auth_sta_deinit(wpa->auth); - wpa_sm_deinit(wpa->supp); - wpa_deinit(wpa->auth_group); - os_free(wpa->auth_eapol); - wpa->auth_eapol = NULL; - os_free(wpa->supp_eapol); - wpa->supp_eapol = NULL; -} - - -int main(int argc, char *argv[]) -{ - const char *file; - int ret; - struct wpa wpa; - - if (os_program_init()) - return -1; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - os_memset(&wpa, 0, sizeof(wpa)); - - if (argc < 4) - usage(); - - if (os_strcmp(argv[1], "auth") == 0) { - wpa.test_peer = AUTH; - } else if (os_strcmp(argv[1], "auth1") == 0) { - wpa.test_peer = AUTH; - wpa.wpa1 = 1; - } else if (os_strcmp(argv[1], "supp") == 0) { - wpa.test_peer = SUPP; - } else if (os_strcmp(argv[1], "supp1") == 0) { - wpa.test_peer = SUPP; - wpa.wpa1 = 1; - } else { - usage(); - } - - if (os_strcmp(argv[2], "read") == 0) - wpa.test_oper = READ; - else if (os_strcmp(argv[2], "write") == 0) - wpa.test_oper = WRITE; - else - usage(); - - file = argv[3]; - - wpa.f = fopen(file, wpa.test_oper == READ ? "r" : "w"); - if (!wpa.f) - return -1; - - os_memset(wpa.auth_addr, 0x12, ETH_ALEN); - os_memset(wpa.supp_addr, 0x32, ETH_ALEN); - os_memset(wpa.psk, 0x44, PMK_LEN); - - if (eloop_init()) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - goto fail; - } - - if (auth_init_group(&wpa) < 0) - goto fail; - - if (supp_init(&wpa) < 0) - goto fail; - - if (auth_init(&wpa) < 0) - goto fail; - - wpa_printf(MSG_DEBUG, "Starting eloop"); - eloop_run(); - wpa_printf(MSG_DEBUG, "eloop done"); - - ret = 0; -fail: - deinit(&wpa); - fclose(wpa.f); - - eloop_destroy(); - - os_program_deinit(); - - return ret; -} diff --git a/tests/test-json.c b/tests/test-json.c deleted file mode 100644 index b33a79214..000000000 --- a/tests/test-json.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * JSON parser - test program - * Copyright (c) 2019, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" -#include "utils/common.h" -#include "utils/os.h" -#include "utils/json.h" -#include "utils/wpa_debug.h" - - -void run_test(const char *buf, size_t len) -{ - struct json_token *root; - char *txt; - size_t buflen = 10000; - - root = json_parse(buf, len); - if (!root) { - wpa_printf(MSG_DEBUG, "JSON parsing failed"); - return; - } - - txt = os_zalloc(buflen); - if (txt) { - json_print_tree(root, txt, buflen); - wpa_printf(MSG_DEBUG, "%s", txt); - os_free(txt); - } - json_free(root); -} - - -#ifdef TEST_LIBFUZZER -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - run_test((const char *) data, size); - return 0; -} -#else /* TEST_LIBFUZZER */ -int main(int argc, char *argv[]) -{ - char *buf; - size_t len; - - wpa_debug_level = 0; - - if (argc < 2) - return -1; - - buf = os_readfile(argv[1], &len); - if (!buf) - return -1; - - run_test(buf, len); - os_free(buf); - - return 0; -} -#endif /* TEST_LIBFUZZER */ diff --git a/tests/test-tls.c b/tests/test-tls.c deleted file mode 100644 index 9941fb5fa..000000000 --- a/tests/test-tls.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Testing tool for TLSv1 client/server routines - * Copyright (c) 2019, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "crypto/tls.h" - - -static void usage(void) { - wpa_printf(MSG_INFO, - "usage: test-tls "); - exit(-1); -} - - -static void write_msg(FILE *f, struct wpabuf *msg) -{ - u8 len[2]; - - wpa_printf(MSG_DEBUG, "TEST: Write message to file (msg_len=%u)", - (unsigned int) wpabuf_len(msg)); - WPA_PUT_BE16(len, wpabuf_len(msg)); - fwrite(len, 2, 1, f); - fwrite(wpabuf_head(msg), wpabuf_len(msg), 1, f); -} - - -static struct wpabuf * read_msg(FILE *f) -{ - u8 len[2]; - u16 msg_len; - struct wpabuf *msg; - - if (fread(len, 2, 1, f) != 1) { - wpa_printf(MSG_ERROR, "TEST-ERROR: Could not read msg len"); - return NULL; - } - msg_len = WPA_GET_BE16(len); - - msg = wpabuf_alloc(msg_len); - if (!msg) - return NULL; - if (msg_len > 0 && - fread(wpabuf_put(msg, msg_len), msg_len, 1, f) != 1) { - wpa_printf(MSG_ERROR, "TEST-ERROR: Truncated msg (msg_len=%u)", - msg_len); - wpabuf_free(msg); - return NULL; - } - wpa_hexdump_buf(MSG_DEBUG, "TEST: Read message from file", msg); - - return msg; -} - - -int main(int argc, char *argv[]) -{ - struct tls_config conf; - void *tls_server, *tls_client; - struct tls_connection_params params; - struct tls_connection *conn_server = NULL, *conn_client = NULL; - int ret = -1; - struct wpabuf *in = NULL, *out = NULL, *appl; - enum { SERVER, CLIENT } test_peer; - enum { READ, WRITE } test_oper; - const char *file; - FILE *f; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (argc < 4) - usage(); - - if (os_strcmp(argv[1], "server") == 0) - test_peer = SERVER; - else if (os_strcmp(argv[1], "client") == 0) - test_peer = CLIENT; - else - usage(); - - if (os_strcmp(argv[2], "read") == 0) - test_oper = READ; - else if (os_strcmp(argv[2], "write") == 0) - test_oper = WRITE; - else - usage(); - - file = argv[3]; - - f = fopen(file, test_oper == READ ? "r" : "w"); - if (!f) - return -1; - - os_memset(&conf, 0, sizeof(conf)); - tls_server = tls_init(&conf); - tls_client = tls_init(&conf); - if (!tls_server || !tls_client) - goto fail; - - os_memset(¶ms, 0, sizeof(params)); - params.ca_cert = "hwsim/auth_serv/ca.pem"; - params.client_cert = "hwsim/auth_serv/server.pem"; - params.private_key = "hwsim/auth_serv/server.key"; - params.dh_file = "hwsim/auth_serv/dh.conf"; - - if (tls_global_set_params(tls_server, ¶ms)) { - wpa_printf(MSG_ERROR, "Failed to set TLS parameters"); - goto fail; - } - - conn_server = tls_connection_init(tls_server); - conn_client = tls_connection_init(tls_client); - if (!conn_server || !conn_client) - goto fail; - - in = NULL; - for (;;) { - appl = NULL; - if (test_peer == CLIENT && test_oper == READ) - out = read_msg(f); - else - out = tls_connection_handshake(tls_client, conn_client, - in, &appl); - wpabuf_free(in); - in = NULL; - if (!out) - goto fail; - if (test_peer == CLIENT && test_oper == WRITE && - wpabuf_len(out) > 0) - write_msg(f, out); - if (!(test_peer == CLIENT && test_oper == READ) && - tls_connection_get_failed(tls_client, conn_client)) { - wpa_printf(MSG_ERROR, "TLS handshake failed"); - goto fail; - } - if (((test_peer == CLIENT && test_oper == READ) || - tls_connection_established(tls_client, conn_client)) && - ((test_peer == SERVER && test_oper == READ) || - tls_connection_established(tls_server, conn_server))) - break; - - appl = NULL; - if (test_peer == SERVER && test_oper == READ) - in = read_msg(f); - else - in = tls_connection_server_handshake(tls_server, - conn_server, - out, &appl); - wpabuf_free(out); - out = NULL; - if (!in) - goto fail; - if (test_peer == SERVER && test_oper == WRITE) - write_msg(f, in); - if (!(test_peer == SERVER && test_oper == READ) && - tls_connection_get_failed(tls_server, conn_server)) { - wpa_printf(MSG_ERROR, "TLS handshake failed"); - goto fail; - } - if (((test_peer == CLIENT && test_oper == READ) || - tls_connection_established(tls_client, conn_client)) && - ((test_peer == SERVER && test_oper == READ) || - tls_connection_established(tls_server, conn_server))) - break; - } - - wpabuf_free(in); - in = wpabuf_alloc(100); - if (!in) - goto fail; - wpabuf_put_str(in, "PING"); - wpabuf_free(out); - if (test_peer == CLIENT && test_oper == READ) - out = read_msg(f); - else - out = tls_connection_encrypt(tls_client, conn_client, in); - wpabuf_free(in); - in = NULL; - if (!out) - goto fail; - if (test_peer == CLIENT && test_oper == WRITE) - write_msg(f, out); - - if (!(test_peer == SERVER && test_oper == READ)) { - in = tls_connection_decrypt(tls_server, conn_server, out); - wpabuf_free(out); - out = NULL; - if (!in) - goto fail; - wpa_hexdump_buf(MSG_DEBUG, "Server decrypted ApplData", in); - } - - wpabuf_free(in); - in = wpabuf_alloc(100); - if (!in) - goto fail; - wpabuf_put_str(in, "PONG"); - wpabuf_free(out); - if (test_peer == SERVER && test_oper == READ) - out = read_msg(f); - else - out = tls_connection_encrypt(tls_server, conn_server, in); - wpabuf_free(in); - in = NULL; - if (!out) - goto fail; - if (test_peer == SERVER && test_oper == WRITE) - write_msg(f, out); - - if (!(test_peer == CLIENT && test_oper == READ)) { - in = tls_connection_decrypt(tls_client, conn_client, out); - wpabuf_free(out); - out = NULL; - if (!in) - goto fail; - wpa_hexdump_buf(MSG_DEBUG, "Client decrypted ApplData", in); - } - - ret = 0; -fail: - if (tls_server) { - if (conn_server) - tls_connection_deinit(tls_server, conn_server); - tls_deinit(tls_server); - } - if (tls_client) { - if (conn_client) - tls_connection_deinit(tls_server, conn_client); - tls_deinit(tls_client); - } - wpabuf_free(in); - wpabuf_free(out); - fclose(f); - - return ret; -} diff --git a/tests/test-x509.c b/tests/test-x509.c deleted file mode 100644 index 055446ecc..000000000 --- a/tests/test-x509.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Testing tool for X.509v3 routines - * Copyright (c) 2006-2019, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "includes.h" - -#include "common.h" -#include "tls/x509v3.h" - - -#ifdef TEST_LIBFUZZER -int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) -{ - struct x509_certificate *cert; - - cert = x509_certificate_parse(data, size); - x509_certificate_free(cert); - return 0; -} -#else /* TEST_LIBFUZZER */ -int main(int argc, char *argv[]) -{ - FILE *f; - u8 buf[3000]; - size_t len; - struct x509_certificate *cert; - - wpa_debug_level = 0; - - f = fopen(argv[1], "rb"); - if (f == NULL) - return -1; - len = fread(buf, 1, sizeof(buf), f); - fclose(f); - - cert = x509_certificate_parse(buf, len); - if (cert == NULL) - printf("Failed to parse X.509 certificate\n"); - x509_certificate_free(cert); - - return 0; -} -#endif /* TEST_LIBFUZZER */ diff --git a/tests/test-x509v3.c b/tests/test-x509v3.c index bfb069871..06cd6eaab 100644 --- a/tests/test-x509v3.c +++ b/tests/test-x509v3.c @@ -21,6 +21,7 @@ int main(int argc, char *argv[]) int i, reason; wpa_debug_level = 0; + wpa_debug_show_keys = 1; if (argc < 3 || strcmp(argv[1], "-v") != 0) { printf("usage: test_x509v3 -v ..\n"); diff --git a/tests/wnm-fuzzer/Makefile b/tests/wnm-fuzzer/Makefile deleted file mode 100644 index 482a1ad63..000000000 --- a/tests/wnm-fuzzer/Makefile +++ /dev/null @@ -1,94 +0,0 @@ -all: wnm-fuzzer - -ifndef CC -CC=gcc -endif - -ifndef LDO -LDO=$(CC) -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif - -SRC=../../src - -CFLAGS += -I$(SRC) -CFLAGS += -DCONFIG_WNM -CFLAGS += -DCONFIG_INTERWORKING -CFLAGS += -DCONFIG_GAS -CFLAGS += -DCONFIG_HS20 -CFLAGS += -DIEEE8021X_EAPOL - -$(SRC)/utils/libutils.a: - $(MAKE) -C $(SRC)/utils - -$(SRC)/common/libcommon.a: - $(MAKE) -C $(SRC)/common - -$(SRC)/crypto/libcrypto.a: - $(MAKE) -C $(SRC)/crypto - -$(SRC)/tls/libtls.a: - $(MAKE) -C $(SRC)/tls - -$(SRC)/rsn_supp/librsn_supp.a: - $(MAKE) -C $(SRC)/rsn_supp - -$(SRC)/eapol_supp/libeapol_supp.a: - $(MAKE) -C $(SRC)/eapol_supp - -$(SRC)/eap_peer/libeap_peer.a: - $(MAKE) -C $(SRC)/eap_peer - -$(SRC)/eap_common/libeap_common.a: - $(MAKE) -C $(SRC)/eap_common - -$(SRC)/l2_packet/libl2_packet.a: - $(MAKE) -C $(SRC)/l2_packet - -LIBS += $(SRC)/common/libcommon.a -LIBS += $(SRC)/crypto/libcrypto.a -LIBS += $(SRC)/tls/libtls.a -LIBS += $(SRC)/rsn_supp/librsn_supp.a -LIBS += $(SRC)/eapol_supp/libeapol_supp.a -LIBS += $(SRC)/eap_peer/libeap_peer.a -LIBS += $(SRC)/eap_common/libeap_common.a -LIBS += $(SRC)/l2_packet/libl2_packet.a -LIBS += $(SRC)/utils/libutils.a - -ELIBS += $(SRC)/crypto/libcrypto.a -ELIBS += $(SRC)/tls/libtls.a - -CFLAGS += -I$(SRC)/utils -OBJS += ../../wpa_supplicant/wnm_sta.o -OBJS += ../../wpa_supplicant/bss.o -OBJS += ../../wpa_supplicant/scan.o -OBJS += ../../wpa_supplicant/notify.o -OBJS += ../../wpa_supplicant/wpa_supplicant.o -OBJS += ../../wpa_supplicant/config.o -OBJS += ../../wpa_supplicant/config_file.o -OBJS += ../../wpa_supplicant/blacklist.o -OBJS += ../../wpa_supplicant/events.o -OBJS += ../../wpa_supplicant/wpas_glue.o -OBJS += ../../wpa_supplicant/wmm_ac.o -OBJS += ../../wpa_supplicant/eap_register.o -OBJS += ../../wpa_supplicant/gas_query.o -OBJS += ../../wpa_supplicant/offchannel.o -OBJS += ../../wpa_supplicant/interworking.o -OBJS += ../../wpa_supplicant/hs20_supplicant.o -OBJS += ../../wpa_supplicant/rrm.o -OBJS += ../../wpa_supplicant/op_classes.o -OBJS += $(SRC)/drivers/drivers.o -OBJS += $(SRC)/drivers/driver_common.o - -wnm-fuzzer: wnm-fuzzer.o $(OBJS) $(LIBS) - $(LDO) $(LDFLAGS) -o $@ $^ $(LIBS) $(ELIBS) - -clean: - $(MAKE) -C $(SRC) clean - $(MAKE) -C ../../wpa_supplicant clean - rm -f wnm-fuzzer *~ *.o *.d - --include $(OBJS:%.o=%.d) diff --git a/tests/wnm-fuzzer/bss-tm-req.dat b/tests/wnm-fuzzer/bss-tm-req.dat deleted file mode 100644 index 14510bb3a..000000000 Binary files a/tests/wnm-fuzzer/bss-tm-req.dat and /dev/null differ diff --git a/tests/wnm-fuzzer/wnm-fuzzer.c b/tests/wnm-fuzzer/wnm-fuzzer.c deleted file mode 100644 index 2517b5c85..000000000 --- a/tests/wnm-fuzzer/wnm-fuzzer.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * wpa_supplicant - WNM fuzzer - * Copyright (c) 2015-2019, Jouni Malinen - * - * This software may be distributed under the terms of the BSD license. - * See README for more details. - */ - -#include "utils/includes.h" - -#include "utils/common.h" -#include "utils/eloop.h" -#include "common/ieee802_11_defs.h" -#include "rsn_supp/wpa.h" -#include "rsn_supp/wpa_i.h" -#include "../../wpa_supplicant/wpa_supplicant_i.h" -#include "../../wpa_supplicant/bss.h" -#include "../../wpa_supplicant/wnm_sta.h" -#include "../../wpa_supplicant/config.h" - - -struct arg_ctx { - const char *fname; - struct wpa_supplicant wpa_s; - struct wpa_bss bss; - struct wpa_driver_ops driver; - struct wpa_sm wpa; - struct wpa_config conf; -}; - - -static void test_send_wnm(void *eloop_data, void *user_ctx) -{ - struct arg_ctx *ctx = eloop_data; - char *data; - size_t len; - struct ieee80211_mgmt *mgmt; - - wpa_printf(MSG_INFO, "wnm-fuzzer: Send '%s'", ctx->fname); - - data = os_readfile(ctx->fname, &len); - if (!data) { - wpa_printf(MSG_ERROR, "Could not read '%s'", ctx->fname); - goto out; - } - - wpa_hexdump(MSG_MSGDUMP, "fuzzer - WNM", data, len); - - mgmt = (struct ieee80211_mgmt *) data; - ieee802_11_rx_wnm_action(&ctx->wpa_s, mgmt, len); - -out: - os_free(data); - eloop_terminate(); -} - - -static int init_wpa(struct arg_ctx *ctx) -{ - ctx->wpa_s.wpa_state = WPA_COMPLETED; - os_memcpy(ctx->wpa_s.bssid, "\x02\x00\x00\x00\x03\x00", ETH_ALEN); - ctx->wpa_s.current_bss = &ctx->bss; - ctx->wpa_s.driver = &ctx->driver; - ctx->wpa_s.wpa = &ctx->wpa; - ctx->wpa_s.conf = &ctx->conf; - - return 0; -} - - -static void deinit_wpa(struct arg_ctx *ctx) -{ - wnm_deallocate_memory(&ctx->wpa_s); -} - - -int main(int argc, char *argv[]) -{ - struct arg_ctx ctx; - int ret = -1; - - if (argc < 2) { - printf("usage: %s \n", argv[0]); - return -1; - } - - if (os_program_init()) - return -1; - - wpa_debug_level = 0; - wpa_debug_show_keys = 1; - - if (eloop_init()) { - wpa_printf(MSG_ERROR, "Failed to initialize event loop"); - return -1; - } - - os_memset(&ctx, 0, sizeof(ctx)); - ctx.fname = argv[1]; - if (init_wpa(&ctx)) - goto fail; - - eloop_register_timeout(0, 0, test_send_wnm, &ctx, NULL); - - wpa_printf(MSG_DEBUG, "Starting eloop"); - eloop_run(); - wpa_printf(MSG_DEBUG, "eloop done"); - deinit_wpa(&ctx); - - ret = 0; -fail: - eloop_destroy(); - os_program_deinit(); - - return ret; -} diff --git a/tests/wnm-fuzzer/wnm-notif.dat b/tests/wnm-fuzzer/wnm-notif.dat deleted file mode 100644 index c234d3ad5..000000000 Binary files a/tests/wnm-fuzzer/wnm-notif.dat and /dev/null differ diff --git a/wlantest/.gitignore b/wlantest/.gitignore new file mode 100644 index 000000000..7ffabe601 --- /dev/null +++ b/wlantest/.gitignore @@ -0,0 +1,4 @@ +libwlantest.a +test_vectors +wlantest +wlantest_cli diff --git a/wlantest/Makefile b/wlantest/Makefile index 0fdf3ff91..602375112 100644 --- a/wlantest/Makefile +++ b/wlantest/Makefile @@ -1,49 +1,20 @@ ALL=wlantest wlantest_cli test_vectors -all: $(ALL) - -ifndef CC -CC=gcc -endif - -ifndef RANLIB -RANLIB=ranlib -endif - -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g -endif +include ../src/build.rules +UNAME := $(shell uname -s) CFLAGS += -I. CFLAGS += -I../src CFLAGS += -I../src/utils +ifneq ($(UNAME),Darwin) # glibc < 2.17 needs -lrt for clock_gettime() LIBS += -lrt - -ifndef LDO -LDO=$(CC) endif -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif -ifeq ($(QUIET), 1) -Q=@ -E=true -endif - -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< - - -OBJS_lib += ../src/utils/libutils.a -OBJS_lib += ../src/crypto/libcrypto.a +OWN_LIBS += ../src/utils/libutils.a +OWN_LIBS += ../src/crypto/libcrypto.a CFLAGS += -DCONFIG_OCV CFLAGS += -DCONFIG_IEEE80211R @@ -91,44 +62,25 @@ TOBJS += bip.o TOBJS += gcmp.o -../src/utils/libutils.a: - $(MAKE) -C ../src/utils - -../src/crypto/libcrypto.a: - $(MAKE) -C ../src/crypto - - -ifneq ($(CONFIG_SOLIB), yes) -LIBWLANTEST = libwlantest.a -libwlantest.a: $(OBJS_lib) - $(AR) crT libwlantest.a $(OBJS_lib) - $(RANLIB) libwlantest.a - -else -CFLAGS += -fPIC -DPIC -LDFLAGS += -shared - -LIBWLANTEST = libwlantest.so -libwlantest.so: $(OBJS_lib) - $(LDO) $(LDFLAGS) $(OBJS_lib) -o $(LIBWLANTEST) - -endif - - OBJS_cli = wlantest_cli.o +_OBJS_VAR := OBJS +include ../src/objs.mk +_OBJS_VAR := TOBJS +include ../src/objs.mk +_OBJS_VAR := OBJS_cli +include ../src/objs.mk +_OBJS_VAR := OWN_LIBS +include ../src/objs.mk -wlantest: $(OBJS) $(LIBWLANTEST) - $(LDO) $(LDFLAGS) -o wlantest $(OBJS) -L. -lwlantest $(LIBS) +wlantest: $(OBJS) $(OWN_LIBS) + $(LDO) $(LDFLAGS) -o wlantest $(OBJS) $(OWN_LIBS) $(LIBS) -wlantest_cli: $(OBJS_cli) $(LIBWLANTEST) - $(LDO) $(LDFLAGS) -o wlantest_cli $(OBJS_cli) -L. -lwlantest $(LIBS) +wlantest_cli: $(OBJS_cli) $(OWN_LIBS) + $(LDO) $(LDFLAGS) -o wlantest_cli $(OBJS_cli) $(OWN_LIBS) $(LIBS) -test_vectors: $(TOBJS) $(LIBWLANTEST) - $(LDO) $(LDFLAGS) -o test_vectors $(TOBJS) -L. -lwlantest $(LIBS) +test_vectors: $(TOBJS) $(OWN_LIBS) + $(LDO) $(LDFLAGS) -o test_vectors $(TOBJS) $(OWN_LIBS) $(LIBS) -clean: - $(MAKE) -C ../src clean - rm -f core *~ *.o *.d libwlantest.a libwlantest.so $(ALL) - --include $(OBJS:%.o=%.d) +clean: common-clean + rm -f core *~ diff --git a/wlantest/bss.c b/wlantest/bss.c index 298a902c7..92f4a5ebc 100644 --- a/wlantest/bss.c +++ b/wlantest/bss.c @@ -129,7 +129,7 @@ static void bss_add_pmk(struct wlantest *wt, struct wlantest_bss *bss) void bss_update(struct wlantest *wt, struct wlantest_bss *bss, - struct ieee802_11_elems *elems) + struct ieee802_11_elems *elems, int beacon) { struct wpa_ie_data data; int update = 0; @@ -137,15 +137,18 @@ void bss_update(struct wlantest *wt, struct wlantest_bss *bss, if (bss->capab_info != bss->prev_capab_info) update = 1; - if (elems->ssid == NULL || elems->ssid_len > 32) { - wpa_printf(MSG_INFO, "Invalid or missing SSID in a Beacon " - "frame for " MACSTR, MAC2STR(bss->bssid)); + if (beacon && (!elems->ssid || elems->ssid_len > 32)) { + wpa_printf(MSG_INFO, + "Invalid or missing SSID in a %s frame for " MACSTR, + beacon == 1 ? "Beacon" : "Probe Response", + MAC2STR(bss->bssid)); bss->parse_error_reported = 1; return; } - if (bss->ssid_len != elems->ssid_len || - os_memcmp(bss->ssid, elems->ssid, bss->ssid_len) != 0) { + if (beacon && + (bss->ssid_len != elems->ssid_len || + os_memcmp(bss->ssid, elems->ssid, bss->ssid_len) != 0)) { wpa_printf(MSG_DEBUG, "Store SSID '%s' for BSSID " MACSTR, wpa_ssid_txt(elems->ssid, elems->ssid_len), MAC2STR(bss->bssid)); @@ -175,14 +178,18 @@ void bss_update(struct wlantest *wt, struct wlantest_bss *bss, elems->osen_len + 2); } - if (elems->rsn_ie == NULL) { + /* S1G does not include RSNE in beacon, so only clear it from + * Probe Response frames. Note this assumes short beacons were dropped + * due to missing SSID above. + */ + if (!elems->rsn_ie && (!elems->s1g_capab || beacon != 1)) { if (bss->rsnie[0]) { add_note(wt, MSG_INFO, "BSS " MACSTR " - RSN IE removed", MAC2STR(bss->bssid)); bss->rsnie[0] = 0; update = 1; } - } else { + } else if (elems->rsn_ie) { if (bss->rsnie[0] == 0 || os_memcmp(bss->rsnie, elems->rsn_ie - 2, elems->rsn_ie_len + 2) != 0) { @@ -223,7 +230,11 @@ void bss_update(struct wlantest *wt, struct wlantest_bss *bss, if (!update) return; - bss->beacon_seen = 1; + if (beacon == 1) + bss->beacon_seen = 1; + else if (beacon == 2) + bss->proberesp_seen = 1; + bss->ies_set = 1; bss->prev_capab_info = bss->capab_info; bss->proto = 0; bss->pairwise_cipher = 0; @@ -283,7 +294,7 @@ void bss_update(struct wlantest *wt, struct wlantest_bss *bss, "group=%s%s%s%s%s%s%s%s%s" "mgmt_group_cipher=%s%s%s%s%s" "key_mgmt=%s%s%s%s%s%s%s%s%s" - "rsn_capab=%s%s%s%s%s%s", + "rsn_capab=%s%s%s%s%s%s%s", MAC2STR(bss->bssid), bss->proto == 0 ? "OPEN " : "", bss->proto & WPA_PROTO_WPA ? "WPA " : "", @@ -334,7 +345,9 @@ void bss_update(struct wlantest *wt, struct wlantest_bss *bss, bss->rsn_capab & WPA_CAPABILITY_MFPC ? "MFPC " : "", bss->rsn_capab & WPA_CAPABILITY_PEERKEY_ENABLED ? "PEERKEY " : "", - bss->rsn_capab & WPA_CAPABILITY_OCVC ? "OCVC " : ""); + bss->rsn_capab & WPA_CAPABILITY_OCVC ? "OCVC " : "", + bss->rsn_capab & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST ? + "ExtKeyID " : ""); } diff --git a/wlantest/monitor.c b/wlantest/monitor.c index afcc3806f..f28708689 100644 --- a/wlantest/monitor.c +++ b/wlantest/monitor.c @@ -7,14 +7,36 @@ */ #include "utils/includes.h" +#ifndef __APPLE__ #include #include +#endif /* __APPLE__ */ #include "utils/common.h" #include "utils/eloop.h" #include "wlantest.h" +#ifdef __APPLE__ + +int monitor_init(struct wlantest *wt, const char *ifname) +{ + return -1; +} + + +int monitor_init_wired(struct wlantest *wt, const char *ifname) +{ + return -1; +} + + +void monitor_deinit(struct wlantest *wt) +{ +} + +#else /* __APPLE__ */ + static void monitor_read(int sock, void *eloop_ctx, void *sock_ctx) { struct wlantest *wt = eloop_ctx; @@ -146,3 +168,5 @@ void monitor_deinit(struct wlantest *wt) wt->monitor_wired = -1; } } + +#endif /* __APPLE__ */ diff --git a/wlantest/readpcap.c b/wlantest/readpcap.c index 6c3853b05..1e7e66260 100644 --- a/wlantest/readpcap.c +++ b/wlantest/readpcap.c @@ -92,6 +92,7 @@ int read_cap_file(struct wlantest *wt, const char *fname) } /* Packet was read without problems */ + wt->frame_num++; wpa_printf(MSG_EXCESSIVE, "pcap hdr: ts=%d.%06d " "len=%u/%u", (int) hdr->ts.tv_sec, (int) hdr->ts.tv_usec, diff --git a/wlantest/rx_data.c b/wlantest/rx_data.c index d6c7a54c7..b632013a8 100644 --- a/wlantest/rx_data.c +++ b/wlantest/rx_data.c @@ -119,8 +119,53 @@ static void rx_data_process(struct wlantest *wt, const u8 *bssid, } +static void write_decrypted_note(struct wlantest *wt, const u8 *decrypted, + const u8 *tk, size_t tk_len, int keyid) +{ + char tk_hex[65]; + + if (!decrypted) + return; + + wpa_snprintf_hex(tk_hex, sizeof(tk_hex), tk, tk_len); + add_note(wt, MSG_EXCESSIVE, "TK[%d] %s", keyid, tk_hex); +} + + +static u8 * try_ptk(int pairwise_cipher, struct wpa_ptk *ptk, + const struct ieee80211_hdr *hdr, + const u8 *data, size_t data_len, size_t *decrypted_len) +{ + u8 *decrypted; + unsigned int tk_len = ptk->tk_len; + + decrypted = NULL; + if ((pairwise_cipher == WPA_CIPHER_CCMP || + pairwise_cipher == 0) && tk_len == 16) { + decrypted = ccmp_decrypt(ptk->tk, hdr, data, + data_len, decrypted_len); + } else if ((pairwise_cipher == WPA_CIPHER_CCMP_256 || + pairwise_cipher == 0) && tk_len == 32) { + decrypted = ccmp_256_decrypt(ptk->tk, hdr, data, + data_len, decrypted_len); + } else if ((pairwise_cipher == WPA_CIPHER_GCMP || + pairwise_cipher == WPA_CIPHER_GCMP_256 || + pairwise_cipher == 0) && + (tk_len == 16 || tk_len == 32)) { + decrypted = gcmp_decrypt(ptk->tk, tk_len, hdr, + data, data_len, decrypted_len); + } else if ((pairwise_cipher == WPA_CIPHER_TKIP || + pairwise_cipher == 0) && tk_len == 32) { + decrypted = tkip_decrypt(ptk->tk, hdr, data, data_len, + decrypted_len); + } + + return decrypted; +} + + static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher, - const struct ieee80211_hdr *hdr, + const struct ieee80211_hdr *hdr, int keyid, const u8 *data, size_t data_len, size_t *decrypted_len) { struct wlantest_ptk *ptk; @@ -129,30 +174,14 @@ static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher, wpa_debug_level = MSG_WARNING; dl_list_for_each(ptk, &wt->ptk, struct wlantest_ptk, list) { - unsigned int tk_len = ptk->ptk_len - 32; - decrypted = NULL; - if ((pairwise_cipher == WPA_CIPHER_CCMP || - pairwise_cipher == 0) && tk_len == 16) { - decrypted = ccmp_decrypt(ptk->ptk.tk, hdr, data, - data_len, decrypted_len); - } else if ((pairwise_cipher == WPA_CIPHER_CCMP_256 || - pairwise_cipher == 0) && tk_len == 32) { - decrypted = ccmp_256_decrypt(ptk->ptk.tk, hdr, data, - data_len, decrypted_len); - } else if ((pairwise_cipher == WPA_CIPHER_GCMP || - pairwise_cipher == WPA_CIPHER_GCMP_256 || - pairwise_cipher == 0) && - (tk_len == 16 || tk_len == 32)) { - decrypted = gcmp_decrypt(ptk->ptk.tk, tk_len, hdr, - data, data_len, decrypted_len); - } else if ((pairwise_cipher == WPA_CIPHER_TKIP || - pairwise_cipher == 0) && tk_len == 32) { - decrypted = tkip_decrypt(ptk->ptk.tk, hdr, data, - data_len, decrypted_len); - } + decrypted = try_ptk(pairwise_cipher, &ptk->ptk, hdr, + data, data_len, decrypted_len); if (decrypted) { wpa_debug_level = prev_level; - add_note(wt, MSG_DEBUG, "Found PTK match from list of all known PTKs"); + add_note(wt, MSG_DEBUG, + "Found PTK match from list of all known PTKs"); + write_decrypted_note(wt, decrypted, ptk->ptk.tk, + ptk->ptk.tk_len, keyid); return decrypted; } } @@ -162,6 +191,23 @@ static u8 * try_all_ptk(struct wlantest *wt, int pairwise_cipher, } +static void check_plaintext_prot(struct wlantest *wt, + const struct ieee80211_hdr *hdr, + const u8 *data, size_t len) +{ + if (len < 8 + 3 || data[8] != 0xaa || data[9] != 0xaa || + data[10] != 0x03) + return; + + add_note(wt, MSG_DEBUG, + "Plaintext payload in protected frame"); + wpa_printf(MSG_INFO, "Plaintext payload in protected frame #%u: A2=" + MACSTR " seq=%u", + wt->frame_num, MAC2STR(hdr->addr2), + WLAN_GET_SEQ_SEQ(le_to_host16(hdr->seq_ctrl))); +} + + static void rx_data_bss_prot_group(struct wlantest *wt, const struct ieee80211_hdr *hdr, size_t hdrlen, @@ -212,9 +258,11 @@ static void rx_data_bss_prot_group(struct wlantest *wt, } } + check_plaintext_prot(wt, hdr, data, len); keyid = data[3] >> 6; - if (bss->gtk_len[keyid] == 0 && bss->group_cipher != WPA_CIPHER_WEP40) - { + if (bss->gtk_len[keyid] == 0 && + (bss->group_cipher != WPA_CIPHER_WEP40 || + dl_list_empty(&wt->wep))) { add_note(wt, MSG_MSGDUMP, "No GTK known to decrypt the frame " "(A2=" MACSTR " KeyID=%d)", MAC2STR(hdr->addr2), keyid); @@ -229,16 +277,20 @@ static void rx_data_bss_prot_group(struct wlantest *wt, ccmp_get_pn(pn, data); if (os_memcmp(pn, bss->rsc[keyid], 6) <= 0) { u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); - add_note(wt, MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR - " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u%s", + char pn_hex[6 * 2 + 1], rsc_hex[6 * 2 + 1]; + + wpa_snprintf_hex(pn_hex, sizeof(pn_hex), pn, 6); + wpa_snprintf_hex(rsc_hex, sizeof(rsc_hex), bss->rsc[keyid], 6); + add_note(wt, MSG_INFO, "replay detected: A1=" MACSTR + " A2=" MACSTR " A3=" MACSTR + " seq=%u frag=%u%s keyid=%d #%u %s<=%s", MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3), WLAN_GET_SEQ_SEQ(seq_ctrl), WLAN_GET_SEQ_FRAG(seq_ctrl), (le_to_host16(hdr->frame_control) & WLAN_FC_RETRY) ? - " Retry" : ""); - wpa_hexdump(MSG_INFO, "RX PN", pn, 6); - wpa_hexdump(MSG_INFO, "RSC", bss->rsc[keyid], 6); + " Retry" : "", + keyid, wt->frame_num, pn_hex, rsc_hex); replay = 1; } @@ -260,18 +312,48 @@ skip_replay_det: hdr, data, len, &dlen); if (decrypted) { + char gtk[65]; + + wpa_snprintf_hex(gtk, sizeof(gtk), bss->gtk[keyid], + bss->gtk_len[keyid]); + add_note(wt, MSG_EXCESSIVE, "GTK[%d] %s", keyid, gtk); rx_data_process(wt, bss->bssid, NULL, dst, src, decrypted, dlen, 1, NULL); if (!replay) os_memcpy(bss->rsc[keyid], pn, 6); write_pcap_decrypted(wt, (const u8 *) hdr, hdrlen, decrypted, dlen); - } else - add_note(wt, MSG_DEBUG, "Failed to decrypt frame"); + } else { + wpa_printf(MSG_DEBUG, "Failed to decrypt frame (group) #%u A2=" + MACSTR " seq=%u", + wt->frame_num, MAC2STR(hdr->addr2), + WLAN_GET_SEQ_SEQ(le_to_host16(hdr->seq_ctrl))); + add_note(wt, MSG_DEBUG, "Failed to decrypt frame (group)"); + } os_free(decrypted); } +static u8 * try_ptk_decrypt(struct wlantest *wt, struct wlantest_sta *sta, + const struct ieee80211_hdr *hdr, int keyid, + const u8 *data, size_t len, + const u8 *tk, size_t tk_len, size_t *dlen) +{ + u8 *decrypted = NULL; + + if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) + decrypted = ccmp_256_decrypt(tk, hdr, data, len, dlen); + else if (sta->pairwise_cipher == WPA_CIPHER_GCMP || + sta->pairwise_cipher == WPA_CIPHER_GCMP_256) + decrypted = gcmp_decrypt(tk, tk_len, hdr, data, len, dlen); + else + decrypted = ccmp_decrypt(tk, hdr, data, len, dlen); + write_decrypted_note(wt, decrypted, tk, tk_len, keyid); + + return decrypted; +} + + static void rx_data_bss_prot(struct wlantest *wt, const struct ieee80211_hdr *hdr, size_t hdrlen, const u8 *qos, const u8 *dst, const u8 *src, @@ -281,15 +363,17 @@ static void rx_data_bss_prot(struct wlantest *wt, struct wlantest_sta *sta, *sta2; int keyid; u16 fc = le_to_host16(hdr->frame_control); - u8 *decrypted; + u8 *decrypted = NULL; size_t dlen; int tid; - u8 pn[6], *rsc; + u8 pn[6], *rsc = NULL; struct wlantest_tdls *tdls = NULL, *found; const u8 *tk = NULL; int ptk_iter_done = 0; int try_ptk_iter = 0; int replay = 0; + int only_zero_tk = 0; + u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); if (hdr->addr1[0] & 0x01) { rx_data_bss_prot_group(wt, hdr, hdrlen, qos, dst, src, @@ -361,12 +445,20 @@ static void rx_data_bss_prot(struct wlantest *wt, tdls = found; } } + check_plaintext_prot(wt, hdr, data, len); if ((sta == NULL || (!sta->ptk_set && sta->pairwise_cipher != WPA_CIPHER_WEP40)) && tk == NULL) { add_note(wt, MSG_MSGDUMP, "No PTK known to decrypt the frame"); - if (dl_list_empty(&wt->ptk)) + if (dl_list_empty(&wt->ptk)) { + if (len >= 4 && sta) { + keyid = data[3] >> 6; + only_zero_tk = 1; + goto check_zero_tk; + } return; + } + try_ptk_iter = 1; } @@ -407,9 +499,13 @@ static void rx_data_bss_prot(struct wlantest *wt, } keyid = data[3] >> 6; - if (keyid != 0) { - add_note(wt, MSG_INFO, "Unexpected non-zero KeyID %d in " - "individually addressed Data frame from " MACSTR, + if (keyid != 0 && + (!(sta->rsn_capab & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST) || + !(bss->rsn_capab & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST) || + keyid != 1)) { + add_note(wt, MSG_INFO, + "Unexpected KeyID %d in individually addressed Data frame from " + MACSTR, keyid, MAC2STR(hdr->addr2)); } @@ -450,71 +546,118 @@ static void rx_data_bss_prot(struct wlantest *wt, else ccmp_get_pn(pn, data); if (os_memcmp(pn, rsc, 6) <= 0) { - u16 seq_ctrl = le_to_host16(hdr->seq_ctrl); - add_note(wt, MSG_INFO, "CCMP/TKIP replay detected: A1=" MACSTR - " A2=" MACSTR " A3=" MACSTR " seq=%u frag=%u%s", + char pn_hex[6 * 2 + 1], rsc_hex[6 * 2 + 1]; + + wpa_snprintf_hex(pn_hex, sizeof(pn_hex), pn, 6); + wpa_snprintf_hex(rsc_hex, sizeof(rsc_hex), rsc, 6); + add_note(wt, MSG_INFO, "replay detected: A1=" MACSTR + " A2=" MACSTR " A3=" MACSTR + " seq=%u frag=%u%s keyid=%d tid=%d #%u %s<=%s", MAC2STR(hdr->addr1), MAC2STR(hdr->addr2), MAC2STR(hdr->addr3), WLAN_GET_SEQ_SEQ(seq_ctrl), WLAN_GET_SEQ_FRAG(seq_ctrl), (le_to_host16(hdr->frame_control) & WLAN_FC_RETRY) ? - " Retry" : ""); - wpa_hexdump(MSG_INFO, "RX PN", pn, 6); - wpa_hexdump(MSG_INFO, "RSC", rsc, 6); + " Retry" : "", + keyid, tid, wt->frame_num, pn_hex, rsc_hex); replay = 1; } skip_replay_det: if (tk) { - if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) + if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) { decrypted = ccmp_256_decrypt(tk, hdr, data, len, &dlen); - else if (sta->pairwise_cipher == WPA_CIPHER_GCMP || - sta->pairwise_cipher == WPA_CIPHER_GCMP_256) + write_decrypted_note(wt, decrypted, tk, 32, keyid); + } else if (sta->pairwise_cipher == WPA_CIPHER_GCMP || + sta->pairwise_cipher == WPA_CIPHER_GCMP_256) { decrypted = gcmp_decrypt(tk, sta->ptk.tk_len, hdr, data, len, &dlen); - else + write_decrypted_note(wt, decrypted, tk, sta->ptk.tk_len, + keyid); + } else { decrypted = ccmp_decrypt(tk, hdr, data, len, &dlen); + write_decrypted_note(wt, decrypted, tk, 16, keyid); + } } else if (sta->pairwise_cipher == WPA_CIPHER_TKIP) { decrypted = tkip_decrypt(sta->ptk.tk, hdr, data, len, &dlen); + write_decrypted_note(wt, decrypted, sta->ptk.tk, 32, keyid); } else if (sta->pairwise_cipher == WPA_CIPHER_WEP40) { decrypted = wep_decrypt(wt, hdr, data, len, &dlen); } else if (sta->ptk_set) { - if (sta->pairwise_cipher == WPA_CIPHER_CCMP_256) - decrypted = ccmp_256_decrypt(sta->ptk.tk, hdr, data, - len, &dlen); - else if (sta->pairwise_cipher == WPA_CIPHER_GCMP || - sta->pairwise_cipher == WPA_CIPHER_GCMP_256) - decrypted = gcmp_decrypt(sta->ptk.tk, sta->ptk.tk_len, - hdr, data, len, &dlen); - else - decrypted = ccmp_decrypt(sta->ptk.tk, hdr, data, len, - &dlen); + decrypted = try_ptk_decrypt(wt, sta, hdr, keyid, data, len, + sta->ptk.tk, sta->ptk.tk_len, + &dlen); } else { - decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data, - len, &dlen); + decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, keyid, + data, len, &dlen); ptk_iter_done = 1; } if (!decrypted && !ptk_iter_done) { - decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, data, - len, &dlen); + decrypted = try_all_ptk(wt, sta->pairwise_cipher, hdr, keyid, + data, len, &dlen); if (decrypted) { add_note(wt, MSG_DEBUG, "Current PTK did not work, but found a match from all known PTKs"); } } +check_zero_tk: + if (!decrypted) { + struct wpa_ptk zero_ptk; + int old_debug_level = wpa_debug_level; + + os_memset(&zero_ptk, 0, sizeof(zero_ptk)); + zero_ptk.tk_len = wpa_cipher_key_len(sta->pairwise_cipher); + wpa_debug_level = MSG_ERROR; + decrypted = try_ptk(sta->pairwise_cipher, &zero_ptk, hdr, + data, len, &dlen); + wpa_debug_level = old_debug_level; + if (decrypted) { + add_note(wt, MSG_DEBUG, + "Frame was encrypted with zero TK"); + wpa_printf(MSG_INFO, "Zero TK used in frame #%u: A2=" + MACSTR " seq=%u", + wt->frame_num, MAC2STR(hdr->addr2), + WLAN_GET_SEQ_SEQ( + le_to_host16(hdr->seq_ctrl))); + write_decrypted_note(wt, decrypted, zero_ptk.tk, + zero_ptk.tk_len, keyid); + } + } if (decrypted) { u16 fc = le_to_host16(hdr->frame_control); const u8 *peer_addr = NULL; if (!(fc & (WLAN_FC_FROMDS | WLAN_FC_TODS))) peer_addr = hdr->addr1; - if (!replay) + if (!replay && rsc) os_memcpy(rsc, pn, 6); rx_data_process(wt, bss->bssid, sta->addr, dst, src, decrypted, dlen, 1, peer_addr); write_pcap_decrypted(wt, (const u8 *) hdr, hdrlen, decrypted, dlen); + } else if (sta->tptk_set) { + /* Check whether TPTK has a matching TK that could be used to + * decrypt the frame. That could happen if EAPOL-Key msg 4/4 + * was missing in the capture and this was PTK rekeying. */ + decrypted = try_ptk_decrypt(wt, sta, hdr, keyid, data, len, + sta->tptk.tk, sta->tptk.tk_len, + &dlen); + if (decrypted) { + add_note(wt, MSG_DEBUG, + "Update PTK (rekeying; no valid EAPOL-Key msg 4/4 seen)"); + os_memcpy(&sta->ptk, &sta->tptk, sizeof(sta->ptk)); + sta->ptk_set = 1; + sta->tptk_set = 0; + os_memset(sta->rsc_tods, 0, sizeof(sta->rsc_tods)); + os_memset(sta->rsc_fromds, 0, sizeof(sta->rsc_fromds)); + } } else { - if (!try_ptk_iter) + if (!try_ptk_iter && !only_zero_tk) { + wpa_printf(MSG_DEBUG, + "Failed to decrypt frame #%u A2=" MACSTR + " seq=%u", + wt->frame_num, MAC2STR(hdr->addr2), + WLAN_GET_SEQ_SEQ(seq_ctrl)); add_note(wt, MSG_DEBUG, "Failed to decrypt frame"); + } /* Assume the frame was corrupted and there was no FCS to check. * Allow retry of this particular frame to be processed so that diff --git a/wlantest/rx_eapol.c b/wlantest/rx_eapol.c index e18449542..1e5d66735 100644 --- a/wlantest/rx_eapol.c +++ b/wlantest/rx_eapol.c @@ -1,6 +1,6 @@ /* * Received Data frame processing for EAPOL messages - * Copyright (c) 2010-2015, Jouni Malinen + * Copyright (c) 2010-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -100,30 +100,26 @@ static int try_pmk(struct wlantest *wt, struct wlantest_bss *bss, struct wpa_ptk ptk; if (wpa_key_mgmt_ft(sta->key_mgmt)) { - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; u8 ptk_name[WPA_PMK_NAME_LEN]; + int use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt); - if (wpa_derive_pmk_r0(pmk->pmk, PMK_LEN, + if (wpa_derive_pmk_r0(pmk->pmk, pmk->pmk_len, bss->ssid, bss->ssid_len, bss->mdid, bss->r0kh_id, bss->r0kh_id_len, sta->addr, sta->pmk_r0, sta->pmk_r0_name, - 0) < 0) + use_sha384) < 0) return -1; - wpa_hexdump(MSG_DEBUG, "FT: PMK-R0", sta->pmk_r0, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", sta->pmk_r0_name, - WPA_PMK_NAME_LEN); - if (wpa_derive_pmk_r1(sta->pmk_r0, PMK_LEN, sta->pmk_r0_name, + sta->pmk_r0_len = use_sha384 ? PMK_LEN_SUITE_B_192 : PMK_LEN; + if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, + sta->pmk_r0_name, bss->r1kh_id, sta->addr, - pmk_r1, pmk_r1_name) < 0) + sta->pmk_r1, sta->pmk_r1_name) < 0) return -1; - wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, PMK_LEN); - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, - WPA_PMK_NAME_LEN); - if (wpa_pmk_r1_to_ptk(pmk_r1, PMK_LEN, sta->snonce, sta->anonce, - sta->addr, - bss->bssid, pmk_r1_name, &ptk, ptk_name, - sta->key_mgmt, + sta->pmk_r1_len = sta->pmk_r0_len; + if (wpa_pmk_r1_to_ptk(sta->pmk_r1, sta->pmk_r1_len, + sta->snonce, sta->anonce, sta->addr, + bss->bssid, sta->pmk_r1_name, + &ptk, ptk_name, sta->key_mgmt, sta->pairwise_cipher) < 0 || check_mic(ptk.kck, ptk.kck_len, sta->key_mgmt, ver, data, len) < 0) @@ -222,6 +218,25 @@ static void derive_ptk(struct wlantest *wt, struct wlantest_bss *bss, } +static void elems_from_eapol_ie(struct ieee802_11_elems *elems, + struct wpa_eapol_ie_parse *ie) +{ + os_memset(elems, 0, sizeof(*elems)); + if (ie->wpa_ie) { + elems->wpa_ie = ie->wpa_ie + 2; + elems->wpa_ie_len = ie->wpa_ie_len - 2; + } + if (ie->rsn_ie) { + elems->rsn_ie = ie->rsn_ie + 2; + elems->rsn_ie_len = ie->rsn_ie_len - 2; + } + if (ie->osen) { + elems->osen = ie->osen + 2; + elems->osen_len = ie->osen_len - 2; + } +} + + static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, const u8 *src, const u8 *data, size_t len) { @@ -257,7 +272,23 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, } os_memcpy(sta->snonce, hdr->key_nonce, WPA_NONCE_LEN); key_info = WPA_GET_BE16(hdr->key_info); + key_data = mic + mic_len + 2; key_data_len = WPA_GET_BE16(mic + mic_len); + + if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) { + add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data"); + return; + } + + if (!sta->assocreq_seen) { + struct ieee802_11_elems elems; + + elems_from_eapol_ie(&elems, &ie); + wpa_printf(MSG_DEBUG, + "Update STA data based on IEs in EAPOL-Key 2/4"); + sta_update_assoc(sta, &elems); + } + derive_ptk(wt, bss, sta, key_info & WPA_KEY_INFO_TYPE_MASK, data, len); if (!sta->ptk_set && !sta->tptk_set) { @@ -281,18 +312,10 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, } add_note(wt, MSG_DEBUG, "Valid MIC found in EAPOL-Key 2/4"); - key_data = mic + mic_len + 2; - - if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) { - add_note(wt, MSG_INFO, "Failed to parse EAPOL-Key Key Data"); - return; - } - if (ie.wpa_ie) { wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - WPA IE", ie.wpa_ie, ie.wpa_ie_len); if (os_memcmp(ie.wpa_ie, sta->rsnie, ie.wpa_ie_len) != 0) { - struct ieee802_11_elems elems; add_note(wt, MSG_INFO, "Mismatch in WPA IE between EAPOL-Key 2/4 " "and (Re)Association Request from " MACSTR, @@ -303,17 +326,6 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, "Request", sta->rsnie, sta->rsnie[0] ? 2 + sta->rsnie[1] : 0); - /* - * The sniffer may have missed (Re)Association - * Request, so try to survive with the information from - * EAPOL-Key. - */ - os_memset(&elems, 0, sizeof(elems)); - elems.wpa_ie = ie.wpa_ie + 2; - elems.wpa_ie_len = ie.wpa_ie_len - 2; - wpa_printf(MSG_DEBUG, "Update STA data based on WPA " - "IE in EAPOL-Key 2/4"); - sta_update_assoc(sta, &elems); } } @@ -321,7 +333,6 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - RSN IE", ie.rsn_ie, ie.rsn_ie_len); if (os_memcmp(ie.rsn_ie, sta->rsnie, ie.rsn_ie_len) != 0) { - struct ieee802_11_elems elems; add_note(wt, MSG_INFO, "Mismatch in RSN IE between EAPOL-Key 2/4 " "and (Re)Association Request from " MACSTR, @@ -332,17 +343,6 @@ static void rx_data_eapol_key_2_of_4(struct wlantest *wt, const u8 *dst, "Request", sta->rsnie, sta->rsnie[0] ? 2 + sta->rsnie[1] : 0); - /* - * The sniffer may have missed (Re)Association - * Request, so try to survive with the information from - * EAPOL-Key. - */ - os_memset(&elems, 0, sizeof(elems)); - elems.rsn_ie = ie.rsn_ie + 2; - elems.rsn_ie_len = ie.rsn_ie_len - 2; - wpa_printf(MSG_DEBUG, "Update STA data based on RSN " - "IE in EAPOL-Key 2/4"); - sta_update_assoc(sta, &elems); } } } @@ -460,6 +460,9 @@ static void learn_kde_keys(struct wlantest *wt, struct wlantest_bss *bss, ie.rsn_ie, ie.rsn_ie_len); } + if (ie.key_id) + add_note(wt, MSG_DEBUG, "KeyID %u", ie.key_id[0]); + if (ie.gtk) { wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - GTK KDE", ie.gtk, ie.gtk_len); @@ -548,6 +551,65 @@ static void learn_kde_keys(struct wlantest *wt, struct wlantest_bss *bss, (unsigned) ie.igtk_len); } } + + if (ie.bigtk) { + wpa_hexdump(MSG_MSGDUMP, "EAPOL-Key Key Data - BIGTK KDE", + ie.bigtk, ie.bigtk_len); + if (ie.bigtk_len == 24) { + u16 id; + + id = WPA_GET_LE16(ie.bigtk); + if (id < 6 || id > 7) { + add_note(wt, MSG_INFO, + "Unexpected BIGTK KeyID %u", id); + } else { + const u8 *ipn; + + add_note(wt, MSG_DEBUG, "BIGTK KeyID %u", id); + wpa_hexdump(MSG_DEBUG, "BIPN", ie.bigtk + 2, 6); + wpa_hexdump(MSG_DEBUG, "BIGTK", ie.bigtk + 8, + 16); + os_memcpy(bss->igtk[id], ie.bigtk + 8, 16); + bss->igtk_len[id] = 16; + ipn = ie.bigtk + 2; + bss->ipn[id][0] = ipn[5]; + bss->ipn[id][1] = ipn[4]; + bss->ipn[id][2] = ipn[3]; + bss->ipn[id][3] = ipn[2]; + bss->ipn[id][4] = ipn[1]; + bss->ipn[id][5] = ipn[0]; + bss->bigtk_idx = id; + } + } else if (ie.bigtk_len == 40) { + u16 id; + + id = WPA_GET_LE16(ie.bigtk); + if (id < 6 || id > 7) { + add_note(wt, MSG_INFO, + "Unexpected BIGTK KeyID %u", id); + } else { + const u8 *ipn; + + add_note(wt, MSG_DEBUG, "BIGTK KeyID %u", id); + wpa_hexdump(MSG_DEBUG, "BIPN", ie.bigtk + 2, 6); + wpa_hexdump(MSG_DEBUG, "BIGTK", ie.bigtk + 8, + 32); + os_memcpy(bss->igtk[id], ie.bigtk + 8, 32); + bss->igtk_len[id] = 32; + ipn = ie.bigtk + 2; + bss->ipn[id][0] = ipn[5]; + bss->ipn[id][1] = ipn[4]; + bss->ipn[id][2] = ipn[3]; + bss->ipn[id][3] = ipn[2]; + bss->ipn[id][4] = ipn[1]; + bss->ipn[id][5] = ipn[0]; + bss->bigtk_idx = id; + } + } else { + add_note(wt, MSG_INFO, "Invalid BIGTK KDE length %u", + (unsigned) ie.bigtk_len); + } + } } @@ -566,6 +628,7 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, const u8 *decrypted; size_t decrypted_len = 0; struct wpa_eapol_ie_parse ie; + struct wpa_ie_data rsn; wpa_printf(MSG_DEBUG, "EAPOL-Key 3/4 " MACSTR " -> " MACSTR, MAC2STR(src), MAC2STR(dst)); @@ -659,10 +722,9 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, } p += 2 + p[1]; } - if (p && p > decrypted && *p == 0xdd && - p + 1 == decrypted + decrypted_len) { + if (p && p > decrypted && p + 1 == decrypted + decrypted_len && + *p == 0xdd) { /* Remove padding */ - p--; plain_len = p - decrypted; } @@ -694,6 +756,15 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, return; } + if (!bss->ies_set) { + struct ieee802_11_elems elems; + + elems_from_eapol_ie(&elems, &ie); + wpa_printf(MSG_DEBUG, + "Update BSS data based on IEs in EAPOL-Key 3/4"); + bss_update(wt, bss, &elems, 0); + } + if ((ie.wpa_ie && os_memcmp(ie.wpa_ie, bss->wpaie, ie.wpa_ie_len) != 0) || (ie.wpa_ie == NULL && bss->wpaie[0])) { @@ -710,7 +781,9 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, } if ((ie.rsn_ie && - os_memcmp(ie.rsn_ie, bss->rsnie, ie.rsn_ie_len) != 0) || + wpa_compare_rsn_ie(wpa_key_mgmt_ft(sta->key_mgmt), + ie.rsn_ie, ie.rsn_ie_len, + bss->rsnie, 2 + bss->rsnie[1])) || (ie.rsn_ie == NULL && bss->rsnie[0])) { add_note(wt, MSG_INFO, "Mismatch in RSN IE between EAPOL-Key " "3/4 and Beacon/Probe Response from " MACSTR, @@ -722,6 +795,16 @@ static void rx_data_eapol_key_3_of_4(struct wlantest *wt, const u8 *dst, bss->rsnie[0] ? 2 + bss->rsnie[1] : 0); } + if (wpa_key_mgmt_ft(sta->key_mgmt) && + (wpa_parse_wpa_ie_rsn(ie.rsn_ie, ie.rsn_ie_len, &rsn) < 0 || + rsn.num_pmkid != 1 || !rsn.pmkid || + os_memcmp_const(rsn.pmkid, sta->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0)) + add_note(wt, MSG_INFO, + "FT: No matching PMKR1Name in FT 4-way handshake message 3/4"); + + /* TODO: validate MDE and FTE match */ + learn_kde_keys(wt, bss, sta, decrypted, decrypted_len, hdr->key_rsc); os_free(decrypted_buf); } diff --git a/wlantest/rx_ip.c b/wlantest/rx_ip.c index 0e833ec6c..fdf80b7d7 100644 --- a/wlantest/rx_ip.c +++ b/wlantest/rx_ip.c @@ -14,6 +14,8 @@ #include "wlantest.h" +#ifndef __APPLE__ + static void ping_update(struct wlantest *wt, struct wlantest_sta *sta, int req, u32 src, u32 dst, u16 id, u16 seq) { @@ -95,6 +97,8 @@ static void rx_data_icmp(struct wlantest *wt, const u8 *bssid, ping_update(wt, sta, hdr->type == ICMP_ECHO, src, dst, id, seq); } +#endif /* __APPLE__ */ + static int hwsim_test_packet(const u8 *data, size_t len) { @@ -169,9 +173,11 @@ void rx_data_ip(struct wlantest *wt, const u8 *bssid, const u8 *sta_addr, plen = len - 4 * ip->ip_hl; switch (ip->ip_p) { +#ifndef __APPLE__ case IPPROTO_ICMP: rx_data_icmp(wt, bssid, sta_addr, ip->ip_dst.s_addr, ip->ip_src.s_addr, payload, plen, peer_addr); break; +#endif /* __APPLE__ */ } } diff --git a/wlantest/rx_mgmt.c b/wlantest/rx_mgmt.c index 39b23b27c..0bc7eb2b2 100644 --- a/wlantest/rx_mgmt.c +++ b/wlantest/rx_mgmt.c @@ -1,6 +1,6 @@ /* * Received Management frame processing - * Copyright (c) 2010-2015, Jouni Malinen + * Copyright (c) 2010-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -19,6 +19,11 @@ #include "wlantest.h" +static int check_mmie_mic(unsigned int mgmt_group_cipher, + const u8 *igtk, size_t igtk_len, + const u8 *data, size_t len); + + static const char * mgmt_stype(u16 stype) { switch (stype) { @@ -57,6 +62,9 @@ static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len) struct wlantest_bss *bss; struct ieee802_11_elems elems; size_t offset; + const u8 *mme; + size_t mic_len; + u16 keyid; mgmt = (const struct ieee80211_mgmt *) data; offset = mgmt->u.beacon.variable - data; @@ -78,7 +86,63 @@ static void rx_mgmt_beacon(struct wlantest *wt, const u8 *data, size_t len) return; } - bss_update(wt, bss, &elems); + bss_update(wt, bss, &elems, 1); + + mme = get_ie(mgmt->u.beacon.variable, len - offset, WLAN_EID_MMIE); + if (!mme) { + if (bss->bigtk_idx) { + add_note(wt, MSG_INFO, + "Unexpected unprotected Beacon frame from " + MACSTR, MAC2STR(mgmt->sa)); + bss->counters[WLANTEST_BSS_COUNTER_MISSING_BIP_MMIE]++; + } + return; + } + + mic_len = bss->mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC ? 8 : 16; + if (len < 24 + 10 + mic_len || + data[len - (10 + mic_len)] != WLAN_EID_MMIE || + data[len - (10 + mic_len - 1)] != 8 + mic_len) { + add_note(wt, MSG_INFO, "Invalid MME in a Beacon frame from " + MACSTR, MAC2STR(mgmt->sa)); + return; + } + + mme += 2; + keyid = WPA_GET_LE16(mme); + if (keyid < 6 || keyid > 7) { + add_note(wt, MSG_INFO, "Unexpected MME KeyID %u from " MACSTR, + keyid, MAC2STR(mgmt->sa)); + bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++; + return; + } + + wpa_printf(MSG_DEBUG, "Beacon frame MME KeyID %u", keyid); + wpa_hexdump(MSG_MSGDUMP, "MME IPN", mme + 2, 6); + wpa_hexdump(MSG_MSGDUMP, "MME MIC", mme + 8, mic_len); + + if (!bss->igtk_len[keyid]) { + add_note(wt, MSG_DEBUG, "No BIGTK known to validate BIP frame"); + return; + } + + if (os_memcmp(mme + 2, bss->ipn[keyid], 6) <= 0) { + add_note(wt, MSG_INFO, "BIP replay detected: SA=" MACSTR, + MAC2STR(mgmt->sa)); + wpa_hexdump(MSG_INFO, "RX IPN", mme + 2, 6); + wpa_hexdump(MSG_INFO, "Last RX IPN", bss->ipn[keyid], 6); + } + + if (check_mmie_mic(bss->mgmt_group_cipher, bss->igtk[keyid], + bss->igtk_len[keyid], data, len) < 0) { + add_note(wt, MSG_INFO, "Invalid MME MIC in a Beacon frame from " + MACSTR, MAC2STR(mgmt->sa)); + bss->counters[WLANTEST_BSS_COUNTER_INVALID_BIP_MMIE]++; + return; + } + + add_note(wt, MSG_DEBUG, "Valid MME MIC in Beacon frame"); + os_memcpy(bss->ipn[keyid], mme + 2, 6); } @@ -109,7 +173,7 @@ static void rx_mgmt_probe_resp(struct wlantest *wt, const u8 *data, size_t len) return; } - bss_update(wt, bss, &elems); + bss_update(wt, bss, &elems, 2); } @@ -168,8 +232,6 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss, { u16 trans; struct wpa_ft_ies parse; - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; struct wpa_ptk ptk; u8 ptk_name[WPA_PMK_NAME_LEN]; struct wlantest_bss *old_bss; @@ -210,22 +272,24 @@ static void process_ft_auth(struct wlantest *wt, struct wlantest_bss *bss, if (!old_sta) return; - os_memcpy(sta->pmk_r0, old_sta->pmk_r0, sizeof(sta->pmk_r0)); + os_memcpy(sta->pmk_r0, old_sta->pmk_r0, old_sta->pmk_r0_len); + sta->pmk_r0_len = old_sta->pmk_r0_len; os_memcpy(sta->pmk_r0_name, old_sta->pmk_r0_name, sizeof(sta->pmk_r0_name)); if (parse.r1kh_id) os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); - if (wpa_derive_pmk_r1(sta->pmk_r0, PMK_LEN, sta->pmk_r0_name, - bss->r1kh_id, sta->addr, pmk_r1, pmk_r1_name) < 0) + if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, sta->pmk_r0_name, + bss->r1kh_id, sta->addr, sta->pmk_r1, + sta->pmk_r1_name) < 0) return; - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); + sta->pmk_r1_len = sta->pmk_r0_len; if (!parse.fte_anonce || !parse.fte_snonce || - wpa_pmk_r1_to_ptk(pmk_r1, PMK_LEN, parse.fte_snonce, + wpa_pmk_r1_to_ptk(sta->pmk_r1, sta->pmk_r1_len, parse.fte_snonce, parse.fte_anonce, sta->addr, bss->bssid, - pmk_r1_name, &ptk, ptk_name, sta->key_mgmt, + sta->pmk_r1_name, &ptk, ptk_name, sta->key_mgmt, sta->pairwise_cipher) < 0) return; @@ -576,6 +640,7 @@ static void rx_mgmt_assoc_req(struct wlantest *wt, const u8 *data, size_t len) os_memcpy(sta->assocreq_ies, mgmt->u.assoc_req.variable, sta->assocreq_ies_len); + sta->assocreq_seen = 1; sta_update_assoc(sta, &elems); } @@ -811,9 +876,404 @@ static void rx_mgmt_reassoc_req(struct wlantest *wt, const u8 *data, os_memcpy(sta->assocreq_ies, mgmt->u.reassoc_req.variable, sta->assocreq_ies_len); + sta->assocreq_seen = 1; sta_update_assoc(sta, &elems); - /* TODO: FT protocol: verify FTE MIC and update GTK/IGTK for the BSS */ + if (elems.ftie) { + struct wpa_ft_ies parse; + int use_sha384; + struct rsn_mdie *mde; + const u8 *anonce, *snonce, *fte_mic; + u8 fte_elem_count; + unsigned int count; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + size_t mic_len = 16; + const u8 *kck; + size_t kck_len; + + use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt); + + if (wpa_ft_parse_ies(ie, ie_len, &parse, use_sha384) < 0) { + add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs"); + return; + } + + if (!parse.rsn) { + add_note(wt, MSG_INFO, "FT: No RSNE in Reassoc Req"); + return; + } + + if (!parse.rsn_pmkid) { + add_note(wt, MSG_INFO, "FT: No PMKID in RSNE"); + return; + } + + if (os_memcmp_const(parse.rsn_pmkid, sta->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0) { + add_note(wt, MSG_INFO, + "FT: PMKID in Reassoc Req did not match PMKR1Name"); + wpa_hexdump(MSG_DEBUG, + "FT: Received RSNE[PMKR1Name]", + parse.rsn_pmkid, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, + "FT: Previously derived PMKR1Name", + sta->pmk_r1_name, WPA_PMK_NAME_LEN); + return; + } + + mde = (struct rsn_mdie *) parse.mdie; + if (!mde || parse.mdie_len < sizeof(*mde) || + os_memcmp(mde->mobility_domain, bss->mdid, + MOBILITY_DOMAIN_ID_LEN) != 0) { + add_note(wt, MSG_INFO, "FT: Invalid MDE"); + } + + if (use_sha384) { + struct rsn_ftie_sha384 *fte; + + fte = (struct rsn_ftie_sha384 *) parse.ftie; + if (!fte || parse.ftie_len < sizeof(*fte)) { + add_note(wt, MSG_INFO, "FT: Invalid FTE"); + return; + } + + anonce = fte->anonce; + snonce = fte->snonce; + fte_elem_count = fte->mic_control[1]; + fte_mic = fte->mic; + } else { + struct rsn_ftie *fte; + + fte = (struct rsn_ftie *) parse.ftie; + if (!fte || parse.ftie_len < sizeof(*fte)) { + add_note(wt, MSG_INFO, "FT: Invalid FTIE"); + return; + } + + anonce = fte->anonce; + snonce = fte->snonce; + fte_elem_count = fte->mic_control[1]; + fte_mic = fte->mic; + } + + if (os_memcmp(snonce, sta->snonce, WPA_NONCE_LEN) != 0) { + add_note(wt, MSG_INFO, "FT: SNonce mismatch in FTIE"); + wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", + snonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", + sta->snonce, WPA_NONCE_LEN); + return; + } + + if (os_memcmp(anonce, sta->anonce, WPA_NONCE_LEN) != 0) { + add_note(wt, MSG_INFO, "FT: ANonce mismatch in FTIE"); + wpa_hexdump(MSG_DEBUG, "FT: Received ANonce", + anonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", + sta->anonce, WPA_NONCE_LEN); + return; + } + + if (!parse.r0kh_id) { + add_note(wt, MSG_INFO, "FT: No R0KH-ID subelem in FTE"); + return; + } + os_memcpy(bss->r0kh_id, parse.r0kh_id, parse.r0kh_id_len); + bss->r0kh_id_len = parse.r0kh_id_len; + + if (!parse.r1kh_id) { + add_note(wt, MSG_INFO, "FT: No R1KH-ID subelem in FTE"); + return; + } + + os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); + + if (!parse.rsn_pmkid || + os_memcmp_const(parse.rsn_pmkid, sta->pmk_r1_name, + WPA_PMK_NAME_LEN)) { + add_note(wt, MSG_INFO, + "FT: No matching PMKR1Name (PMKID) in RSNE (pmkid=%d)", + !!parse.rsn_pmkid); + return; + } + + count = 3; + if (parse.ric) + count += ieee802_11_ie_count(parse.ric, parse.ric_len); + if (parse.rsnxe) + count++; + if (fte_elem_count != count) { + add_note(wt, MSG_INFO, + "FT: Unexpected IE count in MIC Control: received %u expected %u", + fte_elem_count, count); + return; + } + + if (wpa_key_mgmt_fils(sta->key_mgmt)) { + kck = sta->ptk.kck2; + kck_len = sta->ptk.kck2_len; + } else { + kck = sta->ptk.kck; + kck_len = sta->ptk.kck_len; + } + if (wpa_ft_mic(kck, kck_len, sta->addr, bss->bssid, 5, + parse.mdie - 2, parse.mdie_len + 2, + parse.ftie - 2, parse.ftie_len + 2, + parse.rsn - 2, parse.rsn_len + 2, + parse.ric, parse.ric_len, + parse.rsnxe ? parse.rsnxe - 2 : NULL, + parse.rsnxe ? parse.rsnxe_len + 2 : 0, + mic) < 0) { + add_note(wt, MSG_INFO, "FT: Failed to calculate MIC"); + return; + } + + if (os_memcmp_const(mic, fte_mic, mic_len) != 0) { + add_note(wt, MSG_INFO, "FT: Invalid MIC in FTE"); + wpa_printf(MSG_DEBUG, + "FT: addr=" MACSTR " auth_addr=" MACSTR, + MAC2STR(sta->addr), + MAC2STR(bss->bssid)); + wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", + fte_mic, mic_len); + wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", + mic, mic_len); + wpa_hexdump(MSG_MSGDUMP, "FT: MDE", + parse.mdie - 2, parse.mdie_len + 2); + wpa_hexdump(MSG_MSGDUMP, "FT: FTE", + parse.ftie - 2, parse.ftie_len + 2); + wpa_hexdump(MSG_MSGDUMP, "FT: RSN", + parse.rsn - 2, parse.rsn_len + 2); + wpa_hexdump(MSG_MSGDUMP, "FT: RSNXE", + parse.rsnxe ? parse.rsnxe - 2 : NULL, + parse.rsnxe ? parse.rsnxe_len + 2 : 0); + return; + } + + add_note(wt, MSG_INFO, "FT: Valid FTE MIC"); + } +} + + +static void process_gtk_subelem(struct wlantest *wt, struct wlantest_bss *bss, + struct wlantest_sta *sta, + const u8 *kek, size_t kek_len, + const u8 *gtk_elem, + size_t gtk_elem_len) +{ + u8 gtk[32]; + int keyidx; + enum wpa_alg alg; + size_t gtk_len, keylen; + const u8 *rsc; + + if (!gtk_elem) { + add_note(wt, MSG_INFO, "FT: No GTK included in FTE"); + return; + } + + wpa_hexdump(MSG_DEBUG, "FT: Received GTK in Reassoc Resp", + gtk_elem, gtk_elem_len); + + if (gtk_elem_len < 11 + 24 || (gtk_elem_len - 11) % 8 || + gtk_elem_len - 19 > sizeof(gtk)) { + add_note(wt, MSG_INFO, "FT: Invalid GTK sub-elem length %zu", + gtk_elem_len); + return; + } + gtk_len = gtk_elem_len - 19; + if (aes_unwrap(kek, kek_len, gtk_len / 8, gtk_elem + 11, gtk)) { + add_note(wt, MSG_INFO, + "FT: AES unwrap failed - could not decrypt GTK"); + return; + } + + keylen = wpa_cipher_key_len(bss->group_cipher); + alg = wpa_cipher_to_alg(bss->group_cipher); + if (alg == WPA_ALG_NONE) { + add_note(wt, MSG_INFO, "FT: Unsupported Group Cipher %d", + bss->group_cipher); + return; + } + + if (gtk_len < keylen) { + add_note(wt, MSG_INFO, "FT: Too short GTK in FTE"); + return; + } + + /* Key Info[2] | Key Length[1] | RSC[8] | Key[5..32]. */ + + keyidx = WPA_GET_LE16(gtk_elem) & 0x03; + + if (gtk_elem[2] != keylen) { + add_note(wt, MSG_INFO, + "FT: GTK length mismatch: received %u negotiated %zu", + gtk_elem[2], keylen); + return; + } + + add_note(wt, MSG_DEBUG, "GTK KeyID=%u", keyidx); + wpa_hexdump(MSG_DEBUG, "FT: GTK from Reassoc Resp", gtk, keylen); + if (bss->group_cipher == WPA_CIPHER_TKIP) { + /* Swap Tx/Rx keys for Michael MIC */ + u8 tmp[8]; + + os_memcpy(tmp, gtk + 16, 8); + os_memcpy(gtk + 16, gtk + 24, 8); + os_memcpy(gtk + 24, tmp, 8); + } + + bss->gtk_len[keyidx] = gtk_len; + sta->gtk_len = gtk_len; + os_memcpy(bss->gtk[keyidx], gtk, gtk_len); + os_memcpy(sta->gtk, gtk, gtk_len); + rsc = gtk_elem + 2; + bss->rsc[keyidx][0] = rsc[5]; + bss->rsc[keyidx][1] = rsc[4]; + bss->rsc[keyidx][2] = rsc[3]; + bss->rsc[keyidx][3] = rsc[2]; + bss->rsc[keyidx][4] = rsc[1]; + bss->rsc[keyidx][5] = rsc[0]; + bss->gtk_idx = keyidx; + sta->gtk_idx = keyidx; + wpa_hexdump(MSG_DEBUG, "RSC", bss->rsc[keyidx], 6); +} + + +static void process_igtk_subelem(struct wlantest *wt, struct wlantest_bss *bss, + struct wlantest_sta *sta, + const u8 *kek, size_t kek_len, + const u8 *igtk_elem, size_t igtk_elem_len) +{ + u8 igtk[WPA_IGTK_MAX_LEN]; + size_t igtk_len; + u16 keyidx; + const u8 *ipn; + + if (bss->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC && + bss->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_128 && + bss->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256 && + bss->mgmt_group_cipher != WPA_CIPHER_BIP_CMAC_256) + return; + + if (!igtk_elem) { + add_note(wt, MSG_INFO, "FT: No IGTK included in FTE"); + return; + } + + wpa_hexdump(MSG_DEBUG, "FT: Received IGTK in Reassoc Resp", + igtk_elem, igtk_elem_len); + + igtk_len = wpa_cipher_key_len(bss->mgmt_group_cipher); + if (igtk_elem_len != 2 + 6 + 1 + igtk_len + 8) { + add_note(wt, MSG_INFO, "FT: Invalid IGTK sub-elem length %zu", + igtk_elem_len); + return; + } + if (igtk_elem[8] != igtk_len) { + add_note(wt, MSG_INFO, + "FT: Invalid IGTK sub-elem Key Length %d", + igtk_elem[8]); + return; + } + + if (aes_unwrap(kek, kek_len, igtk_len / 8, igtk_elem + 9, igtk)) { + add_note(wt, MSG_INFO, + "FT: AES unwrap failed - could not decrypt IGTK"); + return; + } + + /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */ + + keyidx = WPA_GET_LE16(igtk_elem); + + wpa_hexdump(MSG_DEBUG, "FT: IGTK from Reassoc Resp", igtk, igtk_len); + + if (keyidx < 4 || keyidx > 5) { + add_note(wt, MSG_INFO, "Unexpected IGTK KeyID %u", keyidx); + return; + } + + add_note(wt, MSG_DEBUG, "IGTK KeyID %u", keyidx); + wpa_hexdump(MSG_DEBUG, "IPN", igtk_elem + 2, 6); + wpa_hexdump(MSG_DEBUG, "IGTK", igtk, igtk_len); + os_memcpy(bss->igtk[keyidx], igtk, igtk_len); + bss->igtk_len[keyidx] = igtk_len; + ipn = igtk_elem + 2; + bss->ipn[keyidx][0] = ipn[5]; + bss->ipn[keyidx][1] = ipn[4]; + bss->ipn[keyidx][2] = ipn[3]; + bss->ipn[keyidx][3] = ipn[2]; + bss->ipn[keyidx][4] = ipn[1]; + bss->ipn[keyidx][5] = ipn[0]; + bss->igtk_idx = keyidx; +} + + +static void process_bigtk_subelem(struct wlantest *wt, struct wlantest_bss *bss, + struct wlantest_sta *sta, + const u8 *kek, size_t kek_len, + const u8 *bigtk_elem, size_t bigtk_elem_len) +{ + u8 bigtk[WPA_BIGTK_MAX_LEN]; + size_t bigtk_len; + u16 keyidx; + const u8 *ipn; + + if (!bigtk_elem || + (bss->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC && + bss->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_128 && + bss->mgmt_group_cipher != WPA_CIPHER_BIP_GMAC_256 && + bss->mgmt_group_cipher != WPA_CIPHER_BIP_CMAC_256)) + return; + + wpa_hexdump_key(MSG_DEBUG, "FT: Received BIGTK in Reassoc Resp", + bigtk_elem, bigtk_elem_len); + + bigtk_len = wpa_cipher_key_len(bss->mgmt_group_cipher); + if (bigtk_elem_len != 2 + 6 + 1 + bigtk_len + 8) { + add_note(wt, MSG_INFO, + "FT: Invalid BIGTK sub-elem length %zu", + bigtk_elem_len); + return; + } + if (bigtk_elem[8] != bigtk_len) { + add_note(wt, MSG_INFO, + "FT: Invalid BIGTK sub-elem Key Length %d", + bigtk_elem[8]); + return; + } + + if (aes_unwrap(kek, kek_len, bigtk_len / 8, bigtk_elem + 9, bigtk)) { + add_note(wt, MSG_INFO, + "FT: AES unwrap failed - could not decrypt BIGTK"); + return; + } + + /* KeyID[2] | IPN[6] | Key Length[1] | Key[16+8] */ + + keyidx = WPA_GET_LE16(bigtk_elem); + + wpa_hexdump(MSG_DEBUG, "FT: BIGTK from Reassoc Resp", bigtk, bigtk_len); + + if (keyidx < 6 || keyidx > 7) { + add_note(wt, MSG_INFO, "Unexpected BIGTK KeyID %u", keyidx); + return; + } + + add_note(wt, MSG_DEBUG, "BIGTK KeyID %u", keyidx); + wpa_hexdump(MSG_DEBUG, "BIPN", bigtk_elem + 2, 6); + wpa_hexdump(MSG_DEBUG, "BIGTK", bigtk, bigtk_len); + os_memcpy(bss->igtk[keyidx], bigtk, bigtk_len); + bss->igtk_len[keyidx] = bigtk_len; + ipn = bigtk_elem + 2; + bss->ipn[keyidx][0] = ipn[5]; + bss->ipn[keyidx][1] = ipn[4]; + bss->ipn[keyidx][2] = ipn[3]; + bss->ipn[keyidx][3] = ipn[2]; + bss->ipn[keyidx][4] = ipn[1]; + bss->ipn[keyidx][5] = ipn[0]; + bss->bigtk_idx = keyidx; } @@ -826,6 +1286,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, u16 capab, status, aid; const u8 *ies; size_t ies_len; + struct ieee802_11_elems elems; mgmt = (const struct ieee80211_mgmt *) data; bss = bss_get(wt, mgmt->bssid); @@ -868,17 +1329,15 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, } } - if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) { - struct ieee802_11_elems elems; + if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == ParseFailed) { + add_note(wt, MSG_INFO, + "Failed to parse IEs in ReassocResp from " MACSTR, + MAC2STR(mgmt->sa)); + } - if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) == - ParseFailed) { - add_note(wt, MSG_INFO, "Failed to parse IEs in " - "ReassocResp from " MACSTR, - MAC2STR(mgmt->sa)); - } else if (elems.timeout_int == NULL || - elems.timeout_int[0] != - WLAN_TIMEOUT_ASSOC_COMEBACK) { + if (status == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) { + if (!elems.timeout_int || + elems.timeout_int[0] != WLAN_TIMEOUT_ASSOC_COMEBACK) { add_note(wt, MSG_INFO, "No valid Timeout Interval IE " "with Assoc Comeback time in ReassocResp " "(status=30) from " MACSTR, @@ -899,7 +1358,7 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, } sta->aid = aid & 0xc000; - if (sta->state < STATE2) { + if (sta->state < STATE2 && !sta->ft_over_ds) { add_note(wt, MSG_DEBUG, "STA " MACSTR " was not in State 2 when " "getting associated", MAC2STR(sta->addr)); @@ -911,6 +1370,212 @@ static void rx_mgmt_reassoc_resp(struct wlantest *wt, const u8 *data, MAC2STR(sta->addr), MAC2STR(bss->bssid)); sta->state = STATE3; } + + if (elems.ftie) { + struct wpa_ft_ies parse; + int use_sha384; + struct rsn_mdie *mde; + const u8 *anonce, *snonce, *fte_mic; + u8 fte_elem_count; + unsigned int count; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + size_t mic_len = 16; + const u8 *kck, *kek; + size_t kck_len, kek_len; + + use_sha384 = wpa_key_mgmt_sha384(sta->key_mgmt); + + if (wpa_ft_parse_ies(ies, ies_len, &parse, use_sha384) < 0) { + add_note(wt, MSG_INFO, "FT: Failed to parse FT IEs"); + return; + } + + if (!parse.rsn) { + add_note(wt, MSG_INFO, "FT: No RSNE in Reassoc Resp"); + return; + } + + if (!parse.rsn_pmkid) { + add_note(wt, MSG_INFO, "FT: No PMKID in RSNE"); + return; + } + + if (os_memcmp_const(parse.rsn_pmkid, sta->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0) { + add_note(wt, MSG_INFO, + "FT: PMKID in Reassoc Resp did not match PMKR1Name"); + wpa_hexdump(MSG_DEBUG, + "FT: Received RSNE[PMKR1Name]", + parse.rsn_pmkid, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, + "FT: Previously derived PMKR1Name", + sta->pmk_r1_name, WPA_PMK_NAME_LEN); + return; + } + + mde = (struct rsn_mdie *) parse.mdie; + if (!mde || parse.mdie_len < sizeof(*mde) || + os_memcmp(mde->mobility_domain, bss->mdid, + MOBILITY_DOMAIN_ID_LEN) != 0) { + add_note(wt, MSG_INFO, "FT: Invalid MDE"); + } + + if (use_sha384) { + struct rsn_ftie_sha384 *fte; + + fte = (struct rsn_ftie_sha384 *) parse.ftie; + if (!fte || parse.ftie_len < sizeof(*fte)) { + add_note(wt, MSG_INFO, "FT: Invalid FTE"); + return; + } + + anonce = fte->anonce; + snonce = fte->snonce; + fte_elem_count = fte->mic_control[1]; + fte_mic = fte->mic; + } else { + struct rsn_ftie *fte; + + fte = (struct rsn_ftie *) parse.ftie; + if (!fte || parse.ftie_len < sizeof(*fte)) { + add_note(wt, MSG_INFO, "FT: Invalid FTIE"); + return; + } + + anonce = fte->anonce; + snonce = fte->snonce; + fte_elem_count = fte->mic_control[1]; + fte_mic = fte->mic; + } + + if (os_memcmp(snonce, sta->snonce, WPA_NONCE_LEN) != 0) { + add_note(wt, MSG_INFO, "FT: SNonce mismatch in FTIE"); + wpa_hexdump(MSG_DEBUG, "FT: Received SNonce", + snonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce", + sta->snonce, WPA_NONCE_LEN); + return; + } + + if (os_memcmp(anonce, sta->anonce, WPA_NONCE_LEN) != 0) { + add_note(wt, MSG_INFO, "FT: ANonce mismatch in FTIE"); + wpa_hexdump(MSG_DEBUG, "FT: Received ANonce", + anonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce", + sta->anonce, WPA_NONCE_LEN); + return; + } + + if (!parse.r0kh_id) { + add_note(wt, MSG_INFO, "FT: No R0KH-ID subelem in FTE"); + return; + } + + if (parse.r0kh_id_len != bss->r0kh_id_len || + os_memcmp_const(parse.r0kh_id, bss->r0kh_id, + parse.r0kh_id_len) != 0) { + add_note(wt, MSG_INFO, + "FT: R0KH-ID in FTE did not match the current R0KH-ID"); + wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE", + parse.r0kh_id, parse.r0kh_id_len); + wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID", + bss->r0kh_id, bss->r0kh_id_len); + os_memcpy(bss->r0kh_id, parse.r0kh_id, + parse.r0kh_id_len); + bss->r0kh_id_len = parse.r0kh_id_len; + } + + if (!parse.r1kh_id) { + add_note(wt, MSG_INFO, "FT: No R1KH-ID subelem in FTE"); + return; + } + + if (os_memcmp_const(parse.r1kh_id, bss->r1kh_id, + FT_R1KH_ID_LEN) != 0) { + add_note(wt, MSG_INFO, + "FT: Unknown R1KH-ID used in ReassocResp"); + os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); + } + + count = 3; + if (parse.ric) + count += ieee802_11_ie_count(parse.ric, parse.ric_len); + if (parse.rsnxe) + count++; + if (fte_elem_count != count) { + add_note(wt, MSG_INFO, + "FT: Unexpected IE count in MIC Control: received %u expected %u", + fte_elem_count, count); + return; + } + + if (wpa_key_mgmt_fils(sta->key_mgmt)) { + kck = sta->ptk.kck2; + kck_len = sta->ptk.kck2_len; + kek = sta->ptk.kek2; + kek_len = sta->ptk.kek2_len; + } else { + kck = sta->ptk.kck; + kck_len = sta->ptk.kck_len; + kek = sta->ptk.kek; + kek_len = sta->ptk.kek_len; + } + if (wpa_ft_mic(kck, kck_len, sta->addr, bss->bssid, 6, + parse.mdie - 2, parse.mdie_len + 2, + parse.ftie - 2, parse.ftie_len + 2, + parse.rsn - 2, parse.rsn_len + 2, + parse.ric, parse.ric_len, + parse.rsnxe ? parse.rsnxe - 2 : NULL, + parse.rsnxe ? parse.rsnxe_len + 2 : 0, + mic) < 0) { + add_note(wt, MSG_INFO, "FT: Failed to calculate MIC"); + return; + } + + if (os_memcmp_const(mic, fte_mic, mic_len) != 0) { + add_note(wt, MSG_INFO, "FT: Invalid MIC in FTE"); + wpa_printf(MSG_DEBUG, + "FT: addr=" MACSTR " auth_addr=" MACSTR, + MAC2STR(sta->addr), + MAC2STR(bss->bssid)); + wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC", + fte_mic, mic_len); + wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", + mic, mic_len); + wpa_hexdump(MSG_MSGDUMP, "FT: MDE", + parse.mdie - 2, parse.mdie_len + 2); + wpa_hexdump(MSG_MSGDUMP, "FT: FTE", + parse.ftie - 2, parse.ftie_len + 2); + wpa_hexdump(MSG_MSGDUMP, "FT: RSN", + parse.rsn - 2, parse.rsn_len + 2); + wpa_hexdump(MSG_MSGDUMP, "FT: RSNXE", + parse.rsnxe ? parse.rsnxe - 2 : NULL, + parse.rsnxe ? parse.rsnxe_len + 2 : 0); + return; + } + + add_note(wt, MSG_INFO, "FT: Valid FTE MIC"); + + if (wpa_compare_rsn_ie(wpa_key_mgmt_ft(sta->key_mgmt), + bss->rsnie, 2 + bss->rsnie[1], + parse.rsn - 2, parse.rsn_len + 2)) { + add_note(wt, MSG_INFO, + "FT: RSNE mismatch between Beacon/ProbeResp and FT protocol Reassociation Response frame"); + wpa_hexdump(MSG_INFO, "RSNE in Beacon/ProbeResp", + &bss->rsnie[2], bss->rsnie[1]); + wpa_hexdump(MSG_INFO, + "RSNE in FT protocol Reassociation Response frame", + parse.rsn ? parse.rsn - 2 : NULL, + parse.rsn ? parse.rsn_len + 2 : 0); + } + + process_gtk_subelem(wt, bss, sta, kek, kek_len, + parse.gtk, parse.gtk_len); + process_igtk_subelem(wt, bss, sta, kek, kek_len, + parse.igtk, parse.igtk_len); + process_bigtk_subelem(wt, bss, sta, kek, kek_len, + parse.bigtk, parse.bigtk_len); + } } @@ -1044,6 +1709,7 @@ static void rx_mgmt_action_ft_request(struct wlantest *wt, if (!sta) return; + sta->ft_over_ds = true; sta->key_mgmt = parse.key_mgmt; sta->pairwise_cipher = parse.pairwise_cipher; } @@ -1059,8 +1725,6 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, const u8 *ies; size_t ies_len; struct wpa_ft_ies parse; - u8 pmk_r1[PMK_LEN]; - u8 pmk_r1_name[WPA_PMK_NAME_LEN]; struct wpa_ptk ptk; u8 ptk_name[WPA_PMK_NAME_LEN]; @@ -1094,22 +1758,28 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, if (parse.r1kh_id) os_memcpy(bss->r1kh_id, parse.r1kh_id, FT_R1KH_ID_LEN); - if (wpa_derive_pmk_r1(sta->pmk_r0, PMK_LEN, sta->pmk_r0_name, - bss->r1kh_id, sta->addr, pmk_r1, pmk_r1_name) < 0) + if (wpa_derive_pmk_r1(sta->pmk_r0, sta->pmk_r0_len, sta->pmk_r0_name, + bss->r1kh_id, sta->addr, sta->pmk_r1, + sta->pmk_r1_name) < 0) return; - wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN); + sta->pmk_r1_len = sta->pmk_r0_len; new_sta = sta_get(bss, sta->addr); if (!new_sta) return; - os_memcpy(new_sta->pmk_r0, sta->pmk_r0, sizeof(sta->pmk_r0)); + os_memcpy(new_sta->pmk_r0, sta->pmk_r0, sta->pmk_r0_len); + new_sta->pmk_r0_len = sta->pmk_r0_len; os_memcpy(new_sta->pmk_r0_name, sta->pmk_r0_name, sizeof(sta->pmk_r0_name)); + os_memcpy(new_sta->pmk_r1, sta->pmk_r1, sta->pmk_r1_len); + new_sta->pmk_r1_len = sta->pmk_r1_len; + os_memcpy(new_sta->pmk_r1_name, sta->pmk_r1_name, + sizeof(sta->pmk_r1_name)); if (!parse.fte_anonce || !parse.fte_snonce || - wpa_pmk_r1_to_ptk(pmk_r1, PMK_LEN, parse.fte_snonce, + wpa_pmk_r1_to_ptk(sta->pmk_r1, sta->pmk_r1_len, parse.fte_snonce, parse.fte_anonce, new_sta->addr, bss->bssid, - pmk_r1_name, &ptk, ptk_name, new_sta->key_mgmt, - new_sta->pairwise_cipher) < 0) + sta->pmk_r1_name, &ptk, ptk_name, + new_sta->key_mgmt, new_sta->pairwise_cipher) < 0) return; add_note(wt, MSG_DEBUG, "Derived new PTK"); @@ -1117,6 +1787,8 @@ static void rx_mgmt_action_ft_response(struct wlantest *wt, new_sta->ptk_set = 1; os_memset(new_sta->rsc_tods, 0, sizeof(new_sta->rsc_tods)); os_memset(new_sta->rsc_fromds, 0, sizeof(new_sta->rsc_fromds)); + os_memcpy(new_sta->snonce, parse.fte_snonce, WPA_NONCE_LEN); + os_memcpy(new_sta->anonce, parse.fte_anonce, WPA_NONCE_LEN); } @@ -1329,6 +2001,11 @@ static int check_mmie_mic(unsigned int mgmt_group_cipher, os_memcpy(buf + 20, data + 24, len - 24 - mic_len); os_memset(buf + 20 + len - 24 - mic_len, 0, mic_len); + if (WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) { + /* Timestamp field masked to zero */ + os_memset(buf + 20, 0, 8); + } + wpa_hexdump(MSG_MSGDUMP, "BIP: AAD|Body(masked)", buf, len + 20 - 24); /* MIC = L(AES-128-CMAC(AAD || Frame Body(masked)), 0, 64) */ if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { @@ -1575,7 +2252,8 @@ static int check_mgmt_ccmp(struct wlantest *wt, const u8 *data, size_t len) if (sta == NULL) return 0; - if ((sta->rsn_capab & WPA_CAPABILITY_MFPC) && + if ((bss->rsn_capab & WPA_CAPABILITY_MFPC) && + (sta->rsn_capab & WPA_CAPABILITY_MFPC) && (sta->state == STATE3 || WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_ACTION)) { add_note(wt, MSG_INFO, "Robust individually-addressed " diff --git a/wlantest/sta.c b/wlantest/sta.c index 3e5ff51b6..62dae0790 100644 --- a/wlantest/sta.c +++ b/wlantest/sta.c @@ -156,7 +156,8 @@ void sta_update_assoc(struct wlantest_sta *sta, struct ieee802_11_elems *elems) MAC2STR(sta->addr), sta->pairwise_cipher, MAC2STR(bss->bssid), bss->pairwise_cipher); } - if (sta->proto && data.group_cipher != bss->group_cipher) { + if (sta->proto && data.group_cipher != bss->group_cipher && + bss->ies_set) { wpa_printf(MSG_INFO, "Mismatch in group cipher: STA " MACSTR " 0x%x != BSS " MACSTR " 0x%x", MAC2STR(sta->addr), data.group_cipher, diff --git a/wlantest/wired.c b/wlantest/wired.c index 653be337a..67ae8a9af 100644 --- a/wlantest/wired.c +++ b/wlantest/wired.c @@ -212,9 +212,9 @@ static void process_udp(struct wlantest *wt, u32 dst, u32 src, return; udp = (const struct udphdr *) data; /* TODO: check UDP checksum */ - sport = be_to_host16(udp->source); - dport = be_to_host16(udp->dest); - ulen = be_to_host16(udp->len); + sport = be_to_host16(udp->uh_sport); + dport = be_to_host16(udp->uh_dport); + ulen = be_to_host16(udp->uh_ulen); if (ulen > len) return; diff --git a/wlantest/wlantest.h b/wlantest/wlantest.h index 4f90b20e2..0c266f4e9 100644 --- a/wlantest/wlantest.h +++ b/wlantest/wlantest.h @@ -1,6 +1,6 @@ /* * wlantest - IEEE 802.11 protocol monitoring and testing tool - * Copyright (c) 2010-2019, Jouni Malinen + * Copyright (c) 2010-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -61,6 +61,7 @@ struct wlantest_sta { STATE3 /* associated */ } state; u16 auth_alg; + bool ft_over_ds; u16 aid; u8 rsnie[257]; /* WPA/RSN IE */ u8 osenie[257]; /* OSEN IE */ @@ -69,10 +70,16 @@ struct wlantest_sta { int group_cipher; int key_mgmt; int rsn_capab; - u8 anonce[32]; /* ANonce from the previous EAPOL-Key msg 1/4 or 3/4 */ - u8 snonce[32]; /* SNonce from the previous EAPOL-Key msg 2/4 */ - u8 pmk_r0[PMK_LEN]; + /* ANonce from the previous EAPOL-Key msg 1/4 or 3/4 */ + u8 anonce[WPA_NONCE_LEN]; + /* SNonce from the previous EAPOL-Key msg 2/4 */ + u8 snonce[WPA_NONCE_LEN]; + u8 pmk_r0[PMK_LEN_MAX]; + size_t pmk_r0_len; u8 pmk_r0_name[WPA_PMK_NAME_LEN]; + u8 pmk_r1[PMK_LEN_MAX]; + size_t pmk_r1_len; + u8 pmk_r1_name[WPA_PMK_NAME_LEN]; struct wpa_ptk ptk; /* Derived PTK */ int ptk_set; struct wpa_ptk tptk; /* Derived PTK during rekeying */ @@ -82,6 +89,7 @@ struct wlantest_sta { u8 ap_sa_query_tr[2]; u8 sta_sa_query_tr[2]; u32 counters[NUM_WLANTEST_STA_COUNTER]; + int assocreq_seen; u16 assocreq_capab_info; u16 assocreq_listen_int; u8 *assocreq_ies; @@ -134,6 +142,7 @@ struct wlantest_bss { size_t ssid_len; int beacon_seen; int proberesp_seen; + int ies_set; int parse_error_reported; u8 wpaie[257]; u8 rsnie[257]; @@ -150,13 +159,14 @@ struct wlantest_bss { size_t gtk_len[4]; int gtk_idx; u8 rsc[4][6]; - u8 igtk[6][32]; - size_t igtk_len[6]; + u8 igtk[8][32]; + size_t igtk_len[8]; int igtk_idx; - u8 ipn[6][6]; + u8 ipn[8][6]; + int bigtk_idx; u32 counters[NUM_WLANTEST_BSS_COUNTER]; struct dl_list tdls; /* struct wlantest_tdls */ - u8 mdid[2]; + u8 mdid[MOBILITY_DOMAIN_ID_LEN]; u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; size_t r0kh_id_len; u8 r1kh_id[FT_R1KH_ID_LEN]; @@ -192,6 +202,7 @@ struct wlantest { unsigned int rx_ctrl; unsigned int rx_data; unsigned int fcs_error; + unsigned int frame_num; void *write_pcap; /* pcap_t* */ void *write_pcap_dumper; /* pcpa_dumper_t */ @@ -263,7 +274,7 @@ struct wlantest_bss * bss_find(struct wlantest *wt, const u8 *bssid); struct wlantest_bss * bss_get(struct wlantest *wt, const u8 *bssid); void bss_deinit(struct wlantest_bss *bss); void bss_update(struct wlantest *wt, struct wlantest_bss *bss, - struct ieee802_11_elems *elems); + struct ieee802_11_elems *elems, int beacon); void bss_flush(struct wlantest *wt); int bss_add_pmk_from_passphrase(struct wlantest_bss *bss, const char *passphrase); diff --git a/wpa_supplicant/.gitignore b/wpa_supplicant/.gitignore index 0e3ad1b06..ff741201e 100644 --- a/wpa_supplicant/.gitignore +++ b/wpa_supplicant/.gitignore @@ -1 +1,15 @@ +.config *.service +eapol_test +nfc_pw_token +preauth_test +wpa_cli +wpa_passphrase +wpa_supplicant +wpa_priv +wpa_gui/Makefile +wpa_gui/wpa_gui +wpa_gui-qt4/Makefile +wpa_gui-qt4/wpa_gui +libwpa_test1 +libwpa_test2 diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index e6c4e18ba..ed7e358ac 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -98,6 +98,7 @@ OBJS += src/utils/crc32.c OBJS += wmm_ac.c OBJS += op_classes.c OBJS += rrm.c +OBJS += robust_av.c OBJS_p = wpa_passphrase.c OBJS_p += src/utils/common.c OBJS_p += src/utils/wpa_debug.c @@ -166,6 +167,10 @@ ifdef CONFIG_VHT_OVERRIDES L_CFLAGS += -DCONFIG_VHT_OVERRIDES endif +ifdef CONFIG_HE_OVERRIDES +L_CFLAGS += -DCONFIG_HE_OVERRIDES +endif + ifndef CONFIG_BACKEND CONFIG_BACKEND=file endif @@ -231,8 +236,13 @@ endif ifdef CONFIG_SAE L_CFLAGS += -DCONFIG_SAE OBJS += src/common/sae.c +ifdef CONFIG_SAE_PK +L_CFLAGS += -DCONFIG_SAE_PK +OBJS += src/common/sae_pk.c +endif NEED_ECC=y NEED_DH_GROUPS=y +NEED_HMAC_SHA256_KDF=y NEED_DRAGONFLY=y ifdef CONFIG_TESTING_OPTIONS NEED_DH_GROUPS_ALL=y @@ -242,6 +252,12 @@ endif ifdef CONFIG_DPP L_CFLAGS += -DCONFIG_DPP OBJS += src/common/dpp.c +OBJS += src/common/dpp_auth.c +OBJS += src/common/dpp_backup.c +OBJS += src/common/dpp_crypto.c +OBJS += src/common/dpp_pkex.c +OBJS += src/common/dpp_reconfig.c +OBJS += src/common/dpp_tcp.c OBJS += dpp_supplicant.c NEED_AES_SIV=y NEED_HMAC_SHA256_KDF=y @@ -378,6 +394,14 @@ OBJS += src/fst/fst_ctrl_iface.c endif endif +ifdef CONFIG_WEP +L_CFLAGS += -DCONFIG_WEP +endif + +ifdef CONFIG_NO_TKIP +L_CFLAGS += -DCONFIG_NO_TKIP +endif + include $(LOCAL_PATH)/src/drivers/drivers.mk @@ -858,7 +882,6 @@ OBJS += src/ap/bss_load.c OBJS += src/ap/eap_user_db.c OBJS += src/ap/neighbor_db.c OBJS += src/ap/rrm.c -ifdef CONFIG_IEEE80211N OBJS += src/ap/ieee802_11_ht.c ifdef CONFIG_IEEE80211AC OBJS += src/ap/ieee802_11_vht.c @@ -866,7 +889,6 @@ endif ifdef CONFIG_IEEE80211AX OBJS += src/ap/ieee802_11_he.c endif -endif ifdef CONFIG_WNM_AP L_CFLAGS += -DCONFIG_WNM_AP OBJS += src/ap/wnm_ap.c @@ -886,15 +908,12 @@ OBJS += src/eap_server/eap_server.c OBJS += src/eap_server/eap_server_identity.c OBJS += src/eap_server/eap_server_methods.c -ifdef CONFIG_IEEE80211N -L_CFLAGS += -DCONFIG_IEEE80211N ifdef CONFIG_IEEE80211AC L_CFLAGS += -DCONFIG_IEEE80211AC endif ifdef CONFIG_IEEE80211AX L_CFLAGS += -DCONFIG_IEEE80211AX endif -endif ifdef NEED_AP_MLME OBJS += src/ap/wmm.c diff --git a/wpa_supplicant/ChangeLog b/wpa_supplicant/ChangeLog index f82e5e0ea..a06a93b22 100644 --- a/wpa_supplicant/ChangeLog +++ b/wpa_supplicant/ChangeLog @@ -533,7 +533,7 @@ ChangeLog for wpa_supplicant * fixed MSCHAP UTF-8 to UCS-2 conversion for three-byte encoding; this fixes password with include UTF-8 characters that use three-byte encoding EAP methods that use NtPasswordHash - * fixed couple of sequencies where radio work items could get stuck, + * fixed couple of sequences where radio work items could get stuck, e.g., when rfkill blocking happens during scanning or when scan-for-auth workaround is used * P2P enhancements/fixes @@ -627,7 +627,7 @@ ChangeLog for wpa_supplicant * added 'dup_network ' command; this can be used to clone the psk field without having toextract it from wpa_supplicant * fixed GSM authentication on USIM - * added support for usin epoll in eloop (CONFIG_ELOOP_EPOLL=y) + * added support for using epoll in eloop (CONFIG_ELOOP_EPOLL=y) * fixed some concurrent virtual interface cases with dedicated P2P management interface to not catch events from removed interface (this could result in the management interface getting disabled) @@ -1113,7 +1113,7 @@ ChangeLog for wpa_supplicant workarounds. - Add support for AuthorizedMACs attribute. * TDLS: - - Propogate TDLS related nl80211 capability flags from kernel and + - Propagate TDLS related nl80211 capability flags from kernel and add them as driver capability flags. If the driver doesn't support capabilities, assume TDLS is supported internally. When TDLS is explicitly not supported, disable all user facing TDLS operations. @@ -2221,7 +2221,7 @@ ChangeLog for wpa_supplicant * added support for EAP-SIM pseudonyms and fast re-authentication * added support for EAP-TLS/PEAP/TTLS fast re-authentication (TLS session resumption) - * added support for EAP-SIM with two challanges + * added support for EAP-SIM with two challenges (phase1="sim_min_num_chal=3" can be used to require three challenges) * added support for configuring DH/DSA parameters for an ephemeral DH key exchange (EAP-TLS/PEAP/TTLS) using new configuration parameters @@ -2332,7 +2332,7 @@ ChangeLog for wpa_supplicant ctrl_interface_group can be used to select which group gets access to the control interface; wpa_cli: by default, try to connect to the first interface available - in /var/run/wpa_supplicant; this path can be overriden with -p option + in /var/run/wpa_supplicant; this path can be overridden with -p option and an interface can be selected with -i option (i.e., in most common cases, wpa_cli does not need to get any arguments) * added support for LEAP diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index bebe915a3..309b12c62 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -1,11 +1,24 @@ -ifndef CC -CC=gcc +BINALL=wpa_supplicant wpa_cli + +ifndef CONFIG_NO_WPA_PASSPHRASE +BINALL += wpa_passphrase endif -ifndef CFLAGS -CFLAGS = -MMD -O2 -Wall -g +ALL = $(BINALL) +ALL += systemd/wpa_supplicant.service +ALL += systemd/wpa_supplicant@.service +ALL += systemd/wpa_supplicant-nl80211@.service +ALL += systemd/wpa_supplicant-wired@.service +ALL += dbus/fi.w1.wpa_supplicant1.service +ifdef CONFIG_BUILD_WPA_CLIENT_SO +ALL += libwpa_client.so endif +EXTRA_TARGETS=dynamic_eap_methods + +CONFIG_FILE=.config +include ../src/build.rules + ifdef LIBS # If LIBS is set with some global build system defaults, clone those for # LIBS_c and LIBS_p to cover wpa_passphrase and wpa_cli as well. @@ -26,8 +39,6 @@ CFLAGS += $(EXTRA_CFLAGS) CFLAGS += -I$(abspath ../src) CFLAGS += -I$(abspath ../src/utils) --include .config - ifndef CONFIG_NO_GITVER # Add VERSION_STR postfix for builds from a git repository ifeq ($(wildcard ../.git),../.git) @@ -45,34 +56,6 @@ CONFIG_WPS_TESTING=y CONFIG_TDLS_TESTING=y endif -BINALL=wpa_supplicant wpa_cli - -ifndef CONFIG_NO_WPA_PASSPHRASE -BINALL += wpa_passphrase -endif - -ALL = $(BINALL) -ALL += systemd/wpa_supplicant.service -ALL += systemd/wpa_supplicant@.service -ALL += systemd/wpa_supplicant-nl80211@.service -ALL += systemd/wpa_supplicant-wired@.service -ALL += dbus/fi.w1.wpa_supplicant1.service -ifdef CONFIG_BUILD_WPA_CLIENT_SO -ALL += libwpa_client.so -endif - - -all: verify_config $(ALL) dynamic_eap_methods - -verify_config: - @if [ ! -r .config ]; then \ - echo 'Building wpa_supplicant requires a configuration file'; \ - echo '(.config). See README for more instructions. You can'; \ - echo 'run "cp defconfig .config" to create an example'; \ - echo 'configuration.'; \ - exit 1; \ - fi - mkconfig: @if [ -f .config ]; then \ echo '.config exists - did not replace it'; \ @@ -108,6 +91,7 @@ OBJS += ../src/utils/ip_addr.o OBJS += ../src/utils/crc32.o OBJS += op_classes.o OBJS += rrm.o +OBJS += robust_av.o OBJS_p = wpa_passphrase.o OBJS_p += ../src/utils/common.o OBJS_p += ../src/utils/wpa_debug.o @@ -199,6 +183,10 @@ ifdef CONFIG_VHT_OVERRIDES CFLAGS += -DCONFIG_VHT_OVERRIDES endif +ifdef CONFIG_HE_OVERRIDES +CFLAGS += -DCONFIG_HE_OVERRIDES +endif + ifndef CONFIG_BACKEND CONFIG_BACKEND=file endif @@ -264,8 +252,13 @@ endif ifdef CONFIG_SAE CFLAGS += -DCONFIG_SAE OBJS += ../src/common/sae.o +ifdef CONFIG_SAE_PK +CFLAGS += -DCONFIG_SAE_PK +OBJS += ../src/common/sae_pk.o +endif NEED_ECC=y NEED_DH_GROUPS=y +NEED_HMAC_SHA256_KDF=y NEED_DRAGONFLY=y ifdef CONFIG_TESTING_OPTIONS NEED_DH_GROUPS_ALL=y @@ -275,6 +268,12 @@ endif ifdef CONFIG_DPP CFLAGS += -DCONFIG_DPP OBJS += ../src/common/dpp.o +OBJS += ../src/common/dpp_auth.o +OBJS += ../src/common/dpp_backup.o +OBJS += ../src/common/dpp_crypto.o +OBJS += ../src/common/dpp_pkex.o +OBJS += ../src/common/dpp_reconfig.o +OBJS += ../src/common/dpp_tcp.o OBJS += dpp_supplicant.o NEED_AES_SIV=y NEED_HMAC_SHA256_KDF=y @@ -905,7 +904,6 @@ OBJS += ../src/ap/bss_load.o OBJS += ../src/ap/eap_user_db.o OBJS += ../src/ap/neighbor_db.o OBJS += ../src/ap/rrm.o -ifdef CONFIG_IEEE80211N OBJS += ../src/ap/ieee802_11_ht.o ifdef CONFIG_IEEE80211AC OBJS += ../src/ap/ieee802_11_vht.o @@ -913,7 +911,6 @@ endif ifdef CONFIG_IEEE80211AX OBJS += ../src/ap/ieee802_11_he.o endif -endif ifdef CONFIG_WNM_AP CFLAGS += -DCONFIG_WNM_AP OBJS += ../src/ap/wnm_ap.o @@ -933,15 +930,12 @@ OBJS += ../src/eap_server/eap_server.o OBJS += ../src/eap_server/eap_server_identity.o OBJS += ../src/eap_server/eap_server_methods.o -ifdef CONFIG_IEEE80211N -CFLAGS += -DCONFIG_IEEE80211N ifdef CONFIG_IEEE80211AC CFLAGS += -DCONFIG_IEEE80211AC endif ifdef CONFIG_IEEE80211AX CFLAGS += -DCONFIG_IEEE80211AX endif -endif ifdef NEED_AP_MLME OBJS += ../src/ap/wmm.o @@ -1072,7 +1066,7 @@ endif ifeq ($(CONFIG_TLS), wolfssl) ifdef TLS_FUNCS -CFLAGS += -DWOLFSSL_DER_LOAD -I/usr/local/include/wolfssl +CFLAGS += -DWOLFSSL_DER_LOAD OBJS += ../src/crypto/tls_wolfssl.o endif OBJS += ../src/crypto/crypto_wolfssl.o @@ -1849,53 +1843,48 @@ OBJS_t2 += $(FST_OBJS) OBJS_nfc += $(FST_OBJS) endif -ifndef LDO -LDO=$(CC) +ifdef CONFIG_WEP +CFLAGS += -DCONFIG_WEP endif -Q=@ -E=echo -ifeq ($(V), 1) -Q= -E=true -endif -ifeq ($(QUIET), 1) -Q=@ -E=true +ifdef CONFIG_NO_TKIP +CFLAGS += -DCONFIG_NO_TKIP endif dynamic_eap_methods: $(EAPDYN) -../src/drivers/build.wpa_supplicant: - @if [ -f ../src/drivers/build.hostapd ]; then \ - $(MAKE) -C ../src/drivers clean; \ - fi - @touch ../src/drivers/build.wpa_supplicant - -BCHECK=../src/drivers/build.wpa_supplicant - +_OBJS_VAR := OBJS_priv +include ../src/objs.mk wpa_priv: $(BCHECK) $(OBJS_priv) $(Q)$(LDO) $(LDFLAGS) -o wpa_priv $(OBJS_priv) $(LIBS) @$(E) " LD " $@ -$(OBJS_c) $(OBJS_t) $(OBJS_t2) $(OBJS) $(BCHECK) $(EXTRA_progs): .config - +_OBJS_VAR := OBJS +include ../src/objs.mk wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs) $(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS) @$(E) " LD " $@ +_OBJS_VAR := OBJS_t +include ../src/objs.mk eapol_test: $(OBJS_t) $(Q)$(LDO) $(LDFLAGS) -o eapol_test $(OBJS_t) $(LIBS) @$(E) " LD " $@ +_OBJS_VAR := OBJS_t2 +include ../src/objs.mk preauth_test: $(OBJS_t2) $(Q)$(LDO) $(LDFLAGS) -o preauth_test $(OBJS_t2) $(LIBS) @$(E) " LD " $@ +_OBJS_VAR := OBJS_p +include ../src/objs.mk wpa_passphrase: $(OBJS_p) $(Q)$(LDO) $(LDFLAGS) -o wpa_passphrase $(OBJS_p) $(LIBS_p) $(LIBS) @$(E) " LD " $@ +_OBJS_VAR := OBJS_c +include ../src/objs.mk wpa_cli: $(OBJS_c) $(Q)$(LDO) $(LDFLAGS) -o wpa_cli $(OBJS_c) $(LIBS_c) @$(E) " LD " $@ @@ -1909,6 +1898,8 @@ LIBCTRLSO += ../src/utils/os_$(CONFIG_OS).c LIBCTRLSO += ../src/utils/common.c LIBCTRLSO += ../src/utils/wpa_debug.c +_OBJS_VAR := LIBCTRL +include ../src/objs.mk libwpa_client.a: $(LIBCTRL) $(Q)rm -f $@ $(Q)$(AR) crs $@ $? @@ -1918,14 +1909,19 @@ libwpa_client.so: $(LIBCTRLSO) @$(E) " CC $@ ($^)" $(Q)$(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -fPIC $^ -libwpa_test1: libwpa_test.o libwpa_client.a - $(Q)$(LDO) $(LDFLAGS) -o libwpa_test1 libwpa_test.o libwpa_client.a $(LIBS_c) +OBJS_wpatest := libwpa_test.o +_OBJS_VAR := OBJS_wpatest +include ../src/objs.mk +libwpa_test1: $(OBJS_wpatest) libwpa_client.a + $(Q)$(LDO) $(LDFLAGS) -o libwpa_test1 $(OBJS_wpatest) libwpa_client.a $(LIBS_c) @$(E) " LD " $@ -libwpa_test2: libwpa_test.o libwpa_client.so - $(Q)$(LDO) $(LDFLAGS) -o libwpa_test2 libwpa_test.o -L. -lwpa_client $(LIBS_c) +libwpa_test2: $(OBJS_wpatest) libwpa_client.so + $(Q)$(LDO) $(LDFLAGS) -o libwpa_test2 $(OBJS_wpatest) -L. -lwpa_client $(LIBS_c) @$(E) " LD " $@ +_OBJS_VAR := OBJS_nfc +include ../src/objs.mk nfc_pw_token: $(OBJS_nfc) $(Q)$(LDO) $(LDFLAGS) -o nfc_pw_token $(OBJS_nfc) $(LIBS) @$(E) " LD " $@ @@ -1962,16 +1958,6 @@ eap_eke.so: ../src/eap_peer/eap_eke.c ../src/eap_common/eap_eke_common.c $(CC) $(LDFLAGS) -o $@ $(CFLAGS) -shared -rdynamic -fPIC $< \ -D$(*F:eap_%=eap_peer_%)_register=eap_peer_method_dynamic_init -ifdef CONFIG_CODE_COVERAGE -%.o: %.c - @$(E) " CC " $< - $(Q)cd $(dir $@); $(CC) -c -o $(notdir $@) $(CFLAGS) $(notdir $<) -else -%.o: %.c - $(Q)$(CC) -c -o $@ $(CFLAGS) $< - @$(E) " CC " $< -endif - %.service: %.service.in $(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@ @$(E) " sed" $< @@ -2013,15 +1999,16 @@ FIPSLD=$(FIPSDIR)/bin/fipsld fips: $(MAKE) CC=$(FIPSLD) FIPSLD_CC="$(CC)" -lcov-html: wpa_supplicant.gcda - lcov -c -d .. > lcov.info +.PHONY: lcov-html +lcov-html: $(call BUILDOBJ,wpa_supplicant.gcda) + lcov -c -d $(BUILDDIR) > lcov.info genhtml lcov.info --output-directory lcov-html -clean: +clean: common-clean $(MAKE) -C ../src clean $(MAKE) -C dbus clean rm -f core *~ *.o *.d *.gcno *.gcda *.gcov - rm -f eap_*.so $(ALL) $(WINALL) eapol_test preauth_test + rm -f eap_*.so $(WINALL) eapol_test preauth_test rm -f wpa_priv rm -f nfc_pw_token rm -f lcov.info @@ -2029,5 +2016,3 @@ clean: rm -f libwpa_client.a rm -f libwpa_client.so rm -f libwpa_test1 libwpa_test2 - --include $(OBJS:%.o=%.d) diff --git a/wpa_supplicant/README b/wpa_supplicant/README index bbc86b137..391912e9b 100644 --- a/wpa_supplicant/README +++ b/wpa_supplicant/README @@ -383,7 +383,7 @@ cp wpa_cli wpa_supplicant /usr/local/bin You will need to make a configuration file, e.g., /etc/wpa_supplicant.conf, with network configuration for the networks you are going to use. Configuration file section below includes -explanation fo the configuration file format and includes various +explanation of the configuration file format and includes various examples. Once the configuration is ready, you can test whether the configuration work by first running wpa_supplicant with following command to start it on foreground with debugging enabled: @@ -778,7 +778,7 @@ wpa_cli commands disconnect = disconnect and wait for reassociate command before connecting scan = request new BSS scan scan_results = get latest scan results - get_capability = get capabilies + get_capability = get capabilities terminate = terminate wpa_supplicant quit = exit wpa_cli diff --git a/wpa_supplicant/README-DPP b/wpa_supplicant/README-DPP index 457e32eef..d378245cd 100644 --- a/wpa_supplicant/README-DPP +++ b/wpa_supplicant/README-DPP @@ -9,40 +9,44 @@ Connector mechanism. Introduction to DPP ------------------- -Device provisioning Protocol allows enrolling of interface-less devices -in a secure Wi-Fi network using many methods like QR code based -authentication( detailed below ), PKEX based authentication etc. In DPP -a Configurator is used to provide network credentials to the devices. -The three phases of DPP connection are authentication, configuration and +Device Provisioning Protocol (also known as Wi-Fi Easy Connect) allows +enrolling of interface-less devices in a secure Wi-Fi network using many +methods like QR code based authentication (detailed below), PKEX based +authentication (password with in-band provisioning), etc. In DPP a +Configurator is used to provide network credentials to the devices. The +three phases of DPP connection are authentication, configuration and network introduction. +More information about Wi-Fi Easy Connect is available from this Wi-Fi +Alliance web page: +https://www.wi-fi.org/discover-wi-fi/wi-fi-easy-connect + Build config setup ------------------ -The following changes must go in the config file used to compile hostapd -and wpa_supplicant. +The following parameters must be included in the config file used to +compile hostapd and wpa_supplicant. wpa_supplicant build config --------------------------- -Enable DPP and protected management frame in wpa_supplicant build config -file +Enable DPP in wpa_supplicant build config file CONFIG_DPP=y hostapd build config -------------------- -Enable DPP and protected management frame in hostapd build config file +Enable DPP in hostapd build config file CONFIG_DPP=y Configurator build config ------------------------- -Any STA or AP device can act as a Configurator. Enable DPP and protected -managment frames in build config. For an AP to act as Configurator, -Interworking needs to be enabled. For wpa_supplicant it is not required. +Any STA or AP device can act as a Configurator. Enable DPP in build +config. For an AP to act as a Configurator, Interworking needs to be +enabled for GAS. For wpa_supplicant it is not required. CONFIG_INTERWORKING=y @@ -90,41 +94,46 @@ To get key of Configurator > dpp_configurator_get_key -How to configure an enrollee using Configurator +How to configure an Enrollee using Configurator ----------------------------------------------- -On enrollee side: +On Enrollee side: -Generate QR code for the device. Store the qr code id returned by the +Generate QR code for the device. Store the QR code id returned by the command. -> dpp_bootstrap_gen type=qrcode mac= chan= key= -(returns bootstrapping info id) +> dpp_bootstrap_gen type=qrcode mac= chan= key= +(Returns bootstrapping info id. If the key parameter is not included, a new key +is generated automatically. The MAC address is specified without octet +separating colons. The channel list includes the possible channels on which the +device is waiting. This uses global operating classes; e.g., 81/1 is the 2.4 +GHz channel 1 on 2412 MHz.) -Get QR Code of device using the bootstrap info id. +Get URI for the QR Code of device using the bootstrap info id. > dpp_bootstrap_get_uri -Make device listen to DPP request (The central frequency of channel 1 is -2412) in case if enrollee is a client device. +Make device listen to DPP request. The central frequency of the 2.4 GHz +band channel 1 is 2412 MHz) in case the Enrollee is a client device. An +AP as an Enrollee is listening on its operating channel. > dpp_listen On Configurator side: Enter the QR Code in the Configurator. -> dpp_qr_code "" +> dpp_qr_code "" On successfully adding QR Code, a bootstrapping info id is returned. -Send provisioning request to enrollee. (conf is ap-dpp if enrollee is an -AP. conf is sta-dpp if enrollee is a client) +Send provisioning request to Enrollee. (conf is ap-dpp if Enrollee is an +AP. conf is sta-dpp if Enrollee is a client) > dpp_auth_init peer= conf= ssid= configurator= or for legacy (PSK/SAE) provisioning for a station Enrollee: > dpp_auth_init peer= conf=sta-psk ssid= pass= -The DPP values will be printed in the console. Save this values into the -config file. If the enrollee is an AP, we need to manually write these -values to the hostapd config file. If the enrollee is a client device, +The DPP values will be printed in the console. Save these values into the +config file. If the Enrollee is an AP, we need to manually write these +values to the hostapd config file. If the Enrollee is a client device, these details can be automatically saved to config file using the following command. @@ -156,7 +165,7 @@ command to get DPP credentials. > dpp_configurator_add (returns configurator id) -> dpp_configurator_sign conf= configurator= +> dpp_configurator_sign conf= configurator= ssid= Sample AP configuration files after provisioning diff --git a/wpa_supplicant/README-HS20 b/wpa_supplicant/README-HS20 index 334287101..484e4cbf4 100644 --- a/wpa_supplicant/README-HS20 +++ b/wpa_supplicant/README-HS20 @@ -78,7 +78,7 @@ hs20=1 # Parameters for controlling scanning -# Homogenous ESS identifier +# Homogeneous ESS identifier # If this is set, scans will be used to request response only from BSSes # belonging to the specified Homogeneous ESS. This is used only if interworking # is enabled. diff --git a/wpa_supplicant/android.config b/wpa_supplicant/android.config index f9d3712a8..283f8eb0a 100644 --- a/wpa_supplicant/android.config +++ b/wpa_supplicant/android.config @@ -438,11 +438,7 @@ CONFIG_ANDROID_LOG=y # either wpa_supplicant or hostapd are run. CONFIG_NO_RANDOM_POOL=y -# IEEE 802.11n (High Throughput) support (mainly for AP mode) -CONFIG_IEEE80211N=y - # IEEE 802.11ac (Very High Throughput) support (mainly for AP mode) -# (depends on CONFIG_IEEE80211N) #CONFIG_IEEE80211AC=y # Wireless Network Management (IEEE Std 802.11v-2011) @@ -538,4 +534,12 @@ CONFIG_WIFI_DISPLAY=y # Experimental implementation of draft-harkins-owe-07.txt #CONFIG_OWE=y +# Wired equivalent privacy (WEP) +# WEP is an obsolete cryptographic data confidentiality algorithm that is not +# considered secure. It should not be used for anything anymore. The +# functionality needed to use WEP is available in the current wpa_supplicant +# release under this optional build parameter. This functionality is subject to +# be completely removed in a future release. +CONFIG_WEP=y + include $(wildcard $(LOCAL_PATH)/android_config_*.inc) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index e552306d7..ac88a7dc9 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -44,7 +44,27 @@ static void wpas_wps_ap_pin_timeout(void *eloop_data, void *user_ctx); #endif /* CONFIG_WPS */ -#ifdef CONFIG_IEEE80211N +static bool is_chanwidth160_supported(struct hostapd_hw_modes *mode, + struct hostapd_config *conf) +{ +#ifdef CONFIG_IEEE80211AX + if (conf->ieee80211ax) { + struct he_capabilities *he_cap; + + he_cap = &mode->he_capab[IEEE80211_MODE_AP]; + if (he_cap->phy_cap[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] & + (HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G | + HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G)) + return true; + } +#endif /* CONFIG_IEEE80211AX */ + if (mode->vht_capab & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | + VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) + return true; + return false; +} + + static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct hostapd_config *conf, @@ -54,30 +74,37 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, u8 center_chan = 0; u8 channel = conf->channel; #endif /* CONFIG_P2P */ + u8 freq_seg_idx; if (!conf->secondary_channel) goto no_vht; /* Use the maximum oper channel width if it's given. */ if (ssid->max_oper_chwidth) - conf->vht_oper_chwidth = ssid->max_oper_chwidth; + hostapd_set_oper_chwidth(conf, ssid->max_oper_chwidth); - ieee80211_freq_to_chan(ssid->vht_center_freq2, - &conf->vht_oper_centr_freq_seg1_idx); + if (hostapd_get_oper_chwidth(conf) == CHANWIDTH_80P80MHZ) { + ieee80211_freq_to_chan(ssid->vht_center_freq2, + &freq_seg_idx); + hostapd_set_oper_centr_freq_seg1_idx(conf, freq_seg_idx); + } if (!ssid->p2p_group) { - if (!ssid->vht_center_freq1 || - conf->vht_oper_chwidth == CHANWIDTH_USE_HT) + if (!ssid->vht_center_freq1) goto no_vht; ieee80211_freq_to_chan(ssid->vht_center_freq1, - &conf->vht_oper_centr_freq_seg0_idx); - wpa_printf(MSG_DEBUG, "VHT seg0 index %d for AP", - conf->vht_oper_centr_freq_seg0_idx); + &freq_seg_idx); + hostapd_set_oper_centr_freq_seg0_idx(conf, freq_seg_idx); + + wpa_printf(MSG_DEBUG, + "VHT seg0 index %d and seg1 index %d for AP", + hostapd_get_oper_centr_freq_seg0_idx(conf), + hostapd_get_oper_centr_freq_seg1_idx(conf)); return; } #ifdef CONFIG_P2P - switch (conf->vht_oper_chwidth) { + switch (hostapd_get_oper_chwidth(conf)) { case CHANWIDTH_80MHZ: case CHANWIDTH_80P80MHZ: center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel); @@ -97,14 +124,14 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, * try oper_cwidth 160 MHz first then VHT 80 MHz, if 160 MHz is * not supported. */ - conf->vht_oper_chwidth = CHANWIDTH_160MHZ; + hostapd_set_oper_chwidth(conf, CHANWIDTH_160MHZ); center_chan = wpas_p2p_get_vht160_center(wpa_s, mode, channel); - if (center_chan) { + if (center_chan && is_chanwidth160_supported(mode, conf)) { wpa_printf(MSG_DEBUG, "VHT center channel %u for auto-selected 160 MHz bandwidth", center_chan); } else { - conf->vht_oper_chwidth = CHANWIDTH_80MHZ; + hostapd_set_oper_chwidth(conf, CHANWIDTH_80MHZ); center_chan = wpas_p2p_get_vht80_center(wpa_s, mode, channel); wpa_printf(MSG_DEBUG, @@ -116,9 +143,9 @@ static void wpas_conf_ap_vht(struct wpa_supplicant *wpa_s, if (!center_chan) goto no_vht; - conf->vht_oper_centr_freq_seg0_idx = center_chan; + hostapd_set_oper_centr_freq_seg0_idx(conf, center_chan); wpa_printf(MSG_DEBUG, "VHT seg0 index %d for P2P GO", - conf->vht_oper_centr_freq_seg0_idx); + hostapd_get_oper_centr_freq_seg0_idx(conf)); return; #endif /* CONFIG_P2P */ @@ -126,11 +153,28 @@ no_vht: wpa_printf(MSG_DEBUG, "No VHT higher bandwidth support for the selected channel %d", conf->channel); - conf->vht_oper_centr_freq_seg0_idx = - conf->channel + conf->secondary_channel * 2; - conf->vht_oper_chwidth = CHANWIDTH_USE_HT; + hostapd_set_oper_centr_freq_seg0_idx( + conf, conf->channel + conf->secondary_channel * 2); + hostapd_set_oper_chwidth(conf, CHANWIDTH_USE_HT); +} + + +static struct hostapd_hw_modes * +wpa_supplicant_find_hw_mode(struct wpa_supplicant *wpa_s, + enum hostapd_hw_mode hw_mode) +{ + struct hostapd_hw_modes *mode = NULL; + int i; + + for (i = 0; i < wpa_s->hw.num_modes; i++) { + if (wpa_s->hw.modes[i].mode == hw_mode) { + mode = &wpa_s->hw.modes[i]; + break; + } + } + + return mode; } -#endif /* CONFIG_IEEE80211N */ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, @@ -146,10 +190,6 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, return -1; } - /* TODO: enable HT40 if driver supports it; - * drop to 11b if driver does not support 11g */ - -#ifdef CONFIG_IEEE80211N /* * Enable HT20 if the driver supports it, by setting conf->ieee80211n * and a mask of allowed capabilities within conf->ht_capab. @@ -158,17 +198,28 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, */ if (wpa_s->hw.modes) { struct hostapd_hw_modes *mode = NULL; - int i, no_ht = 0; + int no_ht = 0; wpa_printf(MSG_DEBUG, "Determining HT/VHT options based on driver capabilities (freq=%u chan=%u)", ssid->frequency, conf->channel); - for (i = 0; i < wpa_s->hw.num_modes; i++) { - if (wpa_s->hw.modes[i].mode == conf->hw_mode) { - mode = &wpa_s->hw.modes[i]; - break; - } + mode = wpa_supplicant_find_hw_mode(wpa_s, conf->hw_mode); + + /* May drop to IEEE 802.11b if the driver does not support IEEE + * 802.11g */ + if (!mode && conf->hw_mode == HOSTAPD_MODE_IEEE80211G) { + conf->hw_mode = HOSTAPD_MODE_IEEE80211B; + wpa_printf(MSG_INFO, + "Try downgrade to IEEE 802.11b as 802.11g is not supported by the current hardware"); + mode = wpa_supplicant_find_hw_mode(wpa_s, + conf->hw_mode); + } + + if (!mode) { + wpa_printf(MSG_ERROR, + "No match between requested and supported hw modes found"); + return -1; } #ifdef CONFIG_HT_OVERRIDES @@ -193,6 +244,14 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET), ssid->ht40); conf->ieee80211n = 1; + + if (ssid->ht40 && + (mode->ht_capab & + HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) + conf->secondary_channel = ssid->ht40; + else + conf->secondary_channel = 0; + #ifdef CONFIG_P2P if (ssid->p2p_group && conf->hw_mode == HOSTAPD_MODE_IEEE80211A && @@ -234,16 +293,19 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, HT_CAP_INFO_TX_STBC | HT_CAP_INFO_MAX_AMSDU_SIZE); + /* check this before VHT, because setting oper chan + * width and friends is the same call for HE and VHT + * and checks if conf->ieee8021ax == 1 */ + if (mode->he_capab[wpas_mode_to_ieee80211_mode( + ssid->mode)].he_supported && + ssid->he) + conf->ieee80211ax = 1; + if (mode->vht_capab && ssid->vht) { conf->ieee80211ac = 1; conf->vht_capab |= mode->vht_capab; wpas_conf_ap_vht(wpa_s, ssid, conf, mode); } - - if (mode->he_capab[wpas_mode_to_ieee80211_mode( - ssid->mode)].he_supported && - ssid->he) - conf->ieee80211ax = 1; } } @@ -269,7 +331,6 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, conf->no_pri_sec_switch = 1; } } -#endif /* CONFIG_IEEE80211N */ return 0; } @@ -348,7 +409,9 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, #endif /* CONFIG_IEEE80211AX */ bss->isolate = !wpa_s->conf->p2p_intra_bss; + bss->extended_key_id = wpa_s->conf->extended_key_id; bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk; + bss->wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey; if (ssid->p2p_group) { os_memcpy(bss->ip_addr_go, wpa_s->p2pdev->conf->ip_addr_go, 4); @@ -393,6 +456,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, bss->ssid.wpa_psk_set = 1; } else if (ssid->passphrase) { bss->ssid.wpa_passphrase = os_strdup(ssid->passphrase); +#ifdef CONFIG_WEP } else if (ssid->wep_key_len[0] || ssid->wep_key_len[1] || ssid->wep_key_len[2] || ssid->wep_key_len[3]) { struct hostapd_wep_keys *wep = &bss->ssid.wep; @@ -408,6 +472,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, } wep->idx = ssid->wep_tx_keyidx; wep->keys_set = 1; +#endif /* CONFIG_WEP */ } #ifdef CONFIG_SAE if (ssid->sae_password) { @@ -489,11 +554,12 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise, bss->rsn_pairwise); - if (bss->wpa && bss->ieee802_1x) + if (bss->wpa && bss->ieee802_1x) { bss->ssid.security_policy = SECURITY_WPA; - else if (bss->wpa) + } else if (bss->wpa) { bss->ssid.security_policy = SECURITY_WPA_PSK; - else if (bss->ieee802_1x) { +#ifdef CONFIG_WEP + } else if (bss->ieee802_1x) { int cipher = WPA_CIPHER_NONE; bss->ssid.security_policy = SECURITY_IEEE_802_1X; bss->ssid.wep.default_len = bss->default_wep_key_len; @@ -511,6 +577,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, bss->wpa_group = cipher; bss->wpa_pairwise = cipher; bss->rsn_pairwise = cipher; +#endif /* CONFIG_WEP */ } else { bss->ssid.security_policy = SECURITY_PLAINTEXT; bss->wpa_group = WPA_CIPHER_NONE; @@ -605,6 +672,8 @@ no_wps: bss->ftm_responder = wpa_s->conf->ftm_responder; bss->ftm_initiator = wpa_s->conf->ftm_initiator; + bss->transition_disable = ssid->transition_disable; + return 0; } @@ -839,7 +908,6 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, return -1; hapd_iface->owner = wpa_s; hapd_iface->drv_flags = wpa_s->drv_flags; - hapd_iface->smps_modes = wpa_s->drv_smps_modes; hapd_iface->probe_resp_offloads = wpa_s->probe_resp_offloads; hapd_iface->extended_capa = wpa_s->extended_capa; hapd_iface->extended_capa_mask = wpa_s->extended_capa_mask; @@ -855,6 +923,9 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, wpa_s->conf->wmm_ac_params, sizeof(wpa_s->conf->wmm_ac_params)); + os_memcpy(wpa_s->ap_iface->conf->tx_queue, wpa_s->conf->tx_queue, + sizeof(wpa_s->conf->tx_queue)); + if (params.uapsd > 0) { conf->bss[0]->wmm_enabled = 1; conf->bss[0]->wmm_uapsd = 1; @@ -1412,10 +1483,17 @@ int ap_switch_channel(struct wpa_supplicant *wpa_s, struct csa_settings *settings) { #ifdef NEED_AP_MLME - if (!wpa_s->ap_iface || !wpa_s->ap_iface->bss[0]) + struct hostapd_iface *iface = NULL; + + if (wpa_s->ap_iface) + iface = wpa_s->ap_iface; + else if (wpa_s->ifmsh) + iface = wpa_s->ifmsh; + + if (!iface || !iface->bss[0]) return -1; - return hostapd_switch_channel(wpa_s->ap_iface->bss[0], settings); + return hostapd_switch_channel(iface->bss[0], settings); #else /* NEED_AP_MLME */ return -1; #endif /* NEED_AP_MLME */ diff --git a/wpa_supplicant/binder/binder.h b/wpa_supplicant/binder/binder.h index 019e3275c..6d7abb134 100644 --- a/wpa_supplicant/binder/binder.h +++ b/wpa_supplicant/binder/binder.h @@ -17,7 +17,7 @@ extern "C" { /** * This is the binder RPC interface entry point to the wpa_supplicant core. * This initializes the binder driver & BinderManager instance and then forwards - * all the notifcations from the supplicant core to the BinderManager. + * all the notifications from the supplicant core to the BinderManager. */ struct wpas_binder_priv; struct wpa_global; diff --git a/wpa_supplicant/blacklist.c b/wpa_supplicant/blacklist.c index e53dc38b3..2f326444b 100644 --- a/wpa_supplicant/blacklist.c +++ b/wpa_supplicant/blacklist.c @@ -26,6 +26,15 @@ struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s, if (wpa_s == NULL || bssid == NULL) return NULL; + if (wpa_s->current_ssid && + wpa_s->current_ssid->was_recently_reconfigured) { + wpa_blacklist_clear(wpa_s); + wpa_s->current_ssid->was_recently_reconfigured = false; + return NULL; + } + + wpa_blacklist_update(wpa_s); + e = wpa_s->blacklist; while (e) { if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) @@ -56,16 +65,29 @@ struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s, int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid) { struct wpa_blacklist *e; + struct os_reltime now; if (wpa_s == NULL || bssid == NULL) return -1; e = wpa_blacklist_get(wpa_s, bssid); + os_get_reltime(&now); if (e) { + e->blacklist_start = now; e->count++; - wpa_printf(MSG_DEBUG, "BSSID " MACSTR " blacklist count " - "incremented to %d", - MAC2STR(bssid), e->count); + if (e->count > 5) + e->timeout_secs = 1800; + else if (e->count == 5) + e->timeout_secs = 600; + else if (e->count == 4) + e->timeout_secs = 120; + else if (e->count == 3) + e->timeout_secs = 60; + else + e->timeout_secs = 10; + wpa_printf(MSG_INFO, "BSSID " MACSTR + " blacklist count incremented to %d, blacklisting for %d seconds", + MAC2STR(bssid), e->count, e->timeout_secs); return e->count; } @@ -74,10 +96,13 @@ int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid) return -1; os_memcpy(e->bssid, bssid, ETH_ALEN); e->count = 1; + e->timeout_secs = 10; + e->blacklist_start = now; e->next = wpa_s->blacklist; wpa_s->blacklist = e; - wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR " into blacklist", - MAC2STR(bssid)); + wpa_printf(MSG_DEBUG, "Added BSSID " MACSTR + " into blacklist, blacklisting for %d seconds", + MAC2STR(bssid), e->timeout_secs); return e->count; } @@ -116,6 +141,27 @@ int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid) } +/** + * wpa_blacklist_is_blacklisted - Check the blacklist status of a BSS + * @wpa_s: Pointer to wpa_supplicant data + * @bssid: BSSID to be checked + * Returns: count if BSS is currently considered to be blacklisted, 0 otherwise + */ +int wpa_blacklist_is_blacklisted(struct wpa_supplicant *wpa_s, const u8 *bssid) +{ + struct wpa_blacklist *e; + struct os_reltime now; + + e = wpa_blacklist_get(wpa_s, bssid); + if (!e) + return 0; + os_get_reltime(&now); + if (os_reltime_expired(&now, &e->blacklist_start, e->timeout_secs)) + return 0; + return e->count; +} + + /** * wpa_blacklist_clear - Clear the blacklist of all entries * @wpa_s: Pointer to wpa_supplicant data @@ -123,19 +169,53 @@ int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid) void wpa_blacklist_clear(struct wpa_supplicant *wpa_s) { struct wpa_blacklist *e, *prev; - int max_count = 0; e = wpa_s->blacklist; wpa_s->blacklist = NULL; while (e) { - if (e->count > max_count) - max_count = e->count; prev = e; e = e->next; wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from " "blacklist (clear)", MAC2STR(prev->bssid)); os_free(prev); } - - wpa_s->extra_blacklist_count += max_count; +} + + +/** + * wpa_blacklist_update - Update the entries in the blacklist, + * deleting entries that have been expired for over an hour. + * @wpa_s: Pointer to wpa_supplicant data + */ +void wpa_blacklist_update(struct wpa_supplicant *wpa_s) +{ + struct wpa_blacklist *e, *prev = NULL; + struct os_reltime now; + + if (!wpa_s) + return; + + e = wpa_s->blacklist; + os_get_reltime(&now); + while (e) { + if (os_reltime_expired(&now, &e->blacklist_start, + e->timeout_secs + 3600)) { + struct wpa_blacklist *to_delete = e; + + if (prev) { + prev->next = e->next; + e = prev->next; + } else { + wpa_s->blacklist = e->next; + e = wpa_s->blacklist; + } + wpa_printf(MSG_INFO, "Removed BSSID " MACSTR + " from blacklist (expired)", + MAC2STR(to_delete->bssid)); + os_free(to_delete); + } else { + prev = e; + e = e->next; + } + } } diff --git a/wpa_supplicant/blacklist.h b/wpa_supplicant/blacklist.h index ae06986f3..a1c60d5e6 100644 --- a/wpa_supplicant/blacklist.h +++ b/wpa_supplicant/blacklist.h @@ -13,12 +13,21 @@ struct wpa_blacklist { struct wpa_blacklist *next; u8 bssid[ETH_ALEN]; int count; + /* Time of most recent blacklist event. */ + struct os_reltime blacklist_start; + /* + * Number of seconds after blacklist_start that the entry will be + * considered blacklisted. + */ + int timeout_secs; }; struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s, const u8 *bssid); int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid); int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid); +int wpa_blacklist_is_blacklisted(struct wpa_supplicant *wpa_s, const u8 *bssid); void wpa_blacklist_clear(struct wpa_supplicant *wpa_s); +void wpa_blacklist_update(struct wpa_supplicant *wpa_s); #endif /* BLACKLIST_H */ diff --git a/wpa_supplicant/bss.c b/wpa_supplicant/bss.c index 943a34081..e9c2f822c 100644 --- a/wpa_supplicant/bss.c +++ b/wpa_supplicant/bss.c @@ -351,10 +351,31 @@ static int wpa_bss_is_wps_candidate(struct wpa_supplicant *wpa_s, } +static bool is_p2p_pending_bss(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss) +{ +#ifdef CONFIG_P2P + u8 addr[ETH_ALEN]; + + if (os_memcmp(bss->bssid, wpa_s->pending_join_iface_addr, + ETH_ALEN) == 0) + return true; + if (!is_zero_ether_addr(wpa_s->pending_join_dev_addr) && + p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len, addr) == 0 && + os_memcmp(addr, wpa_s->pending_join_dev_addr, ETH_ALEN) == 0) + return true; +#endif /* CONFIG_P2P */ + return false; +} + + static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) { struct wpa_ssid *ssid; + if (is_p2p_pending_bss(wpa_s, bss)) + return 1; + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { if (ssid->ssid == NULL || ssid->ssid_len == 0) continue; @@ -443,7 +464,7 @@ static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s, bss->ssid_len = ssid_len; bss->ie_len = res->ie_len; bss->beacon_ie_len = res->beacon_ie_len; - os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); + os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len); wpa_bss_set_hessid(bss); if (wpa_s->num_bss + 1 > wpa_s->conf->bss_max_count && @@ -546,7 +567,7 @@ static u32 wpa_bss_compare_res(const struct wpa_bss *old, changes |= WPA_BSS_MODE_CHANGED_FLAG; if (old->ie_len == new_res->ie_len && - os_memcmp(old + 1, new_res + 1, old->ie_len) == 0) + os_memcmp(wpa_bss_ie_ptr(old), new_res + 1, old->ie_len) == 0) return changes; changes |= WPA_BSS_IES_CHANGED_FLAG; @@ -670,7 +691,7 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, #endif /* CONFIG_P2P */ if (bss->ie_len + bss->beacon_ie_len >= res->ie_len + res->beacon_ie_len) { - os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); + os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len); bss->ie_len = res->ie_len; bss->beacon_ie_len = res->beacon_ie_len; } else { @@ -691,7 +712,7 @@ wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, wpa_s->current_bss = nbss; wpa_bss_update_pending_connect(wpa_s, bss, nbss); bss = nbss; - os_memcpy(bss + 1, res + 1, + os_memcpy(bss->ies, res + 1, res->ie_len + res->beacon_ie_len); bss->ie_len = res->ie_len; bss->beacon_ie_len = res->beacon_ie_len; @@ -906,7 +927,7 @@ void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info, } } - wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%u/%u", + wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%zu/%zu", wpa_s->last_scan_res_used, wpa_s->last_scan_res_size); } @@ -1053,7 +1074,7 @@ struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, *found = NULL; dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) { u8 addr[ETH_ALEN]; - if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len, + if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len, addr) != 0 || os_memcmp(addr, dev_addr, ETH_ALEN) != 0) continue; @@ -1117,7 +1138,22 @@ struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s, */ const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie) { - return get_ie((const u8 *) (bss + 1), bss->ie_len, ie); + return get_ie(wpa_bss_ie_ptr(bss), bss->ie_len, ie); +} + + +/** + * wpa_bss_get_ie_ext - Fetch a specified extended IE from a BSS entry + * @bss: BSS table entry + * @ext: Information element extension identifier (WLAN_EID_EXT_*) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the BSS + * entry. + */ +const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext) +{ + return get_ie_ext(wpa_bss_ie_ptr(bss), bss->ie_len, ext); } @@ -1132,18 +1168,15 @@ const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie) */ const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type) { - const u8 *end, *pos; + const u8 *ies; + const struct element *elem; - pos = (const u8 *) (bss + 1); - end = pos + bss->ie_len; + ies = wpa_bss_ie_ptr(bss); - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, bss->ie_len) { + if (elem->datalen >= 4 && + vendor_type == WPA_GET_BE32(elem->data)) + return &elem->id; } return NULL; @@ -1165,22 +1198,20 @@ const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type) const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, u32 vendor_type) { - const u8 *end, *pos; + const u8 *ies; + const struct element *elem; if (bss->beacon_ie_len == 0) return NULL; - pos = (const u8 *) (bss + 1); - pos += bss->ie_len; - end = pos + bss->beacon_ie_len; + ies = wpa_bss_ie_ptr(bss); + ies += bss->ie_len; - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, + bss->beacon_ie_len) { + if (elem->datalen >= 4 && + vendor_type == WPA_GET_BE32(elem->data)) + return &elem->id; } return NULL; @@ -1207,16 +1238,21 @@ struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, if (buf == NULL) return NULL; - pos = (const u8 *) (bss + 1); + pos = wpa_bss_ie_ptr(bss); end = pos + bss->ie_len; while (end - pos > 1) { - if (2 + pos[1] > end - pos) + u8 ie, len; + + ie = pos[0]; + len = pos[1]; + if (len > end - pos - 2) break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); - pos += 2 + pos[1]; + pos += 2; + if (ie == WLAN_EID_VENDOR_SPECIFIC && len >= 4 && + vendor_type == WPA_GET_BE32(pos)) + wpabuf_put_data(buf, pos + 4, len - 4); + pos += len; } if (wpabuf_len(buf) == 0) { @@ -1251,7 +1287,7 @@ struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss, if (buf == NULL) return NULL; - pos = (const u8 *) (bss + 1); + pos = wpa_bss_ie_ptr(bss); pos += bss->ie_len; end = pos + bss->beacon_ie_len; @@ -1337,7 +1373,7 @@ int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates) #ifdef CONFIG_FILS -const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss) +const u8 * wpa_bss_get_fils_cache_id(const struct wpa_bss *bss) { const u8 *ie; diff --git a/wpa_supplicant/bss.h b/wpa_supplicant/bss.h index 3ce8cd3f4..919bbe113 100644 --- a/wpa_supplicant/bss.h +++ b/wpa_supplicant/bss.h @@ -18,10 +18,12 @@ struct wpa_scan_res; #define WPA_BSS_AUTHENTICATED BIT(4) #define WPA_BSS_ASSOCIATED BIT(5) #define WPA_BSS_ANQP_FETCH_TRIED BIT(6) +#define WPA_BSS_OWE_TRANSITION BIT(7) struct wpa_bss_anqp_elem { struct dl_list list; u16 infoid; + bool protected; /* received in a protected GAS response */ struct wpabuf *payload; }; @@ -110,8 +112,14 @@ struct wpa_bss { size_t beacon_ie_len; /* followed by ie_len octets of IEs */ /* followed by beacon_ie_len octets of IEs */ + u8 ies[]; }; +static inline const u8 * wpa_bss_ie_ptr(const struct wpa_bss *bss) +{ + return bss->ies; +} + void wpa_bss_update_start(struct wpa_supplicant *wpa_s); void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s, struct wpa_scan_res *res, @@ -136,6 +144,7 @@ struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id); struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s, unsigned int idf, unsigned int idl); const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie); +const u8 * wpa_bss_get_ie_ext(const struct wpa_bss *bss, u8 ext); const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type); const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, u32 vendor_type); @@ -147,7 +156,7 @@ int wpa_bss_get_max_rate(const struct wpa_bss *bss); int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates); struct wpa_bss_anqp * wpa_bss_anqp_alloc(void); int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss); -const u8 * wpa_bss_get_fils_cache_id(struct wpa_bss *bss); +const u8 * wpa_bss_get_fils_cache_id(const struct wpa_bss *bss); int wpa_bss_ext_capab(const struct wpa_bss *bss, unsigned int capab); static inline int bss_is_dmg(const struct wpa_bss *bss) @@ -168,7 +177,7 @@ static inline int bss_is_pbss(struct wpa_bss *bss) static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level) { - if (bss != NULL && new_level < 0) + if (bss != NULL && new_level > -WPA_INVALID_NOISE && new_level < 0) bss->level = new_level; } diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index b83c36ae9..0aa92a28c 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1856,6 +1856,8 @@ static char * wpa_config_write_machine_password(const struct parse_data *data, #endif /* IEEE8021X_EAPOL */ +#ifdef CONFIG_WEP + static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line, const char *value, int idx) { @@ -1966,6 +1968,8 @@ static char * wpa_config_write_wep_key3(const struct parse_data *data, } #endif /* NO_CONFIG_WRITE */ +#endif /* CONFIG_WEP */ + #ifdef CONFIG_P2P @@ -2451,11 +2455,13 @@ static const struct parse_data ssid_fields[] = { { STRe(openssl_ciphers, openssl_ciphers) }, { INTe(erp, erp) }, #endif /* IEEE8021X_EAPOL */ +#ifdef CONFIG_WEP { FUNC_KEY(wep_key0) }, { FUNC_KEY(wep_key1) }, { FUNC_KEY(wep_key2) }, { FUNC_KEY(wep_key3) }, { INT(wep_tx_keyidx) }, +#endif /* CONFIG_WEP */ { INT(priority) }, #ifdef IEEE8021X_EAPOL { INT(eap_workaround) }, @@ -2495,6 +2501,7 @@ static const struct parse_data ssid_fields[] = { { INT(dot11MeshHoldingTimeout) }, #endif /* CONFIG_MESH */ { INT(wpa_ptk_rekey) }, + { INT_RANGE(wpa_deny_ptk0_rekey, 0, 2) }, { INT(group_rekey) }, { STR(bgscan) }, { INT_RANGE(ignore_broadcast_ssid, 0, 2) }, @@ -2537,6 +2544,9 @@ static const struct parse_data ssid_fields[] = { { INT_RANGE(vht_tx_mcs_nss_7, -1, 3) }, { INT_RANGE(vht_tx_mcs_nss_8, -1, 3) }, #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + { INT_RANGE(disable_he, 0, 1)}, +#endif /* CONFIG_HE_OVERRIDES */ { INT(ap_max_inactivity) }, { INT(dtim_period) }, { INT(beacon_int) }, @@ -2563,12 +2573,17 @@ static const struct parse_data ssid_fields[] = { { STR_LEN(dpp_netaccesskey) }, { INT(dpp_netaccesskey_expiry) }, { STR_LEN(dpp_csign) }, + { STR_LEN(dpp_pp_key) }, + { INT_RANGE(dpp_pfs, 0, 2) }, #endif /* CONFIG_DPP */ { INT_RANGE(owe_group, 0, 65535) }, { INT_RANGE(owe_only, 0, 1) }, { INT_RANGE(owe_ptk_workaround, 0, 1) }, { INT_RANGE(multi_ap_backhaul_sta, 0, 1) }, { INT_RANGE(ft_eap_pmksa_caching, 0, 1) }, + { INT_RANGE(beacon_prot, 0, 1) }, + { INT_RANGE(transition_disable, 0, 255) }, + { INT_RANGE(sae_pk, 0, 2) }, }; #undef OFFSET @@ -2604,7 +2619,7 @@ static const struct parse_data ssid_fields[] = { int wpa_config_add_prio_network(struct wpa_config *config, struct wpa_ssid *ssid) { - int prio; + size_t prio; struct wpa_ssid *prev, **nlist; /* @@ -2762,6 +2777,7 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid) os_free(ssid->dpp_connector); bin_clear_free(ssid->dpp_netaccesskey, ssid->dpp_netaccesskey_len); os_free(ssid->dpp_csign); + os_free(ssid->dpp_pp_key); while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry, list))) { dl_list_del(&psk->list); @@ -2874,6 +2890,7 @@ void wpa_config_free(struct wpa_config *config) os_free(config->p2p_no_go_freq.range); os_free(config->autoscan); os_free(config->freq_list); + os_free(config->initial_freq_list); wpabuf_free(config->wps_nfc_dh_pubkey); wpabuf_free(config->wps_nfc_dh_privkey); wpabuf_free(config->wps_nfc_dev_pw); @@ -3019,8 +3036,11 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) ssid->pairwise_cipher = DEFAULT_PAIRWISE; ssid->group_cipher = DEFAULT_GROUP; ssid->key_mgmt = DEFAULT_KEY_MGMT; + ssid->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS; ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD; ssid->ht = 1; + ssid->vht = 1; + ssid->he = 1; #ifdef IEEE8021X_EAPOL ssid->eapol_flags = DEFAULT_EAPOL_FLAGS; ssid->eap_workaround = DEFAULT_EAP_WORKAROUND; @@ -3127,6 +3147,7 @@ int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, } ret = -1; } + ssid->was_recently_reconfigured = true; return ret; } @@ -4240,6 +4261,8 @@ int wpa_config_remove_blob(struct wpa_config *config, const char *name) struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, const char *driver_param) { +#define ecw2cw(ecw) ((1 << (ecw)) - 1) + struct wpa_config *config; const int aCWmin = 4, aCWmax = 10; const struct hostapd_wmm_ac_params ac_bk = @@ -4247,9 +4270,20 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, const struct hostapd_wmm_ac_params ac_be = { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ - { aCWmin - 1, aCWmin, 2, 3000 / 32, 0 }; + { aCWmin - 1, aCWmin, 2, 3008 / 32, 0 }; const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ - { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 }; + { aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 }; + const struct hostapd_tx_queue_params txq_bk = + { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 }; + const struct hostapd_tx_queue_params txq_be = + { 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0 }; + const struct hostapd_tx_queue_params txq_vi = + { 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30 }; + const struct hostapd_tx_queue_params txq_vo = + { 1, (ecw2cw(aCWmin) + 1) / 4 - 1, + (ecw2cw(aCWmin) + 1) / 2 - 1, 15 }; + +#undef ecw2cw config = os_zalloc(sizeof(*config)); if (config == NULL) @@ -4279,11 +4313,16 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, config->wmm_ac_params[1] = ac_bk; config->wmm_ac_params[2] = ac_vi; config->wmm_ac_params[3] = ac_vo; + config->tx_queue[0] = txq_vo; + config->tx_queue[1] = txq_vi; + config->tx_queue[2] = txq_be; + config->tx_queue[3] = txq_bk; config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY; config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME; config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD; config->cert_in_cb = DEFAULT_CERT_IN_CB; config->wpa_rsc_relaxation = DEFAULT_WPA_RSC_RELAXATION; + config->extended_key_id = DEFAULT_EXTENDED_KEY_ID; #ifdef CONFIG_MBO config->mbo_cell_capa = DEFAULT_MBO_CELL_CAPA; @@ -4309,7 +4348,7 @@ struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, */ void wpa_config_debug_dump_networks(struct wpa_config *config) { - int prio; + size_t prio; struct wpa_ssid *ssid; for (prio = 0; prio < config->num_prio; prio++) { @@ -4327,13 +4366,31 @@ void wpa_config_debug_dump_networks(struct wpa_config *config) #endif /* CONFIG_NO_STDOUT_DEBUG */ +/** + * Structure for global configuration parsing. This data is used to implement a + * generic parser for the global interface configuration. The table of variables + * is defined below in this file (global_fields[]). + */ struct global_parse_data { + /* Configuration variable name */ char *name; + + /* Parser function for this variable. The parser functions return 0 or 1 + * to indicate success. Value 0 indicates that the parameter value may + * have changed while value 1 means that the value did not change. + * Error cases (failure to parse the string) are indicated by returning + * -1. */ int (*parser)(const struct global_parse_data *data, struct wpa_config *config, int line, const char *value); + + /* Getter function to print the variable in text format to buf. */ int (*get)(const char *name, struct wpa_config *config, long offset, char *buf, size_t buflen, int pretty_print); + + /* Variable specific parameters for the parser. */ void *param1, *param2, *param3; + + /* Indicates which configuration variable has changed. */ unsigned int changed_flag; }; @@ -4344,6 +4401,7 @@ static int wpa_global_config_parse_int(const struct global_parse_data *data, { int val, *dst; char *end; + bool same; dst = (int *) (((u8 *) config) + (long) data->param1); val = strtol(pos, &end, 0); @@ -4352,6 +4410,7 @@ static int wpa_global_config_parse_int(const struct global_parse_data *data, line, pos); return -1; } + same = *dst == val; *dst = val; wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst); @@ -4372,7 +4431,7 @@ static int wpa_global_config_parse_int(const struct global_parse_data *data, return -1; } - return 0; + return same; } @@ -4380,7 +4439,7 @@ static int wpa_global_config_parse_str(const struct global_parse_data *data, struct wpa_config *config, int line, const char *pos) { - size_t len; + size_t len, prev_len; char **dst, *tmp; len = os_strlen(pos); @@ -4404,11 +4463,20 @@ static int wpa_global_config_parse_str(const struct global_parse_data *data, return -1; } + dst = (char **) (((u8 *) config) + (long) data->param1); + if (*dst) + prev_len = os_strlen(*dst); + else + prev_len = 0; + + /* No change to the previously configured value */ + if (*dst && prev_len == len && os_memcmp(*dst, pos, len) == 0) + return 1; + tmp = os_strdup(pos); if (tmp == NULL) return -1; - dst = (char **) (((u8 *) config) + (long) data->param1); os_free(*dst); *dst = tmp; wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst); @@ -4449,6 +4517,10 @@ static int wpa_global_config_parse_bin(const struct global_parse_data *data, return -1; dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1); + if (wpabuf_cmp(*dst, tmp) == 0) { + wpabuf_free(tmp); + return 1; + } wpabuf_free(*dst); *dst = tmp; wpa_printf(MSG_DEBUG, "%s", data->name); @@ -4476,6 +4548,26 @@ static int wpa_config_process_freq_list(const struct global_parse_data *data, } +static int +wpa_config_process_initial_freq_list(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *value) +{ + int *freqs; + + freqs = wpa_config_parse_int_array(value); + if (!freqs) + return -1; + if (freqs[0] == 0) { + os_free(freqs); + freqs = NULL; + } + os_free(config->initial_freq_list); + config->initial_freq_list = freqs; + return 0; +} + + #ifdef CONFIG_P2P static int wpa_global_config_parse_ipv4(const struct global_parse_data *data, struct wpa_config *config, int line, @@ -4490,6 +4582,8 @@ static int wpa_global_config_parse_ipv4(const struct global_parse_data *data, return -1; dst = (u32 *) (((u8 *) config) + (long) data->param1); + if (os_memcmp(dst, &addr.u.v4.s_addr, 4) == 0) + return 1; os_memcpy(dst, &addr.u.v4.s_addr, 4); wpa_printf(MSG_DEBUG, "%s = 0x%x", data->name, WPA_GET_BE32((u8 *) dst)); @@ -4507,6 +4601,8 @@ static int wpa_config_process_country(const struct global_parse_data *data, wpa_printf(MSG_DEBUG, "Invalid country set"); return -1; } + if (pos[0] == config->country[0] && pos[1] == config->country[1]) + return 1; config->country[0] = pos[0]; config->country[1] = pos[1]; wpa_printf(MSG_DEBUG, "country='%c%c'", @@ -4640,7 +4736,7 @@ static int wpa_config_process_p2p_pref_chan( struct wpa_config *config, int line, const char *pos) { struct p2p_channel *pref = NULL, *n; - unsigned int num = 0; + size_t num = 0; const char *pos2; u8 op_class, chan; @@ -4891,7 +4987,7 @@ static const struct global_parse_data global_fields[] = { { INT_RANGE(eapol_version, 1, 2), 0 }, #endif /* CONFIG_MACSEC */ { INT(ap_scan), 0 }, - { FUNC(bgscan), 0 }, + { FUNC(bgscan), CFG_CHANGED_BGSCAN }, #ifdef CONFIG_MESH { INT(user_mpm), 0 }, { INT_RANGE(max_peer_links, 0, 255), 0 }, @@ -4965,6 +5061,7 @@ static const struct global_parse_data global_fields[] = { { INT(p2p_device_random_mac_addr), 0 }, { FUNC(p2p_device_persistent_mac_addr), 0 }, { INT(p2p_interface_random_mac_addr), 0 }, + { INT(p2p_6ghz_disable), 0 }, #endif /* CONFIG_P2P */ { FUNC(country), CFG_CHANGED_COUNTRY }, { INT(bss_max_count), 0 }, @@ -5006,6 +5103,7 @@ static const struct global_parse_data global_fields[] = { { FUNC(ap_vendor_elements), 0 }, { INT_RANGE(ignore_old_scan_res, 0, 1), 0 }, { FUNC(freq_list), 0 }, + { FUNC(initial_freq_list), 0}, { INT(scan_cur_freq), 0 }, { INT(sched_scan_interval), 0 }, { INT(sched_scan_start_delay), 0 }, @@ -5048,6 +5146,7 @@ static const struct global_parse_data global_fields[] = { { INT_RANGE(coloc_intf_reporting, 0, 1), 0 }, #ifdef CONFIG_WNM { INT_RANGE(disable_btm, 0, 1), CFG_CHANGED_DISABLE_BTM }, + { INT_RANGE(extended_key_id, 0, 1), 0 }, #endif /* CONFIG_WNM */ }; @@ -5124,6 +5223,19 @@ const char * wpa_config_get_global_field_name(unsigned int i, int *no_var) } +/** + * wpa_config_process_global - Set a variable in global configuration + * @config: Pointer to global configuration data + * @pos: Name and value in the format "{name}={value}" + * @line: Line number in configuration file or 0 if not used + * Returns: 0 on success with a possible change in value, 1 on success with no + * change to previously configured value, or -1 on failure + * + * This function can be used to set global configuration variables based on + * both the configuration file and management interface input. The value + * parameter must be in the same format as the text-based configuration file is + * using. For example, strings are using double quotation marks. + */ int wpa_config_process_global(struct wpa_config *config, char *pos, int line) { size_t i; @@ -5136,11 +5248,14 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line) pos[flen] != '=') continue; - if (field->parser(field, config, line, pos + flen + 1)) { + ret = field->parser(field, config, line, pos + flen + 1); + if (ret < 0) { wpa_printf(MSG_ERROR, "Line %d: failed to " "parse '%s'.", line, pos); ret = -1; } + if (ret == 1) + break; if (field->changed_flag == CFG_CHANGED_NFC_PASSWORD_TOKEN) config->wps_nfc_pw_from_config = 1; config->changed_parameters |= field->changed_flag; @@ -5148,6 +5263,26 @@ int wpa_config_process_global(struct wpa_config *config, char *pos, int line) } if (i == NUM_GLOBAL_FIELDS) { #ifdef CONFIG_AP + if (os_strncmp(pos, "tx_queue_", 9) == 0) { + char *tmp = os_strchr(pos, '='); + + if (!tmp) { + if (line < 0) + wpa_printf(MSG_ERROR, + "Line %d: invalid line %s", + line, pos); + return -1; + } + *tmp++ = '\0'; + if (hostapd_config_tx_queue(config->tx_queue, pos, + tmp)) { + wpa_printf(MSG_ERROR, + "Line %d: invalid TX queue item", + line); + return -1; + } + } + if (os_strncmp(pos, "wmm_ac_", 7) == 0) { char *tmp = os_strchr(pos, '='); if (tmp == NULL) { diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index b3c779233..d128cd9bf 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -44,6 +44,7 @@ #define DEFAULT_MBO_CELL_CAPA MBO_CELL_CAPA_NOT_SUPPORTED #define DEFAULT_DISASSOC_IMMINENT_RSSI_THRESHOLD -75 #define DEFAULT_OCE_SUPPORT OCE_STA +#define DEFAULT_EXTENDED_KEY_ID 0 #include "config_ssid.h" #include "wps/wps.h" @@ -332,7 +333,7 @@ struct wpa_cred { */ unsigned int max_bss_load; - unsigned int num_req_conn_capab; + size_t num_req_conn_capab; u8 *req_conn_capab_proto; int **req_conn_capab_port; @@ -375,6 +376,7 @@ struct wpa_cred { #define CFG_CHANGED_SCHED_SCAN_PLANS BIT(17) #define CFG_CHANGED_WOWLAN_TRIGGERS BIT(18) #define CFG_CHANGED_DISABLE_BTM BIT(19) +#define CFG_CHANGED_BGSCAN BIT(20) /** * struct wpa_config - wpa_supplicant configuration data @@ -403,7 +405,7 @@ struct wpa_config { * This indicates how many per-priority network lists are included in * pssid. */ - int num_prio; + size_t num_prio; /** * cred - Head of the credential list @@ -648,7 +650,7 @@ struct wpa_config { * This variable control whether wpa_supplicant is allow to re-write * its configuration with wpa_config_write(). If this is zero, * configuration data is only changed in memory and the external data - * is not overriden. If this is non-zero, wpa_supplicant will update + * is not overridden. If this is non-zero, wpa_supplicant will update * the configuration data (e.g., a file) whenever configuration is * changed. This update may replace the old configuration which can * remove comments from it in case of a text file configuration. @@ -778,6 +780,8 @@ struct wpa_config { int p2p_ignore_shared_freq; int p2p_optimize_listen_chan; + int p2p_6ghz_disable; + struct wpabuf *wps_vendor_ext_m1; #define MAX_WPS_VENDOR_EXT 10 @@ -912,6 +916,19 @@ struct wpa_config { */ int *freq_list; + /** + * initial_freq_list - like freq_list but for initial scan + * + * This is an optional zero-terminated array of frequencies in + * megahertz (MHz) to allow for narrowing scanning range when + * the application is started. + * + * This can be used to speed up initial connection time if the + * channel is known ahead of time, without limiting the scanned + * frequencies during normal use. + */ + int *initial_freq_list; + /** * scan_cur_freq - Whether to scan only the current channel * @@ -973,7 +990,7 @@ struct wpa_config { int go_venue_type; /** - * hessid - Homogenous ESS identifier + * hessid - Homogeneous ESS identifier * * If this is set (any octet is non-zero), scans will be used to * request response only from BSSes belonging to the specified @@ -1057,6 +1074,7 @@ struct wpa_config { int p2p_go_max_inactivity; struct hostapd_wmm_ac_params wmm_ac_params[4]; + struct hostapd_tx_queue_params tx_queue[4]; /** * auto_interworking - Whether to use network selection automatically @@ -1570,6 +1588,17 @@ struct wpa_config { * By default BSS transition management is enabled */ int disable_btm; + + /** + * extended_key_id - Extended Key ID support + * + * IEEE Std 802.11-2016 optionally allows to use Key ID 0 and 1 for PTK + * keys with Extended Key ID. + * + * 0 = don't use Extended Key ID + * 1 = use Extended Key ID when possible + */ + int extended_key_id; }; diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index fd2bdff48..cb04a78a2 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -213,8 +213,22 @@ static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id) } } - if (wpa_config_set(ssid, pos, pos2, *line) < 0) + if (wpa_config_set(ssid, pos, pos2, *line) < 0) { +#ifndef CONFIG_WEP + if (os_strcmp(pos, "wep_key0") == 0 || + os_strcmp(pos, "wep_key1") == 0 || + os_strcmp(pos, "wep_key2") == 0 || + os_strcmp(pos, "wep_key3") == 0 || + os_strcmp(pos, "wep_tx_keyidx") == 0) { + wpa_printf(MSG_ERROR, + "Line %d: unsupported WEP parameter", + *line); + ssid->disabled = 1; + continue; + } +#endif /* CONFIG_WEP */ errors++; + } } if (!end) { @@ -653,6 +667,7 @@ static void write_eap(FILE *f, struct wpa_ssid *ssid) #endif /* IEEE8021X_EAPOL */ +#ifdef CONFIG_WEP static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) { char field[20], *value; @@ -667,6 +682,7 @@ static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) os_free(value); } } +#endif /* CONFIG_WEP */ #ifdef CONFIG_P2P @@ -741,8 +757,6 @@ static void write_mka_ckn(FILE *f, struct wpa_ssid *ssid) static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) { - int i; - #define STR(t) write_str(f, #t, ssid) #define INT(t) write_int(f, #t, ssid->t, 0) #define INTe(t, m) write_int(f, #t, ssid->eap.m, 0) @@ -831,9 +845,15 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(openssl_ciphers); INTe(erp, erp); #endif /* IEEE8021X_EAPOL */ - for (i = 0; i < 4; i++) - write_wep_key(f, i, ssid); - INT(wep_tx_keyidx); +#ifdef CONFIG_WEP + { + int i; + + for (i = 0; i < 4; i++) + write_wep_key(f, i, ssid); + INT(wep_tx_keyidx); + } +#endif /* CONFIG_WEP */ INT(priority); #ifdef IEEE8021X_EAPOL INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); @@ -856,9 +876,10 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) write_int(f, "proactive_key_caching", ssid->proactive_key_caching, -1); INT(disabled); INT(mixed_cell); - INT(vht); + INT_DEF(vht, 1); INT_DEF(ht, 1); INT(ht40); + INT_DEF(he, 1); INT_DEF(max_oper_chwidth, DEFAULT_MAX_OPER_CHWIDTH); INT(vht_center_freq1); INT(vht_center_freq2); @@ -900,6 +921,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD); #endif /* CONFIG_MESH */ INT(wpa_ptk_rekey); + INT(wpa_deny_ptk0_rekey); INT(group_rekey); INT(ignore_broadcast_ssid); #ifdef CONFIG_DPP @@ -907,12 +929,17 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) STR(dpp_netaccesskey); INT(dpp_netaccesskey_expiry); STR(dpp_csign); + STR(dpp_pp_key); + INT(dpp_pfs); #endif /* CONFIG_DPP */ INT(owe_group); INT(owe_only); INT(owe_ptk_workaround); INT(multi_ap_backhaul_sta); INT(ft_eap_pmksa_caching); + INT(beacon_prot); + INT(transition_disable); + INT(sae_pk); #ifdef CONFIG_HT_OVERRIDES INT_DEF(disable_ht, DEFAULT_DISABLE_HT); INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40); @@ -947,6 +974,9 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT_DEF(vht_tx_mcs_nss_7, -1); INT_DEF(vht_tx_mcs_nss_8, -1); #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + INT(disable_he); +#endif /* CONFIG_HE_OVERRIDES */ #undef STR #undef INT @@ -1305,6 +1335,10 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) if (config->p2p_go_freq_change_policy != DEFAULT_P2P_GO_FREQ_MOVE) fprintf(f, "p2p_go_freq_change_policy=%u\n", config->p2p_go_freq_change_policy); + + if (config->p2p_6ghz_disable) + fprintf(f, "p2p_6ghz_disable=%d\n", config->p2p_6ghz_disable); + if (WPA_GET_BE32(config->ip_addr_go)) fprintf(f, "ip_addr_go=%u.%u.%u.%u\n", config->ip_addr_go[0], config->ip_addr_go[1], @@ -1441,6 +1475,15 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) } fprintf(f, "\n"); } + if (config->initial_freq_list && config->initial_freq_list[0]) { + int i; + fprintf(f, "initial_freq_list="); + for (i = 0; config->initial_freq_list[i]; i++) { + fprintf(f, "%s%d", i > 0 ? " " : "", + config->initial_freq_list[i]); + } + fprintf(f, "\n"); + } if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ) fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq); @@ -1574,6 +1617,9 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) config->p2p_interface_random_mac_addr); if (config->disable_btm) fprintf(f, "disable_btm=1\n"); + if (config->extended_key_id != DEFAULT_EXTENDED_KEY_ID) + fprintf(f, "extended_key_id=%d\n", + config->extended_key_id); } #endif /* CONFIG_NO_CONFIG_WRITE */ @@ -1590,9 +1636,16 @@ int wpa_config_write(const char *name, struct wpa_config *config) #endif /* CONFIG_NO_CONFIG_BLOBS */ int ret = 0; const char *orig_name = name; - int tmp_len = os_strlen(name) + 5; /* allow space for .tmp suffix */ - char *tmp_name = os_malloc(tmp_len); + int tmp_len; + char *tmp_name; + if (!name) { + wpa_printf(MSG_ERROR, "No configuration file for writing"); + return -1; + } + + tmp_len = os_strlen(name) + 5; /* allow space for .tmp suffix */ + tmp_name = os_malloc(tmp_len); if (tmp_name) { os_snprintf(tmp_name, tmp_len, "%s.tmp", name); name = tmp_name; @@ -1620,8 +1673,11 @@ int wpa_config_write(const char *name, struct wpa_config *config) for (ssid = config->ssid; ssid; ssid = ssid->next) { if (ssid->key_mgmt == WPA_KEY_MGMT_WPS || ssid->temporary) continue; /* do not save temporary networks */ - if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && - !ssid->passphrase) + if (wpa_key_mgmt_wpa_psk_no_sae(ssid->key_mgmt) && + !ssid->psk_set && !ssid->passphrase) + continue; /* do not save invalid network */ + if (wpa_key_mgmt_sae(ssid->key_mgmt) && + !ssid->passphrase && !ssid->sae_password) continue; /* do not save invalid network */ fprintf(f, "\nnetwork={\n"); wpa_config_write_network(f, ssid); diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index b752dfdda..b4fdc8a17 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -19,8 +19,13 @@ EAPOL_FLAG_REQUIRE_KEY_BROADCAST) #define DEFAULT_PROTO (WPA_PROTO_WPA | WPA_PROTO_RSN) #define DEFAULT_KEY_MGMT (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X) +#ifdef CONFIG_NO_TKIP +#define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP) +#define DEFAULT_GROUP (WPA_CIPHER_CCMP) +#else /* CONFIG_NO_TKIP */ #define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) #define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) +#endif /* CONFIG_NO_TKIP */ #define DEFAULT_FRAGMENT_SIZE 1398 #define DEFAULT_BG_SCAN_PERIOD -1 @@ -57,6 +62,12 @@ enum wpas_mode { WPAS_MODE_MESH = 5, }; +enum sae_pk_mode { + SAE_PK_MODE_AUTOMATIC = 0, + SAE_PK_MODE_ONLY = 1, + SAE_PK_MODE_DISABLED = 2, +}; + /** * struct wpa_ssid - Network configuration data * @@ -300,6 +311,7 @@ struct wpa_ssid { struct eap_peer_config eap; #endif /* IEEE8021X_EAPOL */ +#ifdef CONFIG_WEP #define NUM_WEP_KEYS 4 #define MAX_WEP_KEY_LEN 16 /** @@ -316,6 +328,7 @@ struct wpa_ssid { * wep_tx_keyidx - Default key index for TX frames using WEP */ int wep_tx_keyidx; +#endif /* CONFIG_WEP */ /** * proactive_key_caching - Enable proactive key caching @@ -553,6 +566,19 @@ struct wpa_ssid { */ int wpa_ptk_rekey; + /** wpa_deny_ptk0_rekey - Control PTK0 rekeying + * + * Rekeying a pairwise key using only keyid 0 (PTK0 rekey) has many + * broken implementations and should be avoided when using or + * interacting with one. + * + * 0 = always rekey when configured/instructed + * 1 = only rekey when the local driver is explicitly indicating it can + * perform this operation without issues + * 2 = never allow PTK0 rekeys + */ + enum ptk0_rekey_handling wpa_deny_ptk0_rekey; + /** * group_rekey - Group rekeying time in seconds * @@ -764,6 +790,16 @@ struct wpa_ssid { vht_tx_mcs_nss_7, vht_tx_mcs_nss_8; #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + /** + * disable_he - Disable HE (IEEE 802.11ax) for this network + * + * By default, use it if it is available, but this can be configured + * to 1 to have it disabled. + */ + int disable_he; +#endif /* CONFIG_HE_OVERRIDES */ + /** * ap_max_inactivity - Timeout in seconds to detect STA's inactivity * @@ -987,6 +1023,32 @@ struct wpa_ssid { */ size_t dpp_csign_len; + /** + * dpp_pp_key - ppKey (Configurator privacy protection public key) + */ + u8 *dpp_pp_key; + + /** + * dpp_pp_key_len - ppKey length in octets + */ + size_t dpp_pp_key_len; + + /** + * dpp_pfs - DPP PFS + * 0: allow PFS to be used or not used + * 1: require PFS to be used (note: not compatible with DPP R1) + * 2: do not allow PFS to be used + */ + int dpp_pfs; + + /** + * dpp_pfs_fallback - DPP PFS fallback selection + * + * This is an internally used variable (i.e., not used in external + * configuration) to track state of the DPP PFS fallback mechanism. + */ + int dpp_pfs_fallback; + /** * owe_group - OWE DH Group * @@ -1047,6 +1109,53 @@ struct wpa_ssid { * FT initial mobility domain association. */ int ft_eap_pmksa_caching; + + /** + * beacon_prot - Whether Beacon protection is enabled + * + * This depends on management frame protection (ieee80211w) being + * enabled. + */ + int beacon_prot; + + /** + * transition_disable - Transition Disable indication + * The AP can notify authenticated stations to disable transition mode + * in their network profiles when the network has completed transition + * steps, i.e., once sufficiently large number of APs in the ESS have + * been updated to support the more secure alternative. When this + * indication is used, the stations are expected to automatically + * disable transition mode and less secure security options. This + * includes use of WEP, TKIP (including use of TKIP as the group + * cipher), and connections without PMF. + * Bitmap bits: + * bit 0 (0x01): WPA3-Personal (i.e., disable WPA2-Personal = WPA-PSK + * and only allow SAE to be used) + * bit 1 (0x02): SAE-PK (disable SAE without use of SAE-PK) + * bit 2 (0x04): WPA3-Enterprise (move to requiring PMF) + * bit 3 (0x08): Enhanced Open (disable use of open network; require + * OWE) + */ + u8 transition_disable; + + /** + * sae_pk - SAE-PK mode + * 0 = automatic SAE/SAE-PK selection based on password; enable + * transition mode (allow SAE authentication without SAE-PK) + * 1 = SAE-PK only (disable transition mode; allow SAE authentication + * only with SAE-PK) + * 2 = disable SAE-PK (allow SAE authentication only without SAE-PK) + */ + enum sae_pk_mode sae_pk; + + /** + * was_recently_reconfigured - Whether this SSID config has been changed + * recently + * + * This is an internally used variable, i.e., not used in external + * configuration. + */ + bool was_recently_reconfigured; }; #endif /* CONFIG_SSID_H */ diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c index 0f2a30a46..1b7f96ed2 100644 --- a/wpa_supplicant/config_winreg.c +++ b/wpa_supplicant/config_winreg.c @@ -277,6 +277,15 @@ static int wpa_config_read_global(struct wpa_config *config, HKEY hk) wpa_config_read_reg_dword(hk, TEXT("okc"), &config->okc); wpa_config_read_reg_dword(hk, TEXT("pmf"), &val); config->pmf = val; + if (wpa_config_read_reg_dword(hk, TEXT("extended_key_id"), + &val) == 0) { + if (val < 0 || val > 1) { + wpa_printf(MSG_ERROR, + "Invalid Extended Key ID setting (%d)", val); + errors++; + } + config->extended_key_id = val; + } return errors ? -1 : 0; } @@ -823,6 +832,7 @@ static void write_eap(HKEY hk, struct wpa_ssid *ssid) #endif /* IEEE8021X_EAPOL */ +#ifdef CONFIG_WEP static void write_wep_key(HKEY hk, int idx, struct wpa_ssid *ssid) { char field[20], *value; @@ -834,11 +844,12 @@ static void write_wep_key(HKEY hk, int idx, struct wpa_ssid *ssid) os_free(value); } } +#endif /* CONFIG_WEP */ static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id) { - int i, errors = 0; + int errors = 0; HKEY nhk, netw; LONG ret; TCHAR name[5]; @@ -924,9 +935,15 @@ static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id) INTe(engine2, phase2_cert.engine); INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS); #endif /* IEEE8021X_EAPOL */ - for (i = 0; i < 4; i++) - write_wep_key(netw, i, ssid); - INT(wep_tx_keyidx); +#ifdef CONFIG_WEP + { + int i; + + for (i = 0; i < 4; i++) + write_wep_key(netw, i, ssid); + INT(wep_tx_keyidx); + } +#endif /* CONFIG_WEP */ INT(priority); #ifdef IEEE8021X_EAPOL INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND); diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 6d996c473..428bddef0 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -1,7 +1,7 @@ /* * WPA Supplicant / Control interface (shared code for all backends) * Copyright (c) 2020, Mathy Vanhoef - * Copyright (c) 2004-2019, Jouni Malinen + * Copyright (c) 2004-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -306,20 +306,30 @@ static int wpas_ctrl_pno(struct wpa_supplicant *wpa_s, char *cmd) } -static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *band) +static int wpas_ctrl_set_band(struct wpa_supplicant *wpa_s, char *bands) { union wpa_event_data event; + u32 setband_mask = WPA_SETBAND_AUTO; - if (os_strcmp(band, "AUTO") == 0) - wpa_s->setband = WPA_SETBAND_AUTO; - else if (os_strcmp(band, "5G") == 0) - wpa_s->setband = WPA_SETBAND_5G; - else if (os_strcmp(band, "2G") == 0) - wpa_s->setband = WPA_SETBAND_2G; - else - return -1; + /* + * For example: + * SET setband 2G,6G + * SET setband 5G + * SET setband AUTO + */ + if (!os_strstr(bands, "AUTO")) { + if (os_strstr(bands, "5G")) + setband_mask |= WPA_SETBAND_5G; + if (os_strstr(bands, "6G")) + setband_mask |= WPA_SETBAND_6G; + if (os_strstr(bands, "2G")) + setband_mask |= WPA_SETBAND_2G; + if (setband_mask == WPA_SETBAND_AUTO) + return -1; + } - if (wpa_drv_setband(wpa_s, wpa_s->setband) == 0) { + wpa_s->setband_mask = setband_mask; + if (wpa_drv_setband(wpa_s, wpa_s->setband_mask) == 0) { os_memset(&event, 0, sizeof(event)); event.channel_list_changed.initiator = REGDOM_SET_BY_USER; event.channel_list_changed.type = REGDOM_TYPE_UNKNOWN; @@ -703,6 +713,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, ret = -1; else dpp_nonce_override_len = hex_len / 2; + } else if (os_strcasecmp(cmd, "dpp_version_override") == 0) { + dpp_version_override = atoi(value); #endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_DPP */ #ifdef CONFIG_TESTING_OPTIONS @@ -728,6 +740,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, wpa_s->ignore_assoc_disallow = !!atoi(value); wpa_drv_ignore_assoc_disallow(wpa_s, wpa_s->ignore_assoc_disallow); + } else if (os_strcasecmp(cmd, "disable_sa_query") == 0) { + wpa_s->disable_sa_query = !!atoi(value); } else if (os_strcasecmp(cmd, "ignore_sae_h2e_only") == 0) { wpa_s->ignore_sae_h2e_only = !!atoi(value); } else if (os_strcasecmp(cmd, "extra_sae_rejected_groups") == 0) { @@ -752,6 +766,34 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, break; pos++; } + } else if (os_strcasecmp(cmd, "ft_rsnxe_used") == 0) { + wpa_s->ft_rsnxe_used = atoi(value); + } else if (os_strcasecmp(cmd, "oci_freq_override_eapol") == 0) { + wpa_s->oci_freq_override_eapol = atoi(value); + } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_req") == 0) { + wpa_s->oci_freq_override_saquery_req = atoi(value); + } else if (os_strcasecmp(cmd, "oci_freq_override_saquery_resp") == 0) { + wpa_s->oci_freq_override_saquery_resp = atoi(value); + } else if (os_strcasecmp(cmd, "oci_freq_override_eapol_g2") == 0) { + wpa_s->oci_freq_override_eapol_g2 = atoi(value); + /* Populate value to wpa_sm if already associated. */ + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2, + wpa_s->oci_freq_override_eapol_g2); + } else if (os_strcasecmp(cmd, "oci_freq_override_ft_assoc") == 0) { + wpa_s->oci_freq_override_ft_assoc = atoi(value); + /* Populate value to wpa_sm if already associated. */ + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC, + wpa_s->oci_freq_override_ft_assoc); + } else if (os_strcasecmp(cmd, "oci_freq_override_fils_assoc") == 0) { + wpa_s->oci_freq_override_fils_assoc = atoi(value); + } else if (os_strcasecmp(cmd, "oci_freq_override_wnm_sleep") == 0) { + wpa_s->oci_freq_override_wnm_sleep = atoi(value); + } else if (os_strcasecmp(cmd, "rsne_override_eapol") == 0) { + wpabuf_free(wpa_s->rsne_override_eapol); + if (os_strcmp(value, "NULL") == 0) + wpa_s->rsne_override_eapol = NULL; + else + wpa_s->rsne_override_eapol = wpabuf_parse_bin(value); } else if (os_strcasecmp(cmd, "rsnxe_override_assoc") == 0) { wpabuf_free(wpa_s->rsnxe_override_assoc); if (os_strcmp(value, "NULL") == 0) @@ -873,6 +915,8 @@ static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s, ret = wpa_config_process_global(wpa_s->conf, cmd, -1); if (ret == 0) wpa_supplicant_update_config(wpa_s); + else if (ret == 1) + ret = 0; } return ret; @@ -888,6 +932,8 @@ static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, if (os_strcmp(cmd, "version") == 0) { res = os_snprintf(buf, buflen, "%s", VERSION_STR); + } else if (os_strcasecmp(cmd, "max_command_len") == 0) { + res = os_snprintf(buf, buflen, "%u", CTRL_IFACE_MAX_LEN); } else if (os_strcasecmp(cmd, "country") == 0) { if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) res = os_snprintf(buf, buflen, "%c%c", @@ -925,6 +971,8 @@ static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, return wpa_snprintf_hex(buf, buflen, wpa_sm_get_anonce(wpa_s->wpa), WPA_NONCE_LEN); + } else if (os_strcasecmp(cmd, "last_tk_key_idx") == 0) { + res = os_snprintf(buf, buflen, "%d", wpa_s->last_tk_key_idx); #endif /* CONFIG_TESTING_OPTIONS */ } else { res = wpa_config_get_value(cmd, wpa_s->conf, buf, buflen); @@ -2275,8 +2323,12 @@ static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s, !wpa_s->ap_iface && #endif /* CONFIG_AP */ wpa_s->sme.sae.state == SAE_ACCEPTED) { - ret = os_snprintf(pos, end - pos, "sae_group=%d\n", - wpa_s->sme.sae.group); + ret = os_snprintf(pos, end - pos, "sae_group=%d\n" + "sae_h2e=%d\n" + "sae_pk=%d\n", + wpa_s->sme.sae.group, + wpa_s->sme.sae.h2e, + wpa_s->sme.sae.pk); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; @@ -2932,7 +2984,7 @@ static int wpa_supplicant_ctrl_iface_scan_result( { char *pos, *end; int ret; - const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe; + const u8 *ie, *ie2, *osen_ie, *p2p, *mesh, *owe, *rsnxe; mesh = wpa_bss_get_ie(bss, WLAN_EID_MESH_ID); p2p = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); @@ -2959,6 +3011,21 @@ static int wpa_supplicant_ctrl_iface_scan_result( pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2", ie2, 2 + ie2[1]); } + rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); + if (rsnxe && rsnxe[1] >= 1) { + if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) { + ret = os_snprintf(pos, end - pos, "[SAE-H2E]"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) { + ret = os_snprintf(pos, end - pos, "[SAE-PK]"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + } osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); if (osen_ie) pos = wpa_supplicant_ie_txt(pos, end, "OSEN", @@ -2987,8 +3054,7 @@ static int wpa_supplicant_ctrl_iface_scan_result( if (bss_is_dmg(bss)) { const char *s; - if (get_ie_ext((const u8 *) (bss + 1), bss->ie_len, - WLAN_EID_EXT_EDMG_OPERATION)) { + if (wpa_bss_get_ie_ext(bss, WLAN_EID_EXT_EDMG_OPERATION)) { ret = os_snprintf(pos, end - pos, "[EDMG]"); if (os_snprintf_error(end - pos, ret)) return -1; @@ -3437,38 +3503,12 @@ static int wpa_supplicant_ctrl_iface_remove_network( struct wpa_supplicant *wpa_s, char *cmd) { int id; - struct wpa_ssid *ssid; int result; /* cmd: "" or "all" */ if (os_strcmp(cmd, "all") == 0) { wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all"); - if (wpa_s->sched_scanning) - wpa_supplicant_cancel_sched_scan(wpa_s); - - eapol_sm_invalidate_cached_session(wpa_s->eapol); - if (wpa_s->current_ssid) { -#ifdef CONFIG_SME - wpa_s->sme.prev_bssid_set = 0; -#endif /* CONFIG_SME */ - wpa_sm_set_config(wpa_s->wpa, NULL); - eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); - if (wpa_s->wpa_state >= WPA_AUTHENTICATING) - wpa_s->own_disconnect_req = 1; - wpa_supplicant_deauthenticate( - wpa_s, WLAN_REASON_DEAUTH_LEAVING); - } - ssid = wpa_s->conf->ssid; - while (ssid) { - struct wpa_ssid *remove_ssid = ssid; - id = ssid->id; - ssid = ssid->next; - if (wpa_s->last_ssid == remove_ssid) - wpa_s->last_ssid = NULL; - wpas_notify_network_removed(wpa_s, remove_ssid); - wpa_config_remove_network(wpa_s->conf, id); - } - return 0; + return wpa_supplicant_remove_all_networks(wpa_s); } id = atoi(cmd); @@ -3504,6 +3544,20 @@ static int wpa_supplicant_ctrl_iface_update_network( if (ret == 1) return 0; /* No change to the previously configured value */ +#ifdef CONFIG_BGSCAN + if (os_strcmp(name, "bgscan") == 0) { + /* + * Reset the bgscan parameters for the current network and + * return. There's no need to flush caches for bgscan parameter + * changes. + */ + if (wpa_s->current_ssid == ssid && + wpa_s->wpa_state == WPA_COMPLETED) + wpa_supplicant_reset_bgscan(wpa_s); + return 0; + } +#endif /* CONFIG_BGSCAN */ + if (os_strcmp(name, "bssid") != 0 && os_strcmp(name, "bssid_hint") != 0 && os_strcmp(name, "priority") != 0) { @@ -3961,10 +4015,14 @@ static const struct cipher_info ciphers[] = { { WPA_DRIVER_CAPA_ENC_GCMP_256, "GCMP-256", 0 }, { WPA_DRIVER_CAPA_ENC_CCMP, "CCMP", 0 }, { WPA_DRIVER_CAPA_ENC_GCMP, "GCMP", 0 }, +#ifndef CONFIG_NO_TKIP { WPA_DRIVER_CAPA_ENC_TKIP, "TKIP", 0 }, +#endif /* CONFIG_NO_TKIP */ { WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE, "NONE", 0 }, +#ifdef CONFIG_WEP { WPA_DRIVER_CAPA_ENC_WEP104, "WEP104", 1 }, { WPA_DRIVER_CAPA_ENC_WEP40, "WEP40", 1 } +#endif /* CONFIG_WEP */ }; static const struct cipher_info ciphers_group_mgmt[] = { @@ -3975,7 +4033,7 @@ static const struct cipher_info ciphers_group_mgmt[] = { }; -static int ctrl_iface_get_capability_pairwise(int res, char *strict, +static int ctrl_iface_get_capability_pairwise(int res, bool strict, struct wpa_driver_capa *capa, char *buf, size_t buflen) { @@ -3990,7 +4048,11 @@ static int ctrl_iface_get_capability_pairwise(int res, char *strict, if (res < 0) { if (strict) return 0; +#ifdef CONFIG_NO_TKIP + len = os_strlcpy(buf, "CCMP NONE", buflen); +#else /* CONFIG_NO_TKIP */ len = os_strlcpy(buf, "CCMP TKIP NONE", buflen); +#endif /* CONFIG_NO_TKIP */ if (len >= buflen) return -1; return len; @@ -4011,7 +4073,7 @@ static int ctrl_iface_get_capability_pairwise(int res, char *strict, } -static int ctrl_iface_get_capability_group(int res, char *strict, +static int ctrl_iface_get_capability_group(int res, bool strict, struct wpa_driver_capa *capa, char *buf, size_t buflen) { @@ -4026,7 +4088,19 @@ static int ctrl_iface_get_capability_group(int res, char *strict, if (res < 0) { if (strict) return 0; +#ifdef CONFIG_WEP +#ifdef CONFIG_NO_TKIP + len = os_strlcpy(buf, "CCMP WEP104 WEP40", buflen); +#else /* CONFIG_NO_TKIP */ len = os_strlcpy(buf, "CCMP TKIP WEP104 WEP40", buflen); +#endif /* CONFIG_NO_TKIP */ +#else /* CONFIG_WEP */ +#ifdef CONFIG_NO_TKIP + len = os_strlcpy(buf, "CCMP", buflen); +#else /* CONFIG_NO_TKIP */ + len = os_strlcpy(buf, "CCMP TKIP", buflen); +#endif /* CONFIG_NO_TKIP */ +#endif /* CONFIG_WEP */ if (len >= buflen) return -1; return len; @@ -4047,7 +4121,7 @@ static int ctrl_iface_get_capability_group(int res, char *strict, } -static int ctrl_iface_get_capability_group_mgmt(int res, char *strict, +static int ctrl_iface_get_capability_group_mgmt(int res, bool strict, struct wpa_driver_capa *capa, char *buf, size_t buflen) { @@ -4076,11 +4150,49 @@ static int ctrl_iface_get_capability_group_mgmt(int res, char *strict, } -static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, +static int iftype_str_to_index(const char *iftype_str) +{ + if (!iftype_str) + return WPA_IF_MAX; + + if (os_strcmp(iftype_str, "STATION") == 0) + return WPA_IF_STATION; + + if (os_strcmp(iftype_str, "AP_VLAN") == 0) + return WPA_IF_AP_VLAN; + + if (os_strcmp(iftype_str, "AP") == 0) + return WPA_IF_AP_BSS; + + if (os_strcmp(iftype_str, "P2P_GO") == 0) + return WPA_IF_P2P_GO; + + if (os_strcmp(iftype_str, "P2P_CLIENT") == 0) + return WPA_IF_P2P_CLIENT; + + if (os_strcmp(iftype_str, "P2P_DEVICE") == 0) + return WPA_IF_P2P_DEVICE; + + if (os_strcmp(iftype_str, "MESH") == 0) + return WPA_IF_MESH; + + if (os_strcmp(iftype_str, "IBSS") == 0) + return WPA_IF_IBSS; + + if (os_strcmp(iftype_str, "NAN") == 0) + return WPA_IF_NAN; + + return WPA_IF_MAX; +} + + +static int ctrl_iface_get_capability_key_mgmt(int res, bool strict, struct wpa_driver_capa *capa, + const char *iftype_str, char *buf, size_t buflen) { int ret; + unsigned int key_mgmt; char *pos, *end; size_t len; @@ -4097,36 +4209,68 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, return len; } + if (iftype_str) { + enum wpa_driver_if_type iftype; + + iftype = iftype_str_to_index(iftype_str); + if (iftype == WPA_IF_MAX) + return -1; + key_mgmt = capa->key_mgmt_iftype[iftype]; + } else { + key_mgmt = capa->key_mgmt; + } + ret = os_snprintf(pos, end - pos, "NONE IEEE8021X"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; - if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { + if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) { ret = os_snprintf(pos, end - pos, " WPA-EAP"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } - if (capa->key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | - WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { + if (key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK | + WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { ret = os_snprintf(pos, end - pos, " WPA-PSK"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) { ret = os_snprintf(pos, end - pos, " WPA-NONE"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK) { + ret = os_snprintf(pos, end - pos, " WAPI-PSK"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_TPK_HANDSHAKE) { + ret = os_snprintf(pos, end - pos, " TPK-HANDSHAKE"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_CCKM) { + ret = os_snprintf(pos, end - pos, " CCKM"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + #ifdef CONFIG_SUITEB - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B) { ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4134,7 +4278,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_SUITEB */ #ifdef CONFIG_SUITEB192 - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192) { ret = os_snprintf(pos, end - pos, " WPA-EAP-SUITE-B-192"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4142,7 +4286,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_SUITEB192 */ #ifdef CONFIG_OWE - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OWE) { ret = os_snprintf(pos, end - pos, " OWE"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4150,7 +4294,7 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_OWE */ #ifdef CONFIG_DPP - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_DPP) { ret = os_snprintf(pos, end - pos, " DPP"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4158,26 +4302,26 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, } #endif /* CONFIG_DPP */ #ifdef CONFIG_FILS - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA256) { ret = os_snprintf(pos, end - pos, " FILS-SHA256"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FILS_SHA384) { ret = os_snprintf(pos, end - pos, " FILS-SHA384"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } #ifdef CONFIG_IEEE80211R - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA256) { ret = os_snprintf(pos, end - pos, " FT-FILS-SHA256"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_FILS_SHA384) { ret = os_snprintf(pos, end - pos, " FT-FILS-SHA384"); if (os_snprintf_error(end - pos, ret)) return pos - buf; @@ -4186,27 +4330,72 @@ static int ctrl_iface_get_capability_key_mgmt(int res, char *strict, #endif /* CONFIG_IEEE80211R */ #endif /* CONFIG_FILS */ #ifdef CONFIG_IEEE80211R - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK) { ret = os_snprintf(pos, end - pos, " FT-PSK"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) { + ret = os_snprintf(pos, end - pos, " FT-EAP"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#ifdef CONFIG_SAE + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_SAE) { + ret = os_snprintf(pos, end - pos, " FT-SAE"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_SAE */ +#ifdef CONFIG_SHA384 + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT_802_1X_SHA384) { + ret = os_snprintf(pos, end - pos, " FT-EAP-SHA384"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_SHA384 */ #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_SAE - if (capa->key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) { + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) { ret = os_snprintf(pos, end - pos, " SAE"); if (os_snprintf_error(end - pos, ret)) return pos - buf; pos += ret; } #endif /* CONFIG_SAE */ +#ifdef CONFIG_SHA256 + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_802_1X_SHA256) { + ret = os_snprintf(pos, end - pos, " WPA-EAP-SHA256"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_PSK_SHA256) { + ret = os_snprintf(pos, end - pos, " WPA-PSK-SHA256"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_SHA256 */ +#ifdef CONFIG_HS20 + if (key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_OSEN) { + ret = os_snprintf(pos, end - pos, " OSEN"); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_HS20 */ return pos - buf; } -static int ctrl_iface_get_capability_proto(int res, char *strict, +static int ctrl_iface_get_capability_proto(int res, bool strict, struct wpa_driver_capa *capa, char *buf, size_t buflen) { @@ -4249,7 +4438,7 @@ static int ctrl_iface_get_capability_proto(int res, char *strict, static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s, - int res, char *strict, + int res, bool strict, struct wpa_driver_capa *capa, char *buf, size_t buflen) { @@ -4327,7 +4516,7 @@ static int ctrl_iface_get_capability_auth_alg(struct wpa_supplicant *wpa_s, } -static int ctrl_iface_get_capability_modes(int res, char *strict, +static int ctrl_iface_get_capability_modes(int res, bool strict, struct wpa_driver_capa *capa, char *buf, size_t buflen) { @@ -4490,23 +4679,36 @@ static int wpa_supplicant_ctrl_iface_get_capability( { struct wpa_driver_capa capa; int res; - char *strict; - char field[30]; + char *next_param, *curr_param, *iftype = NULL; + bool strict = false; + char field[50]; size_t len; /* Determine whether or not strict checking was requested */ len = os_strlcpy(field, _field, sizeof(field)); if (len >= sizeof(field)) return -1; - strict = os_strchr(field, ' '); - if (strict != NULL) { - *strict++ = '\0'; - if (os_strcmp(strict, "strict") != 0) + + next_param = os_strchr(field, ' '); + while (next_param) { + *next_param++ = '\0'; + curr_param = next_param; + next_param = os_strchr(next_param, ' '); + + if (next_param) + *next_param = '\0'; + + if (os_strcmp(curr_param, "strict") == 0) + strict = true; + else if (os_strncmp(curr_param, "iftype=", 7) == 0) + iftype = curr_param + 7; + else return -1; } - wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s", - field, strict ? strict : ""); + wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'%s%s%s", + field, iftype ? " iftype=" : "", iftype ? iftype : "", + strict ? " strict" : ""); if (os_strcmp(field, "eap") == 0) { return eap_get_names(buf, buflen); @@ -4528,7 +4730,7 @@ static int wpa_supplicant_ctrl_iface_get_capability( if (os_strcmp(field, "key_mgmt") == 0) return ctrl_iface_get_capability_key_mgmt(res, strict, &capa, - buf, buflen); + iftype, buf, buflen); if (os_strcmp(field, "proto") == 0) return ctrl_iface_get_capability_proto(res, strict, &capa, @@ -4621,6 +4823,20 @@ static int wpa_supplicant_ctrl_iface_get_capability( } #endif /* CONFIG_DPP */ +#ifdef CONFIG_SAE + if (os_strcmp(field, "sae") == 0 && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) { +#ifdef CONFIG_SAE_PK + res = os_snprintf(buf, buflen, "H2E PK"); +#else /* CONFIG_SAE_PK */ + res = os_snprintf(buf, buflen, "H2E"); +#endif /* CONFIG_SAE_PK */ + if (os_snprintf_error(buflen, res)) + return -1; + return res; + } +#endif /* CONFIG_SAE */ + wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'", field); @@ -4741,7 +4957,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, size_t i; int ret; char *pos, *end; - const u8 *ie, *ie2, *osen_ie, *mesh, *owe; + const u8 *ie, *ie2, *osen_ie, *mesh, *owe, *rsnxe; pos = buf; end = buf + buflen; @@ -4830,7 +5046,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, return 0; pos += ret; - ie = (const u8 *) (bss + 1); + ie = wpa_bss_ie_ptr(bss); for (i = 0; i < bss->ie_len; i++) { ret = os_snprintf(pos, end - pos, "%02x", *ie++); if (os_snprintf_error(end - pos, ret)) @@ -4861,6 +5077,21 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, pos = wpa_supplicant_ie_txt(pos, end, mesh ? "RSN" : "WPA2", ie2, 2 + ie2[1]); + rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); + if (rsnxe && rsnxe[1] >= 1) { + if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)) { + ret = os_snprintf(pos, end - pos, "[SAE-H2E]"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + if (rsnxe[2] & BIT(WLAN_RSNX_CAPAB_SAE_PK)) { + ret = os_snprintf(pos, end - pos, "[SAE-PK]"); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + } osen_ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); if (osen_ie) pos = wpa_supplicant_ie_txt(pos, end, "OSEN", @@ -4982,7 +5213,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, #ifdef CONFIG_WPS if (mask & WPA_BSS_MASK_WPS_SCAN) { - ie = (const u8 *) (bss + 1); + ie = wpa_bss_ie_ptr(bss); ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end); if (ret >= end - pos) return 0; @@ -4993,7 +5224,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, #ifdef CONFIG_P2P if (mask & WPA_BSS_MASK_P2P_SCAN) { - ie = (const u8 *) (bss + 1); + ie = wpa_bss_ie_ptr(bss); ret = wpas_p2p_scan_result_text(ie, bss->ie_len, pos, end); if (ret >= end - pos) return 0; @@ -5005,7 +5236,8 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, #ifdef CONFIG_WIFI_DISPLAY if (mask & WPA_BSS_MASK_WIFI_DISPLAY) { struct wpabuf *wfd; - ie = (const u8 *) (bss + 1); + + ie = wpa_bss_ie_ptr(bss); wfd = ieee802_11_vendor_ie_concat(ie, bss->ie_len, WFD_IE_VENDOR_TYPE); if (wfd) { @@ -5077,13 +5309,21 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, os_snprintf(title, sizeof(title), "anqp[%u]", elem->infoid); pos = anqp_add_hex(pos, end, title, elem->payload); + if (elem->protected) { + ret = os_snprintf(pos, end - pos, + "protected-anqp-info[%u]=1\n", + elem->infoid); + if (os_snprintf_error(end - pos, ret)) + return 0; + pos += ret; + } } } #endif /* CONFIG_INTERWORKING */ #ifdef CONFIG_MESH if (mask & WPA_BSS_MASK_MESH_SCAN) { - ie = (const u8 *) (bss + 1); + ie = wpa_bss_ie_ptr(bss); ret = wpas_mesh_scan_result_text(ie, bss->ie_len, pos, end); if (ret >= end - pos) return 0; @@ -5130,7 +5370,7 @@ static int print_bss_info(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, return 0; pos += ret; - ie = (const u8 *) (bss + 1); + ie = wpa_bss_ie_ptr(bss); ie += bss->ie_len; for (i = 0; i < bss->beacon_ie_len; i++) { ret = os_snprintf(pos, end - pos, "%02x", *ie++); @@ -5374,6 +5614,9 @@ static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE); + if (wpa_sm_ext_key_id(wpa_s->wpa)) + wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 1, 0, + NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE); /* MLME-SETPROTECTION.request(None) */ wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, MLME_SETPROTECTION_PROTECT_TYPE_NONE, @@ -7210,7 +7453,7 @@ static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst, return -1; } - bss = wpa_bss_get_bssid(wpa_s, bssid); + bss = wpa_bss_get_bssid_latest(wpa_s, bssid); if (bss == NULL) { wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR, MAC2STR(bssid)); @@ -7245,7 +7488,7 @@ static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst, static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) { u8 dst_addr[ETH_ALEN]; - int used; + int used, freq = 0; char *pos; #define MAX_ANQP_INFO_ID 100 u16 id[MAX_ANQP_INFO_ID]; @@ -7259,6 +7502,15 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) pos = dst + used; if (*pos == ' ') pos++; + + if (os_strncmp(pos, "freq=", 5) == 0) { + freq = atoi(pos + 5); + pos = os_strchr(pos, ' '); + if (!pos) + return -1; + pos++; + } + while (num_id < MAX_ANQP_INFO_ID) { if (os_strncmp(pos, "hs20:", 5) == 0) { #ifdef CONFIG_HS20 @@ -7293,7 +7545,7 @@ static int get_anqp(struct wpa_supplicant *wpa_s, char *dst) if (num_id == 0 && !subtypes && !mbo_subtypes) return -1; - return anqp_send_req(wpa_s, dst_addr, id, num_id, subtypes, + return anqp_send_req(wpa_s, dst_addr, freq, id, num_id, subtypes, mbo_subtypes); } @@ -7939,6 +8191,34 @@ static int wpas_ctrl_iface_driver_flags(struct wpa_supplicant *wpa_s, } +static int wpas_ctrl_iface_driver_flags2(struct wpa_supplicant *wpa_s, + char *buf, size_t buflen) +{ + int ret, i; + char *pos, *end; + + ret = os_snprintf(buf, buflen, "%016llX:\n", + (long long unsigned) wpa_s->drv_flags2); + if (os_snprintf_error(buflen, ret)) + return -1; + + pos = buf + ret; + end = buf + buflen; + + for (i = 0; i < 64; i++) { + if (wpa_s->drv_flags2 & (1LLU << i)) { + ret = os_snprintf(pos, end - pos, "%s\n", + driver_flag2_to_string(1LLU << i)); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + } + + return pos - buf; +} + + static int wpa_supplicant_pktcnt_poll(struct wpa_supplicant *wpa_s, char *buf, size_t buflen) { @@ -7988,13 +8268,17 @@ static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen) { int ret; - char *pos; + char *pos, *temp = NULL; u8 *data = NULL; unsigned int vendor_id, subcmd; + enum nested_attr nested_attr_flag = NESTED_ATTR_UNSPECIFIED; struct wpabuf *reply; size_t data_len = 0; - /* cmd: [] */ + /** + * cmd: [] + * [nested=<0|1>] + */ vendor_id = strtoul(cmd, &pos, 16); if (!isblank((unsigned char) *pos)) return -EINVAL; @@ -8004,7 +8288,9 @@ static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, if (*pos != '\0') { if (!isblank((unsigned char) *pos++)) return -EINVAL; - data_len = os_strlen(pos); + + temp = os_strchr(pos, ' '); + data_len = temp ? (size_t) (temp - pos) : os_strlen(pos); } if (data_len) { @@ -8021,6 +8307,11 @@ static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, } } + pos = os_strstr(cmd, "nested="); + if (pos) + nested_attr_flag = atoi(pos + 7) ? NESTED_ATTR_USED : + NESTED_ATTR_NOT_USED; + reply = wpabuf_alloc((buflen - 1) / 2); if (!reply) { os_free(data); @@ -8028,7 +8319,7 @@ static int wpa_supplicant_vendor_cmd(struct wpa_supplicant *wpa_s, char *cmd, } ret = wpa_drv_vendor_cmd(wpa_s, vendor_id, subcmd, data, data_len, - reply); + nested_attr_flag, reply); if (ret == 0) ret = wpa_snprintf_hex(buf, buflen, wpabuf_head_u8(reply), @@ -8099,12 +8390,21 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->dpp_resp_wait_time = 0; wpa_s->dpp_resp_max_tries = 0; wpa_s->dpp_resp_retry_time = 0; +#ifdef CONFIG_DPP2 + wpas_dpp_chirp_stop(wpa_s); + wpa_s->dpp_pfs_fallback = 0; +#endif /* CONFIG_DPP2 */ #ifdef CONFIG_TESTING_OPTIONS os_memset(dpp_pkex_own_mac_override, 0, ETH_ALEN); os_memset(dpp_pkex_peer_mac_override, 0, ETH_ALEN); dpp_pkex_ephemeral_key_override_len = 0; dpp_protocol_key_override_len = 0; dpp_nonce_override_len = 0; +#ifdef CONFIG_DPP2 + dpp_version_override = 2; +#else /* CONFIG_DPP2 */ + dpp_version_override = 1; +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_DPP */ @@ -8122,6 +8422,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->no_keep_alive = 0; wpa_s->own_disconnect_req = 0; + wpa_s->own_reconnect_req = 0; + wpa_s->deny_ptk0_rekey = 0; os_free(wpa_s->disallow_aps_bssid); wpa_s->disallow_aps_bssid = NULL; @@ -8133,9 +8435,10 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->set_sta_uapsd = 0; wpa_s->sta_uapsd = 0; + wpa_s->consecutive_conn_failures = 0; + wpa_drv_radio_disable(wpa_s, 0); wpa_blacklist_clear(wpa_s); - wpa_s->extra_blacklist_count = 0; wpa_supplicant_ctrl_iface_remove_network(wpa_s, "all"); wpa_supplicant_ctrl_iface_remove_cred(wpa_s, "all"); wpa_config_flush_blobs(wpa_s->conf); @@ -8148,7 +8451,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, 43200); wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, 70); wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, 60); - eapol_sm_notify_logoff(wpa_s->eapol, FALSE); + eapol_sm_notify_logoff(wpa_s->eapol, false); radio_remove_works(wpa_s, NULL, 1); wpa_s->ext_work_in_progress = 0; @@ -8170,8 +8473,10 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->p2p_go_csa_on_inv = 0; wpa_s->ignore_auth_resp = 0; wpa_s->ignore_assoc_disallow = 0; + wpa_s->disable_sa_query = 0; wpa_s->testing_resend_assoc = 0; wpa_s->ignore_sae_h2e_only = 0; + wpa_s->ft_rsnxe_used = 0; wpa_s->reject_btm_req_reason = 0; wpa_sm_set_test_assoc_ie(wpa_s->wpa, NULL); os_free(wpa_s->get_pref_freq_list_override); @@ -8180,11 +8485,20 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->sae_commit_override = NULL; os_free(wpa_s->extra_sae_rejected_groups); wpa_s->extra_sae_rejected_groups = NULL; + wpabuf_free(wpa_s->rsne_override_eapol); + wpa_s->rsne_override_eapol = NULL; wpabuf_free(wpa_s->rsnxe_override_assoc); wpa_s->rsnxe_override_assoc = NULL; wpabuf_free(wpa_s->rsnxe_override_eapol); wpa_s->rsnxe_override_eapol = NULL; wpas_clear_driver_signal_override(wpa_s); + wpa_s->oci_freq_override_eapol = 0; + wpa_s->oci_freq_override_saquery_req = 0; + wpa_s->oci_freq_override_saquery_resp = 0; + wpa_s->oci_freq_override_eapol_g2 = 0; + wpa_s->oci_freq_override_ft_assoc = 0; + wpa_s->oci_freq_override_fils_assoc = 0; + wpa_s->oci_freq_override_wnm_sleep = 0; #ifdef CONFIG_DPP os_free(wpa_s->dpp_config_obj_override); wpa_s->dpp_config_obj_override = NULL; @@ -8199,8 +8513,11 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_s->disconnected = 0; os_free(wpa_s->next_scan_freqs); wpa_s->next_scan_freqs = NULL; + os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN); + wpa_s->next_scan_bssid_wildcard_ssid = 0; os_free(wpa_s->select_network_scan_freqs); wpa_s->select_network_scan_freqs = NULL; + os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data)); wpa_bss_flush(wpa_s); if (!dl_list_empty(&wpa_s->bss)) { @@ -8226,6 +8543,8 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) wpa_supplicant_update_channel_list(wpa_s, NULL); free_bss_tmp_disallowed(wpa_s); + + os_memset(&wpa_s->robust_av, 0, sizeof(struct robust_av_data)); } @@ -8534,6 +8853,9 @@ static void wpas_ctrl_scan(struct wpa_supplicant *wpa_s, char *params, goto done; } os_memcpy(wpa_s->next_scan_bssid, bssid, ETH_ALEN); + + wpa_s->next_scan_bssid_wildcard_ssid = + os_strstr(params, "wildcard_ssid=1") != NULL; } pos = params; @@ -9063,7 +9385,7 @@ static void wpas_data_test_rx(void *ctx, const u8 *src_addr, const u8 *buf, if (ip.ip_hl != 5 || ip.ip_v != 4 || ntohs(ip.ip_len) > HWSIM_IP_LEN) { wpa_printf(MSG_DEBUG, - "test data: RX - ignore unexpect IP header"); + "test data: RX - ignore unexpected IP header"); return; } @@ -10080,7 +10402,7 @@ static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s, char *cmd) { /* - * We do not check mesh interface existance because PMKSA should be + * We do not check mesh interface existence because PMKSA should be * stored before wpa_s->ifmsh creation to suppress commit message * creation. */ @@ -10138,6 +10460,76 @@ static int wpas_ctrl_cmd_debug_level(const char *cmd) } +static int wpas_ctrl_iface_configure_mscs(struct wpa_supplicant *wpa_s, + const char *cmd) +{ + size_t frame_classifier_len; + const char *pos, *end; + struct robust_av_data *robust_av = &wpa_s->robust_av; + int val; + + /* + * format: + * [up_bitmap=] [up_limit=] + * [stream_timeout=] [frame_classifier=] + */ + os_memset(robust_av, 0, sizeof(struct robust_av_data)); + if (os_strncmp(cmd, "add ", 4) == 0) { + robust_av->request_type = SCS_REQ_ADD; + } else if (os_strcmp(cmd, "remove") == 0) { + robust_av->request_type = SCS_REQ_REMOVE; + robust_av->valid_config = false; + return wpas_send_mscs_req(wpa_s); + } else if (os_strncmp(cmd, "change ", 7) == 0) { + robust_av->request_type = SCS_REQ_CHANGE; + } else { + return -1; + } + + pos = os_strstr(cmd, "up_bitmap="); + if (!pos) + return -1; + + val = hex2byte(pos + 10); + if (val < 0) + return -1; + robust_av->up_bitmap = val; + + pos = os_strstr(cmd, "up_limit="); + if (!pos) + return -1; + + robust_av->up_limit = atoi(pos + 9); + + pos = os_strstr(cmd, "stream_timeout="); + if (!pos) + return -1; + + robust_av->stream_timeout = atoi(pos + 15); + if (robust_av->stream_timeout == 0) + return -1; + + pos = os_strstr(cmd, "frame_classifier="); + if (!pos) + return -1; + + pos += 17; + end = os_strchr(pos, ' '); + if (!end) + end = pos + os_strlen(pos); + + frame_classifier_len = (end - pos) / 2; + if (frame_classifier_len > sizeof(robust_av->frame_classifier) || + hexstr2bin(pos, robust_av->frame_classifier, frame_classifier_len)) + return -1; + + robust_av->frame_classifier_len = frame_classifier_len; + robust_av->valid_config = true; + + return wpas_send_mscs_req(wpa_s); +} + + char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, char *buf, size_t *resp_len) { @@ -10242,9 +10634,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = wpa_supplicant_ctrl_iface_get(wpa_s, buf + 4, reply, reply_size); } else if (os_strcmp(buf, "LOGON") == 0) { - eapol_sm_notify_logoff(wpa_s->eapol, FALSE); + eapol_sm_notify_logoff(wpa_s->eapol, false); } else if (os_strcmp(buf, "LOGOFF") == 0) { - eapol_sm_notify_logoff(wpa_s->eapol, TRUE); + eapol_sm_notify_logoff(wpa_s->eapol, true); } else if (os_strcmp(buf, "REASSOCIATE") == 0) { if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) reply_len = -1; @@ -10783,6 +11175,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strcmp(buf, "DRIVER_FLAGS") == 0) { reply_len = wpas_ctrl_iface_driver_flags(wpa_s, reply, reply_size); + } else if (os_strcmp(buf, "DRIVER_FLAGS2") == 0) { + reply_len = wpas_ctrl_iface_driver_flags2(wpa_s, reply, + reply_size); #ifdef ANDROID } else if (os_strncmp(buf, "DRIVER ", 7) == 0) { reply_len = wpa_supplicant_driver_cmd(wpa_s, buf + 7, reply, @@ -10975,6 +11370,10 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, } else if (os_strncmp(buf, "DPP_BOOTSTRAP_INFO ", 19) == 0) { reply_len = dpp_bootstrap_info(wpa_s->dpp, atoi(buf + 19), reply, reply_size); + } else if (os_strncmp(buf, "DPP_BOOTSTRAP_SET ", 18) == 0) { + if (dpp_bootstrap_set(wpa_s->dpp, atoi(buf + 18), + os_strchr(buf + 18, ' ')) < 0) + reply_len = -1; } else if (os_strncmp(buf, "DPP_AUTH_INIT ", 14) == 0) { if (wpas_dpp_auth_init(wpa_s, buf + 13) < 0) reply_len = -1; @@ -11028,8 +11427,22 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = -1; } else if (os_strcmp(buf, "DPP_CONTROLLER_STOP") == 0) { dpp_controller_stop(wpa_s->dpp); + } else if (os_strncmp(buf, "DPP_CHIRP ", 10) == 0) { + if (wpas_dpp_chirp(wpa_s, buf + 9) < 0) + reply_len = -1; + } else if (os_strcmp(buf, "DPP_STOP_CHIRP") == 0) { + wpas_dpp_chirp_stop(wpa_s); + } else if (os_strncmp(buf, "DPP_RECONFIG ", 13) == 0) { + if (wpas_dpp_reconfig(wpa_s, buf + 13) < 0) + reply_len = -1; + } else if (os_strncmp(buf, "DPP_CA_SET ", 11) == 0) { + if (wpas_dpp_ca_set(wpa_s, buf + 10) < 0) + reply_len = -1; #endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ + } else if (os_strncmp(buf, "MSCS ", 5) == 0) { + if (wpas_ctrl_iface_configure_mscs(wpa_s, buf + 5)) + reply_len = -1; } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16; diff --git a/wpa_supplicant/ctrl_iface.h b/wpa_supplicant/ctrl_iface.h index d54cc076c..510668d49 100644 --- a/wpa_supplicant/ctrl_iface.h +++ b/wpa_supplicant/ctrl_iface.h @@ -1,6 +1,6 @@ /* * WPA Supplicant / UNIX domain socket -based control interface - * Copyright (c) 2004-2005, Jouni Malinen + * Copyright (c) 2004-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -11,6 +11,10 @@ #ifdef CONFIG_CTRL_IFACE +#ifndef CTRL_IFACE_MAX_LEN +#define CTRL_IFACE_MAX_LEN 8192 +#endif /* CTRL_IFACE_MAX_LEN */ + /* Shared functions from ctrl_iface.c; to be called by ctrl_iface backends */ /** diff --git a/wpa_supplicant/ctrl_iface_named_pipe.c b/wpa_supplicant/ctrl_iface_named_pipe.c index 9c0a47e63..79ff7871d 100644 --- a/wpa_supplicant/ctrl_iface_named_pipe.c +++ b/wpa_supplicant/ctrl_iface_named_pipe.c @@ -45,7 +45,7 @@ ConvertStringSecurityDescriptorToSecurityDescriptorA /* Per-interface ctrl_iface */ -#define REQUEST_BUFSIZE 256 +#define REQUEST_BUFSIZE CTRL_IFACE_MAX_LEN #define REPLY_BUFSIZE 4096 struct ctrl_iface_priv; diff --git a/wpa_supplicant/ctrl_iface_udp.c b/wpa_supplicant/ctrl_iface_udp.c index 8a6057a82..1512080d6 100644 --- a/wpa_supplicant/ctrl_iface_udp.c +++ b/wpa_supplicant/ctrl_iface_udp.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / UDP socket -based control interface - * Copyright (c) 2004-2016, Jouni Malinen + * Copyright (c) 2004-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -219,7 +219,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_supplicant *wpa_s = eloop_ctx; struct ctrl_iface_priv *priv = sock_ctx; - char buf[4096], *pos; + char *buf, *pos; int res; #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 struct sockaddr_in6 from; @@ -235,11 +235,15 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, int new_attached = 0; u8 cookie[COOKIE_LEN]; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); return; } @@ -249,6 +253,8 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, if (os_strcmp(addr, "::1")) { wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s", addr); + os_free(buf); + return; } #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { @@ -260,11 +266,17 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, */ wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " "source %s", inet_ntoa(from.sin_addr)); + os_free(buf); return; } #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); + return; + } buf[res] = '\0'; if (os_strcmp(buf, "GET_COOKIE") == 0) { @@ -282,18 +294,21 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, if (os_strncmp(buf, "COOKIE=", 7) != 0) { wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " "drop request"); + os_free(buf); return; } if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " "request - drop request"); + os_free(buf); return; } if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " "drop request"); + os_free(buf); return; } @@ -339,6 +354,8 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, fromlen); } + os_free(buf); + if (new_attached) eapol_sm_notify_ctrl_attached(wpa_s->eapol); } @@ -516,7 +533,7 @@ static void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, return; if (ifname) - os_snprintf(levelstr, sizeof(levelstr), "IFACE=%s <%d>", + os_snprintf(levelstr, sizeof(levelstr), "IFNAME=%s <%d>", ifname, level); else os_snprintf(levelstr, sizeof(levelstr), "<%d>", level); @@ -600,10 +617,13 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_global *global = eloop_ctx; struct ctrl_iface_global_priv *priv = sock_ctx; - char buf[4096], *pos; + char *buf, *pos; int res; #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 struct sockaddr_in6 from; +#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE + char addr[INET6_ADDRSTRLEN]; +#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ struct sockaddr_in from; #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ @@ -612,16 +632,28 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, size_t reply_len; u8 cookie[COOKIE_LEN]; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); return; } #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE -#ifndef CONFIG_CTRL_IFACE_UDP_IPV6 +#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 + inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from)); + if (os_strcmp(addr, "::1")) { + wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s", + addr); + os_free(buf); + return; + } +#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { /* * The OS networking stack is expected to drop this kind of @@ -631,11 +663,17 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, */ wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " "source %s", inet_ntoa(from.sin_addr)); + os_free(buf); return; } #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); + return; + } buf[res] = '\0'; if (os_strcmp(buf, "GET_COOKIE") == 0) { @@ -646,18 +684,21 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, if (os_strncmp(buf, "COOKIE=", 7) != 0) { wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " "drop request"); + os_free(buf); return; } if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " "request - drop request"); + os_free(buf); return; } if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " "drop request"); + os_free(buf); return; } @@ -694,6 +735,8 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, fromlen); } + + os_free(buf); } diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c index 71fe7ed6b..953fd2ccf 100644 --- a/wpa_supplicant/ctrl_iface_unix.c +++ b/wpa_supplicant/ctrl_iface_unix.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / UNIX domain socket -based control interface - * Copyright (c) 2004-2014, Jouni Malinen + * Copyright (c) 2004-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -131,7 +131,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_supplicant *wpa_s = eloop_ctx; struct ctrl_iface_priv *priv = sock_ctx; - char buf[4096]; + char *buf; int res; struct sockaddr_storage from; socklen_t fromlen = sizeof(from); @@ -139,11 +139,20 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, size_t reply_len = 0; int new_attached = 0; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN + 1, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); + return; + } + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); return; } buf[res] = '\0'; @@ -221,6 +230,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, } } os_free(reply_buf); + os_free(buf); if (new_attached) eapol_sm_notify_ctrl_attached(wpa_s->eapol); @@ -1046,18 +1056,27 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_global *global = eloop_ctx; struct ctrl_iface_global_priv *priv = sock_ctx; - char buf[4096]; + char *buf; int res; struct sockaddr_storage from; socklen_t fromlen = sizeof(from); char *reply = NULL, *reply_buf = NULL; size_t reply_len; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN + 1, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); + return; + } + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); return; } buf[res] = '\0'; @@ -1105,6 +1124,7 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, } } os_free(reply_buf); + os_free(buf); } diff --git a/wpa_supplicant/dbus/dbus_common.c b/wpa_supplicant/dbus/dbus_common.c index efa6c7b20..a727217fd 100644 --- a/wpa_supplicant/dbus/dbus_common.c +++ b/wpa_supplicant/dbus/dbus_common.c @@ -108,17 +108,18 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data) flags = dbus_watch_get_flags(watch); fd = dbus_watch_get_unix_fd(watch); - eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception, - priv, watch); + if (eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, + process_watch_exception, priv, watch) < 0) + return FALSE; - if (flags & DBUS_WATCH_READABLE) { - eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read, - priv, watch); - } - if (flags & DBUS_WATCH_WRITABLE) { - eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write, - priv, watch); - } + if ((flags & DBUS_WATCH_READABLE) && + eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read, + priv, watch) < 0) + return FALSE; + if ((flags & DBUS_WATCH_WRITABLE) && + eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write, + priv, watch) < 0) + return FALSE; dbus_watch_set_data(watch, priv, NULL); diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index e9e77bd18..2c01943f7 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -750,10 +750,12 @@ void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s, if (cred->auth_type & WPS_AUTH_OPEN) auth_type[at_num++] = "open"; +#ifndef CONFIG_NO_TKIP if (cred->auth_type & WPS_AUTH_WPAPSK) auth_type[at_num++] = "wpa-psk"; if (cred->auth_type & WPS_AUTH_WPA) auth_type[at_num++] = "wpa-eap"; +#endif /* CONFIG_NO_TKIP */ if (cred->auth_type & WPS_AUTH_WPA2) auth_type[at_num++] = "wpa2-eap"; if (cred->auth_type & WPS_AUTH_WPA2PSK) @@ -761,8 +763,10 @@ void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s, if (cred->encr_type & WPS_ENCR_NONE) encr_type[et_num++] = "none"; +#ifndef CONFIG_NO_TKIP if (cred->encr_type & WPS_ENCR_TKIP) encr_type[et_num++] = "tkip"; +#endif /* CONFIG_NO_TKIP */ if (cred->encr_type & WPS_ENCR_AES) encr_type[et_num++] = "aes"; @@ -1820,7 +1824,7 @@ void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s, * @sa: station addr (p2p i/f) of the peer * @dialog_token: service discovery request dialog token * @update_indic: service discovery request update indicator - * @tlvs: service discovery request genrated byte array of tlvs + * @tlvs: service discovery request generated byte array of tlvs * @tlvs_len: service discovery request tlvs length */ void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s, @@ -1889,7 +1893,7 @@ void wpas_dbus_signal_p2p_sd_request(struct wpa_supplicant *wpa_s, * @wpa_s: %wpa_supplicant network interface data * @sa: station addr (p2p i/f) of the peer * @update_indic: service discovery request update indicator - * @tlvs: service discovery request genrated byte array of tlvs + * @tlvs: service discovery request generated byte array of tlvs * @tlvs_len: service discovery request tlvs length */ void wpas_dbus_signal_p2p_sd_response(struct wpa_supplicant *wpa_s, @@ -3208,6 +3212,14 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { END_ARGS } }, + { "Roam", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_roam, + { + { "addr", "s", ARG_IN }, + END_ARGS + } + }, + #ifndef CONFIG_NO_CONFIG_BLOBS { "AddBlob", WPAS_DBUS_NEW_IFACE_INTERFACE, (WPADBusMethodHandler) wpas_dbus_handler_add_blob, @@ -3609,7 +3621,7 @@ static const struct wpa_dbus_property_desc wpas_dbus_interface_properties[] = { }, { "BridgeIfname", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", wpas_dbus_getter_bridge_ifname, - NULL, + wpas_dbus_setter_bridge_ifname, NULL }, { "ConfigFile", WPAS_DBUS_NEW_IFACE_INTERFACE, "s", diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 4b6dabcc9..fa9a1a370 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -139,6 +139,7 @@ static const char * const dont_quote[] = { "key_mgmt", "proto", "pairwise", "auth_alg", "group", "eap", "bssid", "scan_freq", "freq_list", "scan_ssid", "bssid_hint", "bssid_blacklist", "bssid_whitelist", "group_mgmt", + "ignore_broadcast_ssid", #ifdef CONFIG_MESH "mesh_basic_rates", #endif /* CONFIG_MESH */ @@ -229,8 +230,6 @@ dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s, } else if (entry.type == DBUS_TYPE_STRING) { if (should_quote_opt(entry.key)) { size = os_strlen(entry.str_value); - if (size == 0) - goto error; size += 3; value = os_zalloc(size); @@ -267,8 +266,28 @@ dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s, } else goto error; - if (wpa_config_set(ssid, entry.key, value, 0) < 0) + ret = wpa_config_set(ssid, entry.key, value, 0); + if (ret < 0) goto error; + if (ret == 1) + goto skip_update; + +#ifdef CONFIG_BGSCAN + if (os_strcmp(entry.key, "bgscan") == 0) { + /* + * Reset the bgscan parameters for the current network + * and continue. There's no need to flush caches for + * bgscan parameter changes. + */ + if (wpa_s->current_ssid == ssid && + wpa_s->wpa_state == WPA_COMPLETED) + wpa_supplicant_reset_bgscan(wpa_s); + os_free(value); + value = NULL; + wpa_dbus_dict_entry_clear(&entry); + continue; + } +#endif /* CONFIG_BGSCAN */ if (os_strcmp(entry.key, "bssid") != 0 && os_strcmp(entry.key, "priority") != 0) @@ -290,6 +309,7 @@ dbus_bool_t set_network_properties(struct wpa_supplicant *wpa_s, else if (os_strcmp(entry.key, "priority") == 0) wpa_config_update_prio_list(wpa_s->conf); + skip_update: os_free(value); value = NULL; wpa_dbus_dict_entry_clear(&entry); @@ -991,20 +1011,25 @@ dbus_bool_t wpas_dbus_getter_global_capabilities( const struct wpa_dbus_property_desc *property_desc, DBusMessageIter *iter, DBusError *error, void *user_data) { - const char *capabilities[11]; + const char *capabilities[12]; size_t num_items = 0; -#ifdef CONFIG_FILS struct wpa_global *global = user_data; struct wpa_supplicant *wpa_s; +#ifdef CONFIG_FILS int fils_supported = 0, fils_sk_pfs_supported = 0; +#endif /* CONFIG_FILS */ + int ext_key_id_supported = 0; for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { +#ifdef CONFIG_FILS if (wpa_is_fils_supported(wpa_s)) fils_supported = 1; if (wpa_is_fils_sk_pfs_supported(wpa_s)) fils_sk_pfs_supported = 1; - } #endif /* CONFIG_FILS */ + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID) + ext_key_id_supported = 1; + } #ifdef CONFIG_AP capabilities[num_items++] = "ap"; @@ -1037,6 +1062,8 @@ dbus_bool_t wpas_dbus_getter_global_capabilities( #ifdef CONFIG_OWE capabilities[num_items++] = "owe"; #endif /* CONFIG_OWE */ + if (ext_key_id_supported) + capabilities[num_items++] = "extended_key_id"; return wpas_dbus_simple_array_property_getter(iter, DBUS_TYPE_STRING, @@ -1146,7 +1173,7 @@ static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var, DBusMessage **reply) { u8 *ies = NULL, *nies; - int ies_len = 0; + size_t ies_len = 0; DBusMessageIter array_iter, sub_array_iter; char *val; int len; @@ -1177,7 +1204,7 @@ static int wpas_dbus_get_scan_ies(DBusMessage *message, DBusMessageIter *var, dbus_message_iter_recurse(&array_iter, &sub_array_iter); dbus_message_iter_get_fixed_array(&sub_array_iter, &val, &len); - if (len == 0) { + if (len <= 0) { dbus_message_iter_next(&array_iter); continue; } @@ -1208,7 +1235,7 @@ static int wpas_dbus_get_scan_channels(DBusMessage *message, { DBusMessageIter array_iter, sub_array_iter; int *freqs = NULL, *nfreqs; - int freqs_num = 0; + size_t freqs_num = 0; if (dbus_message_iter_get_arg_type(var) != DBUS_TYPE_ARRAY) { wpa_printf(MSG_DEBUG, @@ -1790,25 +1817,6 @@ out: } -static void remove_network(void *arg, struct wpa_ssid *ssid) -{ - struct wpa_supplicant *wpa_s = arg; - - wpas_notify_network_removed(wpa_s, ssid); - - if (wpa_config_remove_network(wpa_s->conf, ssid->id) < 0) { - wpa_printf(MSG_ERROR, - "%s[dbus]: error occurred when removing network %d", - __func__, ssid->id); - return; - } - - if (ssid == wpa_s->current_ssid) - wpa_supplicant_deauthenticate(wpa_s, - WLAN_REASON_DEAUTH_LEAVING); -} - - /** * wpas_dbus_handler_remove_all_networks - Remove all configured networks * @message: Pointer to incoming dbus message @@ -1820,11 +1828,8 @@ static void remove_network(void *arg, struct wpa_ssid *ssid) DBusMessage * wpas_dbus_handler_remove_all_networks( DBusMessage *message, struct wpa_supplicant *wpa_s) { - if (wpa_s->sched_scanning) - wpa_supplicant_cancel_sched_scan(wpa_s); - /* NB: could check for failure and return an error */ - wpa_config_foreach_network(wpa_s->conf, remove_network, wpa_s); + wpa_supplicant_remove_all_networks(wpa_s); return NULL; } @@ -1949,6 +1954,55 @@ out: } +/** + * wpas_dbus_handler_roam - Initiate a roam to another BSS within the ESS + * @message: Pointer to incoming dbus message + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: NULL on success or dbus error on failure + * + * Handler function for "Roam" method call of network interface. + */ +DBusMessage * wpas_dbus_handler_roam(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ +#ifdef CONFIG_NO_SCAN_PROCESSING + return wpas_dbus_error_unknown_error(message, + "scan processing not included"); +#else /* CONFIG_NO_SCAN_PROCESSING */ + u8 bssid[ETH_ALEN]; + struct wpa_bss *bss; + struct wpa_ssid *ssid = wpa_s->current_ssid; + char *addr; + + if (!dbus_message_get_args(message, NULL, DBUS_TYPE_STRING, &addr, + DBUS_TYPE_INVALID)) + return wpas_dbus_error_invalid_args(message, NULL); + + if (hwaddr_aton(addr, bssid)) + return wpas_dbus_error_invalid_args( + message, "Invalid hardware address format"); + + wpa_printf(MSG_DEBUG, "dbus: Roam " MACSTR, MAC2STR(bssid)); + + if (!ssid) + return dbus_message_new_error( + message, WPAS_DBUS_ERROR_NOT_CONNECTED, + "This interface is not connected"); + + bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len); + if (!bss) { + wpa_printf(MSG_DEBUG, "dbus: Roam: Target BSS not found"); + return wpas_dbus_error_invalid_args( + message, "Target BSS not found"); + } + + wpa_s->reassociate = 1; + wpa_supplicant_connect(wpa_s, bss, ssid); + + return NULL; +#endif /* CONFIG_NO_SCAN_PROCESSING */ +} + #ifndef CONFIG_NO_CONFIG_BLOBS /** @@ -2514,7 +2568,7 @@ wpas_dbus_handler_tdls_cancel_channel_switch(DBusMessage *message, * wpas_dbus_handler_save_config - Save configuration to configuration file * @message: Pointer to incoming dbus message * @wpa_s: wpa_supplicant structure for a network interface - * Returns: NULL on Success, Otherwise errror message + * Returns: NULL on Success, Otherwise error message * * Handler function for "SaveConfig" method call of network interface. */ @@ -2625,7 +2679,11 @@ dbus_bool_t wpas_dbus_getter_capabilities( /***** pairwise cipher */ if (res < 0) { +#ifdef CONFIG_NO_TKIP + const char *args[] = {"ccmp", "none"}; +#else /* CONFIG_NO_TKIP */ const char *args[] = {"ccmp", "tkip", "none"}; +#endif /* CONFIG_NO_TKIP */ if (!wpa_dbus_dict_append_string_array( &iter_dict, "Pairwise", args, @@ -2648,9 +2706,11 @@ dbus_bool_t wpas_dbus_getter_capabilities( ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) && !wpa_dbus_dict_string_array_add_element( &iter_array, "gcmp")) || +#ifndef CONFIG_NO_TKIP ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) && !wpa_dbus_dict_string_array_add_element( &iter_array, "tkip")) || +#endif /* CONFIG_NO_TKIP */ ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) && !wpa_dbus_dict_string_array_add_element( &iter_array, "none")) || @@ -2664,7 +2724,13 @@ dbus_bool_t wpas_dbus_getter_capabilities( /***** group cipher */ if (res < 0) { const char *args[] = { - "ccmp", "tkip", "wep104", "wep40" + "ccmp", +#ifndef CONFIG_NO_TKIP + "tkip", +#endif /* CONFIG_NO_TKIP */ +#ifdef CONFIG_WEP + "wep104", "wep40" +#endif /* CONFIG_WEP */ }; if (!wpa_dbus_dict_append_string_array( @@ -2688,15 +2754,19 @@ dbus_bool_t wpas_dbus_getter_capabilities( ((capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) && !wpa_dbus_dict_string_array_add_element( &iter_array, "gcmp")) || +#ifndef CONFIG_NO_TKIP ((capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) && !wpa_dbus_dict_string_array_add_element( &iter_array, "tkip")) || +#endif /* CONFIG_NO_TKIP */ +#ifdef CONFIG_WEP ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) && !wpa_dbus_dict_string_array_add_element( &iter_array, "wep104")) || ((capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) && !wpa_dbus_dict_string_array_add_element( &iter_array, "wep40")) || +#endif /* CONFIG_WEP */ !wpa_dbus_dict_end_string_array(&iter_dict, &iter_dict_entry, &iter_dict_val, @@ -2793,6 +2863,12 @@ dbus_bool_t wpas_dbus_getter_capabilities( goto nomem; #endif /* CONFIG_WPS */ +#ifdef CONFIG_SAE + if ((capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) && + !wpa_dbus_dict_string_array_add_element(&iter_array, "sae")) + goto nomem; +#endif /* CONFIG_SAE */ + if (!wpa_dbus_dict_end_string_array(&iter_dict, &iter_dict_entry, &iter_dict_val, @@ -3605,6 +3681,43 @@ dbus_bool_t wpas_dbus_getter_bridge_ifname( } +dbus_bool_t wpas_dbus_setter_bridge_ifname( + const struct wpa_dbus_property_desc *property_desc, + DBusMessageIter *iter, DBusError *error, void *user_data) +{ + struct wpa_supplicant *wpa_s = user_data; + const char *bridge_ifname = NULL; + const char *msg; + int r; + + if (!wpas_dbus_simple_property_setter(iter, error, DBUS_TYPE_STRING, + &bridge_ifname)) + return FALSE; + + r = wpa_supplicant_update_bridge_ifname(wpa_s, bridge_ifname); + if (r != 0) { + switch (r) { + case -EINVAL: + msg = "invalid interface name"; + break; + case -EBUSY: + msg = "interface is busy"; + break; + case -EIO: + msg = "socket error"; + break; + default: + msg = "unknown error"; + break; + } + dbus_set_error_const(error, DBUS_ERROR_FAILED, msg); + return FALSE; + } + + return TRUE; +} + + /** * wpas_dbus_getter_config_file - Get interface configuration file path * @iter: Pointer to incoming dbus message iter @@ -3912,14 +4025,15 @@ dbus_bool_t wpas_dbus_setter_iface_global( return FALSE; } - if (wpa_config_process_global(wpa_s->conf, buf, -1)) { + ret = wpa_config_process_global(wpa_s->conf, buf, -1); + if (ret < 0) { dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Failed to set interface property %s", property_desc->dbus_property); return FALSE; + } else if (ret == 0) { + wpa_supplicant_update_config(wpa_s); } - - wpa_supplicant_update_config(wpa_s); return TRUE; } @@ -4733,21 +4847,25 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop( /* Group */ switch (ie_data->group_cipher) { +#ifdef CONFIG_WEP case WPA_CIPHER_WEP40: group = "wep40"; break; + case WPA_CIPHER_WEP104: + group = "wep104"; + break; +#endif /* CONFIG_WEP */ +#ifndef CONFIG_NO_TKIP case WPA_CIPHER_TKIP: group = "tkip"; break; +#endif /* CONFIG_NO_TKIP */ case WPA_CIPHER_CCMP: group = "ccmp"; break; case WPA_CIPHER_GCMP: group = "gcmp"; break; - case WPA_CIPHER_WEP104: - group = "wep104"; - break; case WPA_CIPHER_CCMP_256: group = "ccmp-256"; break; @@ -4764,8 +4882,10 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop( /* Pairwise */ n = 0; +#ifndef CONFIG_NO_TKIP if (ie_data->pairwise_cipher & WPA_CIPHER_TKIP) pairwise[n++] = "tkip"; +#endif /* CONFIG_NO_TKIP */ if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP) pairwise[n++] = "ccmp"; if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP) diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h index afa26efed..c36383f05 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/wpa_supplicant/dbus/dbus_new_handlers.h @@ -117,6 +117,9 @@ DBusMessage * wpas_dbus_handler_select_network(DBusMessage *message, DBusMessage * wpas_dbus_handler_network_reply(DBusMessage *message, struct wpa_supplicant *wpa_s); +DBusMessage * wpas_dbus_handler_roam(DBusMessage *message, + struct wpa_supplicant *wpa_s); + DBusMessage * wpas_dbus_handler_add_blob(DBusMessage *message, struct wpa_supplicant *wpa_s); @@ -167,6 +170,7 @@ DECLARE_ACCESSOR(wpas_dbus_setter_scan_interval); DECLARE_ACCESSOR(wpas_dbus_getter_ifname); DECLARE_ACCESSOR(wpas_dbus_getter_driver); DECLARE_ACCESSOR(wpas_dbus_getter_bridge_ifname); +DECLARE_ACCESSOR(wpas_dbus_setter_bridge_ifname); DECLARE_ACCESSOR(wpas_dbus_getter_config_file); DECLARE_ACCESSOR(wpas_dbus_getter_current_bss); DECLARE_ACCESSOR(wpas_dbus_getter_current_network); diff --git a/wpa_supplicant/dbus/dbus_new_introspect.c b/wpa_supplicant/dbus/dbus_new_introspect.c index aee105b4b..6c721bf55 100644 --- a/wpa_supplicant/dbus/dbus_new_introspect.c +++ b/wpa_supplicant/dbus/dbus_new_introspect.c @@ -257,7 +257,7 @@ DBusMessage * wpa_dbus_introspect(DBusMessage *message, DBusMessage *reply; struct wpabuf *xml; - xml = wpabuf_alloc(20000); + xml = wpabuf_alloc(30000); if (xml == NULL) return NULL; diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig index b7371817a..538f798fc 100644 --- a/wpa_supplicant/defconfig +++ b/wpa_supplicant/defconfig @@ -248,7 +248,7 @@ CONFIG_CTRL_IFACE=y # Simultaneous Authentication of Equals (SAE), WPA3-Personal CONFIG_SAE=y -# Disable scan result processing (ap_mode=1) to save code size by about 1 kB. +# Disable scan result processing (ap_scan=1) to save code size by about 1 kB. # This can be used if ap_scan=1 mode is never enabled. #CONFIG_NO_SCAN_PROCESSING=y @@ -471,11 +471,7 @@ CONFIG_DEBUG_SYSLOG=y # Requires glibc 2.25 to build, falls back to /dev/random if unavailable. #CONFIG_GETRANDOM=y -# IEEE 802.11n (High Throughput) support (mainly for AP mode) -CONFIG_IEEE80211N=y - # IEEE 802.11ac (Very High Throughput) support (mainly for AP mode) -# (depends on CONFIG_IEEE80211N) CONFIG_IEEE80211AC=y # Wireless Network Management (IEEE Std 802.11v-2011) @@ -510,7 +506,7 @@ CONFIG_AP=y CONFIG_P2P=y # Enable TDLS support -#CONFIG_TDLS=y +CONFIG_TDLS=y # Wi-Fi Display # This can be used to enable Wi-Fi Display extensions for P2P using an external @@ -608,4 +604,21 @@ CONFIG_BGSCAN_SIMPLE=y # Device Provisioning Protocol (DPP) CONFIG_DPP=y +# Wired equivalent privacy (WEP) +# WEP is an obsolete cryptographic data confidentiality algorithm that is not +# considered secure. It should not be used for anything anymore. The +# functionality needed to use WEP is available in the current wpa_supplicant +# release under this optional build parameter. This functionality is subject to +# be completely removed in a future release. +#CONFIG_WEP=y + +# Remove all TKIP functionality +# TKIP is an old cryptographic data confidentiality algorithm that is not +# considered secure. It should not be used anymore for anything else than a +# backwards compatibility option as a group cipher when connecting to APs that +# use WPA+WPA2 mixed mode. For now, the default wpa_supplicant build includes +# support for this by default, but that functionality is subject to be removed +# in the future. +#CONFIG_NO_TKIP=y + CONFIG_TESTING_OPTIONS=y diff --git a/wpa_supplicant/doc/docbook/.gitignore b/wpa_supplicant/doc/docbook/.gitignore index 8c3945c52..dac35c5a5 100644 --- a/wpa_supplicant/doc/docbook/.gitignore +++ b/wpa_supplicant/doc/docbook/.gitignore @@ -1,5 +1,6 @@ manpage.links manpage.refs +manpage.log *.8 *.5 *.html diff --git a/wpa_supplicant/dpp_supplicant.c b/wpa_supplicant/dpp_supplicant.c index 6d9427bb3..09355cf7f 100644 --- a/wpa_supplicant/dpp_supplicant.c +++ b/wpa_supplicant/dpp_supplicant.c @@ -12,6 +12,7 @@ #include "utils/common.h" #include "utils/eloop.h" #include "utils/ip_addr.h" +#include "utils/base64.h" #include "common/dpp.h" #include "common/gas.h" #include "common/gas_server.h" @@ -45,6 +46,13 @@ wpas_dpp_tx_pkex_status(struct wpa_supplicant *wpa_s, const u8 *src, const u8 *bssid, const u8 *data, size_t data_len, enum offchannel_send_action_result result); +#ifdef CONFIG_DPP2 +static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, + void *timeout_ctx); +static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s); +static int wpas_dpp_process_conf_obj(void *ctx, + struct dpp_authentication *auth); +#endif /* CONFIG_DPP2 */ static const u8 broadcast[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; @@ -84,6 +92,10 @@ int wpas_dpp_qr_code(struct wpa_supplicant *wpa_s, const char *cmd) 500, wpas_dpp_tx_status, 0); } +#ifdef CONFIG_DPP2 + dpp_controller_new_qr_code(wpa_s->dpp, bi); +#endif /* CONFIG_DPP2 */ + return bi->id; } @@ -118,6 +130,7 @@ int wpas_dpp_nfc_handover_req(struct wpa_supplicant *wpa_s, const char *cmd) own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); if (!own_bi) return -1; + own_bi->nfc_negotiated = 1; pos = os_strstr(cmd, " uri="); if (!pos) @@ -149,6 +162,7 @@ int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd) own_bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); if (!own_bi) return -1; + own_bi->nfc_negotiated = 1; pos = os_strstr(cmd, " uri="); if (!pos) @@ -244,6 +258,35 @@ static void wpas_dpp_try_to_connect(struct wpa_supplicant *wpa_s) #ifdef CONFIG_DPP2 +static void wpas_dpp_stop_listen_for_tx(struct wpa_supplicant *wpa_s, + unsigned int freq, + unsigned int wait_time) +{ + struct os_reltime now, res; + unsigned int remaining; + + if (!wpa_s->dpp_listen_freq) + return; + + os_get_reltime(&now); + if (os_reltime_before(&now, &wpa_s->dpp_listen_end)) { + os_reltime_sub(&wpa_s->dpp_listen_end, &now, &res); + remaining = res.sec * 1000 + res.usec / 1000; + } else { + remaining = 0; + } + if (wpa_s->dpp_listen_freq == freq && remaining > wait_time) + return; + + wpa_printf(MSG_DEBUG, + "DPP: Stop listen on %u MHz ending in %u ms to allow immediate TX on %u MHz for %u ms", + wpa_s->dpp_listen_freq, remaining, freq, wait_time); + wpas_dpp_listen_stop(wpa_s); + + /* TODO: Restart listen in some cases after TX? */ +} + + static void wpas_dpp_conn_status_result_timeout(void *eloop_ctx, void *timeout_ctx) { @@ -432,6 +475,10 @@ static void wpas_dpp_tx_status(struct wpa_supplicant *wpa_s, eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); +#ifdef CONFIG_DPP2 + eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, + wpa_s, NULL); +#endif /* CONFIG_DPP2 */ offchannel_send_action_done(wpa_s); dpp_auth_deinit(wpa_s->dpp_auth); wpa_s->dpp_auth = NULL; @@ -764,17 +811,21 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_auth_resp_retry_timeout, wpa_s, NULL); +#ifdef CONFIG_DPP2 + eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, + wpa_s, NULL); +#endif /* CONFIG_DPP2 */ offchannel_send_action_done(wpa_s); dpp_auth_deinit(wpa_s->dpp_auth); wpa_s->dpp_auth = NULL; } - auth = dpp_auth_init(wpa_s, peer_bi, own_bi, allowed_roles, neg_freq, - wpa_s->hw.modes, wpa_s->hw.num_modes); + auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, own_bi, allowed_roles, + neg_freq, wpa_s->hw.modes, wpa_s->hw.num_modes); if (!auth) goto fail; wpas_dpp_set_testing_options(wpa_s, auth); - if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) < 0) { + if (dpp_set_configurator(auth, cmd) < 0) { dpp_auth_deinit(auth); goto fail; } @@ -786,7 +837,9 @@ int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd) #ifdef CONFIG_DPP2 if (tcp) - return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port); + return dpp_tcp_init(wpa_s->dpp, auth, &ipaddr, tcp_port, + wpa_s->conf->dpp_name, DPP_NETROLE_STA, + wpa_s, wpa_s, wpas_dpp_process_conf_obj); #endif /* CONFIG_DPP2 */ wpa_s->dpp_auth = auth; @@ -855,6 +908,7 @@ static void dpp_start_listen_cb(struct wpa_radio_work *work, int deinit) } wpa_s->off_channel_freq = 0; wpa_s->roc_waiting_drv_freq = lwork->freq; + wpa_drv_dpp_listen(wpa_s, true); } @@ -929,11 +983,30 @@ void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s) wpa_printf(MSG_DEBUG, "DPP: Stop listen on %u MHz", wpa_s->dpp_listen_freq); wpa_drv_cancel_remain_on_channel(wpa_s); + wpa_drv_dpp_listen(wpa_s, false); wpa_s->dpp_listen_freq = 0; wpas_dpp_listen_work_done(wpa_s); } +void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s, + unsigned int freq, unsigned int duration) +{ + if (wpa_s->dpp_listen_freq != freq) + return; + + wpa_printf(MSG_DEBUG, + "DPP: Remain-on-channel started for listen on %u MHz for %u ms", + freq, duration); + os_get_reltime(&wpa_s->dpp_listen_end); + wpa_s->dpp_listen_end.usec += duration * 1000; + while (wpa_s->dpp_listen_end.usec >= 1000000) { + wpa_s->dpp_listen_end.sec++; + wpa_s->dpp_listen_end.usec -= 1000000; + } +} + + void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, unsigned int freq) { @@ -975,6 +1048,10 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, wpa_printf(MSG_DEBUG, "DPP: Authentication Request from " MACSTR, MAC2STR(src)); +#ifdef CONFIG_DPP2 + wpas_dpp_chirp_stop(wpa_s); +#endif /* CONFIG_DPP2 */ + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, &r_bootstrap_len); if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { @@ -1013,7 +1090,8 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, wpa_s->dpp_gas_client = 0; wpa_s->dpp_auth_ok_on_ack = 0; - wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s, wpa_s->dpp_allowed_roles, + wpa_s->dpp_auth = dpp_auth_req_rx(wpa_s->dpp, wpa_s, + wpa_s->dpp_allowed_roles, wpa_s->dpp_qr_mutual, peer_bi, own_bi, freq, hdr, buf, len); if (!wpa_s->dpp_auth) { @@ -1021,7 +1099,7 @@ static void wpas_dpp_rx_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, return; } wpas_dpp_set_testing_options(wpa_s, wpa_s->dpp_auth); - if (dpp_set_configurator(wpa_s->dpp, wpa_s, wpa_s->dpp_auth, + if (dpp_set_configurator(wpa_s->dpp_auth, wpa_s->dpp_configurator_params) < 0) { dpp_auth_deinit(wpa_s->dpp_auth); wpa_s->dpp_auth = NULL; @@ -1068,7 +1146,8 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, res = wpa_drv_get_capa(wpa_s, &capa); if (res == 0 && - !(capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_SAE) && + !(capa.key_mgmt_iftype[WPA_IF_STATION] & + WPA_DRIVER_CAPA_KEY_MGMT_SAE) && !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) { wpa_printf(MSG_DEBUG, "DPP: SAE not supported by the driver"); @@ -1095,8 +1174,10 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, ssid->ssid_len = conf->ssid_len; if (conf->connector) { - ssid->key_mgmt = WPA_KEY_MGMT_DPP; - ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; + if (dpp_akm_dpp(conf->akm)) { + ssid->key_mgmt = WPA_KEY_MGMT_DPP; + ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; + } ssid->dpp_connector = os_strdup(conf->connector); if (!ssid->dpp_connector) goto fail; @@ -1111,6 +1192,15 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, ssid->dpp_csign_len = wpabuf_len(conf->c_sign_key); } + if (conf->pp_key) { + ssid->dpp_pp_key = os_malloc(wpabuf_len(conf->pp_key)); + if (!ssid->dpp_pp_key) + goto fail; + os_memcpy(ssid->dpp_pp_key, wpabuf_head(conf->pp_key), + wpabuf_len(conf->pp_key)); + ssid->dpp_pp_key_len = wpabuf_len(conf->pp_key); + } + if (auth->net_access_key) { ssid->dpp_netaccesskey = os_malloc(wpabuf_len(auth->net_access_key)); @@ -1125,7 +1215,7 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, if (!conf->connector || dpp_akm_psk(conf->akm) || dpp_akm_sae(conf->akm)) { - if (!conf->connector) + if (!conf->connector || !dpp_akm_dpp(conf->akm)) ssid->key_mgmt = 0; if (dpp_akm_psk(conf->akm)) ssid->key_mgmt |= WPA_KEY_MGMT_PSK | @@ -1146,6 +1236,102 @@ static struct wpa_ssid * wpas_dpp_add_network(struct wpa_supplicant *wpa_s, } } +#if defined(CONFIG_DPP2) && defined(IEEE8021X_EAPOL) + if (conf->akm == DPP_AKM_DOT1X) { + int i; + char name[100], blobname[128]; + struct wpa_config_blob *blob; + + ssid->key_mgmt = WPA_KEY_MGMT_IEEE8021X | + WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SHA256; + ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; + + if (conf->cacert) { + /* caCert is DER-encoded X.509v3 certificate for the + * server certificate if that is different from the + * trust root included in certBag. */ + /* TODO: ssid->eap.cert.ca_cert */ + } + + if (conf->certs) { + for (i = 0; ; i++) { + os_snprintf(name, sizeof(name), "dpp-certs-%d", + i); + if (!wpa_config_get_blob(wpa_s->conf, name)) + break; + } + + blob = os_zalloc(sizeof(*blob)); + if (!blob) + goto fail; + blob->len = wpabuf_len(conf->certs); + blob->name = os_strdup(name); + blob->data = os_malloc(blob->len); + if (!blob->name || !blob->data) { + wpa_config_free_blob(blob); + goto fail; + } + os_memcpy(blob->data, wpabuf_head(conf->certs), + blob->len); + os_snprintf(blobname, sizeof(blobname), "blob://%s", + name); + wpa_config_set_blob(wpa_s->conf, blob); + wpa_printf(MSG_DEBUG, "DPP: Added certificate blob %s", + name); + ssid->eap.cert.client_cert = os_strdup(blobname); + if (!ssid->eap.cert.client_cert) + goto fail; + + /* TODO: ssid->eap.identity from own certificate */ + if (wpa_config_set(ssid, "identity", "\"dpp-ent\"", + 0) < 0) + goto fail; + } + + if (auth->priv_key) { + for (i = 0; ; i++) { + os_snprintf(name, sizeof(name), "dpp-key-%d", + i); + if (!wpa_config_get_blob(wpa_s->conf, name)) + break; + } + + blob = os_zalloc(sizeof(*blob)); + if (!blob) + goto fail; + blob->len = wpabuf_len(auth->priv_key); + blob->name = os_strdup(name); + blob->data = os_malloc(blob->len); + if (!blob->name || !blob->data) { + wpa_config_free_blob(blob); + goto fail; + } + os_memcpy(blob->data, wpabuf_head(auth->priv_key), + blob->len); + os_snprintf(blobname, sizeof(blobname), "blob://%s", + name); + wpa_config_set_blob(wpa_s->conf, blob); + wpa_printf(MSG_DEBUG, "DPP: Added private key blob %s", + name); + ssid->eap.cert.private_key = os_strdup(blobname); + if (!ssid->eap.cert.private_key) + goto fail; + } + + if (conf->server_name) { + ssid->eap.cert.domain_suffix_match = + os_strdup(conf->server_name); + if (!ssid->eap.cert.domain_suffix_match) + goto fail; + } + + /* TODO: Use entCreds::eapMethods */ + if (wpa_config_set(ssid, "eap", "TLS", 0) < 0) + goto fail; + } +#endif /* CONFIG_DPP2 && IEEE8021X_EAPOL */ + os_memcpy(wpa_s->dpp_last_ssid, conf->ssid, conf->ssid_len); wpa_s->dpp_last_ssid_len = conf->ssid_len; @@ -1187,6 +1373,20 @@ static int wpas_dpp_process_config(struct wpa_supplicant *wpa_s, static void wpas_dpp_post_process_config(struct wpa_supplicant *wpa_s, struct dpp_authentication *auth) { +#ifdef CONFIG_DPP2 + if (auth->reconfig && wpa_s->dpp_reconfig_ssid && + wpa_config_get_network(wpa_s->conf, wpa_s->dpp_reconfig_ssid_id) == + wpa_s->dpp_reconfig_ssid) { + wpa_printf(MSG_DEBUG, + "DPP: Remove reconfigured network profile"); + wpas_notify_network_removed(wpa_s, wpa_s->dpp_reconfig_ssid); + wpa_config_remove_network(wpa_s->conf, + wpa_s->dpp_reconfig_ssid_id); + wpa_s->dpp_reconfig_ssid = NULL; + wpa_s->dpp_reconfig_ssid_id = -1; + } +#endif /* CONFIG_DPP2 */ + if (wpa_s->conf->dpp_config_processing < 2) return; @@ -1238,6 +1438,20 @@ static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s, os_free(hex); } } + if (conf->pp_key) { + char *hex; + size_t hexlen; + + hexlen = 2 * wpabuf_len(conf->pp_key) + 1; + hex = os_malloc(hexlen); + if (hex) { + wpa_snprintf_hex(hex, hexlen, + wpabuf_head(conf->pp_key), + wpabuf_len(conf->pp_key)); + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_PP_KEY "%s", hex); + os_free(hex); + } + } if (auth->net_access_key) { char *hex; size_t hexlen; @@ -1260,6 +1474,32 @@ static int wpas_dpp_handle_config_obj(struct wpa_supplicant *wpa_s, } } +#ifdef CONFIG_DPP2 + if (conf->certbag) { + char *b64; + + b64 = base64_encode_no_lf(wpabuf_head(conf->certbag), + wpabuf_len(conf->certbag), NULL); + if (b64) + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CERTBAG "%s", b64); + os_free(b64); + } + + if (conf->cacert) { + char *b64; + + b64 = base64_encode_no_lf(wpabuf_head(conf->cacert), + wpabuf_len(conf->cacert), NULL); + if (b64) + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CACERT "%s", b64); + os_free(b64); + } + + if (conf->server_name) + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_SERVER_NAME "%s", + conf->server_name); +#endif /* CONFIG_DPP2 */ + return wpas_dpp_process_config(wpa_s, auth, conf); } @@ -1275,6 +1515,7 @@ static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "DPP: Received Configurator backup"); wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_RECEIVED); + wpa_s->dpp_conf_backup_received = true; while (key) { res = dpp_configurator_from_backup(wpa_s->dpp, key); @@ -1290,6 +1531,31 @@ static int wpas_dpp_handle_key_pkg(struct wpa_supplicant *wpa_s, } +#ifdef CONFIG_DPP2 +static void wpas_dpp_build_csr(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + struct dpp_authentication *auth = wpa_s->dpp_auth; + + if (!auth || !auth->csrattrs) + return; + + wpa_printf(MSG_DEBUG, "DPP: Build CSR"); + wpabuf_free(auth->csr); + /* TODO: Additional information needed for CSR based on csrAttrs */ + auth->csr = dpp_build_csr(auth, wpa_s->conf->dpp_name ? + wpa_s->conf->dpp_name : "Test"); + if (!auth->csr) { + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + return; + } + + wpas_dpp_start_gas_client(wpa_s); +} +#endif /* CONFIG_DPP2 */ + + static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, @@ -1304,7 +1570,8 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, wpa_s->dpp_gas_dialog_token = -1; - if (!auth || !auth->auth_success) { + if (!auth || (!auth->auth_success && !auth->reconfig_success) || + os_memcmp(addr, auth->peer_mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); return; } @@ -1333,11 +1600,20 @@ static void wpas_dpp_gas_resp_cb(void *ctx, const u8 *addr, u8 dialog_token, goto fail; } - if (dpp_conf_resp_rx(auth, resp) < 0) { + res = dpp_conf_resp_rx(auth, resp); +#ifdef CONFIG_DPP2 + if (res == -2) { + wpa_printf(MSG_DEBUG, "DPP: CSR needed"); + eloop_register_timeout(0, 0, wpas_dpp_build_csr, wpa_s, NULL); + return; + } +#endif /* CONFIG_DPP2 */ + if (res < 0) { wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed"); goto fail; } + wpa_s->dpp_conf_backup_received = false; for (i = 0; i < auth->num_conf_obj; i++) { res = wpas_dpp_handle_config_obj(wpa_s, auth, &auth->conf_obj[i]); @@ -1381,6 +1657,9 @@ fail: wpabuf_free(msg); /* This exchange will be terminated in the TX status handler */ + if (wpa_s->conf->dpp_config_processing < 2 || + wpa_s->dpp_conf_backup_received) + auth->remove_on_tx_status = 1; return; } fail2: @@ -1417,7 +1696,7 @@ static void wpas_dpp_start_gas_client(struct wpa_supplicant *wpa_s) MAC2STR(auth->peer_mac_addr), auth->curr_freq); res = gas_query_req(wpa_s->gas, auth->peer_mac_addr, auth->curr_freq, - 1, buf, wpas_dpp_gas_resp_cb, wpa_s); + 1, 1, buf, wpas_dpp_gas_resp_cb, wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request"); wpabuf_free(buf); @@ -1680,6 +1959,321 @@ static int wpas_dpp_process_conf_obj(void *ctx, return res; } + +static void wpas_dpp_remove_bi(void *ctx, struct dpp_bootstrap_info *bi) +{ + struct wpa_supplicant *wpa_s = ctx; + + if (bi == wpa_s->dpp_chirp_bi) + wpas_dpp_chirp_stop(wpa_s); +} + + +static void +wpas_dpp_rx_presence_announcement(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + const u8 *r_bootstrap; + u16 r_bootstrap_len; + struct dpp_bootstrap_info *peer_bi; + struct dpp_authentication *auth; + + if (!wpa_s->dpp) + return; + + if (wpa_s->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Presence Announcement during ongoing Authentication"); + return; + } + + wpa_printf(MSG_DEBUG, "DPP: Presence Announcement from " MACSTR, + MAC2STR(src)); + + r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + peer_bi = dpp_bootstrap_find_chirp(wpa_s->dpp, r_bootstrap); + dpp_notify_chirp_received(wpa_s, peer_bi ? (int) peer_bi->id : -1, src, + freq, r_bootstrap); + if (!peer_bi) { + wpa_printf(MSG_DEBUG, + "DPP: No matching bootstrapping information found"); + return; + } + + auth = dpp_auth_init(wpa_s->dpp, wpa_s, peer_bi, NULL, + DPP_CAPAB_CONFIGURATOR, freq, NULL, 0); + if (!auth) + return; + wpas_dpp_set_testing_options(wpa_s, auth); + if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) { + dpp_auth_deinit(auth); + return; + } + + auth->neg_freq = freq; + + if (!is_zero_ether_addr(peer_bi->mac_addr)) + os_memcpy(auth->peer_mac_addr, peer_bi->mac_addr, ETH_ALEN); + + wpa_s->dpp_auth = auth; + if (wpas_dpp_auth_init_next(wpa_s) < 0) { + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + } +} + + +static void wpas_dpp_reconfig_reply_wait_timeout(void *eloop_ctx, + void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + struct dpp_authentication *auth = wpa_s->dpp_auth; + + if (!auth) + return; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Reply wait timeout"); + offchannel_send_action_done(wpa_s); + wpas_dpp_listen_stop(wpa_s); + dpp_auth_deinit(auth); + wpa_s->dpp_auth = NULL; +} + + +static void +wpas_dpp_rx_reconfig_announcement(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + const u8 *csign_hash, *fcgroup, *a_nonce, *e_id; + u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len; + struct dpp_configurator *conf; + struct dpp_authentication *auth; + unsigned int wait_time, max_wait_time; + u16 group; + + if (!wpa_s->dpp) + return; + + if (wpa_s->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore Reconfig Announcement during ongoing Authentication"); + return; + } + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement from " MACSTR, + MAC2STR(src)); + + csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH, + &csign_hash_len); + if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) { + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Configurator C-sign key Hash attribute"); + return; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)", + csign_hash, csign_hash_len); + conf = dpp_configurator_find_kid(wpa_s->dpp, csign_hash); + if (!conf) { + wpa_printf(MSG_DEBUG, + "DPP: No matching Configurator information found"); + return; + } + + fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP, + &fcgroup_len); + if (!fcgroup || fcgroup_len != 2) { + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Finite Cyclic Group attribute"); + return; + } + group = WPA_GET_LE16(fcgroup); + wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group); + + a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len); + e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len); + + auth = dpp_reconfig_init(wpa_s->dpp, wpa_s, conf, freq, group, + a_nonce, a_nonce_len, e_id, e_id_len); + if (!auth) + return; + wpas_dpp_set_testing_options(wpa_s, auth); + if (dpp_set_configurator(auth, wpa_s->dpp_configurator_params) < 0) { + dpp_auth_deinit(auth); + return; + } + + os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); + wpa_s->dpp_auth = auth; + + wpa_s->dpp_in_response_listen = 0; + wpa_s->dpp_auth_ok_on_ack = 0; + wait_time = wpa_s->max_remain_on_chan; + max_wait_time = wpa_s->dpp_resp_wait_time ? + wpa_s->dpp_resp_wait_time : 2000; + if (wait_time > max_wait_time) + wait_time = max_wait_time; + wait_time += 10; /* give the driver some extra time to complete */ + eloop_register_timeout(wait_time / 1000, (wait_time % 1000) * 1000, + wpas_dpp_reconfig_reply_wait_timeout, + wpa_s, NULL); + wait_time -= 10; + + wpas_dpp_stop_listen_for_tx(wpa_s, freq, wait_time); + + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", + MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_REQ); + if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast, + wpabuf_head(auth->reconfig_req_msg), + wpabuf_len(auth->reconfig_req_msg), + wait_time, wpas_dpp_tx_status, 0) < 0) { + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + } +} + + +static void +wpas_dpp_rx_reconfig_auth_req(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + struct wpa_ssid *ssid; + struct dpp_authentication *auth; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Request from " + MACSTR, MAC2STR(src)); + + if (!wpa_s->dpp) + return; + if (wpa_s->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Not ready for reconfiguration - pending authentication exchange in progress"); + return; + } + if (!wpa_s->dpp_reconfig_ssid) { + wpa_printf(MSG_DEBUG, + "DPP: Not ready for reconfiguration - not requested"); + return; + } + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (ssid == wpa_s->dpp_reconfig_ssid && + ssid->id == wpa_s->dpp_reconfig_ssid_id) + break; + } + if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey || + !ssid->dpp_csign) { + wpa_printf(MSG_DEBUG, + "DPP: Not ready for reconfiguration - no matching network profile with Connector found"); + return; + } + + auth = dpp_reconfig_auth_req_rx(wpa_s->dpp, wpa_s, ssid->dpp_connector, + ssid->dpp_netaccesskey, + ssid->dpp_netaccesskey_len, + ssid->dpp_csign, ssid->dpp_csign_len, + freq, hdr, buf, len); + if (!auth) + return; + os_memcpy(auth->peer_mac_addr, src, ETH_ALEN); + wpa_s->dpp_auth = auth; + + wpas_dpp_chirp_stop(wpa_s); + + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", + MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_RESP); + if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast, + wpabuf_head(auth->reconfig_resp_msg), + wpabuf_len(auth->reconfig_resp_msg), + 500, wpas_dpp_tx_status, 0) < 0) { + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + } +} + + +static void +wpas_dpp_rx_reconfig_auth_resp(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + struct dpp_authentication *auth = wpa_s->dpp_auth; + struct wpabuf *conf; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response from " + MACSTR, MAC2STR(src)); + + if (!auth || !auth->reconfig || !auth->configurator) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Reconfig Authentication in progress - drop"); + return; + } + + if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " + MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); + return; + } + + conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len); + if (!conf) + return; + + eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, wpa_s, NULL); + + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", + MAC2STR(src), freq, DPP_PA_RECONFIG_AUTH_CONF); + if (offchannel_send_action(wpa_s, freq, src, wpa_s->own_addr, broadcast, + wpabuf_head(conf), wpabuf_len(conf), + 500, wpas_dpp_tx_status, 0) < 0) { + wpabuf_free(conf); + dpp_auth_deinit(wpa_s->dpp_auth); + wpa_s->dpp_auth = NULL; + return; + } + wpabuf_free(conf); + + wpas_dpp_start_gas_server(wpa_s); +} + + +static void +wpas_dpp_rx_reconfig_auth_conf(struct wpa_supplicant *wpa_s, const u8 *src, + const u8 *hdr, const u8 *buf, size_t len, + unsigned int freq) +{ + struct dpp_authentication *auth = wpa_s->dpp_auth; + + wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Confirm from " + MACSTR, MAC2STR(src)); + + if (!auth || !auth->reconfig || auth->configurator) { + wpa_printf(MSG_DEBUG, + "DPP: No DPP Reconfig Authentication in progress - drop"); + return; + } + + if (os_memcmp(src, auth->peer_mac_addr, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, "DPP: MAC address mismatch (expected " + MACSTR ") - drop", MAC2STR(auth->peer_mac_addr)); + return; + } + + if (dpp_reconfig_auth_conf_rx(auth, hdr, buf, len) < 0) + return; + + wpas_dpp_start_gas_client(wpa_s); +} + #endif /* CONFIG_DPP2 */ @@ -1690,6 +2284,11 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid; const u8 *connector, *trans_id, *status; u16 connector_len, trans_id_len, status_len; +#ifdef CONFIG_DPP2 + const u8 *version; + u16 version_len; +#endif /* CONFIG_DPP2 */ + u8 peer_version = 1; struct dpp_introduction intro; struct rsn_pmksa_cache_entry *entry; struct os_time now; @@ -1790,6 +2389,13 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s, os_memcpy(entry->pmk, intro.pmk, intro.pmk_len); entry->pmk_len = intro.pmk_len; entry->akmp = WPA_KEY_MGMT_DPP; +#ifdef CONFIG_DPP2 + version = dpp_get_attr(buf, len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (version && version_len >= 1) + peer_version = version[0]; + entry->dpp_pfs = peer_version >= 2; +#endif /* CONFIG_DPP2 */ if (expiry) { os_get_time(&now); seconds = expiry - now.sec; @@ -1803,7 +2409,7 @@ static void wpas_dpp_rx_peer_disc_resp(struct wpa_supplicant *wpa_s, wpa_sm_pmksa_cache_add_entry(wpa_s->wpa, entry); wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_INTRO "peer=" MACSTR - " status=%u", MAC2STR(src), status[0]); + " status=%u version=%u", MAC2STR(src), status[0], peer_version); wpa_printf(MSG_DEBUG, "DPP: Try connection again after successful network introduction"); @@ -2225,6 +2831,23 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, case DPP_PA_CONNECTION_STATUS_RESULT: wpas_dpp_rx_conn_status_result(wpa_s, src, hdr, buf, len); break; + case DPP_PA_PRESENCE_ANNOUNCEMENT: + wpas_dpp_rx_presence_announcement(wpa_s, src, hdr, buf, len, + freq); + break; + case DPP_PA_RECONFIG_ANNOUNCEMENT: + wpas_dpp_rx_reconfig_announcement(wpa_s, src, hdr, buf, len, + freq); + break; + case DPP_PA_RECONFIG_AUTH_REQ: + wpas_dpp_rx_reconfig_auth_req(wpa_s, src, hdr, buf, len, freq); + break; + case DPP_PA_RECONFIG_AUTH_RESP: + wpas_dpp_rx_reconfig_auth_resp(wpa_s, src, hdr, buf, len, freq); + break; + case DPP_PA_RECONFIG_AUTH_CONF: + wpas_dpp_rx_reconfig_auth_conf(wpa_s, src, hdr, buf, len, freq); + break; #endif /* CONFIG_DPP2 */ default: wpa_printf(MSG_DEBUG, @@ -2246,8 +2869,8 @@ void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, static struct wpabuf * -wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query, - size_t query_len) +wpas_dpp_gas_req_handler(void *ctx, void *resp_ctx, const u8 *sa, + const u8 *query, size_t query_len, u16 *comeback_delay) { struct wpa_supplicant *wpa_s = ctx; struct dpp_authentication *auth = wpa_s->dpp_auth; @@ -2255,7 +2878,7 @@ wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query, wpa_printf(MSG_DEBUG, "DPP: GAS request from " MACSTR, MAC2STR(sa)); - if (!auth || !auth->auth_success || + if (!auth || (!auth->auth_success && !auth->reconfig_success) || os_memcmp(sa, auth->peer_mac_addr, ETH_ALEN) != 0) { wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress"); return NULL; @@ -2278,6 +2901,16 @@ wpas_dpp_gas_req_handler(void *ctx, const u8 *sa, const u8 *query, wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_REQ_RX "src=" MACSTR, MAC2STR(sa)); resp = dpp_conf_req_rx(auth, query, query_len); + +#ifdef CONFIG_DPP2 + if (!resp && auth->waiting_cert) { + wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready"); + auth->cert_resp_ctx = resp_ctx; + *comeback_delay = 500; + return NULL; + } +#endif /* CONFIG_DPP2 */ + if (!resp) wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CONF_FAILED); auth->conf_resp = resp; @@ -2303,6 +2936,14 @@ wpas_dpp_gas_status_handler(void *ctx, struct wpabuf *resp, int ok) return; } +#ifdef CONFIG_DPP2 + if (auth->waiting_csr && ok) { + wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR"); + wpabuf_free(resp); + return; + } +#endif /* CONFIG_DPP2 */ + wpa_printf(MSG_DEBUG, "DPP: Configuration exchange completed (ok=%d)", ok); eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); @@ -2340,13 +2981,13 @@ int wpas_dpp_configurator_sign(struct wpa_supplicant *wpa_s, const char *cmd) int ret = -1; char *curve = NULL; - auth = os_zalloc(sizeof(*auth)); + auth = dpp_alloc_auth(wpa_s->dpp, wpa_s); if (!auth) return -1; curve = get_param(cmd, " curve="); wpas_dpp_set_testing_options(wpa_s, auth); - if (dpp_set_configurator(wpa_s->dpp, wpa_s, auth, cmd) == 0 && + if (dpp_set_configurator(auth, cmd) == 0 && dpp_configurator_own_config(auth, curve, 0) == 0) ret = wpas_dpp_handle_config_obj(wpa_s, auth, &auth->conf_obj[0]); @@ -2389,6 +3030,7 @@ int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, unsigned int wait_time; const u8 *rsn; struct wpa_ie_data ied; + size_t len; if (!(ssid->key_mgmt & WPA_KEY_MGMT_DPP) || !bss) return 0; /* Not using DPP AKM - continue */ @@ -2422,8 +3064,11 @@ int wpas_dpp_check_connect(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, "DPP: Starting network introduction protocol to derive PMKSA for " MACSTR, MAC2STR(bss->bssid)); - msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, - 5 + 4 + os_strlen(ssid->dpp_connector)); + len = 5 + 4 + os_strlen(ssid->dpp_connector); +#ifdef CONFIG_DPP2 + len += 5; +#endif /* CONFIG_DPP2 */ + msg = dpp_alloc_msg(DPP_PA_PEER_DISCOVERY_REQ, len); if (!msg) return -1; @@ -2478,6 +3123,15 @@ skip_trans_id: skip_connector: #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_DPP2 + if (DPP_VERSION > 1) { + /* Protocol Version */ + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, DPP_VERSION); + } +#endif /* CONFIG_DPP2 */ + /* TODO: Timeout on AP response */ wait_time = wpa_s->max_remain_on_chan; if (wait_time > 2000) @@ -2646,10 +3300,9 @@ int wpas_dpp_init(struct wpa_supplicant *wpa_s) return -1; os_memset(&config, 0, sizeof(config)); - config.msg_ctx = wpa_s; config.cb_ctx = wpa_s; #ifdef CONFIG_DPP2 - config.process_conf_obj = wpas_dpp_process_conf_obj; + config.remove_bi = wpas_dpp_remove_bi; #endif /* CONFIG_DPP2 */ wpa_s->dpp = dpp_global_init(&config); return wpa_s->dpp ? 0 : -1; @@ -2669,7 +3322,6 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) #endif /* CONFIG_TESTING_OPTIONS */ if (!wpa_s->dpp) return; - dpp_global_clear(wpa_s->dpp); eloop_cancel_timeout(wpas_dpp_pkex_retry_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_reply_wait_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_init_timeout, wpa_s, NULL); @@ -2679,8 +3331,14 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) eloop_cancel_timeout(wpas_dpp_conn_status_result_wait_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_dpp_conn_status_result_timeout, wpa_s, NULL); + eloop_cancel_timeout(wpas_dpp_reconfig_reply_wait_timeout, + wpa_s, NULL); + eloop_cancel_timeout(wpas_dpp_build_csr, wpa_s, NULL); dpp_pfs_free(wpa_s->dpp_pfs); wpa_s->dpp_pfs = NULL; + wpas_dpp_chirp_stop(wpa_s); + dpp_free_reconfig_id(wpa_s->dpp_reconfig_id); + wpa_s->dpp_reconfig_id = NULL; #endif /* CONFIG_DPP2 */ offchannel_send_action_done(wpa_s); wpas_dpp_listen_stop(wpa_s); @@ -2689,24 +3347,521 @@ void wpas_dpp_deinit(struct wpa_supplicant *wpa_s) os_memset(wpa_s->dpp_intro_bssid, 0, ETH_ALEN); os_free(wpa_s->dpp_configurator_params); wpa_s->dpp_configurator_params = NULL; + dpp_global_clear(wpa_s->dpp); } #ifdef CONFIG_DPP2 + int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd) { struct dpp_controller_config config; const char *pos; os_memset(&config, 0, sizeof(config)); + config.allowed_roles = DPP_CAPAB_ENROLLEE | DPP_CAPAB_CONFIGURATOR; + config.netrole = DPP_NETROLE_STA; + config.msg_ctx = wpa_s; + config.cb_ctx = wpa_s; + config.process_conf_obj = wpas_dpp_process_conf_obj; if (cmd) { pos = os_strstr(cmd, " tcp_port="); if (pos) { pos += 10; config.tcp_port = atoi(pos); } + + pos = os_strstr(cmd, " role="); + if (pos) { + pos += 6; + if (os_strncmp(pos, "configurator", 12) == 0) + config.allowed_roles = DPP_CAPAB_CONFIGURATOR; + else if (os_strncmp(pos, "enrollee", 8) == 0) + config.allowed_roles = DPP_CAPAB_ENROLLEE; + else if (os_strncmp(pos, "either", 6) == 0) + config.allowed_roles = DPP_CAPAB_CONFIGURATOR | + DPP_CAPAB_ENROLLEE; + else + return -1; + } + + config.qr_mutual = os_strstr(cmd, " qr=mutual") != NULL; } config.configurator_params = wpa_s->dpp_configurator_params; return dpp_controller_start(wpa_s->dpp, &config); } + + +static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx); + +static void wpas_dpp_chirp_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + + wpa_printf(MSG_DEBUG, "DPP: No chirp response received"); + offchannel_send_action_done(wpa_s); + wpas_dpp_chirp_next(wpa_s, NULL); +} + + +static void wpas_dpp_chirp_tx_status(struct wpa_supplicant *wpa_s, + unsigned int freq, const u8 *dst, + const u8 *src, const u8 *bssid, + const u8 *data, size_t data_len, + enum offchannel_send_action_result result) +{ + if (result == OFFCHANNEL_SEND_ACTION_FAILED) { + wpa_printf(MSG_DEBUG, "DPP: Failed to send chirp on %d MHz", + wpa_s->dpp_chirp_freq); + if (eloop_register_timeout(0, 0, wpas_dpp_chirp_next, + wpa_s, NULL) < 0) + wpas_dpp_chirp_stop(wpa_s); + return; + } + + wpa_printf(MSG_DEBUG, "DPP: Chirp send completed - wait for response"); + if (eloop_register_timeout(2, 0, wpas_dpp_chirp_timeout, + wpa_s, NULL) < 0) + wpas_dpp_chirp_stop(wpa_s); +} + + +static void wpas_dpp_chirp_start(struct wpa_supplicant *wpa_s) +{ + struct wpabuf *msg, *announce = NULL; + int type; + + msg = wpa_s->dpp_presence_announcement; + type = DPP_PA_PRESENCE_ANNOUNCEMENT; + if (!msg) { + struct wpa_ssid *ssid = wpa_s->dpp_reconfig_ssid; + + if (ssid && wpa_s->dpp_reconfig_id && + wpa_config_get_network(wpa_s->conf, + wpa_s->dpp_reconfig_ssid_id) == + ssid) { + announce = dpp_build_reconfig_announcement( + ssid->dpp_csign, + ssid->dpp_csign_len, + ssid->dpp_netaccesskey, + ssid->dpp_netaccesskey_len, + wpa_s->dpp_reconfig_id); + msg = announce; + } + if (!msg) + return; + type = DPP_PA_RECONFIG_ANNOUNCEMENT; + } + wpa_printf(MSG_DEBUG, "DPP: Chirp on %d MHz", wpa_s->dpp_chirp_freq); + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_TX "dst=" MACSTR " freq=%u type=%d", + MAC2STR(broadcast), wpa_s->dpp_chirp_freq, type); + if (offchannel_send_action( + wpa_s, wpa_s->dpp_chirp_freq, broadcast, + wpa_s->own_addr, broadcast, + wpabuf_head(msg), wpabuf_len(msg), + 2000, wpas_dpp_chirp_tx_status, 0) < 0) + wpas_dpp_chirp_stop(wpa_s); + + wpabuf_free(announce); +} + + +static void wpas_dpp_chirp_scan_res_handler(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res) +{ + struct dpp_bootstrap_info *bi = wpa_s->dpp_chirp_bi; + unsigned int i; + struct hostapd_hw_modes *mode; + int c; + struct wpa_bss *bss; + bool chan6; + + if (!bi && !wpa_s->dpp_reconfig_ssid) + return; + + wpa_s->dpp_chirp_scan_done = 1; + + os_free(wpa_s->dpp_chirp_freqs); + wpa_s->dpp_chirp_freqs = NULL; + + /* Channels from own bootstrapping info */ + if (bi) { + for (i = 0; i < bi->num_freq; i++) + int_array_add_unique(&wpa_s->dpp_chirp_freqs, + bi->freq[i]); + } + + /* Preferred chirping channels */ + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, + HOSTAPD_MODE_IEEE80211G, false); + chan6 = mode == NULL; + if (mode) { + for (c = 0; c < mode->num_channels; c++) { + struct hostapd_channel_data *chan = &mode->channels[c]; + + if ((chan->flag & HOSTAPD_CHAN_DISABLED) || + chan->freq != 2437) + continue; + chan6 = true; + break; + } + } + if (chan6) + int_array_add_unique(&wpa_s->dpp_chirp_freqs, 2437); + + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, + HOSTAPD_MODE_IEEE80211A, false); + if (mode) { + int chan44 = 0, chan149 = 0; + + for (c = 0; c < mode->num_channels; c++) { + struct hostapd_channel_data *chan = &mode->channels[c]; + + if (chan->flag & (HOSTAPD_CHAN_DISABLED | + HOSTAPD_CHAN_RADAR)) + continue; + if (chan->freq == 5220) + chan44 = 1; + if (chan->freq == 5745) + chan149 = 1; + } + if (chan149) + int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5745); + else if (chan44) + int_array_add_unique(&wpa_s->dpp_chirp_freqs, 5220); + } + + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, + HOSTAPD_MODE_IEEE80211AD, false); + if (mode) { + for (c = 0; c < mode->num_channels; c++) { + struct hostapd_channel_data *chan = &mode->channels[c]; + + if ((chan->flag & (HOSTAPD_CHAN_DISABLED | + HOSTAPD_CHAN_RADAR)) || + chan->freq != 60480) + continue; + int_array_add_unique(&wpa_s->dpp_chirp_freqs, 60480); + break; + } + } + + /* Add channels from scan results for APs that advertise Configurator + * Connectivity element */ + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + if (wpa_bss_get_vendor_ie(bss, DPP_CC_IE_VENDOR_TYPE)) + int_array_add_unique(&wpa_s->dpp_chirp_freqs, + bss->freq); + } + + if (!wpa_s->dpp_chirp_freqs || + eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL) < 0) + wpas_dpp_chirp_stop(wpa_s); +} + + +static void wpas_dpp_chirp_next(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + int i; + + if (wpa_s->dpp_chirp_listen) + wpas_dpp_listen_stop(wpa_s); + + if (wpa_s->dpp_chirp_freq == 0) { + if (wpa_s->dpp_chirp_round % 4 == 0 && + !wpa_s->dpp_chirp_scan_done) { + wpa_printf(MSG_DEBUG, + "DPP: Update channel list for chirping"); + wpa_s->scan_req = MANUAL_SCAN_REQ; + wpa_s->scan_res_handler = + wpas_dpp_chirp_scan_res_handler; + wpa_supplicant_req_scan(wpa_s, 0, 0); + return; + } + wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[0]; + wpa_s->dpp_chirp_round++; + wpa_printf(MSG_DEBUG, "DPP: Start chirping round %d", + wpa_s->dpp_chirp_round); + } else { + for (i = 0; wpa_s->dpp_chirp_freqs[i]; i++) + if (wpa_s->dpp_chirp_freqs[i] == wpa_s->dpp_chirp_freq) + break; + if (!wpa_s->dpp_chirp_freqs[i]) { + wpa_printf(MSG_DEBUG, + "DPP: Previous chirp freq %d not found", + wpa_s->dpp_chirp_freq); + return; + } + i++; + if (wpa_s->dpp_chirp_freqs[i]) { + wpa_s->dpp_chirp_freq = wpa_s->dpp_chirp_freqs[i]; + } else { + wpa_s->dpp_chirp_iter--; + if (wpa_s->dpp_chirp_iter <= 0) { + wpa_printf(MSG_DEBUG, + "DPP: Chirping iterations completed"); + wpas_dpp_chirp_stop(wpa_s); + return; + } + wpa_s->dpp_chirp_freq = 0; + wpa_s->dpp_chirp_scan_done = 0; + if (eloop_register_timeout(30, 0, wpas_dpp_chirp_next, + wpa_s, NULL) < 0) { + wpas_dpp_chirp_stop(wpa_s); + return; + } + if (wpa_s->dpp_chirp_listen) { + wpa_printf(MSG_DEBUG, + "DPP: Listen on %d MHz during chirp 30 second wait", + wpa_s->dpp_chirp_listen); + wpas_dpp_listen_start(wpa_s, + wpa_s->dpp_chirp_listen); + } else { + wpa_printf(MSG_DEBUG, + "DPP: Wait 30 seconds before starting the next chirping round"); + } + return; + } + } + + wpas_dpp_chirp_start(wpa_s); +} + + +int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd) +{ + const char *pos; + int iter = 1, listen_freq = 0; + struct dpp_bootstrap_info *bi; + + pos = os_strstr(cmd, " own="); + if (!pos) + return -1; + pos += 5; + bi = dpp_bootstrap_get_id(wpa_s->dpp, atoi(pos)); + if (!bi) { + wpa_printf(MSG_DEBUG, + "DPP: Identified bootstrap info not found"); + return -1; + } + + pos = os_strstr(cmd, " iter="); + if (pos) { + iter = atoi(pos + 6); + if (iter <= 0) + return -1; + } + + pos = os_strstr(cmd, " listen="); + if (pos) { + listen_freq = atoi(pos + 8); + if (listen_freq <= 0) + return -1; + } + + wpas_dpp_chirp_stop(wpa_s); + wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; + wpa_s->dpp_qr_mutual = 0; + wpa_s->dpp_chirp_bi = bi; + wpa_s->dpp_presence_announcement = dpp_build_presence_announcement(bi); + if (!wpa_s->dpp_presence_announcement) + return -1; + wpa_s->dpp_chirp_iter = iter; + wpa_s->dpp_chirp_round = 0; + wpa_s->dpp_chirp_scan_done = 0; + wpa_s->dpp_chirp_listen = listen_freq; + + return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL); +} + + +void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->dpp_presence_announcement || + wpa_s->dpp_reconfig_ssid) { + offchannel_send_action_done(wpa_s); + wpa_msg(wpa_s, MSG_INFO, DPP_EVENT_CHIRP_STOPPED); + } + wpa_s->dpp_chirp_bi = NULL; + wpabuf_free(wpa_s->dpp_presence_announcement); + wpa_s->dpp_presence_announcement = NULL; + if (wpa_s->dpp_chirp_listen) + wpas_dpp_listen_stop(wpa_s); + wpa_s->dpp_chirp_listen = 0; + wpa_s->dpp_chirp_freq = 0; + os_free(wpa_s->dpp_chirp_freqs); + wpa_s->dpp_chirp_freqs = NULL; + eloop_cancel_timeout(wpas_dpp_chirp_next, wpa_s, NULL); + eloop_cancel_timeout(wpas_dpp_chirp_timeout, wpa_s, NULL); + if (wpa_s->scan_res_handler == wpas_dpp_chirp_scan_res_handler) { + wpas_abort_ongoing_scan(wpa_s); + wpa_s->scan_res_handler = NULL; + } +} + + +int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd) +{ + struct wpa_ssid *ssid; + int iter = 1; + const char *pos; + + ssid = wpa_config_get_network(wpa_s->conf, atoi(cmd)); + if (!ssid || !ssid->dpp_connector || !ssid->dpp_netaccesskey || + !ssid->dpp_csign) { + wpa_printf(MSG_DEBUG, + "DPP: Not a valid network profile for reconfiguration"); + return -1; + } + + pos = os_strstr(cmd, " iter="); + if (pos) { + iter = atoi(pos + 6); + if (iter <= 0) + return -1; + } + + if (wpa_s->dpp_auth) { + wpa_printf(MSG_DEBUG, + "DPP: Not ready to start reconfiguration - pending authentication exchange in progress"); + return -1; + } + + dpp_free_reconfig_id(wpa_s->dpp_reconfig_id); + wpa_s->dpp_reconfig_id = dpp_gen_reconfig_id(ssid->dpp_csign, + ssid->dpp_csign_len, + ssid->dpp_pp_key, + ssid->dpp_pp_key_len); + if (!wpa_s->dpp_reconfig_id) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to generate E-id for reconfiguration"); + return -1; + } + if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { + wpa_printf(MSG_DEBUG, "DPP: Disconnect for reconfiguration"); + wpa_s->own_disconnect_req = 1; + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + } + wpas_dpp_chirp_stop(wpa_s); + wpa_s->dpp_allowed_roles = DPP_CAPAB_ENROLLEE; + wpa_s->dpp_qr_mutual = 0; + wpa_s->dpp_reconfig_ssid = ssid; + wpa_s->dpp_reconfig_ssid_id = ssid->id; + wpa_s->dpp_chirp_iter = iter; + wpa_s->dpp_chirp_round = 0; + wpa_s->dpp_chirp_scan_done = 0; + wpa_s->dpp_chirp_listen = 0; + + return eloop_register_timeout(0, 0, wpas_dpp_chirp_next, wpa_s, NULL); +} + + +static int wpas_dpp_build_conf_resp(struct wpa_supplicant *wpa_s, + struct dpp_authentication *auth, bool tcp) +{ + struct wpabuf *resp; + + resp = dpp_build_conf_resp(auth, auth->e_nonce, auth->curve->nonce_len, + auth->e_netrole, true); + if (!resp) + return -1; + + if (tcp) { + auth->conf_resp_tcp = resp; + return 0; + } + + if (gas_server_set_resp(wpa_s->gas_server, auth->cert_resp_ctx, + resp) < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Could not find pending GAS response"); + wpabuf_free(resp); + return -1; + } + auth->conf_resp = resp; + return 0; +} + + +int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd) +{ + int peer = -1; + const char *pos, *value; + struct dpp_authentication *auth = wpa_s->dpp_auth; + u8 *bin; + size_t bin_len; + struct wpabuf *buf; + bool tcp = false; + + pos = os_strstr(cmd, " peer="); + if (pos) { + peer = atoi(pos + 6); + if (!auth || !auth->waiting_cert || + (auth->peer_bi && + (unsigned int) peer != auth->peer_bi->id)) { + auth = dpp_controller_get_auth(wpa_s->dpp, peer); + tcp = true; + } + } + + if (!auth || !auth->waiting_cert) { + wpa_printf(MSG_DEBUG, + "DPP: No authentication exchange waiting for certificate information"); + return -1; + } + + if (peer >= 0 && + (!auth->peer_bi || + (unsigned int) peer != auth->peer_bi->id) && + (!auth->tmp_peer_bi || + (unsigned int) peer != auth->tmp_peer_bi->id)) { + wpa_printf(MSG_DEBUG, "DPP: Peer mismatch"); + return -1; + } + + pos = os_strstr(cmd, " value="); + if (!pos) + return -1; + value = pos + 7; + + pos = os_strstr(cmd, " name="); + if (!pos) + return -1; + pos += 6; + + if (os_strncmp(pos, "status ", 7) == 0) { + auth->force_conf_resp_status = atoi(value); + return wpas_dpp_build_conf_resp(wpa_s, auth, tcp); + } + + if (os_strncmp(pos, "trustedEapServerName ", 21) == 0) { + os_free(auth->trusted_eap_server_name); + auth->trusted_eap_server_name = os_strdup(value); + return auth->trusted_eap_server_name ? 0 : -1; + } + + bin = base64_decode(value, os_strlen(value), &bin_len); + if (!bin) + return -1; + buf = wpabuf_alloc_copy(bin, bin_len); + os_free(bin); + + if (os_strncmp(pos, "caCert ", 7) == 0) { + wpabuf_free(auth->cacert); + auth->cacert = buf; + return 0; + } + + if (os_strncmp(pos, "certBag ", 8) == 0) { + wpabuf_free(auth->certbag); + auth->certbag = buf; + return wpas_dpp_build_conf_resp(wpa_s, auth, tcp); + } + + wpabuf_free(buf); + return -1; +} + #endif /* CONFIG_DPP2 */ diff --git a/wpa_supplicant/dpp_supplicant.h b/wpa_supplicant/dpp_supplicant.h index 5c3397a24..b0d5fcf18 100644 --- a/wpa_supplicant/dpp_supplicant.h +++ b/wpa_supplicant/dpp_supplicant.h @@ -19,6 +19,8 @@ int wpas_dpp_nfc_handover_sel(struct wpa_supplicant *wpa_s, const char *cmd); int wpas_dpp_auth_init(struct wpa_supplicant *wpa_s, const char *cmd); int wpas_dpp_listen(struct wpa_supplicant *wpa_s, const char *cmd); void wpas_dpp_listen_stop(struct wpa_supplicant *wpa_s); +void wpas_dpp_remain_on_channel_cb(struct wpa_supplicant *wpa_s, + unsigned int freq, unsigned int duration); void wpas_dpp_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, unsigned int freq); void wpas_dpp_rx_action(struct wpa_supplicant *wpa_s, const u8 *src, @@ -35,5 +37,9 @@ int wpas_dpp_controller_start(struct wpa_supplicant *wpa_s, const char *cmd); void wpas_dpp_connected(struct wpa_supplicant *wpa_s); void wpas_dpp_send_conn_status_result(struct wpa_supplicant *wpa_s, enum dpp_status_error result); +int wpas_dpp_chirp(struct wpa_supplicant *wpa_s, const char *cmd); +void wpas_dpp_chirp_stop(struct wpa_supplicant *wpa_s); +int wpas_dpp_reconfig(struct wpa_supplicant *wpa_s, const char *cmd); +int wpas_dpp_ca_set(struct wpa_supplicant *wpa_s, const char *cmd); #endif /* DPP_SUPPLICANT_H */ diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 45b62bdea..237f4e085 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -165,7 +165,14 @@ static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s, params.key_flag = key_flag; if (alg != WPA_ALG_NONE) { - if (key_idx >= 0 && key_idx <= 6) + /* keyidx = 1 can be either a broadcast or--with + * Extended Key ID--a unicast key. Use bit 15 for + * the pairwise keyidx 1 which is hopefully high enough + * to not clash with future extensions. + */ + if (key_idx == 1 && (key_flag & KEY_FLAG_PAIRWISE)) + wpa_s->keys_cleared &= ~BIT(15); + else if (key_idx >= 0 && key_idx <= 5) wpa_s->keys_cleared &= ~BIT(key_idx); else wpa_s->keys_cleared = 0; @@ -312,12 +319,12 @@ static inline int wpa_drv_set_country(struct wpa_supplicant *wpa_s, static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s, const u8 *data, size_t data_len, int noack, - unsigned int freq) + unsigned int freq, unsigned int wait) { if (wpa_s->driver->send_mlme) return wpa_s->driver->send_mlme(wpa_s->drv_priv, data, data_len, noack, - freq, NULL, 0, 0); + freq, NULL, 0, 0, wait); return -1; } @@ -712,12 +719,14 @@ static inline int wpa_drv_wowlan(struct wpa_supplicant *wpa_s, static inline int wpa_drv_vendor_cmd(struct wpa_supplicant *wpa_s, int vendor_id, int subcmd, const u8 *data, - size_t data_len, struct wpabuf *buf) + size_t data_len, + enum nested_attr nested_attr_flag, + struct wpabuf *buf) { if (!wpa_s->driver->vendor_cmd) return -1; return wpa_s->driver->vendor_cmd(wpa_s->drv_priv, vendor_id, subcmd, - data, data_len, buf); + data, data_len, nested_attr_flag, buf); } static inline int wpa_drv_roaming(struct wpa_supplicant *wpa_s, int allowed, @@ -771,7 +780,7 @@ static inline int wpa_drv_macsec_get_capability(struct wpa_supplicant *wpa_s, } static inline int wpa_drv_enable_protect_frames(struct wpa_supplicant *wpa_s, - Boolean enabled) + bool enabled) { if (!wpa_s->driver->enable_protect_frames) return -1; @@ -779,7 +788,7 @@ static inline int wpa_drv_enable_protect_frames(struct wpa_supplicant *wpa_s, } static inline int wpa_drv_enable_encrypt(struct wpa_supplicant *wpa_s, - Boolean enabled) + bool enabled) { if (!wpa_s->driver->enable_encrypt) return -1; @@ -787,7 +796,7 @@ static inline int wpa_drv_enable_encrypt(struct wpa_supplicant *wpa_s, } static inline int wpa_drv_set_replay_protect(struct wpa_supplicant *wpa_s, - Boolean enabled, u32 window) + bool enabled, u32 window) { if (!wpa_s->driver->set_replay_protect) return -1; @@ -804,7 +813,7 @@ static inline int wpa_drv_set_current_cipher_suite(struct wpa_supplicant *wpa_s, } static inline int wpa_drv_enable_controlled_port(struct wpa_supplicant *wpa_s, - Boolean enabled) + bool enabled) { if (!wpa_s->driver->enable_controlled_port) return -1; @@ -945,11 +954,11 @@ static inline int wpa_drv_disable_transmit_sa(struct wpa_supplicant *wpa_s, #endif /* CONFIG_MACSEC */ static inline int wpa_drv_setband(struct wpa_supplicant *wpa_s, - enum set_band band) + u32 band_mask) { if (!wpa_s->driver->set_band) return -1; - return wpa_s->driver->set_band(wpa_s->drv_priv, band); + return wpa_s->driver->set_band(wpa_s->drv_priv, band_mask); } static inline int wpa_drv_get_pref_freq_list(struct wpa_supplicant *wpa_s, @@ -1062,14 +1071,14 @@ static inline int wpa_drv_ignore_assoc_disallow(struct wpa_supplicant *wpa_s, return wpa_s->driver->ignore_assoc_disallow(wpa_s->drv_priv, val); } -static inline int wpa_drv_set_bssid_blacklist(struct wpa_supplicant *wpa_s, - unsigned int num_bssid, - const u8 *bssids) +static inline int wpa_drv_set_bssid_tmp_disallow(struct wpa_supplicant *wpa_s, + unsigned int num_bssid, + const u8 *bssids) { - if (!wpa_s->driver->set_bssid_blacklist) + if (!wpa_s->driver->set_bssid_tmp_disallow) return -1; - return wpa_s->driver->set_bssid_blacklist(wpa_s->drv_priv, num_bssid, - bssids); + return wpa_s->driver->set_bssid_tmp_disallow(wpa_s->drv_priv, num_bssid, + bssids); } static inline int wpa_drv_update_connect_params( @@ -1101,4 +1110,11 @@ static inline int wpa_drv_set_4addr_mode(struct wpa_supplicant *wpa_s, int val) wpa_s->bridge_ifname, val); } +static inline int wpa_drv_dpp_listen(struct wpa_supplicant *wpa_s, bool enable) +{ + if (!wpa_s->driver->dpp_listen) + return 0; + return wpa_s->driver->dpp_listen(wpa_s->drv_priv, enable); +} + #endif /* DRIVER_I_H */ diff --git a/wpa_supplicant/eapol_test.c b/wpa_supplicant/eapol_test.c index 53d75853b..9f69736b7 100644 --- a/wpa_supplicant/eapol_test.c +++ b/wpa_supplicant/eapol_test.c @@ -644,9 +644,9 @@ static int test_eapol(struct eapol_test_data *e, struct wpa_supplicant *wpa_s, eapol_sm_register_scard_ctx(wpa_s->eapol, wpa_s->scard); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + eapol_sm_notify_portValid(wpa_s->eapol, false); /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); + eapol_sm_notify_portEnabled(wpa_s->eapol, true); return 0; } @@ -1390,7 +1390,7 @@ int main(int argc, char *argv[]) eapol_test.ctrl_iface = 1; break; case 'v': - printf("eapol_test v" VERSION_STR "\n"); + printf("eapol_test v%s\n", VERSION_STR); return 0; case 'W': wait_for_monitor++; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index e3fce8f72..89e6e7306 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -188,6 +188,16 @@ static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s) drv_ssid_len) == 0) return 0; /* current profile still in use */ +#ifdef CONFIG_OWE + if ((wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_OWE) && + wpa_s->current_bss && + (wpa_s->current_bss->flags & WPA_BSS_OWE_TRANSITION) && + drv_ssid_len == wpa_s->current_bss->ssid_len && + os_memcmp(drv_ssid, wpa_s->current_bss->ssid, + drv_ssid_len) == 0) + return 0; /* current profile still in use */ +#endif /* CONFIG_OWE */ + wpa_msg(wpa_s, MSG_DEBUG, "Driver-initiated BSS selection changed the SSID to %s", wpa_ssid_txt(drv_ssid, drv_ssid_len)); @@ -312,12 +322,12 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) if (bssid_changed) wpas_notify_bssid_changed(wpa_s); - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + eapol_sm_notify_portEnabled(wpa_s->eapol, false); + eapol_sm_notify_portValid(wpa_s->eapol, false); if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || wpa_s->key_mgmt == WPA_KEY_MGMT_DPP || wpa_s->drv_authorized_port) - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); + eapol_sm_notify_eap_success(wpa_s->eapol, false); wpa_s->drv_authorized_port = 0; wpa_s->ap_ies_from_associnfo = 0; wpa_s->current_ssid = NULL; @@ -346,6 +356,9 @@ static void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s) int pmksa_set = -1; size_t i; + /* Start with assumption of no PMKSA cache entry match */ + pmksa_cache_clear_current(wpa_s->wpa); + if (wpa_sm_parse_own_wpa_ie(wpa_s->wpa, &ie) < 0 || ie.pmkid == NULL) return; @@ -479,6 +492,7 @@ int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, #ifndef CONFIG_NO_SCAN_PROCESSING +#ifdef CONFIG_WEP static int has_wep_key(struct wpa_ssid *ssid) { int i; @@ -490,6 +504,7 @@ static int has_wep_key(struct wpa_ssid *ssid) return 0; } +#endif /* CONFIG_WEP */ static int wpa_supplicant_match_privacy(struct wpa_bss *bss, @@ -510,8 +525,10 @@ static int wpa_supplicant_match_privacy(struct wpa_bss *bss, return 1; #endif /* CONFIG_OWE */ +#ifdef CONFIG_WEP if (has_wep_key(ssid)) privacy = 1; +#endif /* CONFIG_WEP */ #ifdef IEEE8021X_EAPOL if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && @@ -540,17 +557,21 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, int proto_match = 0; const u8 *rsn_ie, *wpa_ie; int ret; +#ifdef CONFIG_WEP int wep_ok; +#endif /* CONFIG_WEP */ ret = wpas_wps_ssid_bss_match(wpa_s, ssid, bss); if (ret >= 0) return ret; +#ifdef CONFIG_WEP /* Allow TSN if local configuration accepts WEP use without WPA/WPA2 */ wep_ok = !wpa_key_mgmt_wpa(ssid->key_mgmt) && (((ssid->key_mgmt & WPA_KEY_MGMT_NONE) && ssid->wep_key_len[ssid->wep_tx_keyidx] > 0) || (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)); +#endif /* CONFIG_WEP */ rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); while ((ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)) && rsn_ie) { @@ -567,6 +588,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, if (!ie.has_group) ie.group_cipher = wpa_default_rsn_cipher(bss->freq); +#ifdef CONFIG_WEP if (wep_ok && (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104))) { @@ -575,6 +597,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, " selected based on TSN in RSN IE"); return 1; } +#endif /* CONFIG_WEP */ if (!(ie.proto & ssid->proto) && !(ssid->proto & WPA_PROTO_OSEN)) { @@ -655,6 +678,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, break; } +#ifdef CONFIG_WEP if (wep_ok && (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104))) { @@ -663,6 +687,7 @@ static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, " selected based on TSN in WPA IE"); return 1; } +#endif /* CONFIG_WEP */ if (!(ie.proto & ssid->proto)) { if (debug_print) @@ -973,6 +998,24 @@ static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, *ret_ssid = pos; *ret_ssid_len = ssid_len; + if (!(bss->flags & WPA_BSS_OWE_TRANSITION)) { + struct wpa_ssid *ssid; + + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (wpas_network_disabled(wpa_s, ssid)) + continue; + if (ssid->ssid_len == ssid_len && + os_memcmp(ssid->ssid, pos, ssid_len) == 0) { + /* OWE BSS in transition mode for a currently + * enabled OWE network. */ + wpa_dbg(wpa_s, MSG_DEBUG, + "OWE: transition mode OWE SSID for active OWE profile"); + bss->flags |= WPA_BSS_OWE_TRANSITION; + break; + } + } + } + if (bss->ssid_len > 0) return; @@ -1013,6 +1056,7 @@ static void owe_trans_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, wpa_ssid_txt(pos, ssid_len)); os_memcpy(bss->ssid, pos, ssid_len); bss->ssid_len = ssid_len; + bss->flags |= WPA_BSS_OWE_TRANSITION; #endif /* CONFIG_OWE */ } @@ -1039,32 +1083,407 @@ static int disabled_freq(struct wpa_supplicant *wpa_s, int freq) } +static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + const u8 *match_ssid, size_t match_ssid_len, + struct wpa_bss *bss, int blacklist_count, + bool debug_print); + + +#ifdef CONFIG_SAE_PK +static bool sae_pk_acceptable_bss_with_pk(struct wpa_supplicant *wpa_s, + struct wpa_bss *orig_bss, + struct wpa_ssid *ssid, + const u8 *match_ssid, + size_t match_ssid_len) +{ + struct wpa_bss *bss; + + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + int count; + const u8 *ie; + u8 rsnxe_capa = 0; + + if (bss == orig_bss) + continue; + ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX); + if (ie && ie[1] >= 1) + rsnxe_capa = ie[2]; + if (!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK))) + continue; + + /* TODO: Could be more thorough in checking what kind of + * signal strength or throughput estimate would be acceptable + * compared to the originally selected BSS. */ + if (bss->est_throughput < 2000) + return false; + + count = wpa_blacklist_is_blacklisted(wpa_s, bss->bssid); + if (wpa_scan_res_ok(wpa_s, ssid, match_ssid, match_ssid_len, + bss, count, 0)) + return true; + } + + return false; +} +#endif /* CONFIG_SAE_PK */ + + +static bool wpa_scan_res_ok(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + const u8 *match_ssid, size_t match_ssid_len, + struct wpa_bss *bss, int blacklist_count, + bool debug_print) +{ + int res; + bool wpa, check_ssid, osen, rsn_osen = false; + struct wpa_ie_data data; +#ifdef CONFIG_MBO + const u8 *assoc_disallow; +#endif /* CONFIG_MBO */ +#ifdef CONFIG_SAE + u8 rsnxe_capa = 0; +#endif /* CONFIG_SAE */ + const u8 *ie; + + ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); + wpa = ie && ie[1]; + ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); + wpa |= ie && ie[1]; + if (ie && wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) == 0 && + (data.key_mgmt & WPA_KEY_MGMT_OSEN)) + rsn_osen = true; + ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); + osen = ie != NULL; + +#ifdef CONFIG_SAE + ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX); + if (ie && ie[1] >= 1) + rsnxe_capa = ie[2]; +#endif /* CONFIG_SAE */ + + check_ssid = wpa || ssid->ssid_len > 0; + + if (wpas_network_disabled(wpa_s, ssid)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled"); + return false; + } + + res = wpas_temp_disabled(wpa_s, ssid); + if (res > 0) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - disabled temporarily for %d second(s)", + res); + return false; + } + +#ifdef CONFIG_WPS + if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && blacklist_count) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - blacklisted (WPS)"); + return false; + } + + if (wpa && ssid->ssid_len == 0 && + wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) + check_ssid = false; + + if (!wpa && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { + /* Only allow wildcard SSID match if an AP advertises active + * WPS operation that matches our mode. */ + check_ssid = ssid->ssid_len > 0 || + !wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss); + } +#endif /* CONFIG_WPS */ + + if (ssid->bssid_set && ssid->ssid_len == 0 && + os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0) + check_ssid = false; + + if (check_ssid && + (match_ssid_len != ssid->ssid_len || + os_memcmp(match_ssid, ssid->ssid, match_ssid_len) != 0)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID mismatch"); + return false; + } + + if (ssid->bssid_set && + os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID mismatch"); + return false; + } + + /* check blacklist */ + if (ssid->num_bssid_blacklist && + addr_in_list(bss->bssid, ssid->bssid_blacklist, + ssid->num_bssid_blacklist)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - BSSID blacklisted"); + return false; + } + + /* if there is a whitelist, only accept those APs */ + if (ssid->num_bssid_whitelist && + !addr_in_list(bss->bssid, ssid->bssid_whitelist, + ssid->num_bssid_whitelist)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - BSSID not in whitelist"); + return false; + } + + if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss, debug_print)) + return false; + + if (!osen && !wpa && + !(ssid->key_mgmt & WPA_KEY_MGMT_NONE) && + !(ssid->key_mgmt & WPA_KEY_MGMT_WPS) && + !(ssid->key_mgmt & WPA_KEY_MGMT_OWE) && + !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - non-WPA network not allowed"); + return false; + } + +#ifdef CONFIG_WEP + if (wpa && !wpa_key_mgmt_wpa(ssid->key_mgmt) && has_wep_key(ssid)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - ignore WPA/WPA2 AP for WEP network block"); + return false; + } +#endif /* CONFIG_WEP */ + + if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen && !rsn_osen) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - non-OSEN network not allowed"); + return false; + } + + if (!wpa_supplicant_match_privacy(bss, ssid)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - privacy mismatch"); + return false; + } + + if (ssid->mode != WPAS_MODE_MESH && !bss_is_ess(bss) && + !bss_is_pbss(bss)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - not ESS, PBSS, or MBSS"); + return false; + } + + if (ssid->pbss != 2 && ssid->pbss != bss_is_pbss(bss)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - PBSS mismatch (ssid %d bss %d)", + ssid->pbss, bss_is_pbss(bss)); + return false; + } + + if (!freq_allowed(ssid->freq_list, bss->freq)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - frequency not allowed"); + return false; + } + +#ifdef CONFIG_MESH + if (ssid->mode == WPAS_MODE_MESH && ssid->frequency > 0 && + ssid->frequency != bss->freq) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - frequency not allowed (mesh)"); + return false; + } +#endif /* CONFIG_MESH */ + + if (!rate_match(wpa_s, ssid, bss, debug_print)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - rate sets do not match"); + return false; + } + +#ifdef CONFIG_SAE + if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) && + wpa_s->conf->sae_pwe != 3 && wpa_key_mgmt_sae(ssid->key_mgmt) && + !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E))) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - SAE H2E required, but not supported by the AP"); + return false; + } +#endif /* CONFIG_SAE */ + +#ifdef CONFIG_SAE_PK + if (ssid->sae_pk == SAE_PK_MODE_ONLY && + !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK))) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - SAE-PK required, but not supported by the AP"); + return false; + } +#endif /* CONFIG_SAE_PK */ + +#ifndef CONFIG_IBSS_RSN + if (ssid->mode == WPAS_MODE_IBSS && + !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | WPA_KEY_MGMT_WPA_NONE))) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - IBSS RSN not supported in the build"); + return false; + } +#endif /* !CONFIG_IBSS_RSN */ + +#ifdef CONFIG_P2P + if (ssid->p2p_group && + !wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && + !wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P IE seen"); + return false; + } + + if (!is_zero_ether_addr(ssid->go_p2p_dev_addr)) { + struct wpabuf *p2p_ie; + u8 dev_addr[ETH_ALEN]; + + ie = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); + if (!ie) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no P2P element"); + return false; + } + p2p_ie = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE); + if (!p2p_ie) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - could not fetch P2P element"); + return false; + } + + if (p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr) < 0 || + os_memcmp(dev_addr, ssid->go_p2p_dev_addr, ETH_ALEN) != 0) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no matching GO P2P Device Address in P2P element"); + wpabuf_free(p2p_ie); + return false; + } + wpabuf_free(p2p_ie); + } + + /* + * TODO: skip the AP if its P2P IE has Group Formation bit set in the + * P2P Group Capability Bitmap and we are not in Group Formation with + * that device. + */ +#endif /* CONFIG_P2P */ + + if (os_reltime_before(&bss->last_update, &wpa_s->scan_min_time)) { + struct os_reltime diff; + + os_reltime_sub(&wpa_s->scan_min_time, &bss->last_update, &diff); + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - scan result not recent enough (%u.%06u seconds too old)", + (unsigned int) diff.sec, + (unsigned int) diff.usec); + return false; + } +#ifdef CONFIG_MBO +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->ignore_assoc_disallow) + goto skip_assoc_disallow; +#endif /* CONFIG_TESTING_OPTIONS */ + assoc_disallow = wpas_mbo_get_bss_attr(bss, MBO_ATTR_ID_ASSOC_DISALLOW); + if (assoc_disallow && assoc_disallow[1] >= 1) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - MBO association disallowed (reason %u)", + assoc_disallow[2]); + return false; + } + + if (wpa_is_bss_tmp_disallowed(wpa_s, bss)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - AP temporarily disallowed"); + return false; + } +#ifdef CONFIG_TESTING_OPTIONS +skip_assoc_disallow: +#endif /* CONFIG_TESTING_OPTIONS */ +#endif /* CONFIG_MBO */ + +#ifdef CONFIG_DPP + if ((ssid->key_mgmt & WPA_KEY_MGMT_DPP) && + !wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid) && + (!ssid->dpp_connector || !ssid->dpp_netaccesskey || + !ssid->dpp_csign)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no PMKSA entry for DPP"); + return false; + } +#endif /* CONFIG_DPP */ + +#ifdef CONFIG_SAE_PK + if (ssid->sae_pk == SAE_PK_MODE_AUTOMATIC && + wpa_key_mgmt_sae(ssid->key_mgmt) && + ((ssid->sae_password && + sae_pk_valid_password(ssid->sae_password)) || + (!ssid->sae_password && ssid->passphrase && + sae_pk_valid_password(ssid->passphrase))) && + !(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) && + sae_pk_acceptable_bss_with_pk(wpa_s, bss, ssid, match_ssid, + match_ssid_len)) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - another acceptable BSS with SAE-PK in the same ESS"); + return false; + } +#endif /* CONFIG_SAE_PK */ + + if (bss->ssid_len == 0) { + if (debug_print) + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - no SSID known for the BSS"); + return false; + } + + /* Matching configuration found */ + return true; +} + + struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, int i, struct wpa_bss *bss, struct wpa_ssid *group, int only_first_ssid, int debug_print) { u8 wpa_ie_len, rsn_ie_len; - int wpa; - struct wpa_blacklist *e; const u8 *ie; struct wpa_ssid *ssid; - int osen, rsn_osen = 0; -#ifdef CONFIG_MBO - const u8 *assoc_disallow; -#endif /* CONFIG_MBO */ + int osen; const u8 *match_ssid; size_t match_ssid_len; - struct wpa_ie_data data; + int blacklist_count; ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); wpa_ie_len = ie ? ie[1] : 0; ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); rsn_ie_len = ie ? ie[1] : 0; - if (ie && wpa_parse_wpa_ie_rsn(ie, 2 + ie[1], &data) == 0 && - (data.key_mgmt & WPA_KEY_MGMT_OSEN)) - rsn_osen = 1; ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); osen = ie != NULL; @@ -1084,8 +1503,8 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, osen ? " osen=1" : ""); } - e = wpa_blacklist_get(wpa_s, bss->bssid); - if (e) { + blacklist_count = wpa_blacklist_is_blacklisted(wpa_s, bss->bssid); + if (blacklist_count) { int limit = 1; if (wpa_supplicant_enabled_networks(wpa_s) == 1) { /* @@ -1098,11 +1517,11 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, */ limit = 0; } - if (e->count > limit) { + if (blacklist_count > limit) { if (debug_print) { wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted (count=%d limit=%d)", - e->count, limit); + blacklist_count, limit); } return NULL; } @@ -1136,297 +1555,10 @@ struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, return NULL; } - wpa = wpa_ie_len > 0 || rsn_ie_len > 0; - for (ssid = group; ssid; ssid = only_first_ssid ? NULL : ssid->pnext) { - int check_ssid = wpa ? 1 : (ssid->ssid_len != 0); - int res; - - if (wpas_network_disabled(wpa_s, ssid)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled"); - continue; - } - - res = wpas_temp_disabled(wpa_s, ssid); - if (res > 0) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - disabled temporarily for %d second(s)", - res); - continue; - } - -#ifdef CONFIG_WPS - if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - blacklisted (WPS)"); - continue; - } - - if (wpa && ssid->ssid_len == 0 && - wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) - check_ssid = 0; - - if (!wpa && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { - /* Only allow wildcard SSID match if an AP - * advertises active WPS operation that matches - * with our mode. */ - check_ssid = 1; - if (ssid->ssid_len == 0 && - wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) - check_ssid = 0; - } -#endif /* CONFIG_WPS */ - - if (ssid->bssid_set && ssid->ssid_len == 0 && - os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0) - check_ssid = 0; - - if (check_ssid && - (match_ssid_len != ssid->ssid_len || - os_memcmp(match_ssid, ssid->ssid, match_ssid_len) != 0)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - SSID mismatch"); - continue; - } - - if (ssid->bssid_set && - os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - BSSID mismatch"); - continue; - } - - /* check blacklist */ - if (ssid->num_bssid_blacklist && - addr_in_list(bss->bssid, ssid->bssid_blacklist, - ssid->num_bssid_blacklist)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - BSSID blacklisted"); - continue; - } - - /* if there is a whitelist, only accept those APs */ - if (ssid->num_bssid_whitelist && - !addr_in_list(bss->bssid, ssid->bssid_whitelist, - ssid->num_bssid_whitelist)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - BSSID not in whitelist"); - continue; - } - - if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss, - debug_print)) - continue; - - if (!osen && !wpa && - !(ssid->key_mgmt & WPA_KEY_MGMT_NONE) && - !(ssid->key_mgmt & WPA_KEY_MGMT_WPS) && - !(ssid->key_mgmt & WPA_KEY_MGMT_OWE) && - !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - non-WPA network not allowed"); - continue; - } - - if (wpa && !wpa_key_mgmt_wpa(ssid->key_mgmt) && - has_wep_key(ssid)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - ignore WPA/WPA2 AP for WEP network block"); - continue; - } - - if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen && - !rsn_osen) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - non-OSEN network not allowed"); - continue; - } - - if (!wpa_supplicant_match_privacy(bss, ssid)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - privacy mismatch"); - continue; - } - - if (ssid->mode != WPAS_MODE_MESH && !bss_is_ess(bss) && - !bss_is_pbss(bss)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - not ESS, PBSS, or MBSS"); - continue; - } - - if (ssid->pbss != 2 && ssid->pbss != bss_is_pbss(bss)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - PBSS mismatch (ssid %d bss %d)", - ssid->pbss, bss_is_pbss(bss)); - continue; - } - - if (!freq_allowed(ssid->freq_list, bss->freq)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - frequency not allowed"); - continue; - } - -#ifdef CONFIG_MESH - if (ssid->mode == WPAS_MODE_MESH && ssid->frequency > 0 && - ssid->frequency != bss->freq) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - frequency not allowed (mesh)"); - continue; - } -#endif /* CONFIG_MESH */ - - if (!rate_match(wpa_s, ssid, bss, debug_print)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - rate sets do not match"); - continue; - } - -#ifdef CONFIG_SAE - if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) && - wpa_s->conf->sae_pwe != 3 && - wpa_key_mgmt_sae(ssid->key_mgmt) && - (!(ie = wpa_bss_get_ie(bss, WLAN_EID_RSNX)) || - ie[1] < 1 || - !(ie[2] & BIT(WLAN_RSNX_CAPAB_SAE_H2E)))) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - SAE H2E required, but not supported by the AP"); - continue; - } -#endif /* CONFIG_SAE */ - -#ifndef CONFIG_IBSS_RSN - if (ssid->mode == WPAS_MODE_IBSS && - !(ssid->key_mgmt & (WPA_KEY_MGMT_NONE | - WPA_KEY_MGMT_WPA_NONE))) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - IBSS RSN not supported in the build"); - continue; - } -#endif /* !CONFIG_IBSS_RSN */ - -#ifdef CONFIG_P2P - if (ssid->p2p_group && - !wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && - !wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - no P2P IE seen"); - continue; - } - - if (!is_zero_ether_addr(ssid->go_p2p_dev_addr)) { - struct wpabuf *p2p_ie; - u8 dev_addr[ETH_ALEN]; - - ie = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); - if (ie == NULL) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - no P2P element"); - continue; - } - p2p_ie = wpa_bss_get_vendor_ie_multi( - bss, P2P_IE_VENDOR_TYPE); - if (p2p_ie == NULL) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - could not fetch P2P element"); - continue; - } - - if (p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr) < 0 - || os_memcmp(dev_addr, ssid->go_p2p_dev_addr, - ETH_ALEN) != 0) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - no matching GO P2P Device Address in P2P element"); - wpabuf_free(p2p_ie); - continue; - } - wpabuf_free(p2p_ie); - } - - /* - * TODO: skip the AP if its P2P IE has Group Formation - * bit set in the P2P Group Capability Bitmap and we - * are not in Group Formation with that device. - */ -#endif /* CONFIG_P2P */ - - if (os_reltime_before(&bss->last_update, &wpa_s->scan_min_time)) - { - struct os_reltime diff; - - os_reltime_sub(&wpa_s->scan_min_time, - &bss->last_update, &diff); - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - scan result not recent enough (%u.%06u seconds too old)", - (unsigned int) diff.sec, - (unsigned int) diff.usec); - continue; - } -#ifdef CONFIG_MBO -#ifdef CONFIG_TESTING_OPTIONS - if (wpa_s->ignore_assoc_disallow) - goto skip_assoc_disallow; -#endif /* CONFIG_TESTING_OPTIONS */ - assoc_disallow = wpas_mbo_get_bss_attr( - bss, MBO_ATTR_ID_ASSOC_DISALLOW); - if (assoc_disallow && assoc_disallow[1] >= 1) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - MBO association disallowed (reason %u)", - assoc_disallow[2]); - continue; - } - - if (wpa_is_bss_tmp_disallowed(wpa_s, bss)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - AP temporarily disallowed"); - continue; - } -#ifdef CONFIG_TESTING_OPTIONS - skip_assoc_disallow: -#endif /* CONFIG_TESTING_OPTIONS */ -#endif /* CONFIG_MBO */ - -#ifdef CONFIG_DPP - if ((ssid->key_mgmt & WPA_KEY_MGMT_DPP) && - !wpa_sm_pmksa_exists(wpa_s->wpa, bss->bssid, ssid) && - (!ssid->dpp_connector || - !ssid->dpp_netaccesskey || - !ssid->dpp_csign)) { - if (debug_print) - wpa_dbg(wpa_s, MSG_DEBUG, - " skip - no PMKSA entry for DPP"); - continue; - } -#endif /* CONFIG_DPP */ - - /* Matching configuration found */ - return ssid; + if (wpa_scan_res_ok(wpa_s, ssid, match_ssid, match_ssid_len, + bss, blacklist_count, debug_print)) + return ssid; } /* No matching configuration found */ @@ -1493,7 +1625,7 @@ struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s, struct wpa_ssid **selected_ssid) { struct wpa_bss *selected = NULL; - int prio; + size_t prio; struct wpa_ssid *next_ssid = NULL; struct wpa_ssid *ssid; @@ -1648,7 +1780,7 @@ int wpa_supplicant_connect(struct wpa_supplicant *wpa_s, static struct wpa_ssid * wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s) { - int prio; + size_t prio; struct wpa_ssid *ssid; for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { @@ -1720,58 +1852,25 @@ wpas_get_est_throughput_from_bss_snr(const struct wpa_supplicant *wpa_s, const struct wpa_bss *bss, int snr) { int rate = wpa_bss_get_max_rate(bss); - const u8 *ies = (const void *) (bss + 1); + const u8 *ies = wpa_bss_ie_ptr(bss); size_t ie_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len; return wpas_get_est_tpt(wpa_s, ies, ie_len, rate, snr); } -#endif /* CONFIG_NO_ROAMING */ - -static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, - struct wpa_bss *selected, - struct wpa_ssid *ssid) +int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s, + struct wpa_bss *current_bss, + struct wpa_bss *selected) { - struct wpa_bss *current_bss = NULL; -#ifndef CONFIG_NO_ROAMING int min_diff, diff; int to_5ghz; int cur_level; unsigned int cur_est, sel_est; struct wpa_signal_info si; int cur_snr = 0; -#endif /* CONFIG_NO_ROAMING */ + int ret = 0; - if (wpa_s->reassociate) - return 1; /* explicit request to reassociate */ - if (wpa_s->wpa_state < WPA_ASSOCIATED) - return 1; /* we are not associated; continue */ - if (wpa_s->current_ssid == NULL) - return 1; /* unknown current SSID */ - if (wpa_s->current_ssid != ssid) - return 1; /* different network block */ - - if (wpas_driver_bss_selection(wpa_s)) - return 0; /* Driver-based roaming */ - - if (wpa_s->current_ssid->ssid) - current_bss = wpa_bss_get(wpa_s, wpa_s->bssid, - wpa_s->current_ssid->ssid, - wpa_s->current_ssid->ssid_len); - if (!current_bss) - current_bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid); - - if (!current_bss) - return 1; /* current BSS not seen in scan results */ - - if (current_bss == selected) - return 0; - - if (selected->last_update_idx > current_bss->last_update_idx) - return 1; /* current BSS not seen in the last scan */ - -#ifndef CONFIG_NO_ROAMING wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation"); wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR " freq=%d level=%d snr=%d est_throughput=%u", @@ -1890,13 +1989,64 @@ static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference in signal level (%d < %d)", diff, min_diff); - return 0; + ret = 0; + } else { + wpa_dbg(wpa_s, MSG_DEBUG, + "Allow reassociation due to difference in signal level (%d >= %d)", + diff, min_diff); + ret = 1; } + wpa_msg_ctrl(wpa_s, MSG_INFO, "%scur_bssid=" MACSTR + " cur_freq=%d cur_level=%d cur_est=%d sel_bssid=" MACSTR + " sel_freq=%d sel_level=%d sel_est=%d", + ret ? WPA_EVENT_DO_ROAM : WPA_EVENT_SKIP_ROAM, + MAC2STR(current_bss->bssid), + current_bss->freq, cur_level, cur_est, + MAC2STR(selected->bssid), + selected->freq, selected->level, sel_est); + return ret; +} - wpa_dbg(wpa_s, MSG_DEBUG, - "Allow reassociation due to difference in signal level (%d >= %d)", - diff, min_diff); - return 1; +#endif /* CONFIG_NO_ROAMING */ + + +static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, + struct wpa_bss *selected, + struct wpa_ssid *ssid) +{ + struct wpa_bss *current_bss = NULL; + + if (wpa_s->reassociate) + return 1; /* explicit request to reassociate */ + if (wpa_s->wpa_state < WPA_ASSOCIATED) + return 1; /* we are not associated; continue */ + if (wpa_s->current_ssid == NULL) + return 1; /* unknown current SSID */ + if (wpa_s->current_ssid != ssid) + return 1; /* different network block */ + + if (wpas_driver_bss_selection(wpa_s)) + return 0; /* Driver-based roaming */ + + if (wpa_s->current_ssid->ssid) + current_bss = wpa_bss_get(wpa_s, wpa_s->bssid, + wpa_s->current_ssid->ssid, + wpa_s->current_ssid->ssid_len); + if (!current_bss) + current_bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid); + + if (!current_bss) + return 1; /* current BSS not seen in scan results */ + + if (current_bss == selected) + return 0; + + if (selected->last_update_idx > current_bss->last_update_idx) + return 1; /* current BSS not seen in the last scan */ + +#ifndef CONFIG_NO_ROAMING + return wpa_supplicant_need_to_roam_within_ess(wpa_s, current_bss, + selected); #else /* CONFIG_NO_ROAMING */ return 0; #endif /* CONFIG_NO_ROAMING */ @@ -1981,15 +2131,6 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, goto scan_work_done; } - if (ap) { - wpa_dbg(wpa_s, MSG_DEBUG, "Ignore scan results in AP mode"); -#ifdef CONFIG_AP - if (wpa_s->ap_iface->scan_cb) - wpa_s->ap_iface->scan_cb(wpa_s->ap_iface); -#endif /* CONFIG_AP */ - goto scan_work_done; - } - wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available (own=%u ext=%u)", wpa_s->own_scan_running, data ? data->scan_info.external_scan : 0); @@ -2006,6 +2147,15 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, wpas_notify_scan_done(wpa_s, 1); + if (ap) { + wpa_dbg(wpa_s, MSG_DEBUG, "Ignore scan results in AP mode"); +#ifdef CONFIG_AP + if (wpa_s->ap_iface->scan_cb) + wpa_s->ap_iface->scan_cb(wpa_s->ap_iface); +#endif /* CONFIG_AP */ + goto scan_work_done; + } + if (data && data->scan_info.external_scan) { wpa_dbg(wpa_s, MSG_DEBUG, "Do not use results from externally requested scan operation for network selection"); wpa_scan_results_free(scan_res); @@ -2422,28 +2572,41 @@ static void multi_ap_process_assoc_resp(struct wpa_supplicant *wpa_s, const u8 *map_sub_elem, *pos; size_t len; - if (!wpa_s->current_ssid || - !wpa_s->current_ssid->multi_ap_backhaul_sta || - !ies || - ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) - return; + wpa_s->multi_ap_ie = 0; - if (!elems.multi_ap || elems.multi_ap_len < 7) { - wpa_printf(MSG_INFO, "AP doesn't support Multi-AP protocol"); - goto fail; - } + if (!ies || + ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed || + !elems.multi_ap || elems.multi_ap_len < 7) + return; pos = elems.multi_ap + 4; len = elems.multi_ap_len - 4; map_sub_elem = get_ie(pos, len, MULTI_AP_SUB_ELEM_TYPE); - if (!map_sub_elem || map_sub_elem[1] < 1) { - wpa_printf(MSG_INFO, "invalid Multi-AP sub elem type"); + if (!map_sub_elem || map_sub_elem[1] < 1) + return; + + wpa_s->multi_ap_backhaul = !!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS); + wpa_s->multi_ap_fronthaul = !!(map_sub_elem[2] & + MULTI_AP_FRONTHAUL_BSS); + wpa_s->multi_ap_ie = 1; +} + + +static void multi_ap_set_4addr_mode(struct wpa_supplicant *wpa_s) +{ + if (!wpa_s->current_ssid || + !wpa_s->current_ssid->multi_ap_backhaul_sta) + return; + + if (!wpa_s->multi_ap_ie) { + wpa_printf(MSG_INFO, + "AP does not include valid Multi-AP element"); goto fail; } - if (!(map_sub_elem[2] & MULTI_AP_BACKHAUL_BSS)) { - if ((map_sub_elem[2] & MULTI_AP_FRONTHAUL_BSS) && + if (!wpa_s->multi_ap_backhaul) { + if (wpa_s->multi_ap_fronthaul && wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) { wpa_printf(MSG_INFO, "WPS active, accepting fronthaul-only BSS"); @@ -2515,11 +2678,11 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, { int l, len, found = 0, found_x = 0, wpa_found, rsn_found; const u8 *p; -#if defined(CONFIG_IEEE80211R) || defined(CONFIG_OWE) u8 bssid[ETH_ALEN]; -#endif /* CONFIG_IEEE80211R || CONFIG_OWE */ + bool bssid_known; wpa_dbg(wpa_s, MSG_DEBUG, "Association info event"); + bssid_known = wpa_drv_get_bssid(wpa_s, bssid) == 0; if (data->assoc_info.req_ies) wpa_hexdump(MSG_DEBUG, "req_ies", data->assoc_info.req_ies, data->assoc_info.req_ies_len); @@ -2636,7 +2799,7 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, #ifdef CONFIG_OWE if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE && - (wpa_drv_get_bssid(wpa_s, bssid) < 0 || + (!bssid_known || owe_process_assoc_resp(wpa_s->wpa, bssid, data->assoc_info.resp_ies, data->assoc_info.resp_ies_len) < 0)) { @@ -2647,7 +2810,8 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, #ifdef CONFIG_DPP2 wpa_sm_set_dpp_z(wpa_s->wpa, NULL); - if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->dpp_pfs) { + if (DPP_VERSION > 1 && wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && + wpa_s->dpp_pfs) { struct ieee802_11_elems elems; if (ieee802_11_parse_elems(data->assoc_info.resp_ies, @@ -2670,7 +2834,7 @@ no_pfs: #ifdef CONFIG_IEEE80211R #ifdef CONFIG_SME if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) { - if (wpa_drv_get_bssid(wpa_s, bssid) < 0 || + if (!bssid_known || wpa_ft_validate_reassoc_resp(wpa_s->wpa, data->assoc_info.resp_ies, data->assoc_info.resp_ies_len, @@ -2730,7 +2894,7 @@ no_pfs: /* Process FT when SME is in the driver */ if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) && wpa_ft_is_completed(wpa_s->wpa)) { - if (wpa_drv_get_bssid(wpa_s, bssid) < 0 || + if (!bssid_known || wpa_ft_validate_reassoc_resp(wpa_s->wpa, data->assoc_info.resp_ies, data->assoc_info.resp_ies_len, @@ -2748,6 +2912,11 @@ no_pfs: data->assoc_info.resp_ies_len); #endif /* CONFIG_IEEE80211R */ + if (bssid_known) + wpas_handle_assoc_resp_mscs(wpa_s, bssid, + data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); + /* WPA/RSN IE from Beacon/ProbeResp */ p = data->assoc_info.beacon_ies; l = data->assoc_info.beacon_ies_len; @@ -2860,7 +3029,7 @@ static void wpas_fst_update_mb_assoc(struct wpa_supplicant *wpa_s, if (!bss) return; - ieprb = (const u8 *) (bss + 1); + ieprb = wpa_bss_ie_ptr(bss); iebcn = ieprb + bss->ie_len; if (!wpas_fst_update_mbie(wpa_s, ieprb, bss->ie_len)) @@ -2895,6 +3064,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, #endif /* CONFIG_AP */ eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); + wpa_s->own_reconnect_req = 0; ft_completed = wpa_ft_is_completed(wpa_s->wpa); if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0) @@ -2944,6 +3114,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, } } + multi_ap_set_4addr_mode(wpa_s); + if (wpa_s->conf->ap_scan == 1 && wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION) { if (wpa_supplicant_assoc_update_ie(wpa_s) < 0 && new_bss) @@ -2974,7 +3146,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, already_authorized = data && data->assoc_info.authorized; /* - * Set portEnabled first to FALSE in order to get EAP state machine out + * Set portEnabled first to false in order to get EAP state machine out * of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE * state machine may transit to AUTHENTICATING state based on obsolete * eapSuccess and then trigger BE_AUTH to SUCCESS and PAE to @@ -2982,16 +3154,16 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, * reset the state. */ if (!ft_completed && !already_authorized) { - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + eapol_sm_notify_portEnabled(wpa_s->eapol, false); + eapol_sm_notify_portValid(wpa_s->eapol, false); } if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || wpa_s->key_mgmt == WPA_KEY_MGMT_DPP || wpa_s->key_mgmt == WPA_KEY_MGMT_OWE || ft_completed || already_authorized || wpa_s->drv_authorized_port) - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); + eapol_sm_notify_eap_success(wpa_s->eapol, false); /* 802.1X::portControl = Auto */ - eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); + eapol_sm_notify_portEnabled(wpa_s->eapol, true); wpa_s->eapol_received = 0; if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE || @@ -3023,8 +3195,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, */ wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); - eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + eapol_sm_notify_portValid(wpa_s->eapol, true); + eapol_sm_notify_eap_success(wpa_s->eapol, true); } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) && wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { /* @@ -3033,8 +3205,8 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, */ wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); - eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + eapol_sm_notify_portValid(wpa_s->eapol, true); + eapol_sm_notify_eap_success(wpa_s->eapol, true); } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_8021X) && wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { /* @@ -3042,12 +3214,19 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, * to allow EAPOL supplicant to complete its work without * waiting for WPA supplicant. */ - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); + eapol_sm_notify_portValid(wpa_s->eapol, true); } wpa_s->last_eapol_matches_bssid = 0; #ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->rsne_override_eapol) { + wpa_printf(MSG_DEBUG, + "TESTING: RSNE EAPOL-Key msg 2/4 override"); + wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, + wpabuf_head(wpa_s->rsne_override_eapol), + wpabuf_len(wpa_s->rsne_override_eapol)); + } if (wpa_s->rsnxe_override_eapol) { wpa_printf(MSG_DEBUG, "TESTING: RSNXE EAPOL-Key msg 2/4 override"); @@ -3076,6 +3255,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, wpa_s->pending_eapol_rx = NULL; } +#ifdef CONFIG_WEP if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) && wpa_s->current_ssid && @@ -3083,6 +3263,7 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, /* Set static WEP keys again */ wpa_set_wep_keys(wpa_s, wpa_s->current_ssid); } +#endif /* CONFIG_WEP */ #ifdef CONFIG_IBSS_RSN if (wpa_s->current_ssid && @@ -3128,6 +3309,10 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, #ifdef CONFIG_MBO wpas_mbo_check_pmf(wpa_s, bss, wpa_s->current_ssid); #endif /* CONFIG_MBO */ + +#ifdef CONFIG_DPP2 + wpa_s->dpp_pfs_fallback = 0; +#endif /* CONFIG_DPP2 */ } @@ -3255,21 +3440,25 @@ static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s, if (wpa_s->wpa_state == WPA_COMPLETED && wpa_s->current_ssid && wpa_s->current_ssid->mode == WPAS_MODE_INFRA && - !locally_generated && - disconnect_reason_recoverable(reason_code)) { + (wpa_s->own_reconnect_req || + (!locally_generated && + disconnect_reason_recoverable(reason_code)))) { /* * It looks like the AP has dropped association with - * us, but could allow us to get back in. Try to - * reconnect to the same BSS without full scan to save - * time for some common cases. + * us, but could allow us to get back in. This is also + * triggered for cases where local reconnection request + * is used to force reassociation with the same BSS. + * Try to reconnect to the same BSS without a full scan + * to save time for some common cases. */ fast_reconnect = wpa_s->current_bss; fast_reconnect_ssid = wpa_s->current_ssid; - } else if (wpa_s->wpa_state >= WPA_ASSOCIATING) + } else if (wpa_s->wpa_state >= WPA_ASSOCIATING) { wpa_supplicant_req_scan(wpa_s, 0, 100000); - else + } else { wpa_dbg(wpa_s, MSG_DEBUG, "Do not request new " "immediate scan"); + } } else { wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect disabled: do not " "try to re-connect"); @@ -4061,6 +4250,13 @@ static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_DPP */ + if (category == WLAN_ACTION_ROBUST_AV_STREAMING && + payload[0] == ROBUST_AV_MSCS_RESP) { + wpas_handle_robust_av_recv_action(wpa_s, mgmt->sa, + payload + 1, plen - 1); + return; + } + wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid, category, payload, plen, freq); if (wpa_s->ifmsh) @@ -4106,8 +4302,8 @@ static void wpa_supplicant_event_port_authorized(struct wpa_supplicant *wpa_s) if (wpa_s->wpa_state == WPA_ASSOCIATED) { wpa_supplicant_cancel_auth_timeout(wpa_s); wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); - eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + eapol_sm_notify_portValid(wpa_s->eapol, true); + eapol_sm_notify_eap_success(wpa_s->eapol, true); wpa_s->drv_authorized_port = 1; } } @@ -4229,6 +4425,31 @@ static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s, } +static const char * connect_fail_reason(enum sta_connect_fail_reason_codes code) +{ + switch (code) { + case STA_CONNECT_FAIL_REASON_UNSPECIFIED: + return ""; + case STA_CONNECT_FAIL_REASON_NO_BSS_FOUND: + return "no_bss_found"; + case STA_CONNECT_FAIL_REASON_AUTH_TX_FAIL: + return "auth_tx_fail"; + case STA_CONNECT_FAIL_REASON_AUTH_NO_ACK_RECEIVED: + return "auth_no_ack_received"; + case STA_CONNECT_FAIL_REASON_AUTH_NO_RESP_RECEIVED: + return "auth_no_resp_received"; + case STA_CONNECT_FAIL_REASON_ASSOC_REQ_TX_FAIL: + return "assoc_req_tx_fail"; + case STA_CONNECT_FAIL_REASON_ASSOC_NO_ACK_RECEIVED: + return "assoc_no_ack_received"; + case STA_CONNECT_FAIL_REASON_ASSOC_NO_RESP_RECEIVED: + return "assoc_no_resp_received"; + default: + return "unknown_reason"; + } +} + + static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { @@ -4248,21 +4469,29 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s, if (data->assoc_reject.bssid) wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT - "bssid=" MACSTR " status_code=%u%s%s%s", + "bssid=" MACSTR " status_code=%u%s%s%s%s%s", MAC2STR(data->assoc_reject.bssid), data->assoc_reject.status_code, data->assoc_reject.timed_out ? " timeout" : "", data->assoc_reject.timeout_reason ? "=" : "", data->assoc_reject.timeout_reason ? - data->assoc_reject.timeout_reason : ""); + data->assoc_reject.timeout_reason : "", + data->assoc_reject.reason_code != + STA_CONNECT_FAIL_REASON_UNSPECIFIED ? + " qca_driver_reason=" : "", + connect_fail_reason(data->assoc_reject.reason_code)); else wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT - "status_code=%u%s%s%s", + "status_code=%u%s%s%s%s%s", data->assoc_reject.status_code, data->assoc_reject.timed_out ? " timeout" : "", data->assoc_reject.timeout_reason ? "=" : "", data->assoc_reject.timeout_reason ? - data->assoc_reject.timeout_reason : ""); + data->assoc_reject.timeout_reason : "", + data->assoc_reject.reason_code != + STA_CONNECT_FAIL_REASON_UNSPECIFIED ? + " qca_driver_reason=" : "", + connect_fail_reason(data->assoc_reject.reason_code)); wpa_s->assoc_status_code = data->assoc_reject.status_code; wpas_notify_assoc_status_code(wpa_s); @@ -4292,6 +4521,41 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP2 + /* Try to follow AP's PFS policy. WLAN_STATUS_ASSOC_DENIED_UNSPEC is + * the status code defined in the DPP R2 tech spec. + * WLAN_STATUS_AKMP_NOT_VALID is addressed in the same manner as an + * interoperability workaround with older hostapd implementation. */ + if (DPP_VERSION > 1 && wpa_s->current_ssid && + (wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_DPP || + ((wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_DPP) && + wpa_s->key_mgmt == WPA_KEY_MGMT_DPP)) && + wpa_s->current_ssid->dpp_pfs == 0 && + (data->assoc_reject.status_code == + WLAN_STATUS_ASSOC_DENIED_UNSPEC || + data->assoc_reject.status_code == WLAN_STATUS_AKMP_NOT_VALID)) { + struct wpa_ssid *ssid = wpa_s->current_ssid; + struct wpa_bss *bss = wpa_s->current_bss; + + wpa_s->current_ssid->dpp_pfs_fallback ^= 1; + if (!bss) + bss = wpa_supplicant_get_new_bss(wpa_s, bssid); + if (!bss || wpa_s->dpp_pfs_fallback) { + wpa_printf(MSG_DEBUG, + "DPP: Updated PFS policy for next try"); + wpas_connection_failed(wpa_s, bssid); + wpa_supplicant_mark_disassoc(wpa_s); + return; + } + wpa_printf(MSG_DEBUG, "DPP: Try again with updated PFS policy"); + wpa_s->dpp_pfs_fallback = 1; + wpas_connect_work_done(wpa_s); + wpa_supplicant_mark_disassoc(wpa_s); + wpa_supplicant_connect(wpa_s, bss, ssid); + return; + } +#endif /* CONFIG_DPP2 */ + #ifdef CONFIG_MBO if (data->assoc_reject.status_code == WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS && @@ -4358,6 +4622,38 @@ static void wpas_event_assoc_reject(struct wpa_supplicant *wpa_s, } +static void wpas_event_unprot_beacon(struct wpa_supplicant *wpa_s, + struct unprot_beacon *data) +{ + struct wpabuf *buf; + int res; + + if (!data || wpa_s->wpa_state != WPA_COMPLETED || + os_memcmp(data->sa, wpa_s->bssid, ETH_ALEN) != 0) + return; + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_UNPROT_BEACON MACSTR, + MAC2STR(data->sa)); + + buf = wpabuf_alloc(4); + if (!buf) + return; + + wpabuf_put_u8(buf, WLAN_ACTION_WNM); + wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ); + wpabuf_put_u8(buf, 1); /* Dialog Token */ + wpabuf_put_u8(buf, WNM_NOTIF_TYPE_BEACON_PROTECTION_FAILURE); + + res = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0); + if (res < 0) + wpa_printf(MSG_DEBUG, + "Failed to send WNM-Notification Request frame"); + + wpabuf_free(buf); +} + + void wpa_supplicant_event(void *ctx, enum wpa_event_type event, union wpa_event_data *data) { @@ -4696,7 +4992,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, } #endif /* CONFIG_AP */ - sme_event_ch_switch(wpa_s); + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) + sme_event_ch_switch(wpa_s); + wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_CS); wnm_clear_coloc_intf_reporting(wpa_s); break; @@ -4863,6 +5161,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, wpas_p2p_remain_on_channel_cb( wpa_s, data->remain_on_channel.freq, data->remain_on_channel.duration); +#ifdef CONFIG_DPP + wpas_dpp_remain_on_channel_cb( + wpa_s, data->remain_on_channel.freq, + data->remain_on_channel.duration); +#endif /* CONFIG_DPP */ break; case EVENT_CANCEL_REMAIN_ON_CHANNEL: #ifdef CONFIG_OFFCHANNEL @@ -5162,6 +5465,9 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, data->sta_opmode.rx_nss); #endif /* CONFIG_AP */ break; + case EVENT_UNPROT_BEACON: + wpas_event_unprot_beacon(wpa_s, &data->unprot_beacon); + break; default: wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event); break; @@ -5199,8 +5505,6 @@ void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event, return; wpa_s = wpa_supplicant_add_iface(ctx, wpa_i, NULL); os_free(wpa_i); - if (wpa_s) - wpa_s->matched = 1; } #endif /* CONFIG_MATCH_IFACE */ diff --git a/wpa_supplicant/examples/dpp-nfc.py b/wpa_supplicant/examples/dpp-nfc.py index f49da34f4..8e865f3fc 100755 --- a/wpa_supplicant/examples/dpp-nfc.py +++ b/wpa_supplicant/examples/dpp-nfc.py @@ -7,7 +7,10 @@ # This software may be distributed under the terms of the BSD license. # See README for more details. +import binascii +import errno import os +import struct import sys import time import threading @@ -18,7 +21,7 @@ import ndef import logging -scriptsdir = os.path.dirname(os.path.realpath("dpp-nfc.py")) +scriptsdir = os.path.dirname(os.path.realpath(sys.modules[__name__].__file__)) sys.path.append(os.path.join(scriptsdir, '..', '..', 'wpaspy')) import wpaspy @@ -28,17 +31,31 @@ init_on_touch = False in_raw_mode = False prev_tcgetattr = 0 no_input = False -srv = None continue_loop = True terminate_now = False summary_file = None success_file = None +netrole = None +operation_success = False +mutex = threading.Lock() -def summary(txt): - print(txt) - if summary_file: - with open(summary_file, 'a') as f: - f.write(txt + "\n") +C_NORMAL = '\033[0m' +C_RED = '\033[91m' +C_GREEN = '\033[92m' +C_YELLOW = '\033[93m' +C_BLUE = '\033[94m' +C_MAGENTA = '\033[95m' +C_CYAN = '\033[96m' + +def summary(txt, color=None): + with mutex: + if color: + print(color + txt + C_NORMAL) + else: + print(txt) + if summary_file: + with open(summary_file, 'a') as f: + f.write(txt + "\n") def success_report(txt): summary(txt) @@ -52,23 +69,26 @@ def wpas_connect(): try: ifaces = [os.path.join(wpas_ctrl, i) for i in os.listdir(wpas_ctrl)] except OSError as error: - print("Could not find wpa_supplicant: ", error) + summary("Could not find wpa_supplicant: %s", str(error)) return None if len(ifaces) < 1: - print("No wpa_supplicant control interface found") + summary("No wpa_supplicant control interface found") return None for ctrl in ifaces: - if ifname: - if ifname not in ctrl: - continue + if ifname and ifname not in ctrl: + continue + if os.path.basename(ctrl).startswith("p2p-dev-"): + # skip P2P management interface + continue try: - print("Trying to use control interface " + ctrl) + summary("Trying to use control interface " + ctrl) wpas = wpaspy.Ctrl(ctrl) return wpas except Exception as e: pass + summary("Could not connect to wpa_supplicant") return None def dpp_nfc_uri_process(uri): @@ -77,38 +97,46 @@ def dpp_nfc_uri_process(uri): return False peer_id = wpas.request("DPP_NFC_URI " + uri) if "FAIL" in peer_id: - print("Could not parse DPP URI from NFC URI record") + summary("Could not parse DPP URI from NFC URI record", color=C_RED) return False peer_id = int(peer_id) - print("peer_id=%d" % peer_id) + summary("peer_id=%d for URI from NFC Tag: %s" % (peer_id, uri)) cmd = "DPP_AUTH_INIT peer=%d" % peer_id + global enrollee_only, configurator_only, config_params + if enrollee_only: + cmd += " role=enrollee" + elif configurator_only: + cmd += " role=configurator" + if config_params: + cmd += " " + config_params + summary("Initiate DPP authentication: " + cmd) res = wpas.request(cmd) if "OK" not in res: - print("Failed to initiate DPP Authentication") + summary("Failed to initiate DPP Authentication", color=C_RED) return False - print("DPP Authentication initiated") + summary("DPP Authentication initiated") return True def dpp_hs_tag_read(record): wpas = wpas_connect() if wpas is None: return False - print(record) + summary(record) if len(record.data) < 5: - print("Too short DPP HS") + summary("Too short DPP HS", color=C_RED) return False if record.data[0] != 0: - print("Unexpected URI Identifier Code") + summary("Unexpected URI Identifier Code", color=C_RED) return False uribuf = record.data[1:] try: uri = uribuf.decode() except: - print("Invalid URI payload") + summary("Invalid URI payload", color=C_RED) return False - print("URI: " + uri) + summary("URI: " + uri) if not uri.startswith("DPP:"): - print("Not a DPP URI") + summary("Not a DPP URI", color=C_RED) return False return dpp_nfc_uri_process(uri) @@ -124,7 +152,7 @@ def get_status(wpas, extra=None): try: [name, value] = l.split('=', 1) except ValueError: - logger.info("Ignore unexpected status line: " + l) + summary("Ignore unexpected status line: %s" % l) continue vals[name] = value return vals @@ -136,7 +164,10 @@ def get_status_field(wpas, field, extra=None): return None def own_addr(wpas): - return get_status_field(wpas, "address") + addr = get_status_field(wpas, "address") + if addr is None: + addr = get_status_field(wpas, "bssid[0]") + return addr def dpp_bootstrap_gen(wpas, type="qrcode", chan=None, mac=None, info=None, curve=None, key=None): @@ -146,7 +177,10 @@ def dpp_bootstrap_gen(wpas, type="qrcode", chan=None, mac=None, info=None, if mac: if mac is True: mac = own_addr(wpas) - cmd += " mac=" + mac.replace(':', '') + if mac is None: + summary("Could not determine local MAC address for bootstrap info") + else: + cmd += " mac=" + mac.replace(':', '') if info: cmd += " info=" + info if curve: @@ -158,17 +192,62 @@ def dpp_bootstrap_gen(wpas, type="qrcode", chan=None, mac=None, info=None, raise Exception("Failed to generate bootstrapping info") return int(res) -def wpas_get_nfc_uri(start_listen=True): +def dpp_start_listen(wpas, freq): + if get_status_field(wpas, "bssid[0]"): + summary("Own AP freq: %s MHz" % str(get_status_field(wpas, "freq"))) + if get_status_field(wpas, "beacon_set", extra="DRIVER") is None: + summary("Enable beaconing to have radio ready for RX") + wpas.request("DISABLE") + wpas.request("SET start_disabled 0") + wpas.request("ENABLE") + cmd = "DPP_LISTEN %d" % freq + global enrollee_only + global configurator_only + if enrollee_only: + cmd += " role=enrollee" + elif configurator_only: + cmd += " role=configurator" + global netrole + if netrole: + cmd += " netrole=" + netrole + summary(cmd) + res = wpas.request(cmd) + if "OK" not in res: + summary("Failed to start DPP listen", color=C_RED) + return False + return True + +def wpas_get_nfc_uri(start_listen=True, pick_channel=False, chan_override=None): + listen_freq = 2412 wpas = wpas_connect() if wpas is None: return None global own_id, chanlist - own_id = dpp_bootstrap_gen(wpas, type="nfc-uri", chan=chanlist, mac=True) + if chan_override: + chan = chan_override + else: + chan = chanlist + if chan and chan.startswith("81/"): + listen_freq = int(chan[3:].split(',')[0]) * 5 + 2407 + if chan is None and get_status_field(wpas, "bssid[0]"): + freq = get_status_field(wpas, "freq") + if freq: + freq = int(freq) + if freq >= 2412 and freq <= 2462: + chan = "81/%d" % ((freq - 2407) / 5) + summary("Use current AP operating channel (%d MHz) as the URI channel list (%s)" % (freq, chan)) + listen_freq = freq + if chan is None and pick_channel: + chan = "81/6" + summary("Use channel 2437 MHz since no other preference provided") + listen_freq = 2437 + own_id = dpp_bootstrap_gen(wpas, type="nfc-uri", chan=chan, mac=True) res = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() if "FAIL" in res: return None if start_listen: - wpas.request("DPP_LISTEN 2412 netrole=configurator") + if not dpp_start_listen(wpas, listen_freq): + raise Exception("Failed to start listen operation on %d MHz" % listen_freq) return res def wpas_report_handover_req(uri): @@ -187,100 +266,248 @@ def wpas_report_handover_sel(uri): cmd = "DPP_NFC_HANDOVER_SEL own=%d uri=%s" % (own_id, uri) return wpas.request(cmd) -def dpp_handover_client(llc): - uri = wpas_get_nfc_uri(start_listen=False) +def dpp_handover_client(handover, alt=False): + summary("About to start run_dpp_handover_client (alt=%s)" % str(alt)) + if alt: + handover.i_m_selector = False + run_dpp_handover_client(handover, alt) + summary("Done run_dpp_handover_client (alt=%s)" % str(alt)) + +def run_client_alt(handover, alt): + if handover.start_client_alt and not alt: + handover.start_client_alt = False + summary("Try to send alternative handover request") + dpp_handover_client(handover, alt=True) + +class HandoverClient(nfc.handover.HandoverClient): + def __init__(self, handover, llc): + super(HandoverClient, self).__init__(llc) + self.handover = handover + + def recv_records(self, timeout=None): + msg = self.recv_octets(timeout) + if msg is None: + return None + records = list(ndef.message_decoder(msg, 'relax')) + if records and records[0].type == 'urn:nfc:wkt:Hs': + summary("Handover client received message '{0}'".format(records[0].type)) + return list(ndef.message_decoder(msg, 'relax')) + summary("Handover client received invalid message: %s" + binascii.hexlify(msg)) + return None + + def recv_octets(self, timeout=None): + start = time.time() + msg = bytearray() + while True: + poll_timeout = 0.1 if timeout is None or timeout > 0.1 else timeout + if not self.socket.poll('recv', poll_timeout): + if timeout: + timeout -= time.time() - start + if timeout <= 0: + return None + start = time.time() + continue + try: + r = self.socket.recv() + if r is None: + return None + msg += r + except TypeError: + return b'' + try: + list(ndef.message_decoder(msg, 'strict', {})) + return bytes(msg) + except ndef.DecodeError: + if timeout: + timeout -= time.time() - start + if timeout <= 0: + return None + start = time.time() + continue + return None + +def run_dpp_handover_client(handover, alt=False): + chan_override = None + if alt: + chan_override = handover.altchanlist + handover.alt_proposal_used = True + global test_uri, test_alt_uri + if test_uri: + summary("TEST MODE: Using specified URI (alt=%s)" % str(alt)) + uri = test_alt_uri if alt else test_uri + else: + uri = wpas_get_nfc_uri(start_listen=False, chan_override=chan_override) + if uri is None: + summary("Cannot start handover client - no bootstrap URI available", + color=C_RED) + return + handover.my_uri = uri uri = ndef.UriRecord(uri) - print("NFC URI record for DPP: " + str(uri)) + summary("NFC URI record for DPP: " + str(uri)) carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) - hr = ndef.HandoverRequestRecord(version="1.4", crn=os.urandom(2)) + global test_crn + if test_crn: + prev, = struct.unpack('>H', test_crn) + summary("TEST MODE: Use specified crn %d" % prev) + crn = test_crn + test_crn = struct.pack('>H', prev + 0x10) + else: + crn = os.urandom(2) + hr = ndef.HandoverRequestRecord(version="1.4", crn=crn) hr.add_alternative_carrier('active', carrier.name) message = [hr, carrier] - print("NFC Handover Request message for DPP: " + str(message)) + summary("NFC Handover Request message for DPP: " + str(message)) - client = nfc.handover.HandoverClient(llc) - try: - summary("Trying to initiate NFC connection handover") - client.connect() - summary("Connected for handover") - except nfc.llcp.ConnectRefused: - summary("Handover connection refused") - client.close() + if handover.peer_crn is not None and not alt: + summary("NFC handover request from peer was already received - do not send own") return - except Exception as e: - summary("Other exception: " + str(e)) - client.close() + if handover.client: + summary("Use already started handover client") + client = handover.client + else: + summary("Start handover client") + client = HandoverClient(handover, handover.llc) + try: + summary("Trying to initiate NFC connection handover") + client.connect() + summary("Connected for handover") + except nfc.llcp.ConnectRefused: + summary("Handover connection refused") + client.close() + return + except Exception as e: + summary("Other exception: " + str(e)) + client.close() + return + handover.client = client + + if handover.peer_crn is not None and not alt: + summary("NFC handover request from peer was already received - do not send own") return summary("Sending handover request") + handover.my_crn_ready = True + if not client.send_records(message): - summary("Failed to send handover request") - client.close() + handover.my_crn_ready = False + summary("Failed to send handover request", color=C_RED) + run_client_alt(handover, alt) return + handover.my_crn, = struct.unpack('>H', crn) + summary("Receiving handover response") - message = client.recv_records(timeout=3.0) + try: + start = time.time() + message = client.recv_records(timeout=3.0) + end = time.time() + summary("Received {} record(s) in {} seconds".format(len(message) if message is not None else -1, end - start)) + except Exception as e: + # This is fine if we are the handover selector + if handover.hs_sent: + summary("Client receive failed as expected since I'm the handover server: %s" % str(e)) + elif handover.alt_proposal_used and not alt: + summary("Client received failed for initial proposal as expected since alternative proposal was also used: %s" % str(e)) + else: + summary("Client receive failed: %s" % str(e), color=C_RED) + message = None if message is None: - summary("No response received") - client.close() + if handover.hs_sent: + summary("No response received as expected since I'm the handover server") + elif handover.alt_proposal_used and not alt: + summary("No response received for initial proposal as expected since alternative proposal was also used") + elif handover.try_own and not alt: + summary("No response received for initial proposal as expected since alternative proposal will also be sent") + else: + summary("No response received", color=C_RED) + run_client_alt(handover, alt) return - print("Received message: " + str(message)) + summary("Received message: " + str(message)) if len(message) < 1 or \ not isinstance(message[0], ndef.HandoverSelectRecord): summary("Response was not Hs - received: " + message.type) - client.close() return - print("Received message") - print("alternative carriers: " + str(message[0].alternative_carriers)) + summary("Received handover select message") + summary("alternative carriers: " + str(message[0].alternative_carriers)) + if handover.i_m_selector: + summary("Ignore the received select since I'm the handover selector") + run_client_alt(handover, alt) + return + + if handover.alt_proposal_used and not alt: + summary("Ignore received handover select for the initial proposal since alternative proposal was sent") + client.close() + return dpp_found = False for carrier in message: if isinstance(carrier, ndef.HandoverSelectRecord): continue - print("Remote carrier type: " + carrier.type) + summary("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": if len(carrier.data) == 0 or carrier.data[0] != 0: - print("URI Identifier Code 'None' not seen") + summary("URI Identifier Code 'None' not seen", color=C_RED) continue - print("DPP carrier type match - send to wpa_supplicant") + summary("DPP carrier type match - send to wpa_supplicant") dpp_found = True uri = carrier.data[1:].decode("utf-8") - print("DPP URI: " + uri) + summary("DPP URI: " + uri) + handover.peer_uri = uri + if test_uri: + summary("TEST MODE: Fake processing") + break res = wpas_report_handover_sel(uri) if res is None or "FAIL" in res: - summary("DPP handover report rejected") + summary("DPP handover report rejected", color=C_RED) break success_report("DPP handover reported successfully (initiator)") - print("peer_id=" + res) + summary("peer_id=" + res) peer_id = int(res) - # TODO: Single Configurator instance wpas = wpas_connect() if wpas is None: break - res = wpas.request("DPP_CONFIGURATOR_ADD") - if "FAIL" in res: - print("Failed to initiate Configurator") - break - conf_id = int(res) + + global enrollee_only + global config_params + if enrollee_only: + extra = " role=enrollee" + elif config_params: + extra = " role=configurator " + config_params + else: + # TODO: Single Configurator instance + res = wpas.request("DPP_CONFIGURATOR_ADD") + if "FAIL" in res: + summary("Failed to initiate Configurator", color=C_RED) + break + conf_id = int(res) + extra = " conf=sta-dpp configurator=%d" % conf_id global own_id - print("Initiate DPP authentication") - cmd = "DPP_AUTH_INIT peer=%d own=%d conf=sta-dpp configurator=%d" % (peer_id, own_id, conf_id) + summary("Initiate DPP authentication") + cmd = "DPP_AUTH_INIT peer=%d own=%d" % (peer_id, own_id) + cmd += extra res = wpas.request(cmd) if "FAIL" in res: - print("Failed to initiate DPP authentication") + summary("Failed to initiate DPP authentication", color=C_RED) break - if not dpp_found: - print("DPP carrier not seen in response - allow peer to initiate a new handover with different parameters") - client.close() - print("Returning from dpp_handover_client") + if not dpp_found and handover.no_alt_proposal: + summary("DPP carrier not seen in response - do not allow alternative proposal anymore") + elif not dpp_found: + summary("DPP carrier not seen in response - allow peer to initiate a new handover with different parameters") + handover.alt_proposal = True + handover.my_crn_ready = False + handover.my_crn = None + handover.peer_crn = None + handover.hs_sent = False + summary("Returning from dpp_handover_client") return - print("Remove peer") - client.close() - print("Done with handover") + summary("Remove peer") + handover.close() + summary("Done with handover") global only_one if only_one: print("only_one -> stop loop") @@ -288,27 +515,107 @@ def dpp_handover_client(llc): continue_loop = False global no_wait - if no_wait: - print("Trying to exit..") + if no_wait or only_one: + summary("Trying to exit..") global terminate_now terminate_now = True - print("Returning from dpp_handover_client") + summary("Returning from dpp_handover_client") class HandoverServer(nfc.handover.HandoverServer): - def __init__(self, llc): + def __init__(self, handover, llc): super(HandoverServer, self).__init__(llc) self.sent_carrier = None self.ho_server_processing = False self.success = False - self.try_own = False + self.llc = llc + self.handover = handover + + def serve(self, socket): + peer_sap = socket.getpeername() + summary("Serving handover client on remote sap {0}".format(peer_sap)) + send_miu = socket.getsockopt(nfc.llcp.SO_SNDMIU) + try: + while socket.poll("recv"): + req = bytearray() + while socket.poll("recv"): + r = socket.recv() + if r is None: + return None + summary("Received %d octets" % len(r)) + req += r + if len(req) == 0: + continue + try: + list(ndef.message_decoder(req, 'strict', {})) + except ndef.DecodeError: + continue + summary("Full message received") + resp = self._process_request_data(req) + if resp is None or len(resp) == 0: + summary("No handover select to send out - wait for a possible alternative handover request") + handover.alt_proposal = True + req = bytearray() + continue + + for offset in range(0, len(resp), send_miu): + if not socket.send(resp[offset:offset + send_miu]): + summary("Failed to send handover select - connection closed") + return + summary("Sent out full handover select") + if handover.terminate_on_hs_send_completion: + handover.delayed_exit() + + except nfc.llcp.Error as e: + global terminate_now + summary("HandoverServer exception: %s" % e, + color=None if e.errno == errno.EPIPE or terminate_now else C_RED) + finally: + socket.close() + summary("Handover serve thread exiting") def process_handover_request_message(self, records): + handover = self.handover self.ho_server_processing = True + global in_raw_mode + was_in_raw_mode = in_raw_mode clear_raw_mode() - print("\nHandoverServer - request received: " + str(records)) + if was_in_raw_mode: + print("\n") + summary("HandoverServer - request received: " + str(records)) + + for carrier in records: + if not isinstance(carrier, ndef.HandoverRequestRecord): + continue + if carrier.collision_resolution_number: + handover.peer_crn = carrier.collision_resolution_number + summary("peer_crn: %d" % handover.peer_crn) + + if handover.my_crn is None and handover.my_crn_ready: + summary("Still trying to send own handover request - wait a moment to see if that succeeds before checking crn values") + for i in range(10): + if handover.my_crn is not None: + break + time.sleep(0.01) + if handover.my_crn is not None: + summary("my_crn: %d" % handover.my_crn) + + if handover.my_crn is not None and handover.peer_crn is not None: + if handover.my_crn == handover.peer_crn: + summary("Same crn used - automatic collision resolution failed") + # TODO: Should generate a new Handover Request message + return '' + if ((handover.my_crn & 1) == (handover.peer_crn & 1) and \ + handover.my_crn > handover.peer_crn) or \ + ((handover.my_crn & 1) != (handover.peer_crn & 1) and \ + handover.my_crn < handover.peer_crn): + summary("I'm the Handover Selector Device") + handover.i_m_selector = True + else: + summary("Peer is the Handover Selector device") + summary("Ignore the received request.") + return '' - carrier = None hs = ndef.HandoverSelectRecord('1.4') sel = [hs] @@ -317,61 +624,106 @@ class HandoverServer(nfc.handover.HandoverServer): for carrier in records: if isinstance(carrier, ndef.HandoverRequestRecord): continue - print("Remote carrier type: " + carrier.type) + summary("Remote carrier type: " + carrier.type) if carrier.type == "application/vnd.wfa.dpp": - print("DPP carrier type match - add DPP carrier record") + summary("DPP carrier type match - add DPP carrier record") if len(carrier.data) == 0 or carrier.data[0] != 0: - print("URI Identifier Code 'None' not seen") + summary("URI Identifier Code 'None' not seen", color=C_RED) continue uri = carrier.data[1:].decode("utf-8") - print("Received DPP URI: " + uri) + summary("Received DPP URI: " + uri) - data = wpas_get_nfc_uri(start_listen=False) - print("Own URI (pre-processing): %s" % data) + global test_uri, test_alt_uri + if test_uri: + summary("TEST MODE: Using specified URI") + data = test_sel_uri if test_sel_uri else test_uri + elif handover.alt_proposal and handover.altchanlist: + summary("Use alternative channel list while processing alternative proposal from peer") + data = wpas_get_nfc_uri(start_listen=False, + chan_override=handover.altchanlist, + pick_channel=True) + else: + data = wpas_get_nfc_uri(start_listen=False, + pick_channel=True) + summary("Own URI (pre-processing): %s" % data) - res = wpas_report_handover_req(uri) + if test_uri: + summary("TEST MODE: Fake processing") + res = "OK" + data += " [%s]" % uri + else: + res = wpas_report_handover_req(uri) if res is None or "FAIL" in res: - print("DPP handover request processing failed") + summary("DPP handover request processing failed", + color=C_RED) + if handover.altchanlist: + data = wpas_get_nfc_uri(start_listen=False, + chan_override=handover.altchanlist) + summary("Own URI (try another channel list): %s" % data) + continue + + if test_alt_uri: + summary("TEST MODE: Reject initial proposal") continue found = True - self.received_carrier = carrier - wpas = wpas_connect() - if wpas is None: - continue - global own_id - data = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() - if "FAIL" in data: - continue - print("Own URI (post-processing): %s" % data) + if not test_uri: + wpas = wpas_connect() + if wpas is None: + continue + global own_id + data = wpas.request("DPP_BOOTSTRAP_GET_URI %d" % own_id).rstrip() + if "FAIL" in data: + continue + summary("Own URI (post-processing): %s" % data) + handover.my_uri = data + handover.peer_uri = uri uri = ndef.UriRecord(data) - print("Own bootstrapping NFC URI record: " + str(uri)) + summary("Own bootstrapping NFC URI record: " + str(uri)) - info = wpas.request("DPP_BOOTSTRAP_INFO %d" % own_id) - freq = None - for line in info.splitlines(): - if line.startswith("use_freq="): - freq = int(line.split('=')[1]) - if freq is None: - print("No channel negotiated over NFC - use channel 1") - freq = 2412 - res = wpas.request("DPP_LISTEN %d" % freq) - if "OK" not in res: - print("Failed to start DPP listen") - break + if not test_uri: + info = wpas.request("DPP_BOOTSTRAP_INFO %d" % own_id) + freq = None + for line in info.splitlines(): + if line.startswith("use_freq="): + freq = int(line.split('=')[1]) + if freq is None or freq == 0: + summary("No channel negotiated over NFC - use channel 6") + freq = 2437 + else: + summary("Negotiated channel: %d MHz" % freq) + if not dpp_start_listen(wpas, freq): + break carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) - print("Own DPP carrier record: " + str(carrier)) + summary("Own DPP carrier record: " + str(carrier)) hs.add_alternative_carrier('active', carrier.name) sel = [hs, carrier] break summary("Sending handover select: " + str(sel)) if found: + summary("Handover completed successfully") + handover.terminate_on_hs_send_completion = True self.success = True + handover.hs_sent = True + handover.i_m_selector = True + elif handover.no_alt_proposal: + summary("Do not try alternative proposal anymore - handover failed", + color=C_RED) + handover.hs_sent = True else: - self.try_own = True + summary("Try to initiate with alternative parameters") + handover.try_own = True + handover.hs_sent = False + handover.no_alt_proposal = True + if handover.client_thread: + handover.start_client_alt = True + else: + handover.client_thread = threading.Thread(target=llcp_worker, + args=(self.llc, True)) + handover.client_thread.start() return sel def clear_raw_mode(): @@ -403,22 +755,22 @@ def getch(): def dpp_tag_read(tag): success = False for record in tag.ndef.records: - print(record) - print("record type " + record.type) + summary(record) + summary("record type " + record.type) if record.type == "application/vnd.wfa.dpp": summary("DPP HS tag - send to wpa_supplicant") success = dpp_hs_tag_read(record) break if isinstance(record, ndef.UriRecord): - print("URI record: uri=" + record.uri) - print("URI record: iri=" + record.iri) + summary("URI record: uri=" + record.uri) + summary("URI record: iri=" + record.iri) if record.iri.startswith("DPP:"): - print("DPP URI") + summary("DPP URI") if not dpp_nfc_uri_process(record.iri): break success = True else: - print("Ignore unknown URI") + summary("Ignore unknown URI") break if success: @@ -428,17 +780,25 @@ def dpp_tag_read(tag): def rdwr_connected_write_tag(tag): summary("Tag found - writing - " + str(tag)) + if not tag.ndef: + summary("Not a formatted NDEF tag", color=C_RED) + return if not tag.ndef.is_writeable: - print("Not a writable tag") + summary("Not a writable tag", color=C_RED) return global dpp_tag_data if tag.ndef.capacity < len(dpp_tag_data): - print("Not enough room for the message") + summary("Not enough room for the message") + return + try: + tag.ndef.records = dpp_tag_data + except ValueError as e: + summary("Writing the tag failed: %s" % str(e), color=C_RED) return - tag.ndef.records = dpp_tag_data success_report("Tag write succeeded") - print("Done - remove tag") - global only_one + summary("Tag writing completed - remove tag", color=C_GREEN) + global only_one, operation_success + operation_success = True if only_one: global continue_loop continue_loop = False @@ -446,45 +806,45 @@ def rdwr_connected_write_tag(tag): return dpp_sel_wait_remove def write_nfc_uri(clf, wait_remove=True): - print("Write NFC URI record") + summary("Write NFC URI record") data = wpas_get_nfc_uri() if data is None: - summary("Could not get NFC URI from wpa_supplicant") + summary("Could not get NFC URI from wpa_supplicant", color=C_RED) return global dpp_sel_wait_remove dpp_sel_wait_remove = wait_remove - print("URI: %s" % data) + summary("URI: %s" % data) uri = ndef.UriRecord(data) - print(uri) + summary(uri) - print("Touch an NFC tag") + summary("Touch an NFC tag to write URI record", color=C_CYAN) global dpp_tag_data dpp_tag_data = [uri] clf.connect(rdwr={'on-connect': rdwr_connected_write_tag}) def write_nfc_hs(clf, wait_remove=True): - print("Write NFC Handover Select record on a tag") + summary("Write NFC Handover Select record on a tag") data = wpas_get_nfc_uri() if data is None: - summary("Could not get NFC URI from wpa_supplicant") + summary("Could not get NFC URI from wpa_supplicant", color=C_RED) return global dpp_sel_wait_remove dpp_sel_wait_remove = wait_remove - print("URI: %s" % data) + summary("URI: %s" % data) uri = ndef.UriRecord(data) - print(uri) + summary(uri) carrier = ndef.Record('application/vnd.wfa.dpp', 'A', uri.data) hs = ndef.HandoverSelectRecord('1.4') hs.add_alternative_carrier('active', carrier.name) - print(hs) - print(carrier) + summary(hs) + summary(carrier) - print("Touch an NFC tag") + summary("Touch an NFC tag to write HS record", color=C_CYAN) global dpp_tag_data dpp_tag_data = [hs, carrier] - print(dpp_tag_data) + summary(dpp_tag_data) clf.connect(rdwr={'on-connect': rdwr_connected_write_tag}) def rdwr_connected(tag): @@ -492,41 +852,50 @@ def rdwr_connected(tag): summary("Tag connected: " + str(tag)) if tag.ndef: - print("NDEF tag: " + tag.type) - print(tag.ndef.records) + summary("NDEF tag: " + tag.type) + summary(tag.ndef.records) success = dpp_tag_read(tag) if only_one and success: global continue_loop continue_loop = False else: - summary("Not an NDEF tag - remove tag") + summary("Not an NDEF tag - remove tag", color=C_RED) return True return not no_wait -def llcp_worker(llc): +def llcp_worker(llc, try_alt): + global handover + print("Start of llcp_worker()") + if try_alt: + summary("Starting handover client (try_alt)") + dpp_handover_client(handover, alt=True) + summary("Exiting llcp_worker thread (try_alt)") + return global init_on_touch if init_on_touch: - print("Starting handover client") - dpp_handover_client(llc) - print("Exiting llcp_worker thread (init_in_touch)") + summary("Starting handover client (init_on_touch)") + dpp_handover_client(handover) + summary("Exiting llcp_worker thread (init_on_touch)") return global no_input if no_input: - print("Wait for handover to complete") + summary("Wait for handover to complete") else: print("Wait for handover to complete - press 'i' to initiate") - global srv - global wait_connection - while not wait_connection and srv.sent_carrier is None: - if srv.try_own: - srv.try_own = False - print("Try to initiate another handover with own parameters") - dpp_handover_client(llc) - print("Exiting llcp_worker thread (retry with own parameters)") + while not handover.wait_connection and handover.srv.sent_carrier is None: + if handover.try_own: + handover.try_own = False + summary("Try to initiate another handover with own parameters") + handover.my_crn_ready = False + handover.my_crn = None + handover.peer_crn = None + handover.hs_sent = False + dpp_handover_client(handover, alt=True) + summary("Exiting llcp_worker thread (retry with own parameters)") return - if srv.ho_server_processing: + if handover.srv.ho_server_processing: time.sleep(0.025) elif no_input: time.sleep(0.5) @@ -535,34 +904,85 @@ def llcp_worker(llc): if res != 'i': continue clear_raw_mode() - print("Starting handover client") - dpp_handover_client(llc) - print("Exiting llcp_worker thread (manual init)") + summary("Starting handover client") + dpp_handover_client(handover) + summary("Exiting llcp_worker thread (manual init)") return + global in_raw_mode + was_in_raw_mode = in_raw_mode clear_raw_mode() - print("\rExiting llcp_worker thread") + if was_in_raw_mode: + print("\r") + summary("Exiting llcp_worker thread") + +class ConnectionHandover(): + def __init__(self): + self.client = None + self.client_thread = None + self.reset() + self.exit_thread = None + + def reset(self): + self.wait_connection = False + self.my_crn_ready = False + self.my_crn = None + self.peer_crn = None + self.hs_sent = False + self.no_alt_proposal = False + self.alt_proposal_used = False + self.i_m_selector = False + self.start_client_alt = False + self.terminate_on_hs_send_completion = False + self.try_own = False + self.my_uri = None + self.peer_uri = None + self.connected = False + self.alt_proposal = False + + def start_handover_server(self, llc): + summary("Start handover server") + self.llc = llc + self.srv = HandoverServer(self, llc) + + def close(self): + if self.client: + self.client.close() + self.client = None + + def run_delayed_exit(self): + summary("Trying to exit (delayed)..") + time.sleep(0.25) + summary("Trying to exit (after wait)..") + global terminate_now + terminate_now = True + + def delayed_exit(self): + global only_one + if only_one: + self.exit_thread = threading.Thread(target=self.run_delayed_exit) + self.exit_thread.start() def llcp_startup(llc): - print("Start LLCP server") - global srv - srv = HandoverServer(llc) + global handover + handover.start_handover_server(llc) return llc def llcp_connected(llc): - print("P2P LLCP connected") - global wait_connection - wait_connection = False - global init_on_touch - if not init_on_touch: - global srv - srv.start() + summary("P2P LLCP connected") + global handover + handover.connected = True + handover.srv.start() if init_on_touch or not no_input: - threading.Thread(target=llcp_worker, args=(llc,)).start() + handover.client_thread = threading.Thread(target=llcp_worker, + args=(llc, False)) + handover.client_thread.start() return True def llcp_release(llc): - print("LLCP release") + summary("LLCP release") + global handover + handover.close() return True def terminate_loop(): @@ -592,17 +1012,38 @@ def main(): help='tag read only (do not allow connection handover)') parser.add_argument('--handover-only', action='store_true', help='connection handover only (do not allow tag read)') + parser.add_argument('--enrollee', action='store_true', + help='run as Enrollee-only') + parser.add_argument('--configurator', action='store_true', + help='run as Configurator-only') + parser.add_argument('--config-params', default='', + help='configurator parameters') + parser.add_argument('--ctrl', default='/var/run/wpa_supplicant', + help='wpa_supplicant/hostapd control interface') parser.add_argument('--summary', help='summary file for writing status updates') parser.add_argument('--success', help='success file for writing success update') parser.add_argument('--device', default='usb', help='NFC device to open') - parser.add_argument('--chan', default='81/1', help='channel list') + parser.add_argument('--chan', default=None, help='channel list') + parser.add_argument('--altchan', default=None, help='alternative channel list') + parser.add_argument('--netrole', default=None, help='netrole for Enrollee') + parser.add_argument('--test-uri', default=None, + help='test mode: initial URI') + parser.add_argument('--test-alt-uri', default=None, + help='test mode: alternative URI') + parser.add_argument('--test-sel-uri', default=None, + help='test mode: handover select URI') + parser.add_argument('--test-crn', default=None, + help='test mode: hardcoded crn') parser.add_argument('command', choices=['write-nfc-uri', 'write-nfc-hs'], nargs='?') args = parser.parse_args() - print(args) + summary(args) + + global handover + handover = ConnectionHandover() global only_one only_one = args.only_one @@ -610,18 +1051,49 @@ def main(): global no_wait no_wait = args.no_wait - global chanlist + global chanlist, netrole, test_uri, test_alt_uri, test_sel_uri + global test_crn chanlist = args.chan + handover.altchanlist = args.altchan + netrole = args.netrole + test_uri = args.test_uri + test_alt_uri = args.test_alt_uri + test_sel_uri = args.test_sel_uri + if args.test_crn: + test_crn = struct.pack('>H', int(args.test_crn)) + else: + test_crn = None logging.basicConfig(level=args.loglevel) + for l in ['nfc.clf.rcs380', + 'nfc.clf.transport', + 'nfc.clf.device', + 'nfc.clf.__init__', + 'nfc.llcp', + 'nfc.handover']: + log = logging.getLogger(l) + log.setLevel(args.loglevel) global init_on_touch init_on_touch = args.init_on_touch + global enrollee_only + enrollee_only = args.enrollee + + global configurator_only + configurator_only = args.configurator + + global config_params + config_params = args.config_params + if args.ifname: global ifname ifname = args.ifname - print("Selected ifname " + ifname) + summary("Selected ifname " + ifname) + + if args.ctrl: + global wpas_ctrl + wpas_ctrl = args.ctrl if args.summary: global summary_file @@ -636,26 +1108,39 @@ def main(): no_input = True clf = nfc.ContactlessFrontend() - global wait_connection try: if not clf.open(args.device): - print("Could not open connection with an NFC device") - raise SystemExit + summary("Could not open connection with an NFC device", color=C_RED) + raise SystemExit(1) if args.command == "write-nfc-uri": write_nfc_uri(clf, wait_remove=not args.no_wait) + if not operation_success: + raise SystemExit(1) raise SystemExit if args.command == "write-nfc-hs": write_nfc_hs(clf, wait_remove=not args.no_wait) + if not operation_success: + raise SystemExit(1) raise SystemExit global continue_loop while continue_loop: + global in_raw_mode + was_in_raw_mode = in_raw_mode clear_raw_mode() - print("\rWaiting for a tag or peer to be touched") - wait_connection = True + if was_in_raw_mode: + print("\r") + if args.handover_only: + summary("Waiting a peer to be touched", color=C_MAGENTA) + elif args.tag_read_only: + summary("Waiting for a tag to be touched", color=C_BLUE) + else: + summary("Waiting for a tag or peer to be touched", + color=C_GREEN) + handover.wait_connection = True try: if args.tag_read_only: if not clf.connect(rdwr={'on-connect': rdwr_connected}): @@ -674,12 +1159,21 @@ def main(): terminate=terminate_loop): break except Exception as e: - print("clf.connect failed: " + str(e)) + summary("clf.connect failed: " + str(e)) break - global srv - if only_one and srv and srv.success: - raise SystemExit + if only_one and handover.connected: + role = "selector" if handover.i_m_selector else "requestor" + summary("Connection handover result: I'm the %s" % role, + color=C_YELLOW) + if handover.peer_uri: + summary("Peer URI: " + handover.peer_uri, color=C_YELLOW) + if handover.my_uri: + summary("My URI: " + handover.my_uri, color=C_YELLOW) + if not (handover.peer_uri and handover.my_uri): + summary("Negotiated connection handover failed", + color=C_YELLOW) + break except KeyboardInterrupt: raise SystemExit diff --git a/wpa_supplicant/examples/p2p-action-udhcp.sh b/wpa_supplicant/examples/p2p-action-udhcp.sh index d7d0e79b7..53d8b777c 100755 --- a/wpa_supplicant/examples/p2p-action-udhcp.sh +++ b/wpa_supplicant/examples/p2p-action-udhcp.sh @@ -50,7 +50,7 @@ fi if [ "$CMD" = "P2P-CROSS-CONNECT-ENABLE" ]; then GIFNAME=$3 UPLINK=$4 - # enable NAT/masquarade $GIFNAME -> $UPLINK + # enable NAT/masquerade $GIFNAME -> $UPLINK iptables -P FORWARD DROP iptables -t nat -A POSTROUTING -o $UPLINK -j MASQUERADE iptables -A FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT @@ -61,7 +61,7 @@ fi if [ "$CMD" = "P2P-CROSS-CONNECT-DISABLE" ]; then GIFNAME=$3 UPLINK=$4 - # disable NAT/masquarade $GIFNAME -> $UPLINK + # disable NAT/masquerade $GIFNAME -> $UPLINK sysctl net.ipv4.ip_forward=0 iptables -t nat -D POSTROUTING -o $UPLINK -j MASQUERADE iptables -D FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT diff --git a/wpa_supplicant/examples/p2p-action.sh b/wpa_supplicant/examples/p2p-action.sh index 797d43a00..6c27b27b7 100755 --- a/wpa_supplicant/examples/p2p-action.sh +++ b/wpa_supplicant/examples/p2p-action.sh @@ -77,7 +77,7 @@ fi if [ "$CMD" = "P2P-CROSS-CONNECT-ENABLE" ]; then GIFNAME=$3 UPLINK=$4 - # enable NAT/masquarade $GIFNAME -> $UPLINK + # enable NAT/masquerade $GIFNAME -> $UPLINK iptables -P FORWARD DROP iptables -t nat -A POSTROUTING -o $UPLINK -j MASQUERADE iptables -A FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT @@ -88,7 +88,7 @@ fi if [ "$CMD" = "P2P-CROSS-CONNECT-DISABLE" ]; then GIFNAME=$3 UPLINK=$4 - # disable NAT/masquarade $GIFNAME -> $UPLINK + # disable NAT/masquerade $GIFNAME -> $UPLINK sysctl net.ipv4.ip_forward=0 iptables -t nat -D POSTROUTING -o $UPLINK -j MASQUERADE iptables -D FORWARD -i $UPLINK -o $GIFNAME -m state --state RELATED,ESTABLISHED -j ACCEPT diff --git a/wpa_supplicant/examples/p2p/p2p_connect.py b/wpa_supplicant/examples/p2p/p2p_connect.py index 2f62e9c94..bfb553341 100644 --- a/wpa_supplicant/examples/p2p/p2p_connect.py +++ b/wpa_supplicant/examples/p2p/p2p_connect.py @@ -71,7 +71,7 @@ class P2P_Connect(): global wpas_dbus_interfaces_interface global wpas_dbus_interfaces_p2pdevice - # Dictionary of Arguements + # Dictionary of Arguments global p2p_connect_arguements # Constructor @@ -146,9 +146,9 @@ class P2P_Connect(): signal_name="WpsFailed") - #Constructing all the arguements needed to connect + #Constructing all the arguments needed to connect def constructArguements(self): - # Adding required arguements + # Adding required arguments self.p2p_connect_arguements = {'wps_method':self.wps_method, 'peer':dbus.ObjectPath(self.path+'/Peers/'+self.addr)} @@ -198,7 +198,7 @@ class P2P_Connect(): usage() quit() - # Go_intent is optional for all arguements + # Go_intent is optional for all arguments if (self.go_intent != None): self.p2p_connect_arguements.update( {'go_intent':dbus.Int32(self.go_intent)}) @@ -239,7 +239,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): @@ -266,9 +266,9 @@ if __name__ == "__main__": else: assert False, "unhandled option" - # Required Arguements check + # Required Arguments check if (interface_name == None or wps_method == None or addr == None): - print("Error:\n Required arguements not specified") + print("Error:\n Required arguments not specified") usage() quit() @@ -289,7 +289,7 @@ if __name__ == "__main__": addr,pin,wps_method,go_intent) except: - print("Error:\n Invalid Arguements") + print("Error:\n Invalid Arguments") usage() quit() diff --git a/wpa_supplicant/examples/p2p/p2p_disconnect.py b/wpa_supplicant/examples/p2p/p2p_disconnect.py index 85b5a8b39..f04b98e66 100644 --- a/wpa_supplicant/examples/p2p/p2p_disconnect.py +++ b/wpa_supplicant/examples/p2p/p2p_disconnect.py @@ -125,7 +125,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): diff --git a/wpa_supplicant/examples/p2p/p2p_find.py b/wpa_supplicant/examples/p2p/p2p_find.py index e2df52896..412d81200 100644 --- a/wpa_supplicant/examples/p2p/p2p_find.py +++ b/wpa_supplicant/examples/p2p/p2p_find.py @@ -136,7 +136,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): diff --git a/wpa_supplicant/examples/p2p/p2p_flush.py b/wpa_supplicant/examples/p2p/p2p_flush.py index 42fc7a3e9..5cc3a0e18 100644 --- a/wpa_supplicant/examples/p2p/p2p_flush.py +++ b/wpa_supplicant/examples/p2p/p2p_flush.py @@ -125,7 +125,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): diff --git a/wpa_supplicant/examples/p2p/p2p_group_add.py b/wpa_supplicant/examples/p2p/p2p_group_add.py index 6d408218a..db6d60d80 100644 --- a/wpa_supplicant/examples/p2p/p2p_group_add.py +++ b/wpa_supplicant/examples/p2p/p2p_group_add.py @@ -18,7 +18,7 @@ def usage(): print(" [-w ]") print("Options:") print(" -i = interface name") - print(" -p = persistant group = 0 (0=false, 1=true)") + print(" -p = persistent group = 0 (0=false, 1=true)") print(" -f = frequency") print(" -o = persistent group object path") print(" -w = wpas dbus interface = fi.w1.wpa_supplicant1") @@ -57,7 +57,7 @@ class P2P_Group_Add (threading.Thread): global wpas_dbus_interfaces_interface global wpas_dbus_interfaces_p2pdevice - # Arguements + # Arguments global P2PDictionary # Constructor @@ -120,7 +120,7 @@ class P2P_Group_Add (threading.Thread): signal_name="WpsFailed") # Sets up p2p_group_add dictionary - def constructArguements(self): + def constructArguments(self): self.P2PDictionary = {'persistent':self.persistent} if (self.frequency != None): @@ -141,7 +141,7 @@ class P2P_Group_Add (threading.Thread): self.p2p_interface.GroupAdd(self.P2PDictionary) except: - print("Error:\n Could not preform group add") + print("Error:\n Could not perform group add") usage() os._exit(0) @@ -172,7 +172,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): @@ -213,9 +213,9 @@ if __name__ == "__main__": p2p_group_add_test = P2P_Group_Add(interface_name,wpas_dbus_interface, persistent,frequency,persistent_group_object) except: - print("Error:\n Invalid Arguements") + print("Error:\n Invalid Arguments") - p2p_group_add_test.constructArguements() + p2p_group_add_test.constructArguments() p2p_group_add_test.start() time.sleep(5) print("Error:\n Group formation timed out") diff --git a/wpa_supplicant/examples/p2p/p2p_invite.py b/wpa_supplicant/examples/p2p/p2p_invite.py index 341dcd0a9..8944e11ed 100644 --- a/wpa_supplicant/examples/p2p/p2p_invite.py +++ b/wpa_supplicant/examples/p2p/p2p_invite.py @@ -25,7 +25,7 @@ def usage(): # Required Signals def InvitationResult(invite_result): - print("Inviation Result signal :") + print("Invitation Result signal :") status = invite_result['status'] print("status = ", status) if invite_result.has_key('BSSID'): @@ -55,7 +55,7 @@ class P2P_Invite (threading.Thread): global wpas_dbus_interfaces_interface global wpas_dbus_interfaces_p2pdevice - # Arguements + # Arguments global P2PDictionary # Constructor @@ -127,7 +127,7 @@ class P2P_Invite (threading.Thread): self.p2p_interface.Invite(self.P2PDictionary) except: - print("Error:\n Invalid Arguements") + print("Error:\n Invalid Arguments") usage() os._exit(0) @@ -154,7 +154,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): @@ -190,7 +190,7 @@ if __name__ == "__main__": P2P_Invite(interface_name,wpas_dbus_interface, addr,persistent_group_object) except: - print("Error:\n Invalid Arguements") + print("Error:\n Invalid Arguments") usage() os._exit(1) diff --git a/wpa_supplicant/examples/p2p/p2p_listen.py b/wpa_supplicant/examples/p2p/p2p_listen.py index b0837d9df..cbeda9ff4 100644 --- a/wpa_supplicant/examples/p2p/p2p_listen.py +++ b/wpa_supplicant/examples/p2p/p2p_listen.py @@ -126,7 +126,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): diff --git a/wpa_supplicant/examples/p2p/p2p_stop_find.py b/wpa_supplicant/examples/p2p/p2p_stop_find.py index bdb4c0e32..f36719645 100644 --- a/wpa_supplicant/examples/p2p/p2p_stop_find.py +++ b/wpa_supplicant/examples/p2p/p2p_stop_find.py @@ -130,7 +130,7 @@ if __name__ == "__main__": usage() quit() - # If theres a switch, override default option + # If there's a switch, override default option for key, value in options: # Help if (key == "-h"): diff --git a/wpa_supplicant/examples/udhcpd-p2p.conf b/wpa_supplicant/examples/udhcpd-p2p.conf index df5909408..f92cc619e 100644 --- a/wpa_supplicant/examples/udhcpd-p2p.conf +++ b/wpa_supplicant/examples/udhcpd-p2p.conf @@ -11,8 +11,8 @@ end 192.168.42.254 #default: 192.168.0.254 interface wlan2 #default: eth0 -# The maximim number of leases (includes addressesd reserved -# by OFFER's, DECLINE's, and ARP conficts +# The maximum number of leases (includes addresses reserved +# by OFFER's, DECLINE's, and ARP conflicts) #max_leases 254 #default: 254 @@ -52,12 +52,12 @@ interface wlan2 #default: eth0 # If a lease to be given is below this value, the full lease time is # instead used (seconds). -#min_lease 60 #defult: 60 +#min_lease 60 #default: 60 # The location of the leases file -#lease_file /var/lib/misc/udhcpd.leases #defualt: /var/lib/misc/udhcpd.leases +#lease_file /var/lib/misc/udhcpd.leases #default: /var/lib/misc/udhcpd.leases # The location of the pid file pidfile /var/run/udhcpd-wlan2.pid #default: /var/run/udhcpd.pid @@ -77,7 +77,7 @@ pidfile /var/run/udhcpd-wlan2.pid #default: /var/run/udhcpd.pid #boot_file /var/nfs_root #default: (none) -# The remainer of options are DHCP options and can be specifed with the +# The remainder of options are DHCP options and can be specified with the # keyword 'opt' or 'option'. If an option can take multiple items, such # as the dns option, they can be listed on the same line, or multiple # lines. The only option with a default is 'lease'. @@ -116,5 +116,3 @@ option lease 864000 # 10 days of seconds # Static leases map #static_lease 00:60:08:11:CE:4E 192.168.0.54 #static_lease 00:60:08:11:CE:3E 192.168.0.44 - - diff --git a/wpa_supplicant/gas_query.c b/wpa_supplicant/gas_query.c index 8e977a3ec..e60a8c1fe 100644 --- a/wpa_supplicant/gas_query.c +++ b/wpa_supplicant/gas_query.c @@ -43,6 +43,7 @@ struct gas_query_pending { unsigned int offchannel_tx_started:1; unsigned int retry:1; unsigned int wildcard_bssid:1; + unsigned int maintain_addr:1; int freq; u16 status_code; struct wpabuf *req; @@ -693,12 +694,15 @@ static void gas_query_start_cb(struct wpa_radio_work *work, int deinit) return; } - if (wpas_update_random_addr_disassoc(wpa_s) < 0) { - wpa_msg(wpa_s, MSG_INFO, - "Failed to assign random MAC address for GAS"); - gas_query_free(query, 1); - radio_work_done(work); - return; + if (!query->maintain_addr && !wpa_s->conf->gas_rand_mac_addr) { + if (wpas_update_random_addr_disassoc(wpa_s) < 0) { + wpa_msg(wpa_s, MSG_INFO, + "Failed to assign random MAC address for GAS"); + gas_query_free(query, 1); + radio_work_done(work); + return; + } + os_memcpy(query->sa, wpa_s->own_addr, ETH_ALEN); } gas->work = work; @@ -727,19 +731,24 @@ static void gas_query_tx_initial_req(struct gas_query *gas, static int gas_query_new_dialog_token(struct gas_query *gas, const u8 *dst) { - static int next_start = 0; - int dialog_token; + u8 dialog_token; + int i; - for (dialog_token = 0; dialog_token < 256; dialog_token++) { - if (gas_query_dialog_token_available( - gas, dst, (next_start + dialog_token) % 256)) + /* There should never be more than couple active GAS queries in + * progress, so it should be very likely to find an available dialog + * token by checking random values. Use a limit on the number of + * iterations to handle the unexpected case of large number of pending + * queries cleanly. */ + for (i = 0; i < 256; i++) { + /* Get a random number and check if the slot is available */ + if (os_get_random(&dialog_token, sizeof(dialog_token)) < 0) break; + if (gas_query_dialog_token_available(gas, dst, dialog_token)) + return dialog_token; } - if (dialog_token == 256) - return -1; /* Too many pending queries */ - dialog_token = (next_start + dialog_token) % 256; - next_start = (dialog_token + 1) % 256; - return dialog_token; + + /* No dialog token value available */ + return -1; } @@ -749,12 +758,23 @@ static int gas_query_set_sa(struct gas_query *gas, struct wpa_supplicant *wpa_s = gas->wpa_s; struct os_reltime now; - if (!wpa_s->conf->gas_rand_mac_addr || + if (query->maintain_addr || + !wpa_s->conf->gas_rand_mac_addr || !(wpa_s->current_bss ? (wpa_s->drv_flags & WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA_CONNECTED) : (wpa_s->drv_flags & WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA))) { /* Use own MAC address as the transmitter address */ + wpa_printf(MSG_DEBUG, + "GAS: Use own MAC address as the transmitter address%s%s%s", + query->maintain_addr ? " (maintain_addr)" : "", + !wpa_s->conf->gas_rand_mac_addr ? " (no gas_rand_mac_adr set)" : "", + !(wpa_s->current_bss ? + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA_CONNECTED) : + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_MGMT_TX_RANDOM_TA)) ? + " (no driver rand capa" : ""); os_memcpy(query->sa, wpa_s->own_addr, ETH_ALEN); return 0; } @@ -800,6 +820,9 @@ static int gas_query_set_sa(struct gas_query *gas, * @gas: GAS query data from gas_query_init() * @dst: Destination MAC address for the query * @freq: Frequency (in MHz) for the channel on which to send the query + * @wildcard_bssid: Force use of wildcard BSSID value + * @maintain_addr: Maintain own MAC address for exchange (i.e., ignore MAC + * address randomization rules) * @req: GAS query payload (to be freed by gas_query module in case of success * return) * @cb: Callback function for reporting GAS query result and response @@ -807,7 +830,7 @@ static int gas_query_set_sa(struct gas_query *gas, * Returns: dialog token (>= 0) on success or -1 on failure */ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, - int wildcard_bssid, struct wpabuf *req, + int wildcard_bssid, int maintain_addr, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, @@ -829,6 +852,7 @@ int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, return -1; query->gas = gas; + query->maintain_addr = !!maintain_addr; if (gas_query_set_sa(gas, query)) { os_free(query); return -1; diff --git a/wpa_supplicant/gas_query.h b/wpa_supplicant/gas_query.h index d2b455442..f9ce7b680 100644 --- a/wpa_supplicant/gas_query.h +++ b/wpa_supplicant/gas_query.h @@ -35,7 +35,7 @@ enum gas_query_result { }; int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, - int wildcard_bssid, struct wpabuf *req, + int wildcard_bssid, int maintain_addr, struct wpabuf *req, void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, enum gas_query_result result, const struct wpabuf *adv_proto, diff --git a/wpa_supplicant/hs20_supplicant.c b/wpa_supplicant/hs20_supplicant.c index 47a1d0175..de350bbb4 100644 --- a/wpa_supplicant/hs20_supplicant.c +++ b/wpa_supplicant/hs20_supplicant.c @@ -288,7 +288,8 @@ int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes, if (buf == NULL) return -1; - res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s); + res = gas_query_req(wpa_s->gas, dst, freq, 0, 0, buf, anqp_resp_cb, + wpa_s); if (res < 0) { wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request"); wpabuf_free(buf); @@ -900,14 +901,25 @@ static void hs20_osu_add_prov(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, /* OSU Friendly Name Duples */ while (pos - pos2 >= 4 && prov->friendly_name_count < OSU_MAX_ITEMS) { struct osu_lang_string *f; - if (1 + pos2[0] > pos - pos2 || pos2[0] < 3) { + u8 slen; + + slen = pos2[0]; + if (1 + slen > pos - pos2) { wpa_printf(MSG_DEBUG, "Invalid OSU Friendly Name"); break; } + if (slen < 3) { + wpa_printf(MSG_DEBUG, + "Invalid OSU Friendly Name (no room for language)"); + break; + } f = &prov->friendly_name[prov->friendly_name_count++]; - os_memcpy(f->lang, pos2 + 1, 3); - os_memcpy(f->text, pos2 + 1 + 3, pos2[0] - 3); - pos2 += 1 + pos2[0]; + pos2++; + os_memcpy(f->lang, pos2, 3); + pos2 += 3; + slen -= 3; + os_memcpy(f->text, pos2, slen); + pos2 += slen; } /* OSU Server URI */ diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c index 37368c4cb..02e63904c 100644 --- a/wpa_supplicant/ibss_rsn.c +++ b/wpa_supplicant/ibss_rsn.c @@ -200,7 +200,13 @@ static void supp_cancel_auth_timeout(void *ctx) } -static void supp_deauthenticate(void * ctx, u16 reason_code) +static void supp_deauthenticate(void *ctx, u16 reason_code) +{ + wpa_printf(MSG_DEBUG, "SUPP: %s (TODO)", __func__); +} + + +static void supp_reconnect(void *ctx) { wpa_printf(MSG_DEBUG, "SUPP: %s (TODO)", __func__); } @@ -225,6 +231,7 @@ static int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, ctx->mlme_setprotection = supp_mlme_setprotection; ctx->cancel_auth_timeout = supp_cancel_auth_timeout; ctx->deauthenticate = supp_deauthenticate; + ctx->reconnect = supp_reconnect; peer->supp = wpa_sm_init(ctx); if (peer->supp == NULL) { wpa_printf(MSG_DEBUG, "SUPP: wpa_sm_init() failed"); @@ -513,7 +520,7 @@ static int ibss_rsn_send_auth(struct ibss_rsn *ibss_rsn, const u8 *da, int seq) wpa_printf(MSG_DEBUG, "RSN: IBSS TX Auth frame (SEQ %d) to " MACSTR, seq, MAC2STR(da)); - return wpa_drv_send_mlme(wpa_s, (u8 *) &auth, auth_length, 0, 0); + return wpa_drv_send_mlme(wpa_s, (u8 *) &auth, auth_length, 0, 0, 0); } diff --git a/wpa_supplicant/interworking.c b/wpa_supplicant/interworking.c index 49b9907b0..5f9d1dced 100644 --- a/wpa_supplicant/interworking.c +++ b/wpa_supplicant/interworking.c @@ -316,7 +316,7 @@ static int interworking_anqp_send_req(struct wpa_supplicant *wpa_s, if (buf == NULL) return -1; - res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, 0, buf, + res = gas_query_req(wpa_s->gas, bss->bssid, bss->freq, 0, 0, buf, interworking_anqp_resp_cb, wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); @@ -946,7 +946,8 @@ static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s, struct wpa_driver_capa capa; res = wpa_drv_get_capa(wpa_s, &capa); - if (res == 0 && capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_FT) { + if (res == 0 && capa.key_mgmt_iftype[WPA_IF_STATION] & + WPA_DRIVER_CAPA_KEY_MGMT_FT) { key_mgmt = wpa_s->conf->pmf != NO_MGMT_FRAME_PROTECTION ? "WPA-EAP WPA-EAP-SHA256 FT-EAP" : "WPA-EAP FT-EAP"; @@ -958,7 +959,9 @@ static int interworking_set_hs20_params(struct wpa_supplicant *wpa_s, "WPA-EAP WPA-EAP-SHA256" : "WPA-EAP"; if (wpa_config_set(ssid, "key_mgmt", key_mgmt, 0) < 0 || wpa_config_set(ssid, "proto", "RSN", 0) < 0 || - wpa_config_set(ssid, "ieee80211w", "1", 0) < 0 || + wpa_config_set(ssid, "ieee80211w", + wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_REQUIRED ? + "2" : "1", 0) < 0 || wpa_config_set(ssid, "pairwise", "CCMP", 0) < 0) return -1; return 0; @@ -2529,7 +2532,7 @@ static void interworking_select_network(struct wpa_supplicant *wpa_s) (selected_cred == NULL || cred_prio_cmp(selected_home_cred, selected_cred) >= 0)) { /* Prefer network operated by the Home SP */ - wpa_printf(MSG_DEBUG, "Interworking: Overrided selected with selected_home"); + wpa_printf(MSG_DEBUG, "Interworking: Overrode selected with selected_home"); selected = selected_home; selected_cred = selected_home_cred; } @@ -2747,27 +2750,27 @@ void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s) } -int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, +int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, int freq, u16 info_ids[], size_t num_ids, u32 subtypes, u32 mbo_subtypes) { struct wpabuf *buf; struct wpabuf *extra_buf = NULL; int ret = 0; - int freq; struct wpa_bss *bss; int res; bss = wpa_bss_get_bssid(wpa_s, dst); - if (!bss) { + if (!bss && !freq) { wpa_printf(MSG_WARNING, - "ANQP: Cannot send query to unknown BSS " - MACSTR, MAC2STR(dst)); + "ANQP: Cannot send query without BSS freq info"); return -1; } - wpa_bss_anqp_unshare_alloc(bss); - freq = bss->freq; + if (bss) + wpa_bss_anqp_unshare_alloc(bss); + if (bss && !freq) + freq = bss->freq; wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Query Request to " MACSTR " for %u id(s)", @@ -2786,6 +2789,13 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, if (mbo_subtypes) { struct wpabuf *mbo; + if (!bss) { + wpa_printf(MSG_WARNING, + "ANQP: Cannot send MBO query to unknown BSS " + MACSTR, MAC2STR(dst)); + return -1; + } + mbo = mbo_build_anqp_buf(wpa_s, bss, mbo_subtypes); if (mbo) { if (wpabuf_resize(&extra_buf, wpabuf_len(mbo))) { @@ -2804,7 +2814,8 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, if (buf == NULL) return -1; - res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, anqp_resp_cb, wpa_s); + res = gas_query_req(wpa_s->gas, dst, freq, 0, 0, buf, anqp_resp_cb, + wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "ANQP: Failed to send Query Request"); wpabuf_free(buf); @@ -2820,7 +2831,7 @@ int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, static void anqp_add_extra(struct wpa_supplicant *wpa_s, struct wpa_bss_anqp *anqp, u16 info_id, - const u8 *data, size_t slen) + const u8 *data, size_t slen, bool protected) { struct wpa_bss_anqp_elem *tmp, *elem = NULL; @@ -2845,6 +2856,7 @@ static void anqp_add_extra(struct wpa_supplicant *wpa_s, wpabuf_free(elem->payload); } + elem->protected = protected; elem->payload = wpabuf_alloc_copy(data, slen); if (!elem->payload) { dl_list_del(&elem->list); @@ -2887,6 +2899,7 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, const u8 *pos = data; struct wpa_bss_anqp *anqp = NULL; u8 type; + bool protected; if (bss) anqp = bss->anqp; @@ -2987,9 +3000,10 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, case ANQP_VENUE_URL: wpa_msg(wpa_s, MSG_INFO, RX_ANQP MACSTR " Venue URL", MAC2STR(sa)); - anqp_add_extra(wpa_s, anqp, info_id, pos, slen); + protected = pmf_in_use(wpa_s, sa); + anqp_add_extra(wpa_s, anqp, info_id, pos, slen, protected); - if (!pmf_in_use(wpa_s, sa)) { + if (!protected) { wpa_printf(MSG_DEBUG, "ANQP: Ignore Venue URL since PMF was not enabled"); break; @@ -3041,7 +3055,8 @@ static void interworking_parse_rx_anqp_resp(struct wpa_supplicant *wpa_s, default: wpa_msg(wpa_s, MSG_DEBUG, "Interworking: Unsupported ANQP Info ID %u", info_id); - anqp_add_extra(wpa_s, anqp, info_id, data, slen); + anqp_add_extra(wpa_s, anqp, info_id, data, slen, + pmf_in_use(wpa_s, sa)); break; } } @@ -3243,7 +3258,8 @@ int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst, } else wpabuf_put_le16(buf, 0); - res = gas_query_req(wpa_s->gas, dst, freq, 0, buf, gas_resp_cb, wpa_s); + res = gas_query_req(wpa_s->gas, dst, freq, 0, 0, buf, gas_resp_cb, + wpa_s); if (res < 0) { wpa_msg(wpa_s, MSG_DEBUG, "GAS: Failed to send Query Request"); wpabuf_free(buf); diff --git a/wpa_supplicant/interworking.h b/wpa_supplicant/interworking.h index 37ee2e904..77b2c91bd 100644 --- a/wpa_supplicant/interworking.h +++ b/wpa_supplicant/interworking.h @@ -11,7 +11,7 @@ enum gas_query_result; -int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, +int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, int freq, u16 info_ids[], size_t num_ids, u32 subtypes, u32 mbo_subtypes); void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token, diff --git a/wpa_supplicant/mesh.c b/wpa_supplicant/mesh.c index b504124fa..df204478b 100644 --- a/wpa_supplicant/mesh.c +++ b/wpa_supplicant/mesh.c @@ -13,6 +13,7 @@ #include "utils/uuid.h" #include "common/ieee802_11_defs.h" #include "common/wpa_ctrl.h" +#include "common/hw_features_common.h" #include "ap/sta_info.h" #include "ap/hostapd.h" #include "ap/ieee802_11.h" @@ -27,22 +28,29 @@ #include "mesh.h" -static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s) +static void wpa_supplicant_mesh_deinit(struct wpa_supplicant *wpa_s, + bool also_clear_hostapd) { - wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh); - wpa_s->ifmsh = NULL; - wpa_s->current_ssid = NULL; + wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, + also_clear_hostapd); + + if (also_clear_hostapd) { + wpa_s->ifmsh = NULL; + wpa_s->current_ssid = NULL; + os_free(wpa_s->mesh_params); + wpa_s->mesh_params = NULL; + } + os_free(wpa_s->mesh_rsn); wpa_s->mesh_rsn = NULL; - os_free(wpa_s->mesh_params); - wpa_s->mesh_params = NULL; - /* TODO: leave mesh (stop beacon). This will happen on link down - * anyway, so it's not urgent */ + + wpa_supplicant_leave_mesh(wpa_s, false); } void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s, - struct hostapd_iface *ifmsh) + struct hostapd_iface *ifmsh, + bool also_clear_hostapd) { if (!ifmsh) return; @@ -63,8 +71,10 @@ void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s, } /* take care of shared data */ - hostapd_interface_deinit(ifmsh); - hostapd_interface_free(ifmsh); + if (also_clear_hostapd) { + hostapd_interface_deinit(ifmsh); + hostapd_interface_free(ifmsh); + } } @@ -194,6 +204,40 @@ static int wpas_mesh_init_rsn(struct wpa_supplicant *wpa_s) } +static int wpas_mesh_update_freq_params(struct wpa_supplicant *wpa_s) +{ + struct wpa_driver_mesh_join_params *params = wpa_s->mesh_params; + struct hostapd_iface *ifmsh = wpa_s->ifmsh; + struct he_capabilities *he_capab = NULL; + + if (ifmsh->current_mode) + he_capab = &ifmsh->current_mode->he_capab[IEEE80211_MODE_MESH]; + + if (hostapd_set_freq_params( + ¶ms->freq, + ifmsh->conf->hw_mode, + ifmsh->freq, + ifmsh->conf->channel, + ifmsh->conf->enable_edmg, + ifmsh->conf->edmg_channel, + ifmsh->conf->ieee80211n, + ifmsh->conf->ieee80211ac, + ifmsh->conf->ieee80211ax, + ifmsh->conf->secondary_channel, + hostapd_get_oper_chwidth(ifmsh->conf), + hostapd_get_oper_centr_freq_seg0_idx(ifmsh->conf), + hostapd_get_oper_centr_freq_seg1_idx(ifmsh->conf), + ifmsh->conf->vht_capab, + he_capab)) { + wpa_printf(MSG_ERROR, "Error updating mesh frequency params"); + wpa_supplicant_mesh_deinit(wpa_s, true); + return -1; + } + + return 0; +} + + static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) { struct hostapd_iface *ifmsh = wpa_s->ifmsh; @@ -207,12 +251,22 @@ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) return -1; } + /* + * Update channel configuration if the channel has changed since the + * initial setting, i.e., due to DFS radar detection during CAC. + */ + if (ifmsh->freq > 0 && ifmsh->freq != params->freq.freq) { + wpa_s->assoc_freq = ifmsh->freq; + ssid->frequency = ifmsh->freq; + if (wpas_mesh_update_freq_params(wpa_s) < 0) + return -1; + } + if (ifmsh->mconf->security != MESH_CONF_SEC_NONE && wpas_mesh_init_rsn(wpa_s)) { wpa_printf(MSG_ERROR, "mesh: RSN initialization failed - deinit mesh"); - wpa_supplicant_mesh_deinit(wpa_s); - wpa_drv_leave_mesh(wpa_s); + wpa_supplicant_mesh_deinit(wpa_s, false); return -1; } @@ -237,13 +291,90 @@ static int wpas_mesh_complete(struct wpa_supplicant *wpa_s) /* hostapd sets the interface down until we associate */ wpa_drv_set_operstate(wpa_s, 1); - if (!ret) + if (!ret) { wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); + wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len), + ssid->id); + wpas_notify_mesh_group_started(wpa_s, ssid); + } + return ret; } +static void wpas_mesh_complete_cb(void *arg) +{ + struct wpa_supplicant *wpa_s = arg; + + wpas_mesh_complete(wpa_s); +} + + +static int wpa_supplicant_mesh_enable_iface_cb(struct hostapd_iface *ifmsh) +{ + struct wpa_supplicant *wpa_s = ifmsh->owner; + struct hostapd_data *bss; + + ifmsh->mconf = mesh_config_create(wpa_s, wpa_s->current_ssid); + + bss = ifmsh->bss[0]; + bss->msg_ctx = wpa_s; + os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN); + bss->driver = wpa_s->driver; + bss->drv_priv = wpa_s->drv_priv; + bss->iface = ifmsh; + bss->mesh_sta_free_cb = mesh_mpm_free_sta; + bss->setup_complete_cb = wpas_mesh_complete_cb; + bss->setup_complete_cb_ctx = wpa_s; + + bss->conf->start_disabled = 1; + bss->conf->mesh = MESH_ENABLED; + bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity; + + if (wpa_drv_init_mesh(wpa_s)) { + wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver"); + return -1; + } + + if (hostapd_setup_interface(ifmsh)) { + wpa_printf(MSG_ERROR, + "Failed to initialize hostapd interface for mesh"); + return -1; + } + + return 0; +} + + +static int wpa_supplicant_mesh_disable_iface_cb(struct hostapd_iface *ifmsh) +{ + struct wpa_supplicant *wpa_s = ifmsh->owner; + size_t j; + + wpa_supplicant_mesh_deinit(wpa_s, false); + +#ifdef NEED_AP_MLME + for (j = 0; j < ifmsh->num_bss; j++) + hostapd_cleanup_cs_params(ifmsh->bss[j]); +#endif /* NEED_AP_MLME */ + + /* Same as hostapd_interface_deinit() without deinitializing control + * interface */ + for (j = 0; j < ifmsh->num_bss; j++) { + struct hostapd_data *hapd = ifmsh->bss[j]; + + hostapd_bss_deinit_no_free(hapd); + hostapd_free_hapd_data(hapd); + } + + hostapd_cleanup_iface_partial(ifmsh); + + return 0; +} + + static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct hostapd_freq_params *freq) @@ -267,8 +398,12 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, if (!ifmsh) return -ENOMEM; + ifmsh->owner = wpa_s; ifmsh->drv_flags = wpa_s->drv_flags; + ifmsh->drv_flags2 = wpa_s->drv_flags2; ifmsh->num_bss = 1; + ifmsh->enable_iface_cb = wpa_supplicant_mesh_enable_iface_cb; + ifmsh->disable_iface_cb = wpa_supplicant_mesh_disable_iface_cb; ifmsh->bss = os_calloc(wpa_s->ifmsh->num_bss, sizeof(struct hostapd_data *)); if (!ifmsh->bss) @@ -284,11 +419,14 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, bss->drv_priv = wpa_s->drv_priv; bss->iface = ifmsh; bss->mesh_sta_free_cb = mesh_mpm_free_sta; + bss->setup_complete_cb = wpas_mesh_complete_cb; + bss->setup_complete_cb_ctx = wpa_s; frequency = ssid->frequency; if (frequency != freq->freq && frequency == freq->freq + freq->sec_channel_offset * 20) { wpa_printf(MSG_DEBUG, "mesh: pri/sec channels switched"); frequency = freq->freq; + ssid->frequency = frequency; } wpa_s->assoc_freq = frequency; wpa_s->current_ssid = ssid; @@ -310,6 +448,7 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, conf->country[0] = wpa_s->conf->country[0]; conf->country[1] = wpa_s->conf->country[1]; conf->country[2] = ' '; + wpa_s->mesh_params->handle_dfs = true; } bss->iconf = conf; @@ -332,30 +471,6 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, frequency); goto out_free; } - if (ssid->ht40) - conf->secondary_channel = ssid->ht40; - if (conf->hw_mode == HOSTAPD_MODE_IEEE80211A && ssid->vht) { - if (ssid->max_oper_chwidth != DEFAULT_MAX_OPER_CHWIDTH) - conf->vht_oper_chwidth = ssid->max_oper_chwidth; - switch (conf->vht_oper_chwidth) { - case CHANWIDTH_80MHZ: - case CHANWIDTH_80P80MHZ: - ieee80211_freq_to_chan( - frequency, - &conf->vht_oper_centr_freq_seg0_idx); - conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2; - break; - case CHANWIDTH_160MHZ: - ieee80211_freq_to_chan( - frequency, - &conf->vht_oper_centr_freq_seg0_idx); - conf->vht_oper_centr_freq_seg0_idx += ssid->ht40 * 2; - conf->vht_oper_centr_freq_seg0_idx += 40 / 5; - break; - } - ieee80211_freq_to_chan(ssid->vht_center_freq2, - &conf->vht_oper_centr_freq_seg1_idx); - } if (ssid->mesh_basic_rates == NULL) { /* @@ -386,6 +501,31 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, conf->basic_rates[rate_len] = -1; } + /* While it can enhance performance to switch the primary channel, which + * is also the secondary channel of another network at the same time), + * to the other primary channel, problems exist with this in mesh + * networks. + * + * Example with problems: + * - 3 mesh nodes M1-M3, freq (5200, 5180) + * - other node O1, e.g. AP mode, freq (5180, 5200), + * Locations: O1 M1 M2 M3 + * + * M3 can only send frames to M1 over M2, no direct connection is + * possible + * Start O1, M1 and M3 first, M1 or O1 will switch channels to align + * with* each other. M3 does not swap, because M1 or O1 cannot be + * reached. M2 is started afterwards and can either connect to M3 or M1 + * because of this primary secondary channel switch. + * + * Solutions: (1) central coordination -> not always possible + * (2) disable pri/sec channel switch in mesh networks + * + * In AP mode, when all nodes can work independently, this poses of + * course no problem, therefore disable it only in mesh mode. */ + conf->no_pri_sec_switch = 1; + wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf); + if (wpa_drv_init_mesh(wpa_s)) { wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver"); return -1; @@ -397,11 +537,9 @@ static int wpa_supplicant_mesh_init(struct wpa_supplicant *wpa_s, return -1; } - wpa_supplicant_conf_ap_ht(wpa_s, ssid, conf); - return 0; out_free: - wpa_supplicant_mesh_deinit(wpa_s); + wpa_supplicant_mesh_deinit(wpa_s, true); return -ENOMEM; } @@ -449,7 +587,7 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, goto out; } - wpa_supplicant_mesh_deinit(wpa_s); + wpa_supplicant_mesh_deinit(wpa_s, true); wpa_s->pairwise_cipher = WPA_CIPHER_NONE; wpa_s->group_cipher = WPA_CIPHER_NONE; @@ -520,25 +658,25 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, wpa_s->mesh_params = params; if (wpa_supplicant_mesh_init(wpa_s, ssid, ¶ms->freq)) { wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh"); - wpa_drv_leave_mesh(wpa_s); + wpa_supplicant_leave_mesh(wpa_s, true); ret = -1; goto out; } - ret = wpas_mesh_complete(wpa_s); out: return ret; } -int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s) +int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s, bool need_deinit) { int ret = 0; wpa_msg(wpa_s, MSG_INFO, "leaving mesh"); /* Need to send peering close messages first */ - wpa_supplicant_mesh_deinit(wpa_s); + if (need_deinit) + wpa_supplicant_mesh_deinit(wpa_s, true); ret = wpa_drv_leave_mesh(wpa_s); if (ret) diff --git a/wpa_supplicant/mesh.h b/wpa_supplicant/mesh.h index 7317083c9..a429e5e27 100644 --- a/wpa_supplicant/mesh.h +++ b/wpa_supplicant/mesh.h @@ -11,9 +11,11 @@ int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); -int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s); +int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s, + bool need_deinit); void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s, - struct hostapd_iface *ifmsh); + struct hostapd_iface *ifmsh, + bool also_clear_hostapd); int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end); int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname, diff --git a/wpa_supplicant/mesh_mpm.c b/wpa_supplicant/mesh_mpm.c index 31dd1d3c6..b6a5e8857 100644 --- a/wpa_supplicant/mesh_mpm.c +++ b/wpa_supplicant/mesh_mpm.c @@ -147,13 +147,13 @@ static u16 copy_supp_rates(struct wpa_supplicant *wpa_s, /* return true if elems from a neighbor match this MBSS */ -static Boolean matches_local(struct wpa_supplicant *wpa_s, - struct ieee802_11_elems *elems) +static bool matches_local(struct wpa_supplicant *wpa_s, + struct ieee802_11_elems *elems) { struct mesh_conf *mconf = wpa_s->ifmsh->mconf; if (elems->mesh_config_len < 5) - return FALSE; + return false; return (mconf->meshid_len == elems->mesh_id_len && os_memcmp(mconf->meshid, elems->mesh_id, @@ -167,17 +167,17 @@ static Boolean matches_local(struct wpa_supplicant *wpa_s, /* check if local link id is already used with another peer */ -static Boolean llid_in_use(struct wpa_supplicant *wpa_s, u16 llid) +static bool llid_in_use(struct wpa_supplicant *wpa_s, u16 llid) { struct sta_info *sta; struct hostapd_data *hapd = wpa_s->ifmsh->bss[0]; for (sta = hapd->sta_list; sta; sta = sta->next) { if (sta->my_lid == llid) - return TRUE; + return true; } - return FALSE; + return false; } @@ -233,12 +233,10 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s, 2 + 24 + /* peering management */ 2 + 96 + 32 + 32 + /* AMPE (96 + max GTKlen + max IGTKlen) */ 2 + 16; /* MIC */ -#ifdef CONFIG_IEEE80211N if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) { buf_len += 2 + 26 + /* HT capabilities */ 2 + 22; /* HT operation */ } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) { buf_len += 2 + 12 + /* VHT Capabilities */ @@ -354,7 +352,6 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s, wpabuf_put(buf, PMKID_LEN)); } -#ifdef CONFIG_IEEE80211N if (type != PLINK_CLOSE && wpa_s->mesh_ht_enabled) { u8 ht_capa_oper[2 + 26 + 2 + 22]; @@ -362,7 +359,6 @@ static void mesh_mpm_send_plink_action(struct wpa_supplicant *wpa_s, pos = hostapd_eid_ht_operation(bss, pos); wpabuf_put_data(buf, ht_capa_oper, pos - ht_capa_oper); } -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC if (type != PLINK_CLOSE && wpa_s->mesh_vht_enabled) { u8 vht_capa_oper[2 + 12 + 2 + 5]; @@ -537,11 +533,14 @@ static int mesh_mpm_plink_close(struct hostapd_data *hapd, struct sta_info *sta, int reason = WLAN_REASON_MESH_PEERING_CANCELLED; if (sta) { + if (sta->plink_state == PLINK_ESTAB) + hapd->num_plinks--; wpa_mesh_set_plink_state(wpa_s, sta, PLINK_HOLDING); mesh_mpm_send_plink_action(wpa_s, sta, PLINK_CLOSE, reason); wpa_printf(MSG_DEBUG, "MPM closing plink sta=" MACSTR, MAC2STR(sta->addr)); eloop_cancel_timeout(plink_timer, wpa_s, sta); + eloop_cancel_timeout(mesh_auth_timer, wpa_s, sta); return 0; } @@ -696,9 +695,7 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, struct mesh_conf *conf = wpa_s->ifmsh->mconf; struct hostapd_data *data = wpa_s->ifmsh->bss[0]; struct sta_info *sta; -#ifdef CONFIG_IEEE80211N struct ieee80211_ht_operation *oper; -#endif /* CONFIG_IEEE80211N */ int ret; if (elems->mesh_config_len >= 7 && @@ -729,7 +726,6 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, if (!sta->my_lid) mesh_mpm_init_link(wpa_s, sta); -#ifdef CONFIG_IEEE80211N copy_sta_ht_capab(data, sta, elems->ht_capabilities); oper = (struct ieee80211_ht_operation *) elems->ht_operation; @@ -743,7 +739,6 @@ static struct sta_info * mesh_mpm_add_peer(struct wpa_supplicant *wpa_s, } update_ht_state(data, sta); -#endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC copy_sta_vht_capab(data, sta, elems->vht_capabilities); @@ -1298,8 +1293,8 @@ void mesh_mpm_action_rx(struct wpa_supplicant *wpa_s, if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, tx_chanwidth, tx_seg1_idx) != - 0) { - wpa_printf(MSG_WARNING, "MPM: %s", + OCI_SUCCESS) { + wpa_printf(MSG_WARNING, "MPM: OCV failed: %s", ocv_errorstr); return; } diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c index f19bfbfc6..834c7a1cc 100644 --- a/wpa_supplicant/mesh_rsn.c +++ b/wpa_supplicant/mesh_rsn.c @@ -195,7 +195,8 @@ static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr, wpa_hexdump_key(MSG_DEBUG, "mesh: Own TX IGTK", rsn->igtk, rsn->igtk_len); wpa_drv_set_key(rsn->wpa_s, - wpa_cipher_to_alg(rsn->mgmt_group_cipher), NULL, + wpa_cipher_to_alg(rsn->mgmt_group_cipher), + broadcast_ether_addr, rsn->igtk_key_id, 1, seq, sizeof(seq), rsn->igtk, rsn->igtk_len, KEY_FLAG_GROUP_TX_DEFAULT); @@ -204,7 +205,8 @@ static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr, /* group privacy / data frames */ wpa_hexdump_key(MSG_DEBUG, "mesh: Own TX MGTK", rsn->mgtk, rsn->mgtk_len); - wpa_drv_set_key(rsn->wpa_s, wpa_cipher_to_alg(rsn->group_cipher), NULL, + wpa_drv_set_key(rsn->wpa_s, wpa_cipher_to_alg(rsn->group_cipher), + broadcast_ether_addr, rsn->mgtk_key_id, 1, seq, sizeof(seq), rsn->mgtk, rsn->mgtk_len, KEY_FLAG_GROUP_TX_DEFAULT); diff --git a/wpa_supplicant/offchannel.c b/wpa_supplicant/offchannel.c index 77c425fac..e40cf5bbe 100644 --- a/wpa_supplicant/offchannel.c +++ b/wpa_supplicant/offchannel.c @@ -246,7 +246,7 @@ void offchannel_send_action_tx_status( * @buf: Frame to transmit starting from the Category field * @len: Length of @buf in bytes * @wait_time: Wait time for response in milliseconds - * @tx_cb: Callback function for indicating TX status or %NULL for now callback + * @tx_cb: Callback function for indicating TX status or %NULL for no callback * @no_cck: Whether CCK rates are to be disallowed for TX rate selection * Returns: 0 on success or -1 on failure * diff --git a/wpa_supplicant/op_classes.c b/wpa_supplicant/op_classes.c index f49bdb094..41b47cc62 100644 --- a/wpa_supplicant/op_classes.c +++ b/wpa_supplicant/op_classes.c @@ -14,6 +14,7 @@ #include "utils/common.h" #include "common/ieee802_11_common.h" #include "wpa_supplicant_i.h" +#include "bss.h" static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, @@ -21,13 +22,13 @@ static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, unsigned int *flags) { int i; - int is_6ghz = op_class >= 131 && op_class <= 135; + bool is_6ghz = op_class >= 131 && op_class <= 136; for (i = 0; i < mode->num_channels; i++) { - int chan_is_6ghz; + bool chan_is_6ghz; - chan_is_6ghz = mode->channels[i].freq > 5940 && - mode->channels[i].freq <= 7105; + chan_is_6ghz = mode->channels[i].freq >= 5935 && + mode->channels[i].freq <= 7115; if (is_6ghz == chan_is_6ghz && mode->channels[i].chan == chan) break; } @@ -46,15 +47,15 @@ static enum chan_allowed allow_channel(struct hostapd_hw_modes *mode, } -static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel) +static int get_center_80mhz(struct hostapd_hw_modes *mode, u8 channel, + const u8 *center_channels, size_t num_chan) { - u8 center_channels[] = { 42, 58, 106, 122, 138, 155 }; size_t i; if (mode->mode != HOSTAPD_MODE_IEEE80211A) return 0; - for (i = 0; i < ARRAY_SIZE(center_channels); i++) { + for (i = 0; i < num_chan; i++) { /* * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48), * so the center channel is 6 channels away from the start/end. @@ -74,8 +75,22 @@ static enum chan_allowed verify_80mhz(struct hostapd_hw_modes *mode, u8 center_chan; unsigned int i; unsigned int no_ir = 0; + const u8 *center_channels; + size_t num_chan; + const u8 center_channels_5ghz[] = { 42, 58, 106, 122, 138, 155 }; + const u8 center_channels_6ghz[] = { 7, 23, 39, 55, 71, 87, 103, 119, + 135, 151, 167, 183, 199, 215 }; - center_chan = get_center_80mhz(mode, channel); + if (is_6ghz_op_class(op_class)) { + center_channels = center_channels_6ghz; + num_chan = ARRAY_SIZE(center_channels_6ghz); + } else { + center_channels = center_channels_5ghz; + num_chan = ARRAY_SIZE(center_channels_5ghz); + } + + center_chan = get_center_80mhz(mode, channel, center_channels, + num_chan); if (!center_chan) return NOT_ALLOWED; @@ -105,15 +120,15 @@ static enum chan_allowed verify_80mhz(struct hostapd_hw_modes *mode, } -static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel) +static int get_center_160mhz(struct hostapd_hw_modes *mode, u8 channel, + const u8 *center_channels, size_t num_chan) { - u8 center_channels[] = { 50, 114 }; unsigned int i; if (mode->mode != HOSTAPD_MODE_IEEE80211A) return 0; - for (i = 0; i < ARRAY_SIZE(center_channels); i++) { + for (i = 0; i < num_chan; i++) { /* * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64), * so the center channel is 14 channels away from the start/end. @@ -133,8 +148,21 @@ static enum chan_allowed verify_160mhz(struct hostapd_hw_modes *mode, u8 center_chan; unsigned int i; unsigned int no_ir = 0; + const u8 *center_channels; + size_t num_chan; + const u8 center_channels_5ghz[] = { 50, 114 }; + const u8 center_channels_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 }; - center_chan = get_center_160mhz(mode, channel); + if (is_6ghz_op_class(op_class)) { + center_channels = center_channels_6ghz; + num_chan = ARRAY_SIZE(center_channels_6ghz); + } else { + center_channels = center_channels_5ghz; + num_chan = ARRAY_SIZE(center_channels_5ghz); + } + + center_chan = get_center_160mhz(mode, channel, center_channels, + num_chan); if (!center_chan) return NOT_ALLOWED; @@ -175,11 +203,12 @@ enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class, enum chan_allowed res, res2; res2 = res = allow_channel(mode, op_class, channel, &flag); - if (bw == BW40MINUS) { + if (bw == BW40MINUS || (bw == BW40 && (((channel - 1) / 4) % 2))) { if (!(flag & HOSTAPD_CHAN_HT40MINUS)) return NOT_ALLOWED; res2 = allow_channel(mode, op_class, channel - 4, NULL); - } else if (bw == BW40PLUS) { + } else if (bw == BW40PLUS || + (bw == BW40 && !(((channel - 1) / 4) % 2))) { if (!(flag & HOSTAPD_CHAN_HT40PLUS)) return NOT_ALLOWED; res2 = allow_channel(mode, op_class, channel + 4, NULL); @@ -342,6 +371,41 @@ static int wpas_op_class_supported(struct wpa_supplicant *wpa_s, return 0; } + if (op_class->op_class == 135) { + /* Need at least two 80 MHz segments which do not fall under the + * same 160 MHz segment to support 80+80 in 6 GHz. + */ + int first_seg = 0; + int curr_seg = 0; + + for (chan = op_class->min_chan; chan <= op_class->max_chan; + chan += op_class->inc) { + curr_seg++; + if (verify_channel(mode, op_class->op_class, chan, + op_class->bw) != NOT_ALLOWED) { + if (!first_seg) { + first_seg = curr_seg; + continue; + } + + /* Supported if at least two non-consecutive 80 + * MHz segments allowed. + */ + if ((curr_seg - first_seg) > 1) + return 1; + + /* Supported even if the 80 MHz segments are + * consecutive when they do not fall under the + * same 160 MHz segment. + */ + if ((first_seg % 2) == 0) + return 1; + } + } + + return 0; + } + found = 0; for (chan = op_class->min_chan; chan <= op_class->max_chan; chan += op_class->inc) { @@ -356,9 +420,26 @@ static int wpas_op_class_supported(struct wpa_supplicant *wpa_s, } +static int wpas_sta_secondary_channel_offset(struct wpa_bss *bss, u8 *current, + u8 *channel) +{ + + const u8 *ies; + u8 phy_type; + size_t ies_len; + + if (!bss) + return -1; + ies = wpa_bss_ie_ptr(bss); + ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len; + return wpas_get_op_chan_phy(bss->freq, ies, ies_len, current, + channel, &phy_type); +} + + size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, - int freq, u8 *pos, size_t len) + struct wpa_bss *bss, u8 *pos, size_t len) { struct wpabuf *buf; u8 op, current, chan; @@ -366,11 +447,13 @@ size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, size_t res; /* - * Assume 20 MHz channel for now. - * TODO: Use the secondary channel and VHT channel width that will be - * used after association. + * Determine the current operating class correct mode based on + * advertised BSS capabilities, if available. Fall back to a less + * accurate guess based on frequency if the needed IEs are not available + * or used. */ - if (ieee80211_freq_to_channel_ext(freq, 0, CHANWIDTH_USE_HT, + if (wpas_sta_secondary_channel_offset(bss, ¤t, &chan) < 0 && + ieee80211_freq_to_channel_ext(bss->freq, 0, CHANWIDTH_USE_HT, ¤t, &chan) == NUM_HOSTAPD_MODES) return 0; @@ -393,9 +476,13 @@ size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, } *ie_len = wpabuf_len(buf) - 2; - if (*ie_len < 2 || wpabuf_len(buf) > len) { + if (*ie_len < 2) { + wpa_printf(MSG_DEBUG, + "No supported operating classes IE to add"); + res = 0; + } else if (wpabuf_len(buf) > len) { wpa_printf(MSG_ERROR, - "Failed to add supported operating classes IE"); + "Supported operating classes IE exceeds maximum buffer length"); res = 0; } else { os_memcpy(pos, wpabuf_head(buf), wpabuf_len(buf)); diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 41d50f397..867874dd9 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -312,6 +312,15 @@ static void wpas_p2p_trigger_scan_cb(struct wpa_radio_work *work, int deinit) "Request driver to clear scan cache due to local BSS flush"); params->only_new_results = 1; } + + if (wpa_s->conf->p2p_6ghz_disable && !params->freqs) { + wpa_printf(MSG_DEBUG, + "P2P: 6 GHz disabled - update the scan frequency list"); + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params, + 0); + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params, + 0); + } ret = wpa_drv_scan(wpa_s, params); if (ret == 0) wpa_s->curr_scan_cookie = params->scan_cookie; @@ -522,7 +531,7 @@ static int wpas_p2p_disconnect_safely(struct wpa_supplicant *wpa_s, /* * The calling wpa_s instance is going to be removed. Do that * from an eloop callback to keep the instance available until - * the caller has returned. This my be needed, e.g., to provide + * the caller has returned. This may be needed, e.g., to provide * control interface responses on the per-interface socket. */ if (eloop_register_timeout(0, 0, run_wpas_p2p_disconnect, @@ -1063,9 +1072,9 @@ static int wpas_p2p_persistent_group(struct wpa_supplicant *wpa_s, "group is persistent - BSS " MACSTR " did not include P2P IE", MAC2STR(bssid)); wpa_hexdump(MSG_DEBUG, "P2P: Probe Response IEs", - (u8 *) (bss + 1), bss->ie_len); + wpa_bss_ie_ptr(bss), bss->ie_len); wpa_hexdump(MSG_DEBUG, "P2P: Beacon IEs", - ((u8 *) bss + 1) + bss->ie_len, + wpa_bss_ie_ptr(bss) + bss->ie_len, bss->beacon_ie_len); return 0; } @@ -1912,7 +1921,7 @@ static int wpas_p2p_freq_to_edmg_channel(struct wpa_supplicant *wpa_s, return -1; hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, - HOSTAPD_MODE_IEEE80211AD, 0); + HOSTAPD_MODE_IEEE80211AD, false); if (!hwmode) { wpa_printf(MSG_ERROR, "Unsupported AP mode: HOSTAPD_MODE_IEEE80211AD"); @@ -2117,6 +2126,7 @@ do { \ d->go_internet = s->go_internet; d->go_venue_group = s->go_venue_group; d->go_venue_type = s->go_venue_type; + d->p2p_add_cli_chan = s->p2p_add_cli_chan; } @@ -2691,7 +2701,7 @@ static int wpas_send_probe_resp(void *ctx, const struct wpabuf *buf, { struct wpa_supplicant *wpa_s = ctx; return wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, - freq); + freq, 0); } @@ -3182,8 +3192,12 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid, MAC2STR(sa), s->id); } wpas_p2p_group_add_persistent( - wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, 0, - 0, NULL, + wpa_s, s, go, 0, op_freq, 0, + wpa_s->conf->p2p_go_ht40, + wpa_s->conf->p2p_go_vht, + 0, + wpa_s->conf->p2p_go_he, + wpa_s->conf->p2p_go_edmg, NULL, go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 1); } else if (bssid) { @@ -3703,7 +3717,8 @@ static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s, static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s, struct p2p_channels *chan, - struct p2p_channels *cli_chan) + struct p2p_channels *cli_chan, + bool p2p_disable_6ghz) { struct hostapd_hw_modes *mode; int cla, op, cli_cla; @@ -3722,7 +3737,8 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s, u8 ch; struct p2p_reg_class *reg = NULL, *cli_reg = NULL; - if (o->p2p == NO_P2P_SUPP) + if (o->p2p == NO_P2P_SUPP || + (is_6ghz_op_class(o->op_class) && p2p_disable_6ghz)) continue; mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode, @@ -3733,6 +3749,13 @@ static int wpas_p2p_setup_channels(struct wpa_supplicant *wpa_s, wpa_s->global->p2p_24ghz_social_channels = 1; for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { enum chan_allowed res; + + /* Check for non-continuous jump in channel index + * incrementation */ + if ((o->op_class == 128 || o->op_class == 130) && + ch < 149 && ch + o->inc > 149) + ch = 149; + res = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw); if (res == ALLOWED) { if (reg == NULL) { @@ -3793,7 +3816,9 @@ int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s, const struct oper_class_map *o = &global_op_class[op]; u8 ch; - if (o->p2p == NO_P2P_SUPP) + if (o->p2p == NO_P2P_SUPP || + (is_6ghz_op_class(o->op_class) && + wpa_s->conf->p2p_6ghz_disable)) continue; for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) { @@ -3925,6 +3950,10 @@ int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s, wpa_s->ifname); if (os_snprintf_error(sizeof(ifname), ret)) return -1; + /* Cut length at the maximum size. Note that we don't need to ensure + * collision free names here as the created interface is not a netdev. + */ + ifname[IFNAMSIZ - 1] = '\0'; force_name[0] = '\0'; wpa_s->pending_interface_type = WPA_IF_P2P_DEVICE; ret = wpa_drv_if_add(wpa_s, WPA_IF_P2P_DEVICE, ifname, NULL, NULL, @@ -4605,6 +4634,7 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) p2p.prov_disc_resp_cb = wpas_prov_disc_resp_cb; p2p.p2ps_group_capability = p2ps_group_capability; p2p.get_pref_freq_list = wpas_p2p_get_pref_freq_list; + p2p.p2p_6ghz_disable = wpa_s->conf->p2p_6ghz_disable; os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN); os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN); @@ -4618,7 +4648,8 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) p2p.config_methods = wpa_s->wps->config_methods; } - if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels)) { + if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels, + p2p.p2p_6ghz_disable)) { wpa_printf(MSG_ERROR, "P2P: Failed to configure supported channel list"); return -1; @@ -4765,6 +4796,7 @@ void wpas_p2p_deinit(struct wpa_supplicant *wpa_s) eloop_cancel_timeout(wpas_p2p_group_idle_timeout, wpa_s, NULL); wpas_p2p_remove_pending_group_interface(wpa_s); eloop_cancel_timeout(wpas_p2p_group_freq_conflict, wpa_s, NULL); + eloop_cancel_timeout(wpas_p2p_reconsider_moving_go, wpa_s, NULL); wpas_p2p_listen_work_done(wpa_s); if (wpa_s->p2p_send_action_work) { os_free(wpa_s->p2p_send_action_work->ctx); @@ -4913,6 +4945,15 @@ static void wpas_p2p_check_join_scan_limit(struct wpa_supplicant *wpa_s) MAC2STR(wpa_s->pending_join_dev_addr)); return; } + if (wpa_s->p2p_fallback_to_go_neg) { + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Join operation failed - fall back to GO Negotiation"); + wpa_msg_global(wpa_s->p2pdev, MSG_INFO, + P2P_EVENT_FALLBACK_TO_GO_NEG + "reason=join-failed"); + wpas_p2p_fallback_to_go_neg(wpa_s, 0); + return; + } wpa_msg_global(wpa_s->p2pdev, MSG_INFO, P2P_EVENT_GROUP_FORMATION_FAILURE); wpas_notify_p2p_group_formation_failure(wpa_s, ""); @@ -5124,7 +5165,7 @@ static void wpas_p2p_scan_res_join(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "P2P: Target GO operating frequency " "from BSS table: %d MHz (SSID %s)", freq, wpa_ssid_txt(bss->ssid, bss->ssid_len)); - if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len, + if (p2p_parse_dev_addr(wpa_bss_ie_ptr(bss), bss->ie_len, dev_addr) == 0 && os_memcmp(wpa_s->pending_join_dev_addr, wpa_s->pending_join_iface_addr, ETH_ALEN) == 0 && @@ -5263,6 +5304,13 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq, if (freq > 0) { freqs[0] = freq; params.freqs = freqs; + } else if (wpa_s->conf->p2p_6ghz_disable) { + wpa_printf(MSG_DEBUG, + "P2P: 6 GHz disabled - update the scan frequency list"); + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, ¶ms, + 0); + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, ¶ms, + 0); } ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); @@ -5293,6 +5341,8 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq, * the new scan results become available. */ ret = wpa_drv_scan(wpa_s, ¶ms); + if (wpa_s->conf->p2p_6ghz_disable && params.freqs != freqs) + os_free(params.freqs); if (!ret) { os_get_reltime(&wpa_s->scan_trigger_time); wpa_s->scan_res_handler = wpas_p2p_scan_res_join; @@ -5633,6 +5683,9 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, return -1; } + if (is_6ghz_freq(freq) && wpa_s->conf->p2p_6ghz_disable) + return -2; + os_free(wpa_s->global->add_psk); wpa_s->global->add_psk = NULL; @@ -5859,6 +5912,8 @@ int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname) if (os_strcmp(ifname, "*") == 0) { struct wpa_supplicant *prev; + bool calling_wpa_s_group_removed = false; + wpa_s = global->ifaces; while (wpa_s) { prev = wpa_s; @@ -5866,9 +5921,23 @@ int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname) if (prev->p2p_group_interface != NOT_P2P_GROUP_INTERFACE || (prev->current_ssid && - prev->current_ssid->p2p_group)) + prev->current_ssid->p2p_group)) { wpas_p2p_disconnect_safely(prev, calling_wpa_s); + if (prev == calling_wpa_s) + calling_wpa_s_group_removed = true; + } } + + if (!calling_wpa_s_group_removed && + (calling_wpa_s->p2p_group_interface != + NOT_P2P_GROUP_INTERFACE || + (calling_wpa_s->current_ssid && + calling_wpa_s->current_ssid->p2p_group))) { + wpa_printf(MSG_DEBUG, "Remove calling_wpa_s P2P group"); + wpas_p2p_disconnect_safely(calling_wpa_s, + calling_wpa_s); + } + return 0; } @@ -7916,7 +7985,8 @@ void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s, os_memset(&chan, 0, sizeof(chan)); os_memset(&cli_chan, 0, sizeof(cli_chan)); - if (wpas_p2p_setup_channels(wpa_s, &chan, &cli_chan)) { + if (wpas_p2p_setup_channels(wpa_s, &chan, &cli_chan, + is_p2p_6ghz_disabled(wpa_s->global->p2p))) { wpa_printf(MSG_ERROR, "P2P: Failed to update supported " "channel list"); return; @@ -9362,6 +9432,8 @@ static void wpas_p2p_move_go_no_csa(struct wpa_supplicant *wpa_s) { struct p2p_go_neg_results params; struct wpa_ssid *current_ssid = wpa_s->current_ssid; + void (*ap_configured_cb)(void *ctx, void *data); + void *ap_configured_cb_ctx, *ap_configured_cb_data; wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_REMOVE_AND_REFORM_GROUP); @@ -9371,6 +9443,13 @@ static void wpas_p2p_move_go_no_csa(struct wpa_supplicant *wpa_s) /* Stop the AP functionality */ /* TODO: Should do this in a way that does not indicated to possible * P2P Clients in the group that the group is terminated. */ + /* If this action occurs before a group is started, the callback should + * be preserved, or GROUP-STARTED event would be lost. If this action + * occurs after a group is started, these pointers are all NULL and + * harmless. */ + ap_configured_cb = wpa_s->ap_configured_cb; + ap_configured_cb_ctx = wpa_s->ap_configured_cb_ctx; + ap_configured_cb_data = wpa_s->ap_configured_cb_data; wpa_supplicant_ap_deinit(wpa_s); /* Reselect the GO frequency */ @@ -9394,6 +9473,11 @@ static void wpas_p2p_move_go_no_csa(struct wpa_supplicant *wpa_s) return; } + /* Restore preserved callback parameters */ + wpa_s->ap_configured_cb = ap_configured_cb; + wpa_s->ap_configured_cb_ctx = ap_configured_cb_ctx; + wpa_s->ap_configured_cb_data = ap_configured_cb_data; + /* Update the frequency */ current_ssid->frequency = params.freq; wpa_s->connect_without_scan = current_ssid; diff --git a/wpa_supplicant/preauth_test.c b/wpa_supplicant/preauth_test.c index a73282841..de49948f7 100644 --- a/wpa_supplicant/preauth_test.c +++ b/wpa_supplicant/preauth_test.c @@ -41,6 +41,12 @@ static void _wpa_supplicant_deauthenticate(void *wpa_s, u16 reason_code) } +static void _wpa_supplicant_reconnect(void *wpa_s) +{ + wpa_supplicant_reconnect(wpa_s); +} + + static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type, const void *data, u16 data_len, size_t *msg_len, void **data_pos) @@ -147,7 +153,9 @@ static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr, static int wpa_supplicant_add_pmkid(void *wpa_s, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id, - const u8 *pmk, size_t pmk_len) + const u8 *pmk, size_t pmk_len, + u32 pmk_lifetime, u8 pmk_reauth_threshold, + int akmp) { printf("%s - not implemented\n", __func__); return -1; @@ -245,6 +253,7 @@ static void wpa_init_conf(struct wpa_supplicant *wpa_s, const char *ifname) ctx->set_config_blob = wpa_supplicant_set_config_blob; ctx->get_config_blob = wpa_supplicant_get_config_blob; ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection; + ctx->reconnect = _wpa_supplicant_reconnect; wpa_s->wpa = wpa_sm_init(ctx); assert(wpa_s->wpa != NULL); diff --git a/wpa_supplicant/robust_av.c b/wpa_supplicant/robust_av.c new file mode 100644 index 000000000..1280f5d96 --- /dev/null +++ b/wpa_supplicant/robust_av.c @@ -0,0 +1,160 @@ +/* + * wpa_supplicant - Robust AV procedures + * Copyright (c) 2020, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include "utils/common.h" +#include "common/wpa_ctrl.h" +#include "common/ieee802_11_common.h" +#include "wpa_supplicant_i.h" +#include "driver_i.h" +#include "bss.h" + + +void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av, + struct wpabuf *buf) +{ + u8 *len, *len1; + + /* MSCS descriptor element */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); + len = wpabuf_put(buf, 1); + wpabuf_put_u8(buf, WLAN_EID_EXT_MSCS_DESCRIPTOR); + wpabuf_put_u8(buf, robust_av->request_type); + wpabuf_put_u8(buf, robust_av->up_bitmap); + wpabuf_put_u8(buf, robust_av->up_limit); + wpabuf_put_le32(buf, robust_av->stream_timeout); + + if (robust_av->request_type != SCS_REQ_REMOVE) { + /* TCLAS mask element */ + wpabuf_put_u8(buf, WLAN_EID_EXTENSION); + len1 = wpabuf_put(buf, 1); + wpabuf_put_u8(buf, WLAN_EID_EXT_TCLAS_MASK); + + /* Frame classifier */ + wpabuf_put_data(buf, robust_av->frame_classifier, + robust_av->frame_classifier_len); + *len1 = (u8 *) wpabuf_put(buf, 0) - len1 - 1; + } + + *len = (u8 *) wpabuf_put(buf, 0) - len - 1; +} + + +int wpas_send_mscs_req(struct wpa_supplicant *wpa_s) +{ + struct wpabuf *buf; + const u8 *ext_capab = NULL; + size_t buf_len; + int ret; + + if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid) + return 0; + + if (wpa_s->current_bss) + ext_capab = wpa_bss_get_ie(wpa_s->current_bss, + WLAN_EID_EXT_CAPAB); + + if (!ext_capab || ext_capab[1] < 11 || !(ext_capab[12] & 0x20)) { + wpa_dbg(wpa_s, MSG_INFO, + "AP does not support MSCS - could not send MSCS Req"); + return -1; + } + + if (!wpa_s->mscs_setup_done && + wpa_s->robust_av.request_type != SCS_REQ_ADD) { + wpa_msg(wpa_s, MSG_INFO, + "MSCS: Failed to send MSCS Request: request type invalid"); + return -1; + } + + buf_len = 3 + /* Action frame header */ + 3 + /* MSCS descriptor IE header */ + 1 + /* Request type */ + 2 + /* User priority control */ + 4 + /* Stream timeout */ + 3 + /* TCLAS Mask IE header */ + wpa_s->robust_av.frame_classifier_len; + + buf = wpabuf_alloc(buf_len); + if (!buf) { + wpa_printf(MSG_ERROR, "Failed to allocate MSCS req"); + return -1; + } + + wpabuf_put_u8(buf, WLAN_ACTION_ROBUST_AV_STREAMING); + wpabuf_put_u8(buf, ROBUST_AV_MSCS_REQ); + wpa_s->robust_av.dialog_token++; + wpabuf_put_u8(buf, wpa_s->robust_av.dialog_token); + + /* MSCS descriptor element */ + wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, buf); + + wpa_hexdump_buf(MSG_MSGDUMP, "MSCS Request", buf); + ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0); + if (ret < 0) + wpa_dbg(wpa_s, MSG_INFO, "MSCS: Failed to send MSCS Request"); + + wpabuf_free(buf); + return ret; +} + + +void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s, + const u8 *src, const u8 *buf, size_t len) +{ + u8 dialog_token; + u16 status_code; + + if (len < 3) + return; + + dialog_token = *buf++; + if (dialog_token != wpa_s->robust_av.dialog_token) { + wpa_printf(MSG_INFO, + "MSCS: Drop received frame due to dialog token mismatch: received:%u expected:%u", + dialog_token, wpa_s->robust_av.dialog_token); + return; + } + + status_code = *buf; + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR + " status_code=%u", MAC2STR(src), status_code); + wpa_s->mscs_setup_done = status_code == WLAN_STATUS_SUCCESS; +} + + +void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid, + const u8 *ies, size_t ies_len) +{ + const u8 *mscs_desc_ie, *mscs_status; + u16 status; + + /* Process optional MSCS Status subelement when MSCS IE is in + * (Re)Association Response frame */ + if (!ies || ies_len == 0 || !wpa_s->robust_av.valid_config) + return; + + mscs_desc_ie = get_ie_ext(ies, ies_len, WLAN_EID_EXT_MSCS_DESCRIPTOR); + if (!mscs_desc_ie || mscs_desc_ie[1] <= 8) + return; + + /* Subelements start after (ie_id(1) + ie_len(1) + ext_id(1) + + * request type(1) + upc(2) + stream timeout(4) =) 10. + */ + mscs_status = get_ie(&mscs_desc_ie[10], mscs_desc_ie[1] - 8, + MCSC_SUBELEM_STATUS); + if (!mscs_status || mscs_status[1] < 2) + return; + + status = WPA_GET_LE16(mscs_status + 2); + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_MSCS_RESULT "bssid=" MACSTR + " status_code=%u", MAC2STR(bssid), status); + wpa_s->mscs_setup_done = status == WLAN_STATUS_SUCCESS; +} diff --git a/wpa_supplicant/rrm.c b/wpa_supplicant/rrm.c index 66855b877..242496d0a 100644 --- a/wpa_supplicant/rrm.c +++ b/wpa_supplicant/rrm.c @@ -556,23 +556,32 @@ static int * wpas_add_channels(const struct oper_class_map *op, static int * wpas_op_class_freqs(const struct oper_class_map *op, struct hostapd_hw_modes *mode, int active) { - u8 channels_80mhz[] = { 42, 58, 106, 122, 138, 155 }; - u8 channels_160mhz[] = { 50, 114 }; + u8 channels_80mhz_5ghz[] = { 42, 58, 106, 122, 138, 155 }; + u8 channels_160mhz_5ghz[] = { 50, 114 }; + u8 channels_80mhz_6ghz[] = { 7, 23, 39, 55, 71, 87, 103, 119, 135, 151, + 167, 183, 199, 215 }; + u8 channels_160mhz_6ghz[] = { 15, 47, 79, 111, 143, 175, 207 }; + const u8 *channels = NULL; + size_t num_chan = 0; + bool is_6ghz = is_6ghz_op_class(op->op_class); /* * When adding all channels in the operating class, 80 + 80 MHz * operating classes are like 80 MHz channels because we add all valid * channels anyway. */ - if (op->bw == BW80 || op->bw == BW80P80) - return wpas_add_channels(op, mode, active, channels_80mhz, - ARRAY_SIZE(channels_80mhz)); + if (op->bw == BW80 || op->bw == BW80P80) { + channels = is_6ghz ? channels_80mhz_6ghz : channels_80mhz_5ghz; + num_chan = is_6ghz ? ARRAY_SIZE(channels_80mhz_6ghz) : + ARRAY_SIZE(channels_80mhz_5ghz); + } else if (op->bw == BW160) { + channels = is_6ghz ? channels_160mhz_6ghz : + channels_160mhz_5ghz; + num_chan = is_6ghz ? ARRAY_SIZE(channels_160mhz_6ghz) : + ARRAY_SIZE(channels_160mhz_5ghz); + } - if (op->bw == BW160) - return wpas_add_channels(op, mode, active, channels_160mhz, - ARRAY_SIZE(channels_160mhz)); - - return wpas_add_channels(op, mode, active, NULL, 0); + return wpas_add_channels(op, mode, active, channels, num_chan); } @@ -695,8 +704,8 @@ static int * wpas_beacon_request_freqs(struct wpa_supplicant *wpa_s, } -static int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len, - u8 *op_class, u8 *chan, u8 *phy_type) +int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len, + u8 *op_class, u8 *chan, u8 *phy_type) { const u8 *ie; int sec_chan = 0, vht = 0; @@ -766,10 +775,10 @@ static int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len, static int wpas_beacon_rep_add_frame_body(struct bitfield *eids, enum beacon_report_detail detail, struct wpa_bss *bss, u8 *buf, - size_t buf_len, u8 **ies_buf, + size_t buf_len, const u8 **ies_buf, size_t *ie_len, int add_fixed) { - u8 *ies = *ies_buf; + const u8 *ies = *ies_buf; size_t ies_len = *ie_len; u8 *pos = buf; int rem_len; @@ -851,7 +860,7 @@ static int wpas_add_beacon_rep_elem(struct beacon_rep_data *data, struct wpa_bss *bss, struct wpabuf **wpa_buf, struct rrm_measurement_beacon_report *rep, - u8 **ie, size_t *ie_len, u8 idx) + const u8 **ie, size_t *ie_len, u8 idx) { int ret; u8 *buf, *pos; @@ -918,8 +927,8 @@ static int wpas_add_beacon_rep(struct wpa_supplicant *wpa_s, u64 start, u64 parent_tsf) { struct beacon_rep_data *data = &wpa_s->beacon_rep_data; - u8 *ies = (u8 *) (bss + 1); - u8 *pos = ies; + const u8 *ies = wpa_bss_ie_ptr(bss); + const u8 *pos = ies; size_t ies_len = bss->ie_len ? bss->ie_len : bss->beacon_ie_len; struct rrm_measurement_beacon_report rep; u8 idx = 0; diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 17636e3b6..5d3016305 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -237,6 +237,10 @@ static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit) if (wpa_s->disconnected) retry = 0; + /* do not retry if operation is not supported */ + if (ret == -EOPNOTSUPP) + retry = 0; + wpa_supplicant_notify_scanning(wpa_s, 0); wpas_notify_scan_done(wpa_s, 0); if (wpa_s->wpa_state == WPA_SCANNING) @@ -666,30 +670,38 @@ static int non_p2p_network_enabled(struct wpa_supplicant *wpa_s) #endif /* CONFIG_P2P */ -static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s, - enum hostapd_hw_mode band, - struct wpa_driver_scan_params *params, - int is_6ghz) +int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s, + enum hostapd_hw_mode band, + struct wpa_driver_scan_params *params, bool is_6ghz) { /* Include only supported channels for the specified band */ struct hostapd_hw_modes *mode; - int count, i; + int num_chans = 0; + int *freqs, i; mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band, is_6ghz); - if (mode == NULL) { - /* No channels supported in this band - use empty list */ - params->freqs = os_zalloc(sizeof(int)); - return; + if (!mode) + return -1; + + if (params->freqs) { + while (params->freqs[num_chans]) + num_chans++; } - params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); - if (params->freqs == NULL) - return; - for (count = 0, i = 0; i < mode->num_channels; i++) { + freqs = os_realloc(params->freqs, + (num_chans + mode->num_channels + 1) * sizeof(int)); + if (!freqs) + return -1; + + params->freqs = freqs; + for (i = 0; i < mode->num_channels; i++) { if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) continue; - params->freqs[count++] = mode->channels[i].freq; + params->freqs[num_chans++] = mode->channels[i].freq; } + params->freqs[num_chans] = 0; + + return 0; } @@ -700,12 +712,16 @@ static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s, return; /* unknown what channels the driver supports */ if (params->freqs) return; /* already using a limited channel set */ - if (wpa_s->setband == WPA_SETBAND_5G) - wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, - params, 0); - else if (wpa_s->setband == WPA_SETBAND_2G) - wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, - params, 0); + + if (wpa_s->setband_mask & WPA_SETBAND_5G) + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params, + 0); + if (wpa_s->setband_mask & WPA_SETBAND_2G) + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, params, + 0); + if (wpa_s->setband_mask & WPA_SETBAND_6G) + wpa_add_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, params, + 1); } @@ -1109,7 +1125,9 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) tssid = tssid->next) { if (wpas_network_disabled(wpa_s, tssid)) continue; - if ((params.freqs || !freqs_set) && tssid->scan_freq) { + if (((params.freqs || !freqs_set) && + tssid->scan_freq) && + int_array_len(params.freqs) < 100) { int_array_concat(¶ms.freqs, tssid->scan_freq); } else { @@ -1195,7 +1213,12 @@ ssid_list_set: wpa_setband_scan_freqs(wpa_s, ¶ms); /* See if user specified frequencies. If so, scan only those. */ - if (wpa_s->conf->freq_list && !params.freqs) { + if (wpa_s->last_scan_req == INITIAL_SCAN_REQ && + wpa_s->conf->initial_freq_list && !params.freqs) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Optimize scan based on conf->initial_freq_list"); + int_array_concat(¶ms.freqs, wpa_s->conf->initial_freq_list); + } else if (wpa_s->conf->freq_list && !params.freqs) { wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on conf->freq_list"); int_array_concat(¶ms.freqs, wpa_s->conf->freq_list); @@ -1251,7 +1274,8 @@ ssid_list_set: params.bssid = wpa_s->next_scan_bssid; bss = wpa_bss_get_bssid_latest(wpa_s, params.bssid); - if (bss && bss->ssid_len && params.num_ssids == 1 && + if (!wpa_s->next_scan_bssid_wildcard_ssid && + bss && bss->ssid_len && params.num_ssids == 1 && params.ssids[0].ssid_len == 0) { params.ssids[0].ssid = bss->ssid; params.ssids[0].ssid_len = bss->ssid_len; @@ -1328,6 +1352,7 @@ scan: #ifdef CONFIG_INTERWORKING wpa_s->interworking_fast_assoc_tried = 0; #endif /* CONFIG_INTERWORKING */ + wpa_s->next_scan_bssid_wildcard_ssid = 0; if (params.bssid) os_memset(wpa_s->next_scan_bssid, 0, ETH_ALEN); } @@ -1861,18 +1886,15 @@ const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, u32 vendor_type) { - const u8 *end, *pos; + const u8 *ies; + const struct element *elem; - pos = (const u8 *) (res + 1); - end = pos + res->ie_len; + ies = (const u8 *) (res + 1); - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, res->ie_len) { + if (elem->datalen >= 4 && + vendor_type == WPA_GET_BE32(elem->data)) + return &elem->id; } return NULL; @@ -1894,22 +1916,20 @@ const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res, u32 vendor_type) { - const u8 *end, *pos; + const u8 *ies; + const struct element *elem; if (res->beacon_ie_len == 0) return NULL; - pos = (const u8 *) (res + 1); - pos += res->ie_len; - end = pos + res->beacon_ie_len; + ies = (const u8 *) (res + 1); + ies += res->ie_len; - while (end - pos > 1) { - if (2 + pos[1] > end - pos) - break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - return pos; - pos += 2 + pos[1]; + for_each_element_id(elem, WLAN_EID_VENDOR_SPECIFIC, ies, + res->beacon_ie_len) { + if (elem->datalen >= 4 && + vendor_type == WPA_GET_BE32(elem->data)) + return &elem->id; } return NULL; @@ -1940,12 +1960,17 @@ struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, end = pos + res->ie_len; while (end - pos > 1) { - if (2 + pos[1] > end - pos) + u8 ie, len; + + ie = pos[0]; + len = pos[1]; + if (len > end - pos - 2) break; - if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && - vendor_type == WPA_GET_BE32(&pos[2])) - wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); - pos += 2 + pos[1]; + pos += 2; + if (ie == WLAN_EID_VENDOR_SPECIFIC && len >= 4 && + vendor_type == WPA_GET_BE32(pos)) + wpabuf_put_data(buf, pos + 4, len - 4); + pos += len; } if (wpabuf_len(buf) == 0) { @@ -2183,69 +2208,101 @@ void scan_snr(struct wpa_scan_res *res) } -static unsigned int max_ht20_rate(int snr) +/* Minimum SNR required to achieve a certain bitrate. */ +struct minsnr_bitrate_entry { + int minsnr; + unsigned int bitrate; /* in Mbps */ +}; + +/* VHT needs to be enabled in order to achieve MCS8 and MCS9 rates. */ +static const int vht_mcs = 8; + +static const struct minsnr_bitrate_entry vht20_table[] = { + { 0, 0 }, + { 2, 6500 }, /* HT20 MCS0 */ + { 5, 13000 }, /* HT20 MCS1 */ + { 9, 19500 }, /* HT20 MCS2 */ + { 11, 26000 }, /* HT20 MCS3 */ + { 15, 39000 }, /* HT20 MCS4 */ + { 18, 52000 }, /* HT20 MCS5 */ + { 20, 58500 }, /* HT20 MCS6 */ + { 25, 65000 }, /* HT20 MCS7 */ + { 29, 78000 }, /* VHT20 MCS8 */ + { -1, 78000 } /* SNR > 29 */ +}; + +static const struct minsnr_bitrate_entry vht40_table[] = { + { 0, 0 }, + { 5, 13500 }, /* HT40 MCS0 */ + { 8, 27000 }, /* HT40 MCS1 */ + { 12, 40500 }, /* HT40 MCS2 */ + { 14, 54000 }, /* HT40 MCS3 */ + { 18, 81000 }, /* HT40 MCS4 */ + { 21, 108000 }, /* HT40 MCS5 */ + { 23, 121500 }, /* HT40 MCS6 */ + { 28, 135000 }, /* HT40 MCS7 */ + { 32, 162000 }, /* VHT40 MCS8 */ + { 34, 180000 }, /* VHT40 MCS9 */ + { -1, 180000 } /* SNR > 34 */ +}; + +static const struct minsnr_bitrate_entry vht80_table[] = { + { 0, 0 }, + { 8, 29300 }, /* VHT80 MCS0 */ + { 11, 58500 }, /* VHT80 MCS1 */ + { 15, 87800 }, /* VHT80 MCS2 */ + { 17, 117000 }, /* VHT80 MCS3 */ + { 21, 175500 }, /* VHT80 MCS4 */ + { 24, 234000 }, /* VHT80 MCS5 */ + { 26, 263300 }, /* VHT80 MCS6 */ + { 31, 292500 }, /* VHT80 MCS7 */ + { 35, 351000 }, /* VHT80 MCS8 */ + { 37, 390000 }, /* VHT80 MCS9 */ + { -1, 390000 } /* SNR > 37 */ +}; + + +static unsigned int interpolate_rate(int snr, int snr0, int snr1, + int rate0, int rate1) { - if (snr < 6) - return 6500; /* HT20 MCS0 */ - if (snr < 8) - return 13000; /* HT20 MCS1 */ - if (snr < 13) - return 19500; /* HT20 MCS2 */ - if (snr < 17) - return 26000; /* HT20 MCS3 */ - if (snr < 20) - return 39000; /* HT20 MCS4 */ - if (snr < 23) - return 52000; /* HT20 MCS5 */ - if (snr < 24) - return 58500; /* HT20 MCS6 */ - return 65000; /* HT20 MCS7 */ + return rate0 + (snr - snr0) * (rate1 - rate0) / (snr1 - snr0); } -static unsigned int max_ht40_rate(int snr) +static unsigned int max_rate(const struct minsnr_bitrate_entry table[], + int snr, bool vht) { - if (snr < 3) - return 13500; /* HT40 MCS0 */ - if (snr < 6) - return 27000; /* HT40 MCS1 */ - if (snr < 10) - return 40500; /* HT40 MCS2 */ - if (snr < 15) - return 54000; /* HT40 MCS3 */ - if (snr < 17) - return 81000; /* HT40 MCS4 */ - if (snr < 22) - return 108000; /* HT40 MCS5 */ - if (snr < 24) - return 121500; /* HT40 MCS6 */ - return 135000; /* HT40 MCS7 */ + const struct minsnr_bitrate_entry *prev, *entry = table; + + while ((entry->minsnr != -1) && + (snr >= entry->minsnr) && + (vht || entry - table <= vht_mcs)) + entry++; + if (entry == table) + return entry->bitrate; + prev = entry - 1; + if (entry->minsnr == -1 || (!vht && entry - table > vht_mcs)) + return prev->bitrate; + return interpolate_rate(snr, prev->minsnr, entry->minsnr, prev->bitrate, + entry->bitrate); +} + + +static unsigned int max_ht20_rate(int snr, bool vht) +{ + return max_rate(vht20_table, snr, vht); +} + + +static unsigned int max_ht40_rate(int snr, bool vht) +{ + return max_rate(vht40_table, snr, vht); } static unsigned int max_vht80_rate(int snr) { - if (snr < 1) - return 0; - if (snr < 2) - return 29300; /* VHT80 MCS0 */ - if (snr < 5) - return 58500; /* VHT80 MCS1 */ - if (snr < 9) - return 87800; /* VHT80 MCS2 */ - if (snr < 11) - return 117000; /* VHT80 MCS3 */ - if (snr < 15) - return 175500; /* VHT80 MCS4 */ - if (snr < 16) - return 234000; /* VHT80 MCS5 */ - if (snr < 18) - return 263300; /* VHT80 MCS6 */ - if (snr < 20) - return 292500; /* VHT80 MCS7 */ - if (snr < 22) - return 351000; /* VHT80 MCS8 */ - return 390000; /* VHT80 MCS9 */ + return max_rate(vht80_table, snr, 1); } @@ -2268,14 +2325,32 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, rate = 9 * 2; else if (rate > 12 * 2 && snr < 7) rate = 12 * 2; + else if (rate > 12 * 2 && snr < 8) + rate = 14 * 2; + else if (rate > 12 * 2 && snr < 9) + rate = 16 * 2; else if (rate > 18 * 2 && snr < 10) rate = 18 * 2; else if (rate > 24 * 2 && snr < 11) rate = 24 * 2; + else if (rate > 24 * 2 && snr < 12) + rate = 27 * 2; + else if (rate > 24 * 2 && snr < 13) + rate = 30 * 2; + else if (rate > 24 * 2 && snr < 14) + rate = 33 * 2; else if (rate > 36 * 2 && snr < 15) rate = 36 * 2; + else if (rate > 36 * 2 && snr < 16) + rate = 39 * 2; + else if (rate > 36 * 2 && snr < 17) + rate = 42 * 2; + else if (rate > 36 * 2 && snr < 18) + rate = 45 * 2; else if (rate > 48 * 2 && snr < 19) rate = 48 * 2; + else if (rate > 48 * 2 && snr < 20) + rate = 51 * 2; else if (rate > 54 * 2 && snr < 21) rate = 54 * 2; est = rate * 500; @@ -2283,7 +2358,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, if (capab == CAPAB_HT || capab == CAPAB_HT40 || capab == CAPAB_VHT) { ie = get_ie(ies, ies_len, WLAN_EID_HT_CAP); if (ie) { - tmp = max_ht20_rate(snr); + tmp = max_ht20_rate(snr, false); if (tmp > est) est = tmp; } @@ -2293,7 +2368,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, ie = get_ie(ies, ies_len, WLAN_EID_HT_OPERATION); if (ie && ie[1] >= 2 && (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) { - tmp = max_ht40_rate(snr); + tmp = max_ht40_rate(snr, false); if (tmp > est) est = tmp; } @@ -2303,7 +2378,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, /* Use +1 to assume VHT is always faster than HT */ ie = get_ie(ies, ies_len, WLAN_EID_VHT_CAP); if (ie) { - tmp = max_ht20_rate(snr) + 1; + tmp = max_ht20_rate(snr, true) + 1; if (tmp > est) est = tmp; @@ -2311,7 +2386,7 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, if (ie && ie[1] >= 2 && (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) { - tmp = max_ht40_rate(snr) + 1; + tmp = max_ht40_rate(snr, true) + 1; if (tmp > est) est = tmp; } @@ -2604,8 +2679,8 @@ void wpa_scan_free_params(struct wpa_driver_scan_params *params) int wpas_start_pno(struct wpa_supplicant *wpa_s) { - int ret, prio; - size_t i, num_ssid, num_match_ssid; + int ret; + size_t prio, i, num_ssid, num_match_ssid; struct wpa_ssid *ssid; struct wpa_driver_scan_params params; struct sched_scan_plan scan_plan; diff --git a/wpa_supplicant/scan.h b/wpa_supplicant/scan.h index c9ce2cecf..8eb5c73e2 100644 --- a/wpa_supplicant/scan.h +++ b/wpa_supplicant/scan.h @@ -86,5 +86,9 @@ unsigned int wpas_get_est_tpt(const struct wpa_supplicant *wpa_s, const u8 *ies, size_t ies_len, int rate, int snr); void wpa_supplicant_set_default_scan_ies(struct wpa_supplicant *wpa_s); +int wpa_add_scan_freqs_list(struct wpa_supplicant *wpa_s, + enum hostapd_hw_mode band, + struct wpa_driver_scan_params *params, + bool is_6ghz); #endif /* SCAN_H */ diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 81151a7fb..46963e92f 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -85,16 +85,21 @@ static int sme_set_sae_group(struct wpa_supplicant *wpa_s) static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, const u8 *bssid, int external, - int reuse, int *ret_use_pt) + int reuse, int *ret_use_pt, + bool *ret_use_pk) { struct wpabuf *buf; size_t len; const char *password; struct wpa_bss *bss; int use_pt = 0; + bool use_pk = false; + u8 rsnxe_capa = 0; if (ret_use_pt) *ret_use_pt = 0; + if (ret_use_pk) + *ret_use_pk = false; #ifdef CONFIG_TESTING_OPTIONS if (wpa_s->sae_commit_override) { @@ -123,7 +128,8 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, os_memcmp(bssid, wpa_s->sme.sae.tmp->bssid, ETH_ALEN) == 0) { wpa_printf(MSG_DEBUG, "SAE: Reuse previously generated PWE on a retry with the same AP"); - use_pt = wpa_s->sme.sae.tmp->h2e; + use_pt = wpa_s->sme.sae.h2e; + use_pk = wpa_s->sme.sae.pk; goto reuse_data; } if (sme_set_sae_group(wpa_s) < 0) { @@ -131,19 +137,37 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, return NULL; } + bss = wpa_bss_get_bssid_latest(wpa_s, bssid); + if (bss) { + const u8 *rsnxe; + + rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); + if (rsnxe && rsnxe[1] >= 1) + rsnxe_capa = rsnxe[2]; + } + if (ssid->sae_password_id && wpa_s->conf->sae_pwe != 3) use_pt = 1; +#ifdef CONFIG_SAE_PK + if ((rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_PK)) && + ssid->sae_pk != SAE_PK_MODE_DISABLED && + ((ssid->sae_password && + sae_pk_valid_password(ssid->sae_password)) || + (!ssid->sae_password && ssid->passphrase && + sae_pk_valid_password(ssid->passphrase)))) { + use_pt = 1; + use_pk = true; + } + + if (ssid->sae_pk == SAE_PK_MODE_ONLY && !use_pk) { + wpa_printf(MSG_DEBUG, + "SAE: Cannot use PK with the selected AP"); + return NULL; + } +#endif /* CONFIG_SAE_PK */ if (use_pt || wpa_s->conf->sae_pwe == 1 || wpa_s->conf->sae_pwe == 2) { - bss = wpa_bss_get_bssid_latest(wpa_s, bssid); - if (bss) { - const u8 *rsnxe; - - rsnxe = wpa_bss_get_ie(bss, WLAN_EID_RSNX); - if (rsnxe && rsnxe[1] >= 1) - use_pt = !!(rsnxe[2] & - BIT(WLAN_RSNX_CAPAB_SAE_H2E)); - } + use_pt = !!(rsnxe_capa & BIT(WLAN_RSNX_CAPAB_SAE_H2E)); if ((wpa_s->conf->sae_pwe == 1 || ssid->sae_password_id) && wpa_s->conf->sae_pwe != 3 && @@ -157,7 +181,7 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, if (use_pt && sae_prepare_commit_pt(&wpa_s->sme.sae, ssid->pt, wpa_s->own_addr, bssid, - wpa_s->sme.sae_rejected_groups) < 0) + wpa_s->sme.sae_rejected_groups, NULL) < 0) return NULL; if (!use_pt && sae_prepare_commit(wpa_s->own_addr, bssid, @@ -167,8 +191,17 @@ static struct wpabuf * sme_auth_build_sae_commit(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE"); return NULL; } - if (wpa_s->sme.sae.tmp) + if (wpa_s->sme.sae.tmp) { os_memcpy(wpa_s->sme.sae.tmp->bssid, bssid, ETH_ALEN); + if (use_pt && use_pk) + wpa_s->sme.sae.pk = 1; +#ifdef CONFIG_SAE_PK + os_memcpy(wpa_s->sme.sae.tmp->own_addr, wpa_s->own_addr, + ETH_ALEN); + os_memcpy(wpa_s->sme.sae.tmp->peer_addr, bssid, ETH_ALEN); + sae_pk_set_password(&wpa_s->sme.sae, password); +#endif /* CONFIG_SAE_PK */ + } reuse_data: len = wpa_s->sme.sae_token ? 3 + wpabuf_len(wpa_s->sme.sae_token) : 0; @@ -179,13 +212,22 @@ reuse_data: return NULL; if (!external) { wpabuf_put_le16(buf, 1); /* Transaction seq# */ - wpabuf_put_le16(buf, use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT : - WLAN_STATUS_SUCCESS); + if (use_pk) + wpabuf_put_le16(buf, WLAN_STATUS_SAE_PK); + else if (use_pt) + wpabuf_put_le16(buf, WLAN_STATUS_SAE_HASH_TO_ELEMENT); + else + wpabuf_put_le16(buf,WLAN_STATUS_SUCCESS); + } + if (sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token, + ssid->sae_password_id) < 0) { + wpabuf_free(buf); + return NULL; } - sae_write_commit(&wpa_s->sme.sae, buf, wpa_s->sme.sae_token, - ssid->sae_password_id); if (ret_use_pt) *ret_use_pt = use_pt; + if (ret_use_pk) + *ret_use_pk = use_pk; return buf; } @@ -258,7 +300,7 @@ static void sme_auth_handle_rrm(struct wpa_supplicant *wpa_s, *pos++ = WLAN_EID_RRM_ENABLED_CAPABILITIES; *pos++ = rrm_ie_len; - /* Set supported capabilites flags */ + /* Set supported capabilities flags */ if (wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION) *pos |= WLAN_RRM_CAPS_LINK_MEASUREMENT; @@ -286,7 +328,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, #if defined(CONFIG_IEEE80211R) || defined(CONFIG_FILS) const u8 *md = NULL; #endif /* CONFIG_IEEE80211R || CONFIG_FILS */ - int i, bssid_changed; + int bssid_changed; struct wpabuf *resp = NULL; u8 ext_capab[18]; int ext_capab_len; @@ -296,6 +338,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, #ifdef CONFIG_MBO const u8 *mbo_ie; #endif /* CONFIG_MBO */ + int omit_rsnxe = 0; if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " @@ -370,12 +413,18 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, } #endif /* CONFIG_SAE */ - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ssid->wep_key_len[i]) - params.wep_key[i] = ssid->wep_key[i]; - params.wep_key_len[i] = ssid->wep_key_len[i]; +#ifdef CONFIG_WEP + { + int i; + + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (ssid->wep_key_len[i]) + params.wep_key[i] = ssid->wep_key[i]; + params.wep_key_len[i] = ssid->wep_key_len[i]; + } + params.wep_tx_keyidx = ssid->wep_tx_keyidx; } - params.wep_tx_keyidx = ssid->wep_tx_keyidx; +#endif /* CONFIG_WEP */ if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && @@ -497,6 +546,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, wpa_dbg(wpa_s, MSG_DEBUG, "SME: FT mobility domain %02x%02x", md[0], md[1]); + omit_rsnxe = !wpa_bss_get_ie(bss, WLAN_EID_RSNX); if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; @@ -569,7 +619,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, sme_auth_handle_rrm(wpa_s, bss); wpa_s->sme.assoc_req_ie_len += wpas_supp_op_class_ie( - wpa_s, ssid, bss->freq, + wpa_s, ssid, bss, wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len); @@ -605,7 +655,8 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, #endif /* CONFIG_TESTING_OPTIONS */ if (wpa_s->rsnxe_len > 0 && wpa_s->rsnxe_len <= - sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len) { + sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len && + !omit_rsnxe) { os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpa_s->rsnxe, wpa_s->rsnxe_len); wpa_s->sme.assoc_req_ie_len += wpa_s->rsnxe_len; @@ -704,7 +755,8 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, if (start) resp = sme_auth_build_sae_commit(wpa_s, ssid, bss->bssid, 0, - start == 2, NULL); + start == 2, NULL, + NULL); else resp = sme_auth_build_sae_confirm(wpa_s, 0); if (resp == NULL) { @@ -816,7 +868,7 @@ no_fils: " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + eapol_sm_notify_portValid(wpa_s->eapol, false); wpa_clear_keys(wpa_s, bss->bssid); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); if (old_ssid != wpa_s->current_ssid) @@ -996,8 +1048,11 @@ static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s, { struct wpabuf *resp, *buf; int use_pt; + bool use_pk; + u16 status; - resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0, &use_pt); + resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0, &use_pt, + &use_pk); if (!resp) { wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit"); return -1; @@ -1011,11 +1066,15 @@ static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s, } wpa_s->sme.seq_num++; + if (use_pk) + status = WLAN_STATUS_SAE_PK; + else if (use_pt) + status = WLAN_STATUS_SAE_HASH_TO_ELEMENT; + else + status = WLAN_STATUS_SUCCESS; sme_external_auth_build_buf(buf, resp, wpa_s->own_addr, - bssid, 1, wpa_s->sme.seq_num, - use_pt ? WLAN_STATUS_SAE_HASH_TO_ELEMENT : - WLAN_STATUS_SUCCESS); - wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0); + bssid, 1, wpa_s->sme.seq_num, status); + wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0); wpabuf_free(resp); wpabuf_free(buf); @@ -1085,7 +1144,7 @@ static void sme_external_auth_send_sae_confirm(struct wpa_supplicant *wpa_s, sme_external_auth_build_buf(buf, resp, wpa_s->own_addr, da, 2, wpa_s->sme.seq_num, WLAN_STATUS_SUCCESS); - wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0); + wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0, 0); wpabuf_free(resp); wpabuf_free(buf); } @@ -1211,8 +1270,7 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, wpabuf_free(wpa_s->sme.sae_token); token_pos = data + sizeof(le16); token_len = len - sizeof(le16); - if (wpa_s->sme.sae.tmp) - h2e = wpa_s->sme.sae.tmp->h2e; + h2e = wpa_s->sme.sae.h2e; if (h2e) { if (token_len < 3) { wpa_dbg(wpa_s, MSG_DEBUG, @@ -1275,7 +1333,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, } if (status_code != WLAN_STATUS_SUCCESS && - status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT) + status_code != WLAN_STATUS_SAE_HASH_TO_ELEMENT && + status_code != WLAN_STATUS_SAE_PK) return -1; if (auth_transaction == 1) { @@ -1292,24 +1351,30 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, "SAE: Ignore commit message while waiting for confirm"); return 0; } - if (wpa_s->sme.sae.tmp && wpa_s->sme.sae.tmp->h2e && - status_code == WLAN_STATUS_SUCCESS) { + if (wpa_s->sme.sae.h2e && status_code == WLAN_STATUS_SUCCESS) { wpa_printf(MSG_DEBUG, "SAE: Unexpected use of status code 0 in SAE commit when H2E was expected"); return -1; } - if (wpa_s->sme.sae.tmp && !wpa_s->sme.sae.tmp->h2e && + if ((!wpa_s->sme.sae.h2e || wpa_s->sme.sae.pk) && status_code == WLAN_STATUS_SAE_HASH_TO_ELEMENT) { wpa_printf(MSG_DEBUG, "SAE: Unexpected use of status code for H2E in SAE commit when H2E was not expected"); return -1; } + if (!wpa_s->sme.sae.pk && + status_code == WLAN_STATUS_SAE_PK) { + wpa_printf(MSG_DEBUG, + "SAE: Unexpected use of status code for PK in SAE commit when PK was not expected"); + return -1; + } if (groups && groups[0] <= 0) groups = NULL; res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL, groups, status_code == - WLAN_STATUS_SAE_HASH_TO_ELEMENT); + WLAN_STATUS_SAE_HASH_TO_ELEMENT || + status_code == WLAN_STATUS_SAE_PK); if (res == SAE_SILENTLY_DISCARD) { wpa_printf(MSG_DEBUG, "SAE: Drop commit message due to reflection attack"); @@ -1634,6 +1699,7 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, { struct wpa_driver_associate_params params; struct ieee802_11_elems elems; + struct wpa_ssid *ssid = wpa_s->current_ssid; #ifdef CONFIG_FILS u8 nonces[2 * FILS_NONCE_LEN]; #endif /* CONFIG_FILS */ @@ -1743,8 +1809,8 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, struct wpabuf *owe_ie; u16 group; - if (wpa_s->current_ssid && wpa_s->current_ssid->owe_group) { - group = wpa_s->current_ssid->owe_group; + if (ssid && ssid->owe_group) { + group = ssid->owe_group; } else if (wpa_s->assoc_status_code == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) { if (wpa_s->last_owe_group == 19) @@ -1780,9 +1846,14 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, #endif /* CONFIG_OWE */ #ifdef CONFIG_DPP2 - if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && wpa_s->current_ssid && - wpa_s->current_ssid->dpp_netaccesskey) { - struct wpa_ssid *ssid = wpa_s->current_ssid; + if (DPP_VERSION > 1 && wpa_s->key_mgmt == WPA_KEY_MGMT_DPP && ssid && + ssid->dpp_netaccesskey && ssid->dpp_pfs != 2 && + !ssid->dpp_pfs_fallback) { + struct rsn_pmksa_cache_entry *pmksa; + + pmksa = pmksa_cache_get_current(wpa_s->wpa); + if (!pmksa || !pmksa->dpp_pfs) + goto pfs_fail; dpp_pfs_free(wpa_s->dpp_pfs); wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey, @@ -1809,7 +1880,43 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, pfs_fail: #endif /* CONFIG_DPP2 */ - if (wpa_s->current_ssid && wpa_s->current_ssid->multi_ap_backhaul_sta) { + wpa_s->mscs_setup_done = false; + if (wpa_s->current_bss && wpa_s->robust_av.valid_config) { + struct wpabuf *mscs_ie; + size_t mscs_ie_len, buf_len, *wpa_ie_len, max_ie_len; + + if (!wpa_bss_ext_capab(wpa_s->current_bss, WLAN_EXT_CAPAB_MSCS)) + goto mscs_fail; + + buf_len = 3 + /* MSCS descriptor IE header */ + 1 + /* Request type */ + 2 + /* User priority control */ + 4 + /* Stream timeout */ + 3 + /* TCLAS Mask IE header */ + wpa_s->robust_av.frame_classifier_len; + mscs_ie = wpabuf_alloc(buf_len); + if (!mscs_ie) { + wpa_printf(MSG_INFO, + "MSCS: Failed to allocate MSCS IE"); + goto mscs_fail; + } + + wpa_ie_len = &wpa_s->sme.assoc_req_ie_len; + max_ie_len = sizeof(wpa_s->sme.assoc_req_ie); + wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie); + if ((*wpa_ie_len + wpabuf_len(mscs_ie)) <= max_ie_len) { + wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie); + mscs_ie_len = wpabuf_len(mscs_ie); + os_memcpy(wpa_s->sme.assoc_req_ie + *wpa_ie_len, + wpabuf_head(mscs_ie), mscs_ie_len); + *wpa_ie_len += mscs_ie_len; + } + + wpabuf_free(mscs_ie); + } +mscs_fail: + + if (ssid && ssid->multi_ap_backhaul_sta) { size_t multi_ap_ie_len; multi_ap_ie_len = add_multi_ap_ie( @@ -1829,8 +1936,7 @@ pfs_fail: params.ssid = wpa_s->sme.ssid; params.ssid_len = wpa_s->sme.ssid_len; params.freq.freq = wpa_s->sme.freq; - params.bg_scan_period = wpa_s->current_ssid ? - wpa_s->current_ssid->bg_scan_period : -1; + params.bg_scan_period = ssid ? ssid->bg_scan_period : -1; params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? wpa_s->sme.assoc_req_ie : NULL; params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; @@ -1846,15 +1952,18 @@ pfs_fail: os_memset(&htcaps_mask, 0, sizeof(htcaps_mask)); params.htcaps = (u8 *) &htcaps; params.htcaps_mask = (u8 *) &htcaps_mask; - wpa_supplicant_apply_ht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); + wpa_supplicant_apply_ht_overrides(wpa_s, ssid, ¶ms); #endif /* CONFIG_HT_OVERRIDES */ #ifdef CONFIG_VHT_OVERRIDES os_memset(&vhtcaps, 0, sizeof(vhtcaps)); os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask)); params.vhtcaps = &vhtcaps; params.vhtcaps_mask = &vhtcaps_mask; - wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); + wpa_supplicant_apply_vht_overrides(wpa_s, ssid, ¶ms); #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + wpa_supplicant_apply_he_overrides(wpa_s, ssid, ¶ms); +#endif /* CONFIG_HE_OVERRIDES */ #ifdef CONFIG_IEEE80211R if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies && get_ie(wpa_s->sme.ft_ies, wpa_s->sme.ft_ies_len, @@ -1975,7 +2084,7 @@ pfs_fail: elems.rsnxe_len + 2); else wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0); - if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group) + if (ssid && ssid->p2p_group) params.p2p = 1; if (wpa_s->p2pdev->set_sta_uapsd) @@ -2353,7 +2462,7 @@ static void wpa_obss_scan_freqs_list(struct wpa_supplicant *wpa_s, int start, end; mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, - HOSTAPD_MODE_IEEE80211G, 0); + HOSTAPD_MODE_IEEE80211G, false); if (mode == NULL) { /* No channels supported in this band - use empty list */ params->freqs = os_zalloc(sizeof(int)); @@ -2553,6 +2662,16 @@ static void sme_send_sa_query_req(struct wpa_supplicant *wpa_s, return; } +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->oci_freq_override_saquery_req) { + wpa_printf(MSG_INFO, + "TEST: Override SA Query Request OCI frequency %d -> %d MHz", + ci.frequency, + wpa_s->oci_freq_override_saquery_req); + ci.frequency = wpa_s->oci_freq_override_saquery_req; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (ocv_insert_extended_oci(&ci, req + req_len) < 0) return; @@ -2646,6 +2765,10 @@ void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa, return; if (wpa_s->sme.sa_query_count > 0) return; +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->disable_sa_query) + return; +#endif /* CONFIG_TESTING_OPTIONS */ os_get_reltime(&now); if (wpa_s->sme.last_unprot_disconnect.sec && @@ -2703,6 +2826,16 @@ static void sme_process_sa_query_request(struct wpa_supplicant *wpa_s, return; } +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->oci_freq_override_saquery_resp) { + wpa_printf(MSG_INFO, + "TEST: Override SA Query Response OCI frequency %d -> %d MHz", + ci.frequency, + wpa_s->oci_freq_override_saquery_resp); + ci.frequency = wpa_s->oci_freq_override_saquery_resp; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (ocv_insert_extended_oci(&ci, resp + resp_len) < 0) return; @@ -2782,8 +2915,11 @@ void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa, if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { - wpa_printf(MSG_WARNING, "%s", ocv_errorstr); + ci.seg1_idx) != OCI_SUCCESS) { + wpa_msg(wpa_s, MSG_INFO, OCV_FAILURE "addr=" MACSTR + " frame=saquery%s error=%s", + MAC2STR(sa), data[0] == WLAN_SA_QUERY_REQUEST ? + "req" : "resp", ocv_errorstr); return; } } diff --git a/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in b/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in index 03ac50705..da69a8705 100644 --- a/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in +++ b/wpa_supplicant/systemd/wpa_supplicant-nl80211.service.arg.in @@ -12,4 +12,4 @@ Type=simple ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-nl80211-%I.conf -Dnl80211 -i%I [Install] -Alias=multi-user.target.wants/wpa_supplicant-nl80211@%i.service +WantedBy=multi-user.target diff --git a/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in b/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in index c8a744d6e..ca3054bc6 100644 --- a/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in +++ b/wpa_supplicant/systemd/wpa_supplicant-wired.service.arg.in @@ -12,4 +12,4 @@ Type=simple ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-wired-%I.conf -Dwired -i%I [Install] -Alias=multi-user.target.wants/wpa_supplicant-wired@%i.service +WantedBy=multi-user.target diff --git a/wpa_supplicant/systemd/wpa_supplicant.service.arg.in b/wpa_supplicant/systemd/wpa_supplicant.service.arg.in index 7788b380c..55d2b9c81 100644 --- a/wpa_supplicant/systemd/wpa_supplicant.service.arg.in +++ b/wpa_supplicant/systemd/wpa_supplicant.service.arg.in @@ -12,4 +12,4 @@ Type=simple ExecStart=@BINDIR@/wpa_supplicant -c/etc/wpa_supplicant/wpa_supplicant-%I.conf -i%I [Install] -Alias=multi-user.target.wants/wpa_supplicant@%i.service +WantedBy=multi-user.target diff --git a/wpa_supplicant/wmm_ac.c b/wpa_supplicant/wmm_ac.c index 38800cc77..d0fdd55d3 100644 --- a/wpa_supplicant/wmm_ac.c +++ b/wpa_supplicant/wmm_ac.c @@ -400,7 +400,7 @@ static int wmm_ac_ts_req_is_valid(struct wpa_supplicant *wpa_s, req_ac = up_to_ac[params->user_priority]; - /* Requested accesss category must have acm */ + /* Requested access category must have acm */ if (!wpa_s->wmm_ac_assoc_info->ac_params[req_ac].acm) { wpa_printf(MSG_DEBUG, "WMM AC: AC %d is not ACM", req_ac); return 0; diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c index 270be9e2e..19f1eca8a 100644 --- a/wpa_supplicant/wnm_sta.c +++ b/wpa_supplicant/wnm_sta.c @@ -121,6 +121,15 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s, os_free(wnmtfs_ie); return -1; } +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->oci_freq_override_wnm_sleep) { + wpa_printf(MSG_INFO, + "TEST: Override OCI KDE frequency %d -> %d MHz", + ci.frequency, + wpa_s->oci_freq_override_wnm_sleep); + ci.frequency = wpa_s->oci_freq_override_wnm_sleep; + } +#endif /* CONFIG_TESTING_OPTIONS */ oci_ie_len = OCV_OCI_EXTENDED_LEN; oci_ie = os_zalloc(oci_ie_len); @@ -280,6 +289,15 @@ static void wnm_sleep_mode_exit_success(struct wpa_supplicant *wpa_s, wpa_wnmsleep_install_key(wpa_s->wpa, WNM_SLEEP_SUBELEM_IGTK, ptr); ptr += 10 + WPA_IGTK_LEN; + } else if (*ptr == WNM_SLEEP_SUBELEM_BIGTK) { + if (ptr[1] < 2 + 6 + WPA_BIGTK_LEN) { + wpa_printf(MSG_DEBUG, + "WNM: Too short BIGTK subelem"); + break; + } + wpa_wnmsleep_install_key(wpa_s->wpa, + WNM_SLEEP_SUBELEM_BIGTK, ptr); + ptr += 10 + WPA_BIGTK_LEN; } else break; /* skip the loop */ } @@ -365,8 +383,9 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_supplicant *wpa_s, if (ocv_verify_tx_params(oci_ie, oci_ie_len, &ci, channel_width_to_int(ci.chanwidth), - ci.seg1_idx) != 0) { - wpa_msg(wpa_s, MSG_WARNING, "WNM: %s", ocv_errorstr); + ci.seg1_idx) != OCI_SUCCESS) { + wpa_msg(wpa_s, MSG_WARNING, "WNM: OCV failed: %s", + ocv_errorstr); return; } } diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 6d3f56a87..9f2f903cc 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -502,6 +502,7 @@ static char ** wpa_cli_complete_set(const char *str, int pos) "ignore_auth_resp", #endif /* CONFIG_TESTING_OPTIONS */ "relative_rssi", "relative_band_adjust", + "extended_key_id", }; int i, num_fields = ARRAY_SIZE(fields); @@ -593,7 +594,7 @@ static char ** wpa_cli_complete_get(const char *str, int pos) "tdls_external_control", "osu_dir", "wowlan_triggers", "p2p_search_delay", "mac_addr", "rand_addr_lifetime", "preassoc_mac_addr", "key_mgmt_offload", "passive_scan", - "reassoc_same_bss_optim" + "reassoc_same_bss_optim", "extended_key_id" }; int i, num_fields = ARRAY_SIZE(fields); @@ -1441,6 +1442,7 @@ static const char *network_fields[] = { "dot11MeshHoldingTimeout", #endif /* CONFIG_MESH */ "wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid", + "wpa_deny_ptk0_rekey", "enable_edmg", "edmg_channel", #ifdef CONFIG_P2P "go_p2p_dev_addr", "p2p_client_list", "psk_list", @@ -1458,6 +1460,9 @@ static const char *network_fields[] = { "vht_tx_mcs_nss_3", "vht_tx_mcs_nss_4", "vht_tx_mcs_nss_5", "vht_tx_mcs_nss_6", "vht_tx_mcs_nss_7", "vht_tx_mcs_nss_8", #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + "disable_he", +#endif /* CONFIG_HE_OVERRIDES */ "ap_max_inactivity", "dtim_period", "beacon_int", #ifdef CONFIG_MACSEC "macsec_policy", @@ -1701,15 +1706,25 @@ static char ** wpa_cli_complete_bss(const char *str, int pos) static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc, char *argv[]) { - if (argc < 1 || argc > 2) { - printf("Invalid GET_CAPABILITY command: need either one or " - "two arguments\n"); + if (argc < 1 || argc > 3) { + printf("Invalid GET_CAPABILITY command: need at least one argument and max three arguments\n"); return -1; } - if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) { - printf("Invalid GET_CAPABILITY command: second argument, " - "if any, must be 'strict'\n"); + if (argc > 1 && os_strcmp(argv[0], "key_mgmt") != 0 && + os_strncmp(argv[1], "iftype=", 7) == 0) { + printf("Invalid GET_CAPABILITY command: 'iftype=' param is allowed only for 'key_mgmt'\n"); + return -1; + } + + if (argc == 2 && os_strcmp(argv[1], "strict") != 0 && + os_strncmp(argv[1], "iftype=", 7) != 0) { + printf("Invalid GET_CAPABILITY command: the second argument, if any, must be 'strict' OR 'iftype='\n"); + return -1; + } + + if (argc == 3 && os_strcmp(argv[2], "strict") != 0) { + printf("Invalid GET_CAPABILITY command: the third argument, if any, must be 'strict'\n"); return -1; } @@ -1736,7 +1751,13 @@ static char ** wpa_cli_complete_get_capability(const char *str, int pos) "acs", #endif /* CONFIG_ACS */ }; + const char *iftypes[] = { + "iftype=STATION", "iftype=AP", "iftype=P2P_CLIENT", + "iftype=P2P_GO", "iftype=AP_VLAN", "iftype=IBSS", "iftype=NAN", + "iftype=P2P_DEVICE", "iftype=MESH", + }; int i, num_fields = ARRAY_SIZE(fields); + int num_iftypes = ARRAY_SIZE(iftypes); char **res = NULL; if (arg == 1) { @@ -1750,6 +1771,21 @@ static char ** wpa_cli_complete_get_capability(const char *str, int pos) } } if (arg == 2) { + /* the second argument can be "iftype=" OR + * "strict" */ + res = os_calloc(num_iftypes + 2, sizeof(char *)); + if (!res) + return NULL; + res[0] = os_strdup("strict"); + if (!res[0]) + return res; + for (i = 0; i < num_iftypes; i++) { + res[i + 1] = os_strdup(iftypes[i]); + if (!res[i + 1]) + return res; + } + } + if (arg == 3) { res = os_calloc(1 + 1, sizeof(char *)); if (res == NULL) return NULL; @@ -1782,7 +1818,7 @@ static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) } if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) { - printf("Connected to interface '%s.\n", ctrl_ifname); + printf("Connected to interface '%s'.\n", ctrl_ifname); } else { printf("Could not connect to interface '%s' - re-trying\n", ctrl_ifname); @@ -2958,6 +2994,13 @@ static int wpa_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc, } +static int wpa_cli_cmd_dpp_bootstrap_set(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_BOOTSTRAP_SET", 1, argc, argv); +} + + static int wpa_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -3020,9 +3063,115 @@ static int wpa_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc, return wpa_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv); } + +#ifdef CONFIG_DPP2 + +static int wpa_cli_cmd_dpp_controller_start(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_CONTROLLER_START", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_controller_stop(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DPP_CONTROLLER_STOP"); +} + + +static int wpa_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_cli_cmd(ctrl, "DPP_CHIRP", 1, argc, argv); +} + + +static int wpa_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "DPP_STOP_CHIRP"); +} + +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ +static int wpa_ctrl_command_bss(struct wpa_ctrl *ctrl, const char *cmd) +{ + char buf[512], *pos, *bssid = NULL, *freq = NULL, *level = NULL, + *flags = NULL, *ssid = NULL; + size_t len; + int ret, id = -1; + + if (!ctrl_conn) + return -1; + len = sizeof(buf) - 1; + ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, + wpa_cli_msg_cb); + if (ret == -2) { + printf("'%s' command timed out.\n", cmd); + return -2; + } else if (ret < 0) { + printf("'%s' command failed.\n", cmd); + return -1; + } + + buf[len] = '\0'; + if (os_memcmp(buf, "FAIL", 4) == 0) + return -1; + + pos = buf; + while (*pos != '\0') { + if (str_starts(pos, "id=")) + id = atoi(pos + 3); + if (str_starts(pos, "bssid=")) + bssid = pos + 6; + if (str_starts(pos, "freq=")) + freq = pos + 5; + if (str_starts(pos, "level=")) + level = pos + 6; + if (str_starts(pos, "flags=")) + flags = pos + 6; + if (str_starts(pos, "ssid=")) + ssid = pos + 5; + + while (*pos != '\0' && *pos != '\n') + pos++; + *pos++ = '\0'; + } + if (id != -1) + printf("%s\t%s\t%s\t%s\t%s\n", bssid ? bssid : "N/A", + freq ? freq : "N/A", level ? level : "N/A", + flags ? flags : "N/A", ssid ? ssid : "N/A"); + return id; +} + + +static int wpa_cli_cmd_all_bss(struct wpa_ctrl *ctrl, int argc, char *argv[]) +{ + char cmd[64]; + int id = -1; + unsigned int mask; + + printf("bssid / frequency / signal level / flags / ssid\n"); + + mask = WPA_BSS_MASK_ID | WPA_BSS_MASK_BSSID | WPA_BSS_MASK_FREQ | + WPA_BSS_MASK_LEVEL | WPA_BSS_MASK_FLAGS | WPA_BSS_MASK_SSID; + do { + if (id < 0) + os_snprintf(cmd, sizeof(cmd), "BSS FIRST MASK=0x%x", + mask); + else + os_snprintf(cmd, sizeof(cmd), "BSS NEXT-%d MASK=0x%x", + id, mask); + id = wpa_ctrl_command_bss(ctrl, cmd); + } while (id >= 0); + + return 0; +} + + enum wpa_cli_cmd_flags { cli_cmd_flag_none = 0x00, cli_cmd_flag_sensitive = 0x01 @@ -3656,6 +3805,9 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "dpp_bootstrap_info", wpa_cli_cmd_dpp_bootstrap_info, NULL, cli_cmd_flag_none, " = show DPP bootstrap information" }, + { "dpp_bootstrap_set", wpa_cli_cmd_dpp_bootstrap_set, NULL, + cli_cmd_flag_none, + " [conf=..] [ssid=] [ssid_charset=#] [psk=] [pass=] [configurator=] [conn_status=#] [akm_use_selector=<0|1>] [group_id=..] [expiry=#] [csrattrs=..] = set DPP configurator parameters" }, { "dpp_auth_init", wpa_cli_cmd_dpp_auth_init, NULL, cli_cmd_flag_none, "peer= [own=] = initiate DPP bootstrapping" }, { "dpp_listen", wpa_cli_cmd_dpp_listen, NULL, cli_cmd_flag_none, @@ -3681,7 +3833,23 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = { { "dpp_pkex_remove", wpa_cli_cmd_dpp_pkex_remove, NULL, cli_cmd_flag_none, "*| = remove DPP pkex information" }, +#ifdef CONFIG_DPP2 + { "dpp_controller_start", wpa_cli_cmd_dpp_controller_start, NULL, + cli_cmd_flag_none, + "[tcp_port=] [role=..] = start DPP controller" }, + { "dpp_controller_stop", wpa_cli_cmd_dpp_controller_stop, NULL, + cli_cmd_flag_none, + "= stop DPP controller" }, + { "dpp_chirp", wpa_cli_cmd_dpp_chirp, NULL, + cli_cmd_flag_none, + "own= iter= = start DPP chirp" }, + { "dpp_stop_chirp", wpa_cli_cmd_dpp_stop_chirp, NULL, + cli_cmd_flag_none, + "= stop DPP chirp" }, +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ + { "all_bss", wpa_cli_cmd_all_bss, NULL, cli_cmd_flag_none, + "= list all BSS entries (scan results)" }, { NULL, NULL, NULL, cli_cmd_flag_none, NULL } }; diff --git a/wpa_supplicant/wpa_gui-qt4/icons/.gitignore b/wpa_supplicant/wpa_gui-qt4/icons/.gitignore new file mode 100644 index 000000000..8d772cc93 --- /dev/null +++ b/wpa_supplicant/wpa_gui-qt4/icons/.gitignore @@ -0,0 +1,2 @@ +hicolor +pixmaps diff --git a/wpa_supplicant/wpa_gui-qt4/icons/Makefile b/wpa_supplicant/wpa_gui-qt4/icons/Makefile index 709514c12..88efc3c5b 100644 --- a/wpa_supplicant/wpa_gui-qt4/icons/Makefile +++ b/wpa_supplicant/wpa_gui-qt4/icons/Makefile @@ -5,14 +5,28 @@ SIZES := 16x16 22x22 32x32 48x48 64x64 128x128 ICONS := $(addsuffix .png, $(foreach name, $(NAMES), $(foreach size, $(SIZES), $(size)/$(name)))) ICONS += $(addsuffix .xpm, $(NAMES)) +ifeq (1, $(shell which inkscape; echo $$?)) +$(error "No inkscape in PATH, it is required for exporting icons.") +else +ifeq (0, $(shell inkscape --without-gui 2>&1 > /dev/null; echo $$?)) +# Inkscape < 1.0 +INKSCAPE_GUI_FLAG := --without-gui +INKSCAPE_OUTPUT_FLAG := --export-png +else +# Inkscape >= 1.0 +INKSCAPE_GUI_FLAG := +INKSCAPE_OUTPUT_FLAG := --export-filename +endif +endif + all: $(ICONS) %.png: mkdir -p hicolor/$(word 1, $(subst /, ,$(@)))/apps/ - inkscape $(subst .png,.svg, $(word 2, $(subst /, , $(@)))) --without-gui \ + inkscape $(subst .png,.svg, $(word 2, $(subst /, , $(@)))) $(INKSCAPE_GUI_FLAG) \ --export-width=$(word 1, $(subst x, , $(@))) \ --export-height=$(word 2, $(subst x, , $(subst /, , $(@)))) \ - --export-png=hicolor/$(word 1, $(subst /, ,$(@)))/apps/$(word 2, $(subst /, , $@)) + $(INKSCAPE_OUTPUT_FLAG)=hicolor/$(word 1, $(subst /, ,$(@)))/apps/$(word 2, $(subst /, , $@)) %.xpm: mkdir -p pixmaps/ diff --git a/wpa_supplicant/wpa_priv.c b/wpa_supplicant/wpa_priv.c index f42840610..c5d716869 100644 --- a/wpa_supplicant/wpa_priv.c +++ b/wpa_supplicant/wpa_priv.c @@ -413,6 +413,7 @@ static void wpa_priv_cmd_set_key(struct wpa_priv_interface *iface, p.seq_len = params->seq_len; p.key = params->key_len ? params->key : NULL; p.key_len = params->key_len; + p.key_flag = params->key_flag; res = iface->driver->set_key(iface->drv_priv, &p); wpa_printf(MSG_DEBUG, "drv->set_key: res=%d", res); @@ -1189,14 +1190,15 @@ static void wpa_priv_fd_workaround(void) static void usage(void) { - printf("wpa_priv v" VERSION_STR "\n" + printf("wpa_priv v%s\n" "Copyright (c) 2007-2017, Jouni Malinen and " "contributors\n" "\n" "usage:\n" " wpa_priv [-Bdd] [-c] [-P] " " \\\n" - " [driver:ifname ...]\n"); + " [driver:ifname ...]\n", + VERSION_STR); } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 24a7a28e2..fc0574e03 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -130,6 +130,7 @@ static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s); #endif /* CONFIG_OWE */ +#ifdef CONFIG_WEP /* Configure default/group WEP keys for static WEP */ int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { @@ -150,6 +151,7 @@ int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) return set; } +#endif /* CONFIG_WEP */ int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s, @@ -317,14 +319,14 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) * per-BSSID EAPOL authentication. */ eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized); - eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); - eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); + eapol_sm_notify_eap_success(wpa_s->eapol, true); + eapol_sm_notify_eap_fail(wpa_s->eapol, false); return; } #endif /* CONFIG_IBSS_RSN */ - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); - eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); + eapol_sm_notify_eap_success(wpa_s->eapol, false); + eapol_sm_notify_eap_fail(wpa_s->eapol, false); if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) @@ -396,7 +398,9 @@ void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { +#ifdef CONFIG_WEP int i; +#endif /* CONFIG_WEP */ if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) wpa_s->key_mgmt = WPA_KEY_MGMT_WPS; @@ -414,6 +418,7 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, wpa_s->group_cipher = WPA_CIPHER_NONE; wpa_s->mgmt_group_cipher = 0; +#ifdef CONFIG_WEP for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i] > 5) { wpa_s->pairwise_cipher = WPA_CIPHER_WEP104; @@ -425,6 +430,7 @@ void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, break; } } +#endif /* CONFIG_WEP */ wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0); wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt); @@ -530,6 +536,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) wpa_s->last_assoc_req_wpa_ie = NULL; os_free(wpa_s->extra_sae_rejected_groups); wpa_s->extra_sae_rejected_groups = NULL; + wpabuf_free(wpa_s->rsne_override_eapol); + wpa_s->rsne_override_eapol = NULL; wpabuf_free(wpa_s->rsnxe_override_assoc); wpa_s->rsnxe_override_assoc = NULL; wpabuf_free(wpa_s->rsnxe_override_eapol); @@ -740,10 +748,15 @@ void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr) wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0, NULL, 0, KEY_FLAG_GROUP); } - if (!(wpa_s->keys_cleared & BIT(0)) && addr && + /* Pairwise Key ID 1 for Extended Key ID is tracked in bit 15 */ + if (~wpa_s->keys_cleared & (BIT(0) | BIT(15)) && addr && !is_zero_ether_addr(addr)) { - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL, - 0, KEY_FLAG_PAIRWISE); + if (!(wpa_s->keys_cleared & BIT(0))) + wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, + 0, NULL, 0, KEY_FLAG_PAIRWISE); + if (!(wpa_s->keys_cleared & BIT(15))) + wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL, + 0, NULL, 0, KEY_FLAG_PAIRWISE); /* MLME-SETPROTECTION.request(None) */ wpa_drv_mlme_setprotection( wpa_s, addr, @@ -790,7 +803,22 @@ const char * wpa_supplicant_state_txt(enum wpa_states state) #ifdef CONFIG_BGSCAN -static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s) +static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->bgscan_ssid) { + bgscan_deinit(wpa_s); + wpa_s->bgscan_ssid = NULL; + } +} + + +/** + * wpa_supplicant_reset_bgscan - Reset the bgscan for the current SSID. + * @wpa_s: Pointer to the wpa_supplicant data + * + * Stop, start, or reconfigure the scan parameters depending on the method. + */ +void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s) { const char *name; @@ -798,12 +826,12 @@ static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s) name = wpa_s->current_ssid->bgscan; else name = wpa_s->conf->bgscan; - if (name == NULL || name[0] == '\0') + if (!name || name[0] == '\0') { + wpa_supplicant_stop_bgscan(wpa_s); return; + } if (wpas_driver_bss_selection(wpa_s)) return; - if (wpa_s->current_ssid == wpa_s->bgscan_ssid) - return; #ifdef CONFIG_P2P if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) return; @@ -833,15 +861,6 @@ static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s) wpa_s->bgscan_ssid = NULL; } - -static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s) -{ - if (wpa_s->bgscan_ssid != NULL) { - bgscan_deinit(wpa_s); - wpa_s->bgscan_ssid = NULL; - } -} - #endif /* CONFIG_BGSCAN */ @@ -881,7 +900,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, { enum wpa_states old_state = wpa_s->wpa_state; #if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL) - Boolean update_fils_connect_params = FALSE; + bool update_fils_connect_params = false; #endif /* CONFIG_FILS && IEEE8021X_EAPOL */ wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s", @@ -965,8 +984,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, fils_hlp_sent ? " FILS_HLP_SENT" : ""); #endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ wpas_clear_temp_disabled(wpa_s, ssid, 1); - wpa_blacklist_clear(wpa_s); - wpa_s->extra_blacklist_count = 0; + wpa_s->consecutive_conn_failures = 0; wpa_s->new_connection = 0; wpa_drv_set_operstate(wpa_s, 1); #ifndef IEEE8021X_EAPOL @@ -980,7 +998,7 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, #if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL) if (!fils_hlp_sent && ssid && ssid->eap.erp) - update_fils_connect_params = TRUE; + update_fils_connect_params = true; #endif /* CONFIG_FILS && IEEE8021X_EAPOL */ #ifdef CONFIG_OWE if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE)) @@ -998,8 +1016,8 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, wpa_s->wpa_state = state; #ifdef CONFIG_BGSCAN - if (state == WPA_COMPLETED) - wpa_supplicant_start_bgscan(wpa_s); + if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid) + wpa_supplicant_reset_bgscan(wpa_s); else if (state < WPA_ASSOCIATED) wpa_supplicant_stop_bgscan(wpa_s); #endif /* CONFIG_BGSCAN */ @@ -1147,7 +1165,7 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) * Clear forced success to clear EAP state for next * authentication. */ - eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); + eapol_sm_notify_eap_success(wpa_s->eapol, false); } eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); wpa_sm_set_config(wpa_s->wpa, NULL); @@ -1171,6 +1189,7 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); } + wpa_blacklist_clear(wpa_s); wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed"); return 0; } @@ -1451,9 +1470,6 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, #endif /* CONFIG_NO_WPA */ sel = ie.key_mgmt & ssid->key_mgmt; - wpa_dbg(wpa_s, MSG_DEBUG, - "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x", - ie.key_mgmt, ssid->key_mgmt, sel); #ifdef CONFIG_SAE if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE); @@ -1463,6 +1479,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, WPA_DRIVER_FLAGS_UPDATE_FT_IES))) sel &= ~WPA_KEY_MGMT_FT; #endif /* CONFIG_IEEE80211R */ + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: AP key_mgmt 0x%x network profile key_mgmt 0x%x; available key_mgmt 0x%x", + ie.key_mgmt, ssid->key_mgmt, sel); if (0) { #ifdef CONFIG_IEEE80211R #ifdef CONFIG_SHA384 @@ -1626,6 +1645,51 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, if (ssid->sae_password_id && sae_pwe != 3) sae_pwe = 1; wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PWE, sae_pwe); +#ifdef CONFIG_SAE_PK + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SAE_PK, + wpa_key_mgmt_sae(ssid->key_mgmt) && + ssid->sae_pk != SAE_PK_MODE_DISABLED && + ((ssid->sae_password && + sae_pk_valid_password(ssid->sae_password)) || + (!ssid->sae_password && ssid->passphrase && + sae_pk_valid_password(ssid->passphrase)))); +#endif /* CONFIG_SAE_PK */ +#ifdef CONFIG_TESTING_OPTIONS + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_FT_RSNXE_USED, + wpa_s->ft_rsnxe_used); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL, + wpa_s->oci_freq_override_eapol); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_EAPOL_G2, + wpa_s->oci_freq_override_eapol_g2); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FT_ASSOC, + wpa_s->oci_freq_override_ft_assoc); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_OCI_FREQ_FILS_ASSOC, + wpa_s->oci_freq_override_fils_assoc); +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Extended Key ID is only supported in infrastructure BSS so far */ + if (ssid->mode == WPAS_MODE_INFRA && wpa_s->conf->extended_key_id && + (ssid->proto & WPA_PROTO_RSN) && + ssid->pairwise_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_CCMP_256 | + WPA_CIPHER_GCMP | WPA_CIPHER_GCMP_256) && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) { + int use_ext_key_id = 0; + + wpa_msg(wpa_s, MSG_DEBUG, + "WPA: Enable Extended Key ID support"); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, + wpa_s->conf->extended_key_id); + if (bss_rsn && + wpa_s->conf->extended_key_id && + wpa_s->pairwise_cipher != WPA_CIPHER_TKIP && + (ie.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST)) + use_ext_key_id = 1; + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, + use_ext_key_id); + } else { + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXT_KEY_ID, 0); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_USE_EXT_KEY_ID, 0); + } if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE"); @@ -1644,6 +1708,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, } else if (wpa_s->key_mgmt == WPA_KEY_MGMT_DPP) { /* Use PMK from DPP network introduction (PMKSA entry) */ wpa_sm_set_pmk_from_pmksa(wpa_s->wpa); +#ifdef CONFIG_DPP2 + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DPP_PFS, ssid->dpp_pfs); +#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP */ } else if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) { int psk_set = 0; @@ -1760,6 +1827,20 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, } else wpa_sm_set_pmk_from_pmksa(wpa_s->wpa); + if (ssid->mode != WPAS_MODE_IBSS && + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) && + (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER || + (ssid->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK && + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) { + wpa_msg(wpa_s, MSG_INFO, + "Disable PTK0 rekey support - replaced with reconnect"); + wpa_s->deny_ptk0_rekey = 1; + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 1); + } else { + wpa_s->deny_ptk0_rekey = 0; + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_DENY_PTK0_REKEY, 0); + } + return 0; } @@ -1824,6 +1905,9 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx) *pos |= 0x01; #endif /* CONFIG_FILS */ break; + case 10: /* Bits 80-87 */ + *pos |= 0x20; /* Bit 85 - Mirrored SCS */ + break; } } @@ -1831,7 +1915,7 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx) int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen) { u8 *pos = buf; - u8 len = 10, i; + u8 len = 11, i; if (len < wpa_s->extended_capa_len) len = wpa_s->extended_capa_len; @@ -2001,7 +2085,9 @@ static void wpa_s_setup_sae_pt(struct wpa_config *conf, struct wpa_ssid *ssid) if (!password) password = ssid->passphrase; - if ((conf->sae_pwe == 0 && !ssid->sae_password_id) || !password || + if (!password || + (conf->sae_pwe == 0 && !ssid->sae_password_id && + !sae_pk_valid_password(password)) || conf->sae_pwe == 3) { /* PT derivation not needed */ sae_deinit_pt(ssid->pt); @@ -2057,6 +2143,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, int rand_style; wpa_s->own_disconnect_req = 0; + wpa_s->own_reconnect_req = 0; /* * If we are starting a new connection, any previously pending EAPOL @@ -2070,6 +2157,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, else rand_style = ssid->mac_addr; + wpa_s->multi_ap_ie = 0; wmm_ac_clear_saved_tspecs(wpa_s); wpa_s->reassoc_same_bss = 0; wpa_s->reassoc_same_ess = 0; @@ -2161,10 +2249,6 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, return; } wpa_s->current_bss = bss; - wpa_msg(wpa_s, MSG_INFO, MESH_GROUP_STARTED "ssid=\"%s\" id=%d", - wpa_ssid_txt(ssid->ssid, ssid->ssid_len), - ssid->id); - wpas_notify_mesh_group_started(wpa_s, ssid); #else /* CONFIG_MESH */ wpa_msg(wpa_s, MSG_ERROR, "mesh mode support not included in the build"); @@ -2188,8 +2272,7 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, #ifdef CONFIG_TDLS if (bss) - wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1), - bss->ie_len); + wpa_tdls_ap_ies(wpa_s->wpa, wpa_bss_ie_ptr(bss), bss->ie_len); #endif /* CONFIG_TDLS */ #ifdef CONFIG_MBO @@ -2353,6 +2436,10 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, /* Allow HE on 2.4 GHz without VHT: see nl80211_put_freq_params() */ if (is_24ghz) freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported; +#ifdef CONFIG_HE_OVERRIDES + if (is_24ghz && ssid->disable_he) + freq->he_enabled = 0; +#endif /* CONFIG_HE_OVERRIDES */ /* Setup higher BW only for 5 GHz */ if (mode->mode != HOSTAPD_MODE_IEEE80211A) @@ -2375,8 +2462,10 @@ void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, #ifdef CONFIG_HT_OVERRIDES if (ssid->disable_ht40) { +#ifdef CONFIG_VHT_OVERRIDES if (ssid->disable_vht) return; +#endif /* CONFIG_VHT_OVERRIDES */ goto skip_ht40; } #endif /* CONFIG_HT_OVERRIDES */ @@ -2473,8 +2562,8 @@ skip_ht40: if (!vht_freq.vht_enabled) return; - /* Enable HE for VHT */ - vht_freq.he_enabled = mode->he_capab[ieee80211_mode].he_supported; + /* Enable HE with VHT for 5 GHz */ + freq->he_enabled = mode->he_capab[ieee80211_mode].he_supported; /* setup center_freq1, bandwidth */ for (j = 0; j < ARRAY_SIZE(vht80); j++) { @@ -2549,6 +2638,12 @@ skip_ht40: #endif /* CONFIG_HT_OVERRIDES */ } +#ifdef CONFIG_HE_OVERRIDES + if (ssid->disable_he) { + vht_freq.he_enabled = 0; + freq->he_enabled = 0; + } +#endif /* CONFIG_HE_OVERRIDES */ if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq, freq->channel, ssid->enable_edmg, ssid->edmg_channel, freq->ht_enabled, @@ -2669,9 +2764,9 @@ static u8 * wpas_populate_assoc_ies( #ifdef CONFIG_MBO const u8 *mbo_ie; #endif -#ifdef CONFIG_SAE - int sae_pmksa_cached = 0; -#endif /* CONFIG_SAE */ +#if defined(CONFIG_SAE) || defined(CONFIG_FILS) + int pmksa_cached = 0; +#endif /* CONFIG_SAE || CONFIG_FILS */ #ifdef CONFIG_FILS const u8 *realm, *username, *rrk; size_t realm_len, username_len, rrk_len; @@ -2711,9 +2806,9 @@ static u8 * wpas_populate_assoc_ies( ssid, try_opportunistic, cache_id, 0) == 0) { eapol_sm_notify_pmkid_attempt(wpa_s->eapol); -#ifdef CONFIG_SAE - sae_pmksa_cached = 1; -#endif /* CONFIG_SAE */ +#if defined(CONFIG_SAE) || defined(CONFIG_FILS) + pmksa_cached = 1; +#endif /* CONFIG_SAE || CONFIG_FILS */ } wpa_ie_len = max_wpa_ie_len; if (wpa_supplicant_set_suites(wpa_s, bss, ssid, @@ -2812,6 +2907,10 @@ static u8 * wpas_populate_assoc_ies( if (mask) *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO; + } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_FILS_SK_OFFLOAD) && + ssid->eap.erp && wpa_key_mgmt_fils(wpa_s->key_mgmt) && + pmksa_cached) { + algs = WPA_AUTH_ALG_FILS; } #endif /* CONFIG_FILS */ #endif /* IEEE8021X_EAPOL */ @@ -2828,7 +2927,7 @@ static u8 * wpas_populate_assoc_ies( } #ifdef CONFIG_SAE - if (sae_pmksa_cached && algs == WPA_AUTH_ALG_SAE) { + if (pmksa_cached && algs == WPA_AUTH_ALG_SAE) { wpa_dbg(wpa_s, MSG_DEBUG, "SAE: Use WPA_AUTH_ALG_OPEN for PMKSA caching attempt"); algs = WPA_AUTH_ALG_OPEN; @@ -2867,7 +2966,7 @@ static u8 * wpas_populate_assoc_ies( #endif /* CONFIG_P2P */ if (bss) { - wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss->freq, + wpa_ie_len += wpas_supp_op_class_ie(wpa_s, ssid, bss, wpa_ie + wpa_ie_len, max_wpa_ie_len - wpa_ie_len); @@ -3015,8 +3114,16 @@ static u8 * wpas_populate_assoc_ies( #endif /* CONFIG_OWE */ #ifdef CONFIG_DPP2 - if (wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP && - ssid->dpp_netaccesskey) { + if (DPP_VERSION > 1 && + wpa_sm_get_key_mgmt(wpa_s->wpa) == WPA_KEY_MGMT_DPP && + ssid->dpp_netaccesskey && + ssid->dpp_pfs != 2 && !ssid->dpp_pfs_fallback) { + struct rsn_pmksa_cache_entry *pmksa; + + pmksa = pmksa_cache_get_current(wpa_s->wpa); + if (!pmksa || !pmksa->dpp_pfs) + goto pfs_fail; + dpp_pfs_free(wpa_s->dpp_pfs); wpa_s->dpp_pfs = dpp_pfs_init(ssid->dpp_netaccesskey, ssid->dpp_netaccesskey_len); @@ -3086,6 +3193,39 @@ pfs_fail: wpa_ie_len += wpa_s->rsnxe_len; } + if (bss && wpa_s->robust_av.valid_config) { + struct wpabuf *mscs_ie; + size_t mscs_ie_len, buf_len; + + if (!wpa_bss_ext_capab(bss, WLAN_EXT_CAPAB_MSCS)) + goto mscs_fail; + + buf_len = 3 + /* MSCS descriptor IE header */ + 1 + /* Request type */ + 2 + /* User priority control */ + 4 + /* Stream timeout */ + 3 + /* TCLAS Mask IE header */ + wpa_s->robust_av.frame_classifier_len; + mscs_ie = wpabuf_alloc(buf_len); + if (!mscs_ie) { + wpa_printf(MSG_INFO, + "MSCS: Failed to allocate MSCS IE"); + goto mscs_fail; + } + + wpas_populate_mscs_descriptor_ie(&wpa_s->robust_av, mscs_ie); + if ((wpa_ie_len + wpabuf_len(mscs_ie)) <= max_wpa_ie_len) { + wpa_hexdump_buf(MSG_MSGDUMP, "MSCS IE", mscs_ie); + mscs_ie_len = wpabuf_len(mscs_ie); + os_memcpy(wpa_ie + wpa_ie_len, wpabuf_head(mscs_ie), + mscs_ie_len); + wpa_ie_len += mscs_ie_len; + } + + wpabuf_free(mscs_ie); + } +mscs_fail: + if (ssid->multi_ap_backhaul_sta) { size_t multi_ap_ie_len; @@ -3255,7 +3395,7 @@ get_supported_edmg(struct wpa_supplicant *wpa_s, if (hw_mode == NUM_HOSTAPD_MODES) goto fail; - mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, 0); + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, hw_mode, false); if (!mode) goto fail; @@ -3304,10 +3444,12 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) struct wpa_supplicant *wpa_s = work->wpa_s; u8 *wpa_ie; const u8 *edmg_ie_oper; - int use_crypt, ret, i, bssid_changed; + int use_crypt, ret, bssid_changed; unsigned int cipher_pairwise, cipher_group, cipher_group_mgmt; struct wpa_driver_associate_params params; +#if defined(CONFIG_WEP) || defined(IEEE8021X_EAPOL) int wep_keys_set = 0; +#endif /* CONFIG_WEP || IEEE8021X_EAPOL */ int assoc_failed = 0; struct wpa_ssid *old_ssid; u8 prev_bssid[ETH_ALEN]; @@ -3398,6 +3540,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); wpa_sm_set_assoc_rsnxe(wpa_s->wpa, NULL, 0); wpa_s->rsnxe_len = 0; + wpa_s->mscs_setup_done = false; wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, ¶ms, NULL); if (!wpa_ie) { @@ -3414,10 +3557,12 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) use_crypt = 0; +#ifdef CONFIG_WEP if (wpa_set_wep_keys(wpa_s, ssid)) { use_crypt = 1; wep_keys_set = 1; } +#endif /* CONFIG_WEP */ } if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) use_crypt = 0; @@ -3490,8 +3635,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) } if (bss && ssid->enable_edmg) - edmg_ie_oper = get_ie_ext((const u8 *) (bss + 1), bss->ie_len, - WLAN_EID_EXT_EDMG_OPERATION); + edmg_ie_oper = wpa_bss_get_ie_ext(bss, + WLAN_EID_EXT_EDMG_OPERATION); else edmg_ie_oper = NULL; @@ -3562,12 +3707,18 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpa_s->auth_alg = params.auth_alg; params.mode = ssid->mode; params.bg_scan_period = ssid->bg_scan_period; - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (ssid->wep_key_len[i]) - params.wep_key[i] = ssid->wep_key[i]; - params.wep_key_len[i] = ssid->wep_key_len[i]; +#ifdef CONFIG_WEP + { + int i; + + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (ssid->wep_key_len[i]) + params.wep_key[i] = ssid->wep_key[i]; + params.wep_key_len[i] = ssid->wep_key_len[i]; + } + params.wep_tx_keyidx = ssid->wep_tx_keyidx; } - params.wep_tx_keyidx = ssid->wep_tx_keyidx; +#endif /* CONFIG_WEP */ if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE_PSK) && (params.key_mgmt_suite == WPA_KEY_MGMT_PSK || @@ -3644,6 +3795,9 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) params.vhtcaps_mask = &vhtcaps_mask; wpa_supplicant_apply_vht_overrides(wpa_s, ssid, ¶ms); #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES + wpa_supplicant_apply_he_overrides(wpa_s, ssid, ¶ms); +#endif /* CONFIG_HE_OVERRIDES */ #ifdef CONFIG_P2P /* @@ -3672,6 +3826,10 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpa_s->current_ssid) params.prev_bssid = prev_bssid; +#ifdef CONFIG_SAE + params.sae_pwe = wpa_s->conf->sae_pwe; +#endif /* CONFIG_SAE */ + ret = wpa_drv_associate(wpa_s, ¶ms); os_free(wpa_ie); if (ret < 0) { @@ -3725,11 +3883,13 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0); } +#ifdef CONFIG_WEP if (wep_keys_set && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) { /* Set static WEP keys again */ wpa_set_wep_keys(wpa_s, ssid); } +#endif /* CONFIG_WEP */ if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) { /* @@ -3826,7 +3986,7 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, wpa_s->ifname); wpas_notify_mesh_group_removed(wpa_s, mconf->meshid, mconf->meshid_len, reason_code); - wpa_supplicant_leave_mesh(wpa_s); + wpa_supplicant_leave_mesh(wpa_s, true); } #endif /* CONFIG_MESH */ @@ -3843,6 +4003,15 @@ void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, wpa_supplicant_clear_connection(wpa_s, addr); } + +void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s) +{ + wpa_s->own_reconnect_req = 1; + wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED); + +} + + static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { @@ -3952,6 +4121,52 @@ int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id) } +/** + * wpa_supplicant_remove_all_networks - Remove all configured networks + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: 0 on success (errors are currently ignored) + * + * This function performs the following operations: + * 1. Remove all networks. + * 2. Send network removal notifications. + * 3. Update internal state machines. + * 4. Stop any running sched scans. + */ +int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s) +{ + struct wpa_ssid *ssid; + + if (wpa_s->sched_scanning) + wpa_supplicant_cancel_sched_scan(wpa_s); + + eapol_sm_invalidate_cached_session(wpa_s->eapol); + if (wpa_s->current_ssid) { +#ifdef CONFIG_SME + wpa_s->sme.prev_bssid_set = 0; +#endif /* CONFIG_SME */ + wpa_sm_set_config(wpa_s->wpa, NULL); + eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); + if (wpa_s->wpa_state >= WPA_AUTHENTICATING) + wpa_s->own_disconnect_req = 1; + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + } + ssid = wpa_s->conf->ssid; + while (ssid) { + struct wpa_ssid *remove_ssid = ssid; + int id; + + id = ssid->id; + ssid = ssid->next; + if (wpa_s->last_ssid == remove_ssid) + wpa_s->last_ssid = NULL; + wpas_notify_network_removed(wpa_s, remove_ssid); + wpa_config_remove_network(wpa_s->conf, id); + } + return 0; +} + + /** * wpa_supplicant_enable_network - Mark a configured network as enabled * @wpa_s: wpa_supplicant structure for a network interface @@ -4657,16 +4872,23 @@ void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len); else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { /* - * Set portValid = TRUE here since we are going to skip 4-way + * Set portValid = true here since we are going to skip 4-way * handshake processing which would normally set portValid. We * need this to allow the EAPOL state machines to be completed * without going through EAPOL-Key handshake. */ - eapol_sm_notify_portValid(wpa_s->eapol, TRUE); + eapol_sm_notify_portValid(wpa_s->eapol, true); } } +static int wpas_eapol_needs_l2_packet(struct wpa_supplicant *wpa_s) +{ + return !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) || + !(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX); +} + + int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s) { if ((!wpa_s->p2p_mgmt || @@ -4676,7 +4898,9 @@ int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s) wpa_s->l2 = l2_packet_init(wpa_s->ifname, wpa_drv_get_mac_addr(wpa_s), ETH_P_EAPOL, - wpa_supplicant_rx_eapol, wpa_s, 0); + wpas_eapol_needs_l2_packet(wpa_s) ? + wpa_supplicant_rx_eapol : NULL, + wpa_s, 0); if (wpa_s->l2 == NULL) return -1; @@ -4684,17 +4908,18 @@ int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s) L2_PACKET_FILTER_PKTTYPE)) wpa_dbg(wpa_s, MSG_DEBUG, "Failed to attach pkt_type filter"); + + if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) { + wpa_msg(wpa_s, MSG_ERROR, + "Failed to get own L2 address"); + return -1; + } } else { const u8 *addr = wpa_drv_get_mac_addr(wpa_s); if (addr) os_memcpy(wpa_s->own_addr, addr, ETH_ALEN); } - if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) { - wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address"); - return -1; - } - wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); wpas_wps_update_mac_addr(wpa_s); @@ -4732,6 +4957,65 @@ static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr, } +int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s, + const char *bridge_ifname) +{ + if (wpa_s->wpa_state > WPA_SCANNING) + return -EBUSY; + + if (bridge_ifname && + os_strlen(bridge_ifname) >= sizeof(wpa_s->bridge_ifname)) + return -EINVAL; + + if (!bridge_ifname) + bridge_ifname = ""; + + if (os_strcmp(wpa_s->bridge_ifname, bridge_ifname) == 0) + return 0; + + if (wpa_s->l2_br) { + l2_packet_deinit(wpa_s->l2_br); + wpa_s->l2_br = NULL; + } + + os_strlcpy(wpa_s->bridge_ifname, bridge_ifname, + sizeof(wpa_s->bridge_ifname)); + + if (wpa_s->bridge_ifname[0]) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Receiving packets from bridge interface '%s'", + wpa_s->bridge_ifname); + wpa_s->l2_br = l2_packet_init_bridge( + wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr, + ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1); + if (!wpa_s->l2_br) { + wpa_msg(wpa_s, MSG_ERROR, + "Failed to open l2_packet connection for the bridge interface '%s'", + wpa_s->bridge_ifname); + goto fail; + } + } + +#ifdef CONFIG_TDLS + if (!wpa_s->p2p_mgmt && wpa_tdls_init(wpa_s->wpa)) + goto fail; +#endif /* CONFIG_TDLS */ + + return 0; +fail: + wpa_s->bridge_ifname[0] = 0; + if (wpa_s->l2_br) { + l2_packet_deinit(wpa_s->l2_br); + wpa_s->l2_br = NULL; + } +#ifdef CONFIG_TDLS + if (!wpa_s->p2p_mgmt) + wpa_tdls_init(wpa_s->wpa); +#endif /* CONFIG_TDLS */ + return -EIO; +} + + /** * wpa_supplicant_driver_init - Initialize driver interface parameters * @wpa_s: Pointer to wpa_supplicant data @@ -4753,7 +5037,7 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s) os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN); wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); - if (wpa_s->bridge_ifname[0]) { + if (wpa_s->bridge_ifname[0] && wpas_eapol_needs_l2_packet(wpa_s)) { wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge " "interface '%s'", wpa_s->bridge_ifname); wpa_s->l2_br = l2_packet_init_bridge( @@ -4827,6 +5111,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent) wpa_s->parent = parent ? parent : wpa_s; wpa_s->p2pdev = wpa_s->parent; wpa_s->sched_scanning = 0; + wpa_s->setband_mask = WPA_SETBAND_AUTO; dl_list_init(&wpa_s->bss_tmp_disallowed); dl_list_init(&wpa_s->fils_hlp_req); @@ -5195,6 +5480,19 @@ void wpa_supplicant_apply_vht_overrides( #endif /* CONFIG_VHT_OVERRIDES */ +#ifdef CONFIG_HE_OVERRIDES +void wpa_supplicant_apply_he_overrides( + struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + struct wpa_driver_associate_params *params) +{ + if (!ssid) + return; + + params->disable_he = ssid->disable_he; +} +#endif /* CONFIG_HE_OVERRIDES */ + + static int pcsc_reader_init(struct wpa_supplicant *wpa_s) { #ifdef PCSC_FUNCS @@ -5358,7 +5656,7 @@ static void wpas_fst_update_mb_ie_cb(void *ctx, const u8 *addr, static const u8 * wpas_fst_get_peer_first(void *ctx, struct fst_get_peer_ctx **get_ctx, - Boolean mb_only) + bool mb_only) { struct wpa_supplicant *wpa_s = ctx; @@ -5372,7 +5670,7 @@ static const u8 * wpas_fst_get_peer_first(void *ctx, static const u8 * wpas_fst_get_peer_next(void *ctx, struct fst_get_peer_ctx **get_ctx, - Boolean mb_only) + bool mb_only) { return NULL; } @@ -5902,6 +6200,8 @@ next_driver: wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname); if (wpa_s->drv_priv == NULL) { const char *pos; + int level = MSG_ERROR; + pos = driver ? os_strchr(driver, ',') : NULL; if (pos) { wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize " @@ -5909,8 +6209,12 @@ next_driver: driver = pos + 1; goto next_driver; } - wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver " - "interface"); + +#ifdef CONFIG_MATCH_IFACE + if (wpa_s->matched == WPA_IFACE_MATCHED_NULL) + level = MSG_DEBUG; +#endif /* CONFIG_MATCH_IFACE */ + wpa_msg(wpa_s, level, "Failed to initialize driver interface"); return -1; } if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) { @@ -6055,6 +6359,9 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, return -1; } os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname)); +#ifdef CONFIG_MATCH_IFACE + wpa_s->matched = iface->matched; +#endif /* CONFIG_MATCH_IFACE */ if (iface->bridge_ifname) { if (os_strlen(iface->bridge_ifname) >= @@ -6068,8 +6375,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, } /* RSNA Supplicant Key Management - INITIALIZE */ - eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); - eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + eapol_sm_notify_portEnabled(wpa_s->eapol, false); + eapol_sm_notify_portValid(wpa_s->eapol, false); /* Initialize driver interface and register driver event handler before * L2 receive handler so that association events are processed before @@ -6136,8 +6443,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, if (capa_res == 0) { wpa_s->drv_capa_known = 1; wpa_s->drv_flags = capa.flags; + wpa_s->drv_flags2 = capa.flags2; wpa_s->drv_enc = capa.enc; - wpa_s->drv_smps_modes = capa.smps_modes; wpa_s->drv_rrm_flags = capa.rrm_flags; wpa_s->probe_resp_offloads = capa.probe_resp_offloads; wpa_s->max_scan_ssids = capa.max_scan_ssids; @@ -6407,7 +6714,7 @@ static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s, #ifdef CONFIG_MESH if (wpa_s->ifmsh) { - wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh); + wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh, true); wpa_s->ifmsh = NULL; } #endif /* CONFIG_MESH */ @@ -6446,6 +6753,10 @@ struct wpa_interface * wpa_supplicant_match_iface(struct wpa_global *global, if (!iface) return NULL; *iface = *miface; + if (!miface->ifname) + iface->matched = WPA_IFACE_MATCHED_NULL; + else + iface->matched = WPA_IFACE_MATCHED; iface->ifname = ifname; return iface; } @@ -6478,10 +6789,8 @@ static int wpa_supplicant_match_existing(struct wpa_global *global) continue; iface = wpa_supplicant_match_iface(global, ifi->if_name); if (iface) { - wpa_s = wpa_supplicant_add_iface(global, iface, NULL); + wpa_supplicant_add_iface(global, iface, NULL); os_free(iface); - if (wpa_s) - wpa_s->matched = 1; } } @@ -6818,7 +7127,7 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params) wpa_debug_timestamp = global->params.wpa_debug_timestamp = params->wpa_debug_timestamp; - wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR); + wpa_printf(MSG_DEBUG, "wpa_supplicant v%s", VERSION_STR); if (eloop_init()) { wpa_printf(MSG_ERROR, "Failed to initialize event loop"); @@ -7009,6 +7318,18 @@ void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s) if (wpa_s->conf->changed_parameters & CFG_CHANGED_DISABLE_BTM) wpa_supplicant_set_default_scan_ies(wpa_s); +#ifdef CONFIG_BGSCAN + /* + * We default to global bgscan parameters only when per-network bgscan + * parameters aren't set. Only bother resetting bgscan parameters if + * this is the case. + */ + if ((wpa_s->conf->changed_parameters & CFG_CHANGED_BGSCAN) && + wpa_s->current_ssid && !wpa_s->current_ssid->bgscan && + wpa_s->wpa_state == WPA_COMPLETED) + wpa_supplicant_reset_bgscan(wpa_s); +#endif /* CONFIG_BGSCAN */ + #ifdef CONFIG_WPS wpas_wps_update_config(wpa_s); #endif /* CONFIG_WPS */ @@ -7049,7 +7370,7 @@ static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s) continue; if (bss->ssid_len == cbss->ssid_len && os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 && - wpa_blacklist_get(wpa_s, bss->bssid) == NULL) { + !wpa_blacklist_is_blacklisted(wpa_s, bss->bssid)) { add_freq(freqs, &num_freqs, bss->freq); if (num_freqs == max_freqs) break; @@ -7082,7 +7403,7 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) * There is no point in blacklisting the AP if this event is * generated based on local request to disconnect. */ - if (wpa_s->own_disconnect_req) { + if (wpa_s->own_disconnect_req || wpa_s->own_reconnect_req) { wpa_s->own_disconnect_req = 0; wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure due to local request to disconnect"); @@ -7098,10 +7419,6 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) /* * Add the failed BSSID into the blacklist and speed up next scan * attempt if there could be other APs that could accept association. - * The current blacklist count indicates how many times we have tried - * connecting to this AP and multiple attempts mean that other APs are - * either not available or has already been tried, so that we can start - * increasing the delay here to avoid constant scanning. */ count = wpa_blacklist_add(wpa_s, bssid); if (count == 1 && wpa_s->current_bss) { @@ -7126,19 +7443,19 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) } } - /* - * Add previous failure count in case the temporary blacklist was - * cleared due to no other BSSes being available. - */ - count += wpa_s->extra_blacklist_count; + wpa_s->consecutive_conn_failures++; - if (count > 3 && wpa_s->current_ssid) { + if (wpa_s->consecutive_conn_failures > 3 && wpa_s->current_ssid) { wpa_printf(MSG_DEBUG, "Continuous association failures - " "consider temporary network disabling"); wpas_auth_failed(wpa_s, "CONN_FAILED"); } - - switch (count) { + /* + * Multiple consecutive connection failures mean that other APs are + * either not available or have already been tried, so we can start + * increasing the delay here to avoid constant scanning. + */ + switch (wpa_s->consecutive_conn_failures) { case 1: timeout = 100; break; @@ -7156,8 +7473,9 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) break; } - wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d " - "ms", count, timeout); + wpa_dbg(wpa_s, MSG_DEBUG, + "Consecutive connection failures: %d --> request scan in %d ms", + wpa_s->consecutive_conn_failures, timeout); /* * TODO: if more than one possible AP is available in scan results, @@ -7307,8 +7625,10 @@ int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s, int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) { +#ifdef CONFIG_WEP int i; unsigned int drv_enc; +#endif /* CONFIG_WEP */ if (wpa_s->p2p_mgmt) return 1; /* no normal network profiles on p2p_mgmt interface */ @@ -7319,6 +7639,7 @@ int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) if (ssid->disabled) return 1; +#ifdef CONFIG_WEP if (wpa_s->drv_capa_known) drv_enc = wpa_s->drv_enc; else @@ -7336,6 +7657,7 @@ int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) continue; return 1; /* invalid WEP key */ } +#endif /* CONFIG_WEP */ if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk && @@ -7517,7 +7839,6 @@ void wpas_request_connection(struct wpa_supplicant *wpa_s) wpa_s->normal_scans = 0; wpa_s->scan_req = NORMAL_SCAN_REQ; wpa_supplicant_reinit_autoscan(wpa_s); - wpa_s->extra_blacklist_count = 0; wpa_s->disconnected = 0; wpa_s->reassociate = 1; wpa_s->last_owe_group = 0; @@ -7734,7 +8055,7 @@ int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame, struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes, u16 num_modes, enum hostapd_hw_mode mode, - int is_6ghz) + bool is_6ghz) { u16 i; @@ -7783,7 +8104,7 @@ static int wpa_set_driver_tmp_disallow_list(struct wpa_supplicant *wpa_s) ETH_ALEN); num_bssid++; } - ret = wpa_drv_set_bssid_blacklist(wpa_s, num_bssid, bssids); + ret = wpa_drv_set_bssid_tmp_disallow(wpa_s, num_bssid, bssids); os_free(bssids); return ret; } diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index d587bd340..46f78755d 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -481,6 +481,11 @@ fast_reauth=1 # 0 = use permanent MAC address # 1 = use random MAC address # 2 = like 1, but maintain OUI (with local admin bit set) +# Note that this setting is ignored when a specific MAC address is needed for +# a full protocol exchange that includes GAS, e.g., when going through a DPP +# exchange that exposes the configured interface address as part of the DP +# Public Action frame exchanges before using GAS. That same address is then used +# during the GAS exchange as well to avoid breaking the protocol expectations. #gas_rand_mac_addr=0 # Lifetime of GAS random MAC address in seconds (default: 60) @@ -521,7 +526,7 @@ fast_reauth=1 #go_venue_group=7 #go_venue_type=1 -# Homogenous ESS identifier +# Homogeneous ESS identifier # If this is set, scans will be used to request response only from BSSes # belonging to the specified Homogeneous ESS. This is used only if interworking # is enabled. @@ -802,6 +807,11 @@ fast_reauth=1 # Set BIT(1) to Enable OCE in STA-CFON mode #oce=1 +# Extended Key ID support for Individually Addressed frames +# 0 = force off: Do not use Extended Key ID (default) +# 1 = auto: Activate Extended Key ID support if the driver supports it +#extended_key_id=0 + # network block # # Each network (usually AP's sharing the same SSID) is configured as a separate @@ -833,6 +843,16 @@ fast_reauth=1 # bssid: BSSID (optional); if set, this network block is used only when # associating with the AP using the configured BSSID # +# ignore_broadcast_ssid: SSID broadcast behavior +# Send empty SSID in beacons and ignore probe request frames that do not +# specify full SSID, i.e., require stations to know SSID. +# default: disabled (0) +# 1 = send empty (length=0) SSID in beacon and ignore probe request for +# broadcast SSID +# 2 = clear SSID (ASCII 0), but keep the original length (this may be required +# with some clients that do not support empty SSID) and ignore probe +# requests for broadcast SSID +# # priority: priority group (integer) # By default, all networks will get same priority group (0). If some of the # networks are more desirable, this field can be used to change the order in @@ -1101,6 +1121,18 @@ fast_reauth=1 # wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to # enforce rekeying of PTK to mitigate some attacks against TKIP deficiencies. # +# wpa_deny_ptk0_rekey: Workaround for PTK rekey issues +# PTK0 rekeys (using only one Key ID value for pairwise keys) can degrade the +# security and stability with some cards. +# To avoid the issues wpa_supplicant can replace those PTK rekeys (including +# EAP reauthentications) with fast reconnects. +# +# Available options: +# 0 = always rekey when configured/instructed (default) +# 1 = only rekey when the local driver is explicitly indicating it can perform +# this operation without issues +# 2 = never allow problematic PTK0 rekeys +# # group_rekey: Group rekeying time in seconds. This value, if non-zero, is used # as the dot11RSNAConfigGroupRekeyTime parameter when operating in # Authenticator role in IBSS, or in AP and mesh modes. @@ -1444,6 +1476,64 @@ fast_reauth=1 # 1-65535 = DH Group to use for FILS PFS #fils_dh_group=0 +# DPP PFS +# 0: allow PFS to be used or not used (default) +# 1: require PFS to be used (note: not compatible with DPP R1) +# 2: do not allow PFS to be used +#dpp_pfs=0 + +# Whether Beacon protection is enabled +# This depends on management frame protection (ieee80211w) being enabled. +#beacon_prot=0 + +# OWE DH Group +# 0: use default (19) first and then try all supported groups one by one if AP +# rejects the selected group +# 1-65535: DH Group to use for OWE +# Groups 19 (NIST P-256), 20 (NIST P-384), and 21 (NIST P-521) are +# currently supported. +#owe_group=0 + +# OWE-only mode (disable transition mode) +# 0: enable transition mode (allow connection to either OWE or open BSS) +# 1 = disable transition mode (allow connection only with OWE) +#owe_only=0 + +# OWE PTK derivation workaround +# Initial OWE implementation used SHA256 when deriving the PTK for all +# OWE groups. This was supposed to change to SHA384 for group 20 and +# SHA512 for group 21. This parameter can be used to enable older +# behavior mainly for testing purposes. There is no impact to group 19 +# behavior, but if enabled, this will make group 20 and 21 cases use +# SHA256-based PTK derivation which will not work with the updated +# OWE implementation on the AP side. +#owe_ptk_workaround=0 + +# Transition Disable indication +# The AP can notify authenticated stations to disable transition mode +# in their network profiles when the network has completed transition +# steps, i.e., once sufficiently large number of APs in the ESS have +# been updated to support the more secure alternative. When this +# indication is used, the stations are expected to automatically +# disable transition mode and less secure security options. This +# includes use of WEP, TKIP (including use of TKIP as the group +# cipher), and connections without PMF. +# Bitmap bits: +# bit 0 (0x01): WPA3-Personal (i.e., disable WPA2-Personal = WPA-PSK +# and only allow SAE to be used) +# bit 1 (0x02): SAE-PK (disable SAE without use of SAE-PK) +# bit 2 (0x04): WPA3-Enterprise (move to requiring PMF) +# bit 3 (0x08): Enhanced Open (disable use of open network; require +# OWE) + +# SAE-PK mode +# 0: automatic SAE/SAE-PK selection based on password; enable +# transition mode (allow SAE authentication without SAE-PK) +# 1: SAE-PK only (disable transition mode; allow SAE authentication +# only with SAE-PK) +# 2: disable SAE-PK (allow SAE authentication only without SAE-PK) +#sae_pk=0 + # MAC address policy # 0 = use permanent MAC address # 1 = use random MAC address for each ESS connection diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index e0119cc97..42f034f6a 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -122,6 +122,18 @@ struct wpa_interface { * interface that is not a network interface. */ int p2p_mgmt; + +#ifdef CONFIG_MATCH_IFACE + /** + * matched - Interface was matched rather than specified + * + */ + enum { + WPA_IFACE_NOT_MATCHED, + WPA_IFACE_MATCHED_NULL, + WPA_IFACE_MATCHED + } matched; +#endif /* CONFIG_MATCH_IFACE */ }; /** @@ -492,6 +504,17 @@ struct driver_signal_override { int scan_level; }; +struct robust_av_data { + u8 dialog_token; + enum scs_request_type request_type; + u8 up_bitmap; + u8 up_limit; + u32 stream_timeout; + u8 frame_classifier[48]; + size_t frame_classifier_len; + bool valid_config; +}; + /** * struct wpa_supplicant - Internal data for wpa_supplicant interface * @@ -555,6 +578,7 @@ struct wpa_supplicant { /* Selected configuration (based on Beacon/ProbeResp WPA IE) */ int pairwise_cipher; + int deny_ptk0_rekey; int group_cipher; int key_mgmt; int wpa_proto; @@ -571,7 +595,7 @@ struct wpa_supplicant { struct wpa_ssid_value *disallow_aps_ssid; size_t disallow_aps_ssid_count; - enum set_band setband; + u32 setband_mask; /* Preferred network for the next connection attempt */ struct wpa_ssid *next_ssid; @@ -607,8 +631,8 @@ struct wpa_supplicant { * results. */ struct wpa_bss **last_scan_res; - unsigned int last_scan_res_used; - unsigned int last_scan_res_size; + size_t last_scan_res_used; + size_t last_scan_res_size; struct os_reltime last_scan; const struct wpa_driver_ops *driver; @@ -643,17 +667,8 @@ struct wpa_supplicant { struct wpa_blacklist *blacklist; - /** - * extra_blacklist_count - Sum of blacklist counts after last connection - * - * This variable is used to maintain a count of temporary blacklisting - * failures (maximum number for any BSS) over blacklist clear - * operations. This is needed for figuring out whether there has been - * failures prior to the last blacklist clear operation which happens - * whenever no other not-blacklisted BSS candidates are available. This - * gets cleared whenever a connection has been established successfully. - */ - int extra_blacklist_count; + /* Number of connection failures since last successful connection */ + unsigned int consecutive_conn_failures; /** * scan_req - Type of the scan request @@ -715,6 +730,7 @@ struct wpa_supplicant { int scan_id[MAX_SCAN_ID]; unsigned int scan_id_count; u8 next_scan_bssid[ETH_ALEN]; + unsigned int next_scan_bssid_wildcard_ssid:1; struct wpa_ssid_value *ssids_from_scan_req; unsigned int num_ssids_from_scan_req; @@ -724,8 +740,8 @@ struct wpa_supplicant { unsigned int no_suitable_network; u64 drv_flags; + u64 drv_flags2; unsigned int drv_enc; - unsigned int drv_smps_modes; unsigned int drv_rrm_flags; /* @@ -1073,6 +1089,7 @@ struct wpa_supplicant { unsigned int wmm_ac_supported:1; unsigned int ext_work_in_progress:1; unsigned int own_disconnect_req:1; + unsigned int own_reconnect_req:1; unsigned int ignore_post_flush_scan_res:1; #define MAC_ADDR_RAND_SCAN BIT(0) @@ -1132,8 +1149,10 @@ struct wpa_supplicant { unsigned int p2p_go_csa_on_inv:1; unsigned int ignore_auth_resp:1; unsigned int ignore_assoc_disallow:1; + unsigned int disable_sa_query:1; unsigned int testing_resend_assoc:1; unsigned int ignore_sae_h2e_only:1; + int ft_rsnxe_used; struct wpabuf *sae_commit_override; enum wpa_alg last_tk_alg; u8 last_tk_addr[ETH_ALEN]; @@ -1142,9 +1161,17 @@ struct wpa_supplicant { size_t last_tk_len; struct wpabuf *last_assoc_req_wpa_ie; int *extra_sae_rejected_groups; + struct wpabuf *rsne_override_eapol; struct wpabuf *rsnxe_override_assoc; struct wpabuf *rsnxe_override_eapol; struct dl_list drv_signal_override; + unsigned int oci_freq_override_eapol; + unsigned int oci_freq_override_saquery_req; + unsigned int oci_freq_override_saquery_resp; + unsigned int oci_freq_override_eapol_g2; + unsigned int oci_freq_override_ft_assoc; + unsigned int oci_freq_override_fils_assoc; + unsigned int oci_freq_override_wnm_sleep; #endif /* CONFIG_TESTING_OPTIONS */ struct wmm_ac_assoc_data *wmm_ac_assoc_info; @@ -1245,6 +1272,7 @@ struct wpa_supplicant { struct wpa_radio_work *dpp_listen_work; unsigned int dpp_pending_listen_freq; unsigned int dpp_listen_freq; + struct os_reltime dpp_listen_end; u8 dpp_allowed_roles; int dpp_qr_mutual; int dpp_netrole; @@ -1269,8 +1297,21 @@ struct wpa_supplicant { unsigned int dpp_resp_retry_time; u8 dpp_last_ssid[SSID_MAX_LEN]; size_t dpp_last_ssid_len; + bool dpp_conf_backup_received; #ifdef CONFIG_DPP2 struct dpp_pfs *dpp_pfs; + int dpp_pfs_fallback; + struct wpabuf *dpp_presence_announcement; + struct dpp_bootstrap_info *dpp_chirp_bi; + int dpp_chirp_freq; + int *dpp_chirp_freqs; + int dpp_chirp_iter; + int dpp_chirp_round; + int dpp_chirp_scan_done; + int dpp_chirp_listen; + struct wpa_ssid *dpp_reconfig_ssid; + int dpp_reconfig_ssid_id; + struct dpp_reconfig_id *dpp_reconfig_id; #endif /* CONFIG_DPP2 */ #ifdef CONFIG_TESTING_OPTIONS char *dpp_config_obj_override; @@ -1287,6 +1328,11 @@ struct wpa_supplicant { unsigned int enabled_4addr_mode:1; unsigned int multi_bss_support:1; unsigned int drv_authorized_port:1; + unsigned int multi_ap_ie:1; + unsigned int multi_ap_backhaul:1; + unsigned int multi_ap_fronthaul:1; + struct robust_av_data robust_av; + bool mscs_setup_done; }; @@ -1297,6 +1343,9 @@ void wpa_supplicant_apply_ht_overrides( void wpa_supplicant_apply_vht_overrides( struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct wpa_driver_associate_params *params); +void wpa_supplicant_apply_he_overrides( + struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + struct wpa_driver_associate_params *params); int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s, @@ -1307,6 +1356,8 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s); const char * wpa_supplicant_state_txt(enum wpa_states state); int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s); int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s); +int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s, + const char *bridge_ifname); int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid, u8 *wpa_ie, size_t *wpa_ie_len); @@ -1328,9 +1379,11 @@ const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s); void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s); void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, u16 reason_code); +void wpa_supplicant_reconnect(struct wpa_supplicant *wpa_s); struct wpa_ssid * wpa_supplicant_add_network(struct wpa_supplicant *wpa_s); int wpa_supplicant_remove_network(struct wpa_supplicant *wpa_s, int id); +int wpa_supplicant_remove_all_networks(struct wpa_supplicant *wpa_s); void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s, @@ -1393,6 +1446,8 @@ int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style); int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s); void add_freq(int *freqs, int *num_freqs, int freq); +int wpas_get_op_chan_phy(int freq, const u8 *ies, size_t ies_len, + u8 *op_class, u8 *chan, u8 *phy_type); void wpas_rrm_reset(struct wpa_supplicant *wpa_s); void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s, const u8 *report, size_t report_len); @@ -1416,6 +1471,7 @@ int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s, void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s); void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s); void wpas_clear_disabled_interface(void *eloop_ctx, void *timeout_ctx); +void wpa_supplicant_reset_bgscan(struct wpa_supplicant *wpa_s); /* MBO functions */ @@ -1452,7 +1508,7 @@ enum chan_allowed verify_channel(struct hostapd_hw_modes *mode, u8 op_class, u8 channel, u8 bw); size_t wpas_supp_op_class_ie(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, - int freq, u8 *pos, size_t len); + struct wpa_bss *bss, u8 *pos, size_t len); int * wpas_supp_op_classes(struct wpa_supplicant *wpa_s); int wpas_enable_mac_addr_randomization(struct wpa_supplicant *wpa_s, @@ -1494,6 +1550,9 @@ struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s, int wpas_temp_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s, struct channel_list_changed *info); +int wpa_supplicant_need_to_roam_within_ess(struct wpa_supplicant *wpa_s, + struct wpa_bss *current_bss, + struct wpa_bss *seleceted); /* eap_register.c */ int eap_register_methods(void); @@ -1563,7 +1622,7 @@ int wpas_sched_scan_plans_set(struct wpa_supplicant *wpa_s, const char *cmd); struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes, u16 num_modes, enum hostapd_hw_mode mode, - int is_6ghz); + bool is_6ghz); void wpa_bss_tmp_disallow(struct wpa_supplicant *wpa_s, const u8 *bssid, unsigned int sec, int rssi_threshold); @@ -1586,4 +1645,13 @@ int wpa_is_fils_sk_pfs_supported(struct wpa_supplicant *wpa_s); void wpas_clear_driver_signal_override(struct wpa_supplicant *wpa_s); +int wpas_send_mscs_req(struct wpa_supplicant *wpa_s); +void wpas_populate_mscs_descriptor_ie(struct robust_av_data *robust_av, + struct wpabuf *buf); +void wpas_handle_robust_av_recv_action(struct wpa_supplicant *wpa_s, + const u8 *src, const u8 *buf, + size_t len); +void wpas_handle_assoc_resp_mscs(struct wpa_supplicant *wpa_s, const u8 *bssid, + const u8 *ies, size_t ies_len); + #endif /* WPA_SUPPLICANT_I_H */ diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index a8f38460b..75cbb6b76 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -228,6 +228,7 @@ static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf, } +#ifdef CONFIG_WEP /** * wpa_eapol_set_wep_key - set WEP key for the driver * @ctx: Pointer to wpa_supplicant data (wpa_s) @@ -272,6 +273,7 @@ static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx, unicast ? KEY_FLAG_PAIRWISE_RX_TX : KEY_FLAG_GROUP_RX_TX_DEFAULT); } +#endif /* CONFIG_WEP */ static void wpa_supplicant_aborted_cached(void *ctx) @@ -368,7 +370,7 @@ static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, wpa_hexdump_key(MSG_DEBUG, "RSN: Configure PMK for driver-based 4-way " "handshake", pmk, pmk_len); - if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk, + if (wpa_drv_set_key(wpa_s, 0, NULL, 0, 0, NULL, 0, pmk, pmk_len, KEY_FLAG_PMK)) { wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver"); } @@ -417,6 +419,13 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s) curr = bss; break; } +#ifdef CONFIG_OWE + if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) && + (bss->flags & WPA_BSS_OWE_TRANSITION)) { + curr = bss; + break; + } +#endif /* CONFIG_OWE */ } if (curr) { @@ -507,6 +516,12 @@ static void _wpa_supplicant_deauthenticate(void *wpa_s, u16 reason_code) } +static void _wpa_supplicant_reconnect(void *wpa_s) +{ + wpa_supplicant_reconnect(wpa_s); +} + + static void * wpa_supplicant_get_network_ctx(void *wpa_s) { return wpa_supplicant_get_ssid(wpa_s); @@ -540,7 +555,8 @@ static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg, } #endif /* CONFIG_TESTING_GET_GTK */ #ifdef CONFIG_TESTING_OPTIONS - if (addr && !is_broadcast_ether_addr(addr)) { + if (addr && !is_broadcast_ether_addr(addr) && + !(key_flag & KEY_FLAG_MODIFY)) { wpa_s->last_tk_alg = alg; os_memcpy(wpa_s->last_tk_addr, addr, ETH_ALEN); wpa_s->last_tk_key_idx = key_idx; @@ -580,7 +596,9 @@ static struct wpa_ssid * wpas_get_network_ctx(struct wpa_supplicant *wpa_s, static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id, - const u8 *pmk, size_t pmk_len) + const u8 *pmk, size_t pmk_len, + u32 pmk_lifetime, u8 pmk_reauth_threshold, + int akmp) { struct wpa_supplicant *wpa_s = _wpa_s; struct wpa_ssid *ssid; @@ -588,9 +606,22 @@ static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, os_memset(¶ms, 0, sizeof(params)); ssid = wpas_get_network_ctx(wpa_s, network_ctx); - if (ssid) + if (ssid) { wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_ADDED MACSTR " %d", MAC2STR(bssid), ssid->id); + if ((akmp == WPA_KEY_MGMT_FT_IEEE8021X || + akmp == WPA_KEY_MGMT_FT_IEEE8021X_SHA384) && + !ssid->ft_eap_pmksa_caching) { + /* Since we will not be using PMKSA caching for FT-EAP + * within wpa_supplicant to avoid known interop issues + * with APs, do not add this PMKID to the driver either + * so that we won't be hitting those interop issues + * with driver-based RSNE generation. */ + wpa_printf(MSG_DEBUG, + "FT: Do not add PMKID entry to the driver since FT-EAP PMKSA caching is not enabled in configuration"); + return 0; + } + } if (ssid && fils_cache_id) { params.ssid = ssid->ssid; params.ssid_len = ssid->ssid_len; @@ -602,6 +633,8 @@ static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, params.pmkid = pmkid; params.pmk = pmk; params.pmk_len = pmk_len; + params.pmk_lifetime = pmk_lifetime; + params.pmk_reauth_threshold = pmk_reauth_threshold; return wpa_drv_add_pmkid(wpa_s, ¶ms); } @@ -1080,6 +1113,21 @@ static void wpa_supplicant_eap_error_cb(void *ctx, int error_code) } +static int wpa_supplicant_eap_auth_start_cb(void *ctx) +{ + struct wpa_supplicant *wpa_s = ctx; + + if (!wpa_s->new_connection && wpa_s->deny_ptk0_rekey && + !wpa_sm_ext_key_id_active(wpa_s->wpa)) { + wpa_msg(wpa_s, MSG_INFO, + "WPA: PTK0 rekey not allowed, reconnecting"); + wpa_supplicant_reconnect(wpa_s); + return -1; + } + return 0; +} + + static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len) { struct wpa_supplicant *wpa_s = ctx; @@ -1135,7 +1183,9 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) ctx->preauth = 0; ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done; ctx->eapol_send = wpa_supplicant_eapol_send; +#ifdef CONFIG_WEP ctx->set_wep_key = wpa_eapol_set_wep_key; +#endif /* CONFIG_WEP */ #ifndef CONFIG_NO_CONFIG_BLOBS ctx->set_config_blob = wpa_supplicant_set_config_blob; ctx->get_config_blob = wpa_supplicant_get_config_blob; @@ -1158,6 +1208,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) ctx->cert_in_cb = wpa_s->conf->cert_in_cb; ctx->status_cb = wpa_supplicant_status_cb; ctx->eap_error_cb = wpa_supplicant_eap_error_cb; + ctx->confirm_auth_cb = wpa_supplicant_eap_auth_start_cb; ctx->set_anon_id = wpa_supplicant_set_anon_id; ctx->cb_ctx = wpa_s; wpa_s->eapol = eapol_sm_init(ctx); @@ -1193,7 +1244,7 @@ static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk, if (wpa_s->conf->key_mgmt_offload && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) - return wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, + return wpa_drv_set_key(wpa_s, 0, NULL, 0, 0, NULL, 0, pmk, pmk_len, KEY_FLAG_PMK); else return 0; @@ -1226,6 +1277,92 @@ static int wpa_supplicant_channel_info(void *_wpa_s, return wpa_drv_channel_info(wpa_s, ci); } + +static void disable_wpa_wpa2(struct wpa_ssid *ssid) +{ + ssid->proto &= ~WPA_PROTO_WPA; + ssid->proto |= WPA_PROTO_RSN; + ssid->key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_PSK_SHA256); + ssid->group_cipher &= ~WPA_CIPHER_TKIP; + if (!(ssid->group_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | + WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256))) + ssid->group_cipher |= WPA_CIPHER_CCMP; + ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; +} + + +static void wpa_supplicant_transition_disable(void *_wpa_s, u8 bitmap) +{ + struct wpa_supplicant *wpa_s = _wpa_s; + struct wpa_ssid *ssid; + int changed = 0; + + wpa_msg(wpa_s, MSG_INFO, TRANSITION_DISABLE "%02x", bitmap); + + ssid = wpa_s->current_ssid; + if (!ssid) + return; + +#ifdef CONFIG_SAE + if ((bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) && + wpa_key_mgmt_sae(wpa_s->key_mgmt) && + (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) && + (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || + (ssid->group_cipher & WPA_CIPHER_TKIP))) { + wpa_printf(MSG_DEBUG, + "WPA3-Personal transition mode disabled based on AP notification"); + disable_wpa_wpa2(ssid); + changed = 1; + } + + if ((bitmap & TRANSITION_DISABLE_SAE_PK) && + wpa_key_mgmt_sae(wpa_s->key_mgmt) && +#ifdef CONFIG_SME + wpa_s->sme.sae.state == SAE_ACCEPTED && + wpa_s->sme.sae.pk && +#endif /* CONFIG_SME */ + (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) && + (ssid->sae_pk != SAE_PK_MODE_ONLY || + ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || + (ssid->group_cipher & WPA_CIPHER_TKIP))) { + wpa_printf(MSG_DEBUG, + "SAE-PK: SAE authentication without PK disabled based on AP notification"); + disable_wpa_wpa2(ssid); + ssid->sae_pk = SAE_PK_MODE_ONLY; + changed = 1; + } +#endif /* CONFIG_SAE */ + + if ((bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) && + wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) && + (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | + WPA_KEY_MGMT_FT_IEEE8021X | + WPA_KEY_MGMT_IEEE8021X_SHA256)) && + (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || + (ssid->group_cipher & WPA_CIPHER_TKIP))) { + disable_wpa_wpa2(ssid); + changed = 1; + } + + if ((bitmap & TRANSITION_DISABLE_ENHANCED_OPEN) && + wpa_s->key_mgmt == WPA_KEY_MGMT_OWE && + (ssid->key_mgmt & WPA_KEY_MGMT_OWE) && + !ssid->owe_only) { + ssid->owe_only = 1; + changed = 1; + } + + if (!changed) + return; + +#ifndef CONFIG_NO_CONFIG_WRITE + if (wpa_s->conf->update_config && + wpa_config_write(wpa_s->confname, wpa_s->conf)) + wpa_printf(MSG_DEBUG, "Failed to update configuration"); +#endif /* CONFIG_NO_CONFIG_WRITE */ +} + #endif /* CONFIG_NO_WPA */ @@ -1244,6 +1381,7 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) ctx->set_state = _wpa_supplicant_set_state; ctx->get_state = _wpa_supplicant_get_state; ctx->deauthenticate = _wpa_supplicant_deauthenticate; + ctx->reconnect = _wpa_supplicant_reconnect; ctx->set_key = wpa_supplicant_set_key; ctx->get_network_ctx = wpa_supplicant_get_network_ctx; ctx->get_bssid = wpa_supplicant_get_bssid; @@ -1277,6 +1415,7 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk; ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx; ctx->channel_info = wpa_supplicant_channel_info; + ctx->transition_disable = wpa_supplicant_transition_disable; wpa_s->wpa = wpa_sm_init(ctx); if (wpa_s->wpa == NULL) { @@ -1308,6 +1447,7 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, conf.ssid = ssid->ssid; conf.ssid_len = ssid->ssid_len; conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey; + conf.wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey; conf.owe_ptk_workaround = ssid->owe_ptk_workaround; #ifdef CONFIG_P2P if (ssid->p2p_group && wpa_s->current_bss && @@ -1331,6 +1471,7 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, conf.fils_cache_id = wpa_bss_get_fils_cache_id(wpa_s->current_bss); #endif /* CONFIG_FILS */ + conf.beacon_prot = ssid->beacon_prot; } wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL); } diff --git a/wpa_supplicant/wpas_kay.c b/wpa_supplicant/wpas_kay.c index 41477d514..defd0f2f7 100644 --- a/wpa_supplicant/wpas_kay.c +++ b/wpa_supplicant/wpas_kay.c @@ -44,19 +44,19 @@ static int wpas_macsec_get_capability(void *priv, enum macsec_cap *cap) } -static int wpas_enable_protect_frames(void *wpa_s, Boolean enabled) +static int wpas_enable_protect_frames(void *wpa_s, bool enabled) { return wpa_drv_enable_protect_frames(wpa_s, enabled); } -static int wpas_enable_encrypt(void *wpa_s, Boolean enabled) +static int wpas_enable_encrypt(void *wpa_s, bool enabled) { return wpa_drv_enable_encrypt(wpa_s, enabled); } -static int wpas_set_replay_protect(void *wpa_s, Boolean enabled, u32 window) +static int wpas_set_replay_protect(void *wpa_s, bool enabled, u32 window) { return wpa_drv_set_replay_protect(wpa_s, enabled, window); } @@ -68,7 +68,7 @@ static int wpas_set_current_cipher_suite(void *wpa_s, u64 cs) } -static int wpas_enable_controlled_port(void *wpa_s, Boolean enabled) +static int wpas_enable_controlled_port(void *wpa_s, bool enabled) { return wpa_drv_enable_controlled_port(wpa_s, enabled); } @@ -376,7 +376,7 @@ void * ieee802_1x_notify_create_actor(struct wpa_supplicant *wpa_s, wpa_hexdump(MSG_DEBUG, "Derived CKN", ckn->name, ckn->len); res = ieee802_1x_kay_create_mka(wpa_s->kay, ckn, cak, 0, - EAP_EXCHANGE, FALSE); + EAP_EXCHANGE, false); fail: if (msk) { @@ -424,7 +424,7 @@ void * ieee802_1x_create_preshared_mka(struct wpa_supplicant *wpa_s, ckn->len = ssid->mka_ckn_len; os_memcpy(ckn->name, ssid->mka_ckn, ckn->len); - res = ieee802_1x_kay_create_mka(wpa_s->kay, ckn, cak, 0, PSK, FALSE); + res = ieee802_1x_kay_create_mka(wpa_s->kay, ckn, cak, 0, PSK, false); if (res) goto free_cak; diff --git a/wpa_supplicant/wpas_module_tests.c b/wpa_supplicant/wpas_module_tests.c index 4e37591be..1c136f782 100644 --- a/wpa_supplicant/wpas_module_tests.c +++ b/wpa_supplicant/wpas_module_tests.c @@ -59,6 +59,23 @@ static int wpas_blacklist_module_tests(void) wpa_blacklist_add(&wpa_s, (u8 *) "333333") < 0) goto fail; + wpa_blacklist_clear(&wpa_s); + + if (wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0 || + wpa_blacklist_add(&wpa_s, (u8 *) "222222") < 0 || + wpa_blacklist_add(&wpa_s, (u8 *) "333333") < 0 || + wpa_blacklist_add(&wpa_s, (u8 *) "444444") < 0 || + !wpa_blacklist_is_blacklisted(&wpa_s, (u8 *) "111111") || + wpa_blacklist_del(&wpa_s, (u8 *) "111111") < 0 || + wpa_blacklist_is_blacklisted(&wpa_s, (u8 *) "111111") || + wpa_blacklist_add(&wpa_s, (u8 *) "111111") < 0) + goto fail; + + wpa_blacklist_update(&wpa_s); + + if (!wpa_blacklist_is_blacklisted(&wpa_s, (u8 *) "111111")) + goto fail; + ret = 0; fail: wpa_blacklist_clear(&wpa_s); diff --git a/wpa_supplicant/wps_supplicant.c b/wpa_supplicant/wps_supplicant.c index 99ddd26ca..613fe2b6a 100644 --- a/wpa_supplicant/wps_supplicant.c +++ b/wpa_supplicant/wps_supplicant.c @@ -188,6 +188,7 @@ static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s, const u8 *ie; struct wpa_ie_data adv; int wpa2 = 0, ccmp = 0; + enum wpa_driver_if_type iftype; /* * Many existing WPS APs do not know how to negotiate WPA2 or CCMP in @@ -239,9 +240,12 @@ static void wpas_wps_security_workaround(struct wpa_supplicant *wpa_s, return; } + iftype = ssid->p2p_group ? WPA_IF_P2P_CLIENT : WPA_IF_STATION; + if (ccmp && !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && (ssid->pairwise_cipher & WPA_CIPHER_TKIP) && - (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { + (capa.key_mgmt_iftype[iftype] & + WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) { wpa_printf(MSG_DEBUG, "WPS: Add CCMP into the credential " "based on scan results"); if (wpa_s->conf->ap_scan == 1) @@ -484,7 +488,7 @@ static int wpa_supplicant_wps_cred(void *ctx, case WPS_ENCR_NONE: break; case WPS_ENCR_TKIP: - ssid->pairwise_cipher = WPA_CIPHER_TKIP; + ssid->pairwise_cipher = WPA_CIPHER_TKIP | WPA_CIPHER_CCMP; break; case WPS_ENCR_AES: ssid->pairwise_cipher = WPA_CIPHER_CCMP; @@ -525,13 +529,14 @@ static int wpa_supplicant_wps_cred(void *ctx, case WPS_AUTH_WPAPSK: ssid->auth_alg = WPA_AUTH_ALG_OPEN; ssid->key_mgmt = WPA_KEY_MGMT_PSK; - ssid->proto = WPA_PROTO_WPA; + ssid->proto = WPA_PROTO_WPA | WPA_PROTO_RSN; break; case WPS_AUTH_WPA2PSK: ssid->auth_alg = WPA_AUTH_ALG_OPEN; ssid->key_mgmt = WPA_KEY_MGMT_PSK; if (wpa_s->conf->wps_cred_add_sae && cred->key_len != 2 * PMK_LEN) { + ssid->auth_alg = 0; ssid->key_mgmt |= WPA_KEY_MGMT_SAE; ssid->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; } @@ -715,7 +720,7 @@ static void wpa_supplicant_wps_event_success(struct wpa_supplicant *wpa_s) wpas_notify_wps_event_success(wpa_s); if (wpa_s->current_ssid) wpas_clear_temp_disabled(wpa_s, wpa_s->current_ssid, 1); - wpa_s->extra_blacklist_count = 0; + wpa_s->consecutive_conn_failures = 0; /* * Enable the networks disabled during wpas_wps_reassoc after 10 @@ -1617,8 +1622,13 @@ int wpas_wps_init(struct wpa_supplicant *wpa_s) os_memcpy(wps->dev.mac_addr, wpa_s->own_addr, ETH_ALEN); wpas_wps_set_uuid(wpa_s, wps); +#ifdef CONFIG_NO_TKIP + wps->auth_types = WPS_AUTH_WPA2PSK; + wps->encr_types = WPS_ENCR_AES; +#else /* CONFIG_NO_TKIP */ wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK; wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP; +#endif /* CONFIG_NO_TKIP */ os_memset(&rcfg, 0, sizeof(rcfg)); rcfg.new_psk_cb = wpas_wps_new_psk_cb; @@ -1829,6 +1839,10 @@ int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s, wpa_printf(MSG_DEBUG, "WPS: Check whether PBC session overlap is " "present in scan results; selected BSSID " MACSTR, MAC2STR(selected->bssid)); + if (!is_zero_ether_addr(ssid->bssid)) + wpa_printf(MSG_DEBUG, + "WPS: Network profile limited to accept only a single BSSID " MACSTR, + MAC2STR(ssid->bssid)); /* Make sure that only one AP is in active PBC mode */ wps_ie = wpa_bss_get_vendor_ie_multi(selected, WPS_IE_VENDOR_TYPE); @@ -1849,6 +1863,14 @@ int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s, os_memcmp(selected->bssid, ap->bssid, ETH_ALEN) == 0) continue; + if (!is_zero_ether_addr(ssid->bssid) && + os_memcmp(ap->bssid, ssid->bssid, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, "WPS: Ignore another BSS " MACSTR + " in active PBC mode due to local BSSID limitation", + MAC2STR(ap->bssid)); + continue; + } + wpa_printf(MSG_DEBUG, "WPS: Another BSS in active PBC mode: " MACSTR, MAC2STR(ap->bssid)); wpa_hexdump(MSG_DEBUG, "WPS: UUID of the other BSS", diff --git a/wpaspy/Makefile b/wpaspy/Makefile index bc920e0cc..6f720a9fe 100644 --- a/wpaspy/Makefile +++ b/wpaspy/Makefile @@ -2,6 +2,7 @@ all: build SRC=wpaspy.c +.PHONY: build build: $(SRC) setup.py python setup.py build diff --git a/wpaspy/wpaspy.c b/wpaspy/wpaspy.c index 278089b48..4d4c2a495 100644 --- a/wpaspy/wpaspy.c +++ b/wpaspy/wpaspy.c @@ -44,8 +44,7 @@ static void wpaspy_close(struct wpaspy_obj *self) self->ctrl = NULL; } - if (self->ob_type) - self->ob_type->tp_free((PyObject *) self); + PyObject_Del(self); } @@ -193,6 +192,7 @@ static PyTypeObject wpaspy_ctrl = { }; +#if PY_MAJOR_VERSION < 3 static PyMethodDef module_methods[] = { { NULL, NULL, 0, NULL } }; @@ -212,3 +212,34 @@ PyMODINIT_FUNC initwpaspy(void) PyModule_AddObject(mod, "Ctrl", (PyObject *) &wpaspy_ctrl); PyModule_AddObject(mod, "error", wpaspy_error); } +#else +static struct PyModuleDef wpaspy_def = { + PyModuleDef_HEAD_INIT, + "wpaspy", +}; + + +PyMODINIT_FUNC initwpaspy(void) +{ + PyObject *mod; + + mod = PyModule_Create(&wpaspy_def); + if (!mod) + return NULL; + + wpaspy_error = PyErr_NewException("wpaspy.error", NULL, NULL); + + Py_INCREF(&wpaspy_ctrl); + Py_INCREF(wpaspy_error); + + if (PyModule_AddObject(mod, "Ctrl", (PyObject *) &wpaspy_ctrl) < 0 || + PyModule_AddObject(mod, "error", wpaspy_error) < 0) { + Py_DECREF(&wpaspy_ctrl); + Py_DECREF(wpaspy_error); + Py_DECREF(mod); + mod = NULL; + } + + return mod; +} +#endif diff --git a/wpaspy/wpaspy.py b/wpaspy/wpaspy.py index 89e973b98..c50cd531e 100644 --- a/wpaspy/wpaspy.py +++ b/wpaspy/wpaspy.py @@ -113,6 +113,9 @@ class Ctrl: def detach(self): if not self.attached: return None + if self.s.fileno() == -1: + self.attached = False + return None while self.pending(): ev = self.recv() res = self.request("DETACH")