mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 17:42:41 +00:00
26626 lines
834 KiB
Diff
26626 lines
834 KiB
Diff
From 8a37e576b5f0a3171e6f17b3df395cad33a0be07 Mon Sep 17 00:00:00 2001
|
|
From: John Crispin <john@phrozen.org>
|
|
Date: Thu, 17 Aug 2023 15:54:00 +0200
|
|
Subject: [PATCH 49/52] hostapd: add upstream version
|
|
|
|
Signed-off-by: John Crispin <john@phrozen.org>
|
|
---
|
|
package/network/services/hostapd/Config.in | 108 +
|
|
package/network/services/hostapd/Makefile | 858 ++
|
|
package/network/services/hostapd/README.md | 419 +
|
|
.../network/services/hostapd/files/common.uc | 168 +
|
|
.../services/hostapd/files/dhcp-get-server.sh | 2 +
|
|
.../hostapd/files/hostapd-basic.config | 404 +
|
|
.../hostapd/files/hostapd-full.config | 404 +
|
|
.../hostapd/files/hostapd-mini.config | 404 +
|
|
.../network/services/hostapd/files/hostapd.sh | 1593 ++++
|
|
.../network/services/hostapd/files/hostapd.uc | 486 +
|
|
.../services/hostapd/files/multicall.c | 28 +
|
|
.../services/hostapd/files/radius.clients | 1 +
|
|
.../services/hostapd/files/radius.config | 9 +
|
|
.../services/hostapd/files/radius.init | 42 +
|
|
.../services/hostapd/files/radius.users | 14 +
|
|
.../network/services/hostapd/files/wdev.uc | 156 +
|
|
.../hostapd/files/wpa_supplicant-basic.config | 625 ++
|
|
.../hostapd/files/wpa_supplicant-full.config | 625 ++
|
|
.../hostapd/files/wpa_supplicant-mini.config | 625 ++
|
|
.../hostapd/files/wpa_supplicant-p2p.config | 625 ++
|
|
.../services/hostapd/files/wpa_supplicant.uc | 253 +
|
|
.../network/services/hostapd/files/wpad.init | 43 +
|
|
.../network/services/hostapd/files/wpad.json | 22 +
|
|
.../services/hostapd/files/wpad_acl.json | 10 +
|
|
.../services/hostapd/files/wps-hotplug.sh | 69 +
|
|
.../001-wolfssl-init-RNG-with-ECC-key.patch | 43 +
|
|
...hannels-to-be-selected-if-dfs-is-ena.patch | 135 +
|
|
...erministic-channel-on-channel-switch.patch | 81 +
|
|
...ix-sta-add-after-previous-connection.patch | 26 +
|
|
...use-of-uninitialized-stack-variables.patch | 25 +
|
|
...-dl_list_del-before-freeing-ipv6-add.patch | 19 +
|
|
...ewrite-neigh-code-to-not-depend-on-l.patch | 275 +
|
|
...ssing-authentication-frames-in-block.patch | 34 +
|
|
.../hostapd/patches/050-build_fix.patch | 20 +
|
|
.../hostapd/patches/100-daemonize_fix.patch | 97 +
|
|
...edtls-TLS-crypto-option-initial-port.patch | 8051 +++++++++++++++++
|
|
.../patches/120-mbedtls-fips186_2_prf.patch | 114 +
|
|
...otate-with-TEST_FAIL-for-hwsim-tests.patch | 421 +
|
|
...efile-make-run-tests-with-CONFIG_TLS.patch | 1358 +++
|
|
...hecks-encountered-during-tests-hwsim.patch | 45 +
|
|
...-dpp_pkex-EC-point-mul-w-value-prime.patch | 26 +
|
|
...tapd-update-cfs0-and-cfs1-for-160MHz.patch | 141 +
|
|
...S-coloring-fix-CCA-with-multiple-BSS.patch | 103 +
|
|
.../hostapd/patches/200-multicall.patch | 355 +
|
|
.../services/hostapd/patches/300-noscan.patch | 58 +
|
|
.../hostapd/patches/301-mesh-noscan.patch | 71 +
|
|
.../patches/310-rescan_immediately.patch | 11 +
|
|
.../hostapd/patches/320-optional_rfkill.patch | 61 +
|
|
.../patches/330-nl80211_fix_set_freq.patch | 11 +
|
|
.../341-mesh-ctrl-iface-channel-switch.patch | 39 +
|
|
.../patches/350-nl80211_del_beacon_bss.patch | 35 +
|
|
.../patches/380-disable_ctrl_iface_mib.patch | 239 +
|
|
.../381-hostapd_cli_UNKNOWN-COMMAND.patch | 11 +
|
|
.../patches/390-wpa_ie_cap_workaround.patch | 56 +
|
|
.../400-wps_single_auth_enc_type.patch | 23 +
|
|
.../patches/410-limit_debug_messages.patch | 210 +
|
|
.../patches/420-indicate-features.patch | 63 +
|
|
.../patches/430-hostapd_cli_ifdef.patch | 56 +
|
|
.../hostapd/patches/431-wpa_cli_ifdef.patch | 18 +
|
|
...dd-new-config-params-to-be-used-with.patch | 189 +
|
|
.../patches/463-add-mcast_rate-to-11s.patch | 68 +
|
|
.../patches/464-fix-mesh-obss-check.patch | 13 +
|
|
...tapd-config-support-random-BSS-color.patch | 24 +
|
|
.../patches/470-survey_data_fallback.patch | 30 +
|
|
.../patches/500-lto-jobserver-support.patch | 59 +
|
|
.../patches/590-rrm-wnm-statistics.patch | 92 +
|
|
.../599-wpa_supplicant-fix-warnings.patch | 19 +
|
|
.../hostapd/patches/600-ubus_support.patch | 748 ++
|
|
.../hostapd/patches/601-ucode_support.patch | 333 +
|
|
.../610-hostapd_cli_ujail_permission.patch | 33 +
|
|
.../patches/701-reload_config_inline.patch | 33 +
|
|
.../hostapd/patches/710-vlan_no_bridge.patch | 41 +
|
|
.../patches/711-wds_bridge_force.patch | 22 +
|
|
.../patches/720-iface_max_num_sta.patch | 81 +
|
|
.../hostapd/patches/730-ft_iface.patch | 38 +
|
|
.../hostapd/patches/740-snoop_iface.patch | 66 +
|
|
...750-qos_map_set_without_interworking.patch | 97 +
|
|
.../751-qos_map_ignore_when_unsupported.patch | 12 +
|
|
.../hostapd/patches/760-dynamic_own_ip.patch | 109 +
|
|
.../hostapd/patches/761-shared_das_port.patch | 298 +
|
|
.../hostapd/patches/770-radius_server.patch | 154 +
|
|
..._AP-functions-dependant-on-CONFIG_AP.patch | 33 +
|
|
.../services/hostapd/src/hostapd/radius.c | 715 ++
|
|
.../services/hostapd/src/src/ap/ubus.c | 2002 ++++
|
|
.../services/hostapd/src/src/ap/ubus.h | 154 +
|
|
.../services/hostapd/src/src/ap/ucode.c | 545 ++
|
|
.../services/hostapd/src/src/ap/ucode.h | 54 +
|
|
.../hostapd/src/src/utils/build_features.h | 65 +
|
|
.../services/hostapd/src/src/utils/ucode.c | 326 +
|
|
.../services/hostapd/src/src/utils/ucode.h | 29 +
|
|
.../hostapd/src/wpa_supplicant/ubus.c | 280 +
|
|
.../hostapd/src/wpa_supplicant/ubus.h | 55 +
|
|
.../hostapd/src/wpa_supplicant/ucode.c | 270 +
|
|
.../hostapd/src/wpa_supplicant/ucode.h | 49 +
|
|
94 files changed, 27460 insertions(+)
|
|
create mode 100644 package/network/services/hostapd/Config.in
|
|
create mode 100644 package/network/services/hostapd/Makefile
|
|
create mode 100644 package/network/services/hostapd/README.md
|
|
create mode 100644 package/network/services/hostapd/files/common.uc
|
|
create mode 100644 package/network/services/hostapd/files/dhcp-get-server.sh
|
|
create mode 100644 package/network/services/hostapd/files/hostapd-basic.config
|
|
create mode 100644 package/network/services/hostapd/files/hostapd-full.config
|
|
create mode 100644 package/network/services/hostapd/files/hostapd-mini.config
|
|
create mode 100644 package/network/services/hostapd/files/hostapd.sh
|
|
create mode 100644 package/network/services/hostapd/files/hostapd.uc
|
|
create mode 100644 package/network/services/hostapd/files/multicall.c
|
|
create mode 100644 package/network/services/hostapd/files/radius.clients
|
|
create mode 100644 package/network/services/hostapd/files/radius.config
|
|
create mode 100644 package/network/services/hostapd/files/radius.init
|
|
create mode 100644 package/network/services/hostapd/files/radius.users
|
|
create mode 100644 package/network/services/hostapd/files/wdev.uc
|
|
create mode 100644 package/network/services/hostapd/files/wpa_supplicant-basic.config
|
|
create mode 100644 package/network/services/hostapd/files/wpa_supplicant-full.config
|
|
create mode 100644 package/network/services/hostapd/files/wpa_supplicant-mini.config
|
|
create mode 100644 package/network/services/hostapd/files/wpa_supplicant-p2p.config
|
|
create mode 100644 package/network/services/hostapd/files/wpa_supplicant.uc
|
|
create mode 100644 package/network/services/hostapd/files/wpad.init
|
|
create mode 100644 package/network/services/hostapd/files/wpad.json
|
|
create mode 100644 package/network/services/hostapd/files/wpad_acl.json
|
|
create mode 100644 package/network/services/hostapd/files/wps-hotplug.sh
|
|
create mode 100644 package/network/services/hostapd/patches/001-wolfssl-init-RNG-with-ECC-key.patch
|
|
create mode 100644 package/network/services/hostapd/patches/010-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch
|
|
create mode 100644 package/network/services/hostapd/patches/011-mesh-use-deterministic-channel-on-channel-switch.patch
|
|
create mode 100644 package/network/services/hostapd/patches/021-fix-sta-add-after-previous-connection.patch
|
|
create mode 100644 package/network/services/hostapd/patches/022-hostapd-fix-use-of-uninitialized-stack-variables.patch
|
|
create mode 100644 package/network/services/hostapd/patches/023-ndisc_snoop-call-dl_list_del-before-freeing-ipv6-add.patch
|
|
create mode 100644 package/network/services/hostapd/patches/030-driver_nl80211-rewrite-neigh-code-to-not-depend-on-l.patch
|
|
create mode 100644 package/network/services/hostapd/patches/040-mesh-allow-processing-authentication-frames-in-block.patch
|
|
create mode 100644 package/network/services/hostapd/patches/050-build_fix.patch
|
|
create mode 100644 package/network/services/hostapd/patches/100-daemonize_fix.patch
|
|
create mode 100644 package/network/services/hostapd/patches/110-mbedtls-TLS-crypto-option-initial-port.patch
|
|
create mode 100644 package/network/services/hostapd/patches/120-mbedtls-fips186_2_prf.patch
|
|
create mode 100644 package/network/services/hostapd/patches/130-mbedtls-annotate-with-TEST_FAIL-for-hwsim-tests.patch
|
|
create mode 100644 package/network/services/hostapd/patches/140-tests-Makefile-make-run-tests-with-CONFIG_TLS.patch
|
|
create mode 100644 package/network/services/hostapd/patches/150-add-NULL-checks-encountered-during-tests-hwsim.patch
|
|
create mode 100644 package/network/services/hostapd/patches/160-dpp_pkex-EC-point-mul-w-value-prime.patch
|
|
create mode 100644 package/network/services/hostapd/patches/170-hostapd-update-cfs0-and-cfs1-for-160MHz.patch
|
|
create mode 100644 package/network/services/hostapd/patches/180-BSS-coloring-fix-CCA-with-multiple-BSS.patch
|
|
create mode 100644 package/network/services/hostapd/patches/200-multicall.patch
|
|
create mode 100644 package/network/services/hostapd/patches/300-noscan.patch
|
|
create mode 100644 package/network/services/hostapd/patches/301-mesh-noscan.patch
|
|
create mode 100644 package/network/services/hostapd/patches/310-rescan_immediately.patch
|
|
create mode 100644 package/network/services/hostapd/patches/320-optional_rfkill.patch
|
|
create mode 100644 package/network/services/hostapd/patches/330-nl80211_fix_set_freq.patch
|
|
create mode 100644 package/network/services/hostapd/patches/341-mesh-ctrl-iface-channel-switch.patch
|
|
create mode 100644 package/network/services/hostapd/patches/350-nl80211_del_beacon_bss.patch
|
|
create mode 100644 package/network/services/hostapd/patches/380-disable_ctrl_iface_mib.patch
|
|
create mode 100644 package/network/services/hostapd/patches/381-hostapd_cli_UNKNOWN-COMMAND.patch
|
|
create mode 100644 package/network/services/hostapd/patches/390-wpa_ie_cap_workaround.patch
|
|
create mode 100644 package/network/services/hostapd/patches/400-wps_single_auth_enc_type.patch
|
|
create mode 100644 package/network/services/hostapd/patches/410-limit_debug_messages.patch
|
|
create mode 100644 package/network/services/hostapd/patches/420-indicate-features.patch
|
|
create mode 100644 package/network/services/hostapd/patches/430-hostapd_cli_ifdef.patch
|
|
create mode 100644 package/network/services/hostapd/patches/431-wpa_cli_ifdef.patch
|
|
create mode 100644 package/network/services/hostapd/patches/460-wpa_supplicant-add-new-config-params-to-be-used-with.patch
|
|
create mode 100644 package/network/services/hostapd/patches/463-add-mcast_rate-to-11s.patch
|
|
create mode 100644 package/network/services/hostapd/patches/464-fix-mesh-obss-check.patch
|
|
create mode 100644 package/network/services/hostapd/patches/465-hostapd-config-support-random-BSS-color.patch
|
|
create mode 100644 package/network/services/hostapd/patches/470-survey_data_fallback.patch
|
|
create mode 100644 package/network/services/hostapd/patches/500-lto-jobserver-support.patch
|
|
create mode 100644 package/network/services/hostapd/patches/590-rrm-wnm-statistics.patch
|
|
create mode 100644 package/network/services/hostapd/patches/599-wpa_supplicant-fix-warnings.patch
|
|
create mode 100644 package/network/services/hostapd/patches/600-ubus_support.patch
|
|
create mode 100644 package/network/services/hostapd/patches/601-ucode_support.patch
|
|
create mode 100644 package/network/services/hostapd/patches/610-hostapd_cli_ujail_permission.patch
|
|
create mode 100644 package/network/services/hostapd/patches/701-reload_config_inline.patch
|
|
create mode 100644 package/network/services/hostapd/patches/710-vlan_no_bridge.patch
|
|
create mode 100644 package/network/services/hostapd/patches/711-wds_bridge_force.patch
|
|
create mode 100644 package/network/services/hostapd/patches/720-iface_max_num_sta.patch
|
|
create mode 100644 package/network/services/hostapd/patches/730-ft_iface.patch
|
|
create mode 100644 package/network/services/hostapd/patches/740-snoop_iface.patch
|
|
create mode 100644 package/network/services/hostapd/patches/750-qos_map_set_without_interworking.patch
|
|
create mode 100644 package/network/services/hostapd/patches/751-qos_map_ignore_when_unsupported.patch
|
|
create mode 100644 package/network/services/hostapd/patches/760-dynamic_own_ip.patch
|
|
create mode 100644 package/network/services/hostapd/patches/761-shared_das_port.patch
|
|
create mode 100644 package/network/services/hostapd/patches/770-radius_server.patch
|
|
create mode 100644 package/network/services/hostapd/patches/990-ctrl-make-WNM_AP-functions-dependant-on-CONFIG_AP.patch
|
|
create mode 100644 package/network/services/hostapd/src/hostapd/radius.c
|
|
create mode 100644 package/network/services/hostapd/src/src/ap/ubus.c
|
|
create mode 100644 package/network/services/hostapd/src/src/ap/ubus.h
|
|
create mode 100644 package/network/services/hostapd/src/src/ap/ucode.c
|
|
create mode 100644 package/network/services/hostapd/src/src/ap/ucode.h
|
|
create mode 100644 package/network/services/hostapd/src/src/utils/build_features.h
|
|
create mode 100644 package/network/services/hostapd/src/src/utils/ucode.c
|
|
create mode 100644 package/network/services/hostapd/src/src/utils/ucode.h
|
|
create mode 100644 package/network/services/hostapd/src/wpa_supplicant/ubus.c
|
|
create mode 100644 package/network/services/hostapd/src/wpa_supplicant/ubus.h
|
|
create mode 100644 package/network/services/hostapd/src/wpa_supplicant/ucode.c
|
|
create mode 100644 package/network/services/hostapd/src/wpa_supplicant/ucode.h
|
|
|
|
diff --git a/package/network/services/hostapd/Config.in b/package/network/services/hostapd/Config.in
|
|
new file mode 100644
|
|
index 0000000000..87ad7e093e
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/Config.in
|
|
@@ -0,0 +1,108 @@
|
|
+# wpa_supplicant config
|
|
+config WPA_RFKILL_SUPPORT
|
|
+ bool "Add rfkill support"
|
|
+ depends on PACKAGE_wpa-supplicant || \
|
|
+ PACKAGE_wpa-supplicant-openssl || \
|
|
+ PACKAGE_wpa-supplicant-wolfssl || \
|
|
+ PACKAGE_wpa-supplicant-mbedtls || \
|
|
+ PACKAGE_wpa-supplicant-mesh-openssl || \
|
|
+ PACKAGE_wpa-supplicant-mesh-wolfssl || \
|
|
+ PACKAGE_wpa-supplicant-mesh-mbedtls || \
|
|
+ PACKAGE_wpa-supplicant-basic || \
|
|
+ PACKAGE_wpa-supplicant-mini || \
|
|
+ PACKAGE_wpa-supplicant-p2p || \
|
|
+ PACKAGE_wpad || \
|
|
+ PACKAGE_wpad-openssl || \
|
|
+ PACKAGE_wpad-wolfssl || \
|
|
+ PACKAGE_wpad-mbedtls || \
|
|
+ PACKAGE_wpad-basic || \
|
|
+ PACKAGE_wpad-basic-openssl || \
|
|
+ PACKAGE_wpad-basic-wolfssl || \
|
|
+ PACKAGE_wpad-basic-mbedtls || \
|
|
+ PACKAGE_wpad-mini || \
|
|
+ PACKAGE_wpad-mesh-openssl || \
|
|
+ PACKAGE_wpad-mesh-wolfssl || \
|
|
+ PACKAGE_wpad-mesh-mbedtls
|
|
+ default n
|
|
+
|
|
+config WPA_MSG_MIN_PRIORITY
|
|
+ int "Minimum debug message priority"
|
|
+ depends on PACKAGE_wpa-supplicant || \
|
|
+ PACKAGE_wpa-supplicant-openssl || \
|
|
+ PACKAGE_wpa-supplicant-wolfssl || \
|
|
+ PACKAGE_wpa-supplicant-mbedtls || \
|
|
+ PACKAGE_wpa-supplicant-mesh-openssl || \
|
|
+ PACKAGE_wpa-supplicant-mesh-wolfssl || \
|
|
+ PACKAGE_wpa-supplicant-mesh-mbedtls || \
|
|
+ PACKAGE_wpa-supplicant-basic || \
|
|
+ PACKAGE_wpa-supplicant-mini || \
|
|
+ PACKAGE_wpa-supplicant-p2p || \
|
|
+ PACKAGE_wpad || \
|
|
+ PACKAGE_wpad-openssl || \
|
|
+ PACKAGE_wpad-wolfssl || \
|
|
+ PACKAGE_wpad-mbedtls || \
|
|
+ PACKAGE_wpad-basic || \
|
|
+ PACKAGE_wpad-basic-openssl || \
|
|
+ PACKAGE_wpad-basic-wolfssl || \
|
|
+ PACKAGE_wpad-basic-mbedtls || \
|
|
+ PACKAGE_wpad-mini || \
|
|
+ PACKAGE_wpad-mesh-openssl || \
|
|
+ PACKAGE_wpad-mesh-wolfssl || \
|
|
+ PACKAGE_wpad-mesh-mbedtls
|
|
+ default 3
|
|
+ help
|
|
+ Useful values are:
|
|
+ 0 = all messages
|
|
+ 1 = raw message dumps
|
|
+ 2 = most debugging messages
|
|
+ 3 = info messages
|
|
+ 4 = warnings
|
|
+ 5 = errors
|
|
+
|
|
+config WPA_WOLFSSL
|
|
+ bool
|
|
+ default PACKAGE_wpa-supplicant-wolfssl ||\
|
|
+ PACKAGE_wpad-wolfssl ||\
|
|
+ PACKAGE_wpad-basic-wolfssl || \
|
|
+ PACKAGE_wpad-mesh-wolfssl ||\
|
|
+ PACKAGE_eapol-test-wolfssl
|
|
+ select WOLFSSL_HAS_AES_CCM
|
|
+ select WOLFSSL_HAS_ARC4
|
|
+ select WOLFSSL_HAS_DH
|
|
+ select WOLFSSL_HAS_OCSP
|
|
+ select WOLFSSL_HAS_SESSION_TICKET
|
|
+ select WOLFSSL_HAS_WPAS
|
|
+
|
|
+config DRIVER_11AC_SUPPORT
|
|
+ bool
|
|
+ default n
|
|
+
|
|
+config DRIVER_11AX_SUPPORT
|
|
+ bool
|
|
+ default n
|
|
+ select WPA_MBO_SUPPORT
|
|
+
|
|
+config WPA_ENABLE_WEP
|
|
+ bool "Enable support for unsecure and obsolete WEP"
|
|
+ help
|
|
+ Wired equivalent privacy (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 and completely
|
|
+ removed in a future release.
|
|
+
|
|
+config WPA_MBO_SUPPORT
|
|
+ bool "Multi Band Operation (Agile Multiband)"
|
|
+ default PACKAGE_wpa-supplicant || \
|
|
+ PACKAGE_wpa-supplicant-openssl || \
|
|
+ PACKAGE_wpa-supplicant-wolfssl || \
|
|
+ PACKAGE_wpa-supplicant-mbedtls || \
|
|
+ PACKAGE_wpad || \
|
|
+ PACKAGE_wpad-openssl || \
|
|
+ PACKAGE_wpad-wolfssl || \
|
|
+ PACKAGE_wpad-mbedtls
|
|
+ help
|
|
+ Multi Band Operation aka (Agile Multiband) enables features
|
|
+ that facilitate efficient use of multiple frequency bands.
|
|
+ Enabling MBO on an AP using RSN requires 802.11w to be enabled.
|
|
+ Hostapd will refuse to start if MBO and RSN are enabled without 11w.
|
|
diff --git a/package/network/services/hostapd/Makefile b/package/network/services/hostapd/Makefile
|
|
new file mode 100644
|
|
index 0000000000..178dd20fcd
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/Makefile
|
|
@@ -0,0 +1,858 @@
|
|
+# SPDX-License-Identifier: GPL-2.0-only
|
|
+#
|
|
+# Copyright (C) 2006-2021 OpenWrt.org
|
|
+
|
|
+include $(TOPDIR)/rules.mk
|
|
+
|
|
+PKG_NAME:=hostapd
|
|
+PKG_RELEASE:=2
|
|
+
|
|
+PKG_SOURCE_URL:=http://w1.fi/hostap.git
|
|
+PKG_SOURCE_PROTO:=git
|
|
+PKG_SOURCE_DATE:=2023-06-22
|
|
+PKG_SOURCE_VERSION:=599d00be9de2846c6ea18c1487d8329522ade22b
|
|
+PKG_MIRROR_HASH:=828810c558ea181e45ed0c8b940f5c41e55775e2979a15aed8cf0ab17dd7723c
|
|
+
|
|
+PKG_MAINTAINER:=Felix Fietkau <nbd@nbd.name>
|
|
+PKG_LICENSE:=BSD-3-Clause
|
|
+PKG_CPE_ID:=cpe:/a:w1.fi:hostapd
|
|
+
|
|
+PKG_BUILD_PARALLEL:=1
|
|
+PKG_ASLR_PIE_REGULAR:=1
|
|
+
|
|
+PKG_CONFIG_DEPENDS:= \
|
|
+ CONFIG_PACKAGE_kmod-ath9k \
|
|
+ CONFIG_PACKAGE_kmod-cfg80211 \
|
|
+ CONFIG_PACKAGE_hostapd \
|
|
+ CONFIG_PACKAGE_hostapd-basic \
|
|
+ CONFIG_PACKAGE_hostapd-mini \
|
|
+ CONFIG_WPA_RFKILL_SUPPORT \
|
|
+ CONFIG_DRIVER_11AC_SUPPORT \
|
|
+ CONFIG_DRIVER_11AX_SUPPORT \
|
|
+ CONFIG_WPA_ENABLE_WEP
|
|
+
|
|
+PKG_BUILD_FLAGS:=gc-sections lto
|
|
+
|
|
+EAPOL_TEST_PROVIDERS:=eapol-test eapol-test-openssl eapol-test-wolfssl
|
|
+
|
|
+SUPPLICANT_PROVIDERS:=
|
|
+HOSTAPD_PROVIDERS:=
|
|
+
|
|
+LOCAL_TYPE=$(strip \
|
|
+ $(if $(findstring wpad,$(BUILD_VARIANT)),wpad, \
|
|
+ $(if $(findstring supplicant,$(BUILD_VARIANT)),supplicant, \
|
|
+ hostapd \
|
|
+ )))
|
|
+
|
|
+LOCAL_AND_LIB_VARIANT=$(patsubst hostapd-%,%,\
|
|
+ $(patsubst wpad-%,%,\
|
|
+ $(patsubst supplicant-%,%,\
|
|
+ $(BUILD_VARIANT)\
|
|
+ )))
|
|
+
|
|
+LOCAL_VARIANT=$(patsubst %-internal,%,\
|
|
+ $(patsubst %-openssl,%,\
|
|
+ $(patsubst %-wolfssl,%,\
|
|
+ $(patsubst %-mbedtls,%,\
|
|
+ $(LOCAL_AND_LIB_VARIANT)\
|
|
+ ))))
|
|
+
|
|
+SSL_VARIANT=$(strip \
|
|
+ $(if $(findstring openssl,$(LOCAL_AND_LIB_VARIANT)),openssl,\
|
|
+ $(if $(findstring wolfssl,$(LOCAL_AND_LIB_VARIANT)),wolfssl,\
|
|
+ $(if $(findstring mbedtls,$(LOCAL_AND_LIB_VARIANT)),mbedtls,\
|
|
+ internal\
|
|
+ ))))
|
|
+
|
|
+CONFIG_VARIANT:=$(LOCAL_VARIANT)
|
|
+ifeq ($(LOCAL_VARIANT),mesh)
|
|
+ CONFIG_VARIANT:=full
|
|
+endif
|
|
+
|
|
+include $(INCLUDE_DIR)/package.mk
|
|
+
|
|
+STAMP_CONFIGURED:=$(STAMP_CONFIGURED)_$(CONFIG_WPA_MSG_MIN_PRIORITY)
|
|
+
|
|
+ifneq ($(CONFIG_DRIVER_11AC_SUPPORT),)
|
|
+ HOSTAPD_IEEE80211AC:=y
|
|
+endif
|
|
+
|
|
+ifneq ($(CONFIG_DRIVER_11AX_SUPPORT),)
|
|
+ HOSTAPD_IEEE80211AX:=y
|
|
+endif
|
|
+
|
|
+CORE_DEPENDS = +ucode +libubus +libucode +ucode-mod-fs +ucode-mod-nl80211 +ucode-mod-rtnl +ucode-mod-ubus +ucode-mod-uloop +libblobmsg-json
|
|
+
|
|
+DRIVER_MAKEOPTS= \
|
|
+ CONFIG_ACS=$(CONFIG_PACKAGE_kmod-cfg80211) \
|
|
+ CONFIG_DRIVER_NL80211=$(CONFIG_PACKAGE_kmod-cfg80211) \
|
|
+ CONFIG_IEEE80211AC=$(HOSTAPD_IEEE80211AC) \
|
|
+ CONFIG_IEEE80211AX=$(HOSTAPD_IEEE80211AX) \
|
|
+ CONFIG_MBO=$(CONFIG_WPA_MBO_SUPPORT) \
|
|
+ CONFIG_UCODE=y
|
|
+
|
|
+ifeq ($(SSL_VARIANT),openssl)
|
|
+ DRIVER_MAKEOPTS += CONFIG_TLS=openssl CONFIG_SAE=y
|
|
+ TARGET_LDFLAGS += -lcrypto -lssl
|
|
+
|
|
+ ifeq ($(LOCAL_VARIANT),basic)
|
|
+ DRIVER_MAKEOPTS += CONFIG_OWE=y
|
|
+ endif
|
|
+ ifeq ($(LOCAL_VARIANT),mesh)
|
|
+ DRIVER_MAKEOPTS += CONFIG_AP=y CONFIG_MESH=y
|
|
+ endif
|
|
+ ifeq ($(LOCAL_VARIANT),full)
|
|
+ DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y
|
|
+ endif
|
|
+endif
|
|
+
|
|
+ifeq ($(SSL_VARIANT),wolfssl)
|
|
+ DRIVER_MAKEOPTS += CONFIG_TLS=wolfssl CONFIG_SAE=y
|
|
+ TARGET_LDFLAGS += -lwolfssl
|
|
+
|
|
+ ifeq ($(LOCAL_VARIANT),basic)
|
|
+ DRIVER_MAKEOPTS += CONFIG_OWE=y
|
|
+ endif
|
|
+ ifeq ($(LOCAL_VARIANT),mesh)
|
|
+ DRIVER_MAKEOPTS += CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1
|
|
+ endif
|
|
+ ifeq ($(LOCAL_VARIANT),full)
|
|
+ DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1
|
|
+ endif
|
|
+endif
|
|
+
|
|
+ifeq ($(SSL_VARIANT),mbedtls)
|
|
+ DRIVER_MAKEOPTS += CONFIG_TLS=mbedtls CONFIG_SAE=y
|
|
+ TARGET_LDFLAGS += -lmbedcrypto -lmbedx509 -lmbedtls
|
|
+
|
|
+ ifeq ($(LOCAL_VARIANT),basic)
|
|
+ DRIVER_MAKEOPTS += CONFIG_OWE=y
|
|
+ endif
|
|
+ ifeq ($(LOCAL_VARIANT),mesh)
|
|
+ DRIVER_MAKEOPTS += CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1
|
|
+ endif
|
|
+ ifeq ($(LOCAL_VARIANT),full)
|
|
+ DRIVER_MAKEOPTS += CONFIG_OWE=y CONFIG_SUITEB192=y CONFIG_AP=y CONFIG_MESH=y CONFIG_WPS_NFC=1
|
|
+ endif
|
|
+endif
|
|
+
|
|
+ifneq ($(LOCAL_TYPE),hostapd)
|
|
+ ifdef CONFIG_WPA_RFKILL_SUPPORT
|
|
+ DRIVER_MAKEOPTS += NEED_RFKILL=y
|
|
+ endif
|
|
+endif
|
|
+
|
|
+DRV_DEPENDS:=+PACKAGE_kmod-cfg80211:libnl-tiny
|
|
+
|
|
+
|
|
+define Package/hostapd/Default
|
|
+ SECTION:=net
|
|
+ CATEGORY:=Network
|
|
+ SUBMENU:=WirelessAPD
|
|
+ TITLE:=IEEE 802.1x Authenticator
|
|
+ URL:=http://hostap.epitest.fi/
|
|
+ DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS)
|
|
+ EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE))
|
|
+ USERID:=network=101:network=101
|
|
+ PROVIDES:=hostapd
|
|
+ CONFLICTS:=$(HOSTAPD_PROVIDERS)
|
|
+ HOSTAPD_PROVIDERS+=$(1)
|
|
+endef
|
|
+
|
|
+define Package/hostapd
|
|
+$(call Package/hostapd/Default,$(1))
|
|
+ TITLE+= (built-in full)
|
|
+ VARIANT:=full-internal
|
|
+endef
|
|
+
|
|
+define Package/hostapd/description
|
|
+ This package contains a full featured IEEE 802.1x/WPA/EAP/RADIUS
|
|
+ Authenticator.
|
|
+endef
|
|
+
|
|
+define Package/hostapd-openssl
|
|
+$(call Package/hostapd/Default,$(1))
|
|
+ TITLE+= (OpenSSL full)
|
|
+ VARIANT:=full-openssl
|
|
+ DEPENDS+=+PACKAGE_hostapd-openssl:libopenssl
|
|
+endef
|
|
+
|
|
+Package/hostapd-openssl/description = $(Package/hostapd/description)
|
|
+
|
|
+define Package/hostapd-wolfssl
|
|
+$(call Package/hostapd/Default,$(1))
|
|
+ TITLE+= (wolfSSL full)
|
|
+ VARIANT:=full-wolfssl
|
|
+ DEPENDS+=+PACKAGE_hostapd-wolfssl:libwolfssl
|
|
+endef
|
|
+
|
|
+Package/hostapd-wolfssl/description = $(Package/hostapd/description)
|
|
+
|
|
+define Package/hostapd-mbedtls
|
|
+$(call Package/hostapd/Default,$(1))
|
|
+ TITLE+= (mbedTLS full)
|
|
+ VARIANT:=full-mbedtls
|
|
+ DEPENDS+=+PACKAGE_hostapd-mbedtls:libmbedtls
|
|
+endef
|
|
+
|
|
+Package/hostapd-mbedtls/description = $(Package/hostapd/description)
|
|
+
|
|
+define Package/hostapd-basic
|
|
+$(call Package/hostapd/Default,$(1))
|
|
+ TITLE+= (WPA-PSK, 11r, 11w)
|
|
+ VARIANT:=basic
|
|
+endef
|
|
+
|
|
+define Package/hostapd-basic/description
|
|
+ This package contains a basic IEEE 802.1x/WPA Authenticator with WPA-PSK, 802.11r and 802.11w support.
|
|
+endef
|
|
+
|
|
+define Package/hostapd-basic-openssl
|
|
+$(call Package/hostapd/Default,$(1))
|
|
+ TITLE+= (WPA-PSK, 11r and 11w)
|
|
+ VARIANT:=basic-openssl
|
|
+ DEPENDS+=+PACKAGE_hostapd-basic-openssl:libopenssl
|
|
+endef
|
|
+
|
|
+define Package/hostapd-basic-openssl/description
|
|
+ This package contains a basic IEEE 802.1x/WPA Authenticator with WPA-PSK, 802.11r and 802.11w support.
|
|
+endef
|
|
+
|
|
+define Package/hostapd-basic-wolfssl
|
|
+$(call Package/hostapd/Default,$(1))
|
|
+ TITLE+= (WPA-PSK, 11r and 11w)
|
|
+ VARIANT:=basic-wolfssl
|
|
+ DEPENDS+=+PACKAGE_hostapd-basic-wolfssl:libwolfssl
|
|
+endef
|
|
+
|
|
+define Package/hostapd-basic-wolfssl/description
|
|
+ This package contains a basic IEEE 802.1x/WPA Authenticator with WPA-PSK, 802.11r and 802.11w support.
|
|
+endef
|
|
+
|
|
+define Package/hostapd-basic-mbedtls
|
|
+$(call Package/hostapd/Default,$(1))
|
|
+ TITLE+= (WPA-PSK, 11r and 11w)
|
|
+ VARIANT:=basic-mbedtls
|
|
+ DEPENDS+=+PACKAGE_hostapd-basic-mbedtls:libmbedtls
|
|
+endef
|
|
+
|
|
+define Package/hostapd-basic-mbedtls/description
|
|
+ This package contains a basic IEEE 802.1x/WPA Authenticator with WPA-PSK, 802.11r and 802.11w support.
|
|
+endef
|
|
+
|
|
+define Package/hostapd-mini
|
|
+$(call Package/hostapd/Default,$(1))
|
|
+ TITLE+= (WPA-PSK only)
|
|
+ VARIANT:=mini
|
|
+endef
|
|
+
|
|
+define Package/hostapd-mini/description
|
|
+ This package contains a minimal IEEE 802.1x/WPA Authenticator (WPA-PSK only).
|
|
+endef
|
|
+
|
|
+
|
|
+define Package/wpad/Default
|
|
+ SECTION:=net
|
|
+ CATEGORY:=Network
|
|
+ SUBMENU:=WirelessAPD
|
|
+ TITLE:=IEEE 802.1x Auth/Supplicant
|
|
+ DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS)
|
|
+ EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE))
|
|
+ USERID:=network=101:network=101
|
|
+ URL:=http://hostap.epitest.fi/
|
|
+ PROVIDES:=hostapd wpa-supplicant
|
|
+ CONFLICTS:=$(HOSTAPD_PROVIDERS) $(SUPPLICANT_PROVIDERS)
|
|
+ HOSTAPD_PROVIDERS+=$(1)
|
|
+ SUPPLICANT_PROVIDERS+=$(1)
|
|
+endef
|
|
+
|
|
+define Package/wpad
|
|
+$(call Package/wpad/Default,$(1))
|
|
+ TITLE+= (built-in full)
|
|
+ VARIANT:=wpad-full-internal
|
|
+endef
|
|
+
|
|
+define Package/wpad/description
|
|
+ This package contains a full featured IEEE 802.1x/WPA/EAP/RADIUS
|
|
+ Authenticator and Supplicant
|
|
+endef
|
|
+
|
|
+define Package/wpad-openssl
|
|
+$(call Package/wpad/Default,$(1))
|
|
+ TITLE+= (OpenSSL full)
|
|
+ VARIANT:=wpad-full-openssl
|
|
+ DEPENDS+=+PACKAGE_wpad-openssl:libopenssl
|
|
+endef
|
|
+
|
|
+Package/wpad-openssl/description = $(Package/wpad/description)
|
|
+
|
|
+define Package/wpad-wolfssl
|
|
+$(call Package/wpad/Default,$(1))
|
|
+ TITLE+= (wolfSSL full)
|
|
+ VARIANT:=wpad-full-wolfssl
|
|
+ DEPENDS+=+PACKAGE_wpad-wolfssl:libwolfssl
|
|
+endef
|
|
+
|
|
+Package/wpad-wolfssl/description = $(Package/wpad/description)
|
|
+
|
|
+define Package/wpad-mbedtls
|
|
+$(call Package/wpad/Default,$(1))
|
|
+ TITLE+= (mbedTLS full)
|
|
+ VARIANT:=wpad-full-mbedtls
|
|
+ DEPENDS+=+PACKAGE_wpad-mbedtls:libmbedtls
|
|
+endef
|
|
+
|
|
+Package/wpad-mbedtls/description = $(Package/wpad/description)
|
|
+
|
|
+define Package/wpad-basic
|
|
+$(call Package/wpad/Default,$(1))
|
|
+ TITLE+= (WPA-PSK, 11r, 11w)
|
|
+ VARIANT:=wpad-basic
|
|
+endef
|
|
+
|
|
+define Package/wpad-basic/description
|
|
+ This package contains a basic IEEE 802.1x/WPA Authenticator and Supplicant with WPA-PSK, 802.11r and 802.11w support.
|
|
+endef
|
|
+
|
|
+define Package/wpad-basic-openssl
|
|
+$(call Package/wpad/Default,$(1))
|
|
+ TITLE+= (OpenSSL, 11r, 11w)
|
|
+ VARIANT:=wpad-basic-openssl
|
|
+ DEPENDS+=+PACKAGE_wpad-basic-openssl:libopenssl
|
|
+endef
|
|
+
|
|
+define Package/wpad-basic-openssl/description
|
|
+ This package contains a basic IEEE 802.1x/WPA Authenticator and Supplicant with WPA-PSK, SAE (WPA3-Personal), 802.11r and 802.11w support.
|
|
+endef
|
|
+
|
|
+define Package/wpad-basic-wolfssl
|
|
+$(call Package/wpad/Default,$(1))
|
|
+ TITLE+= (wolfSSL, 11r, 11w)
|
|
+ VARIANT:=wpad-basic-wolfssl
|
|
+ DEPENDS+=+PACKAGE_wpad-basic-wolfssl:libwolfssl
|
|
+endef
|
|
+
|
|
+define Package/wpad-basic-wolfssl/description
|
|
+ This package contains a basic IEEE 802.1x/WPA Authenticator and Supplicant with WPA-PSK, SAE (WPA3-Personal), 802.11r and 802.11w support.
|
|
+endef
|
|
+
|
|
+define Package/wpad-basic-mbedtls
|
|
+$(call Package/wpad/Default,$(1))
|
|
+ TITLE+= (mbedTLS, 11r, 11w)
|
|
+ VARIANT:=wpad-basic-mbedtls
|
|
+ DEPENDS+=+PACKAGE_wpad-basic-mbedtls:libmbedtls
|
|
+endef
|
|
+
|
|
+define Package/wpad-basic-mbedtls/description
|
|
+ This package contains a basic IEEE 802.1x/WPA Authenticator and Supplicant with WPA-PSK, SAE (WPA3-Personal), 802.11r and 802.11w support.
|
|
+endef
|
|
+
|
|
+define Package/wpad-mini
|
|
+$(call Package/wpad/Default,$(1))
|
|
+ TITLE+= (WPA-PSK only)
|
|
+ VARIANT:=wpad-mini
|
|
+endef
|
|
+
|
|
+define Package/wpad-mini/description
|
|
+ This package contains a minimal IEEE 802.1x/WPA Authenticator and Supplicant (WPA-PSK only).
|
|
+endef
|
|
+
|
|
+define Package/wpad-mesh
|
|
+$(call Package/wpad/Default,$(1))
|
|
+ DEPENDS+=@PACKAGE_kmod-cfg80211 @(!TARGET_uml||BROKEN)
|
|
+ PROVIDES+=wpa-supplicant-mesh wpad-mesh
|
|
+endef
|
|
+
|
|
+define Package/wpad-mesh/description
|
|
+ This package contains a minimal IEEE 802.1x/WPA Authenticator and Supplicant (with 802.11s mesh and SAE support).
|
|
+endef
|
|
+
|
|
+define Package/wpad-mesh-openssl
|
|
+$(call Package/wpad-mesh,$(1))
|
|
+ TITLE+= (OpenSSL, 11s, SAE)
|
|
+ DEPENDS+=+PACKAGE_wpad-mesh-openssl:libopenssl
|
|
+ VARIANT:=wpad-mesh-openssl
|
|
+endef
|
|
+
|
|
+Package/wpad-mesh-openssl/description = $(Package/wpad-mesh/description)
|
|
+
|
|
+define Package/wpad-mesh-wolfssl
|
|
+$(call Package/wpad-mesh,$(1))
|
|
+ TITLE+= (wolfSSL, 11s, SAE)
|
|
+ DEPENDS+=+PACKAGE_wpad-mesh-wolfssl:libwolfssl
|
|
+ VARIANT:=wpad-mesh-wolfssl
|
|
+endef
|
|
+
|
|
+Package/wpad-mesh-wolfssl/description = $(Package/wpad-mesh/description)
|
|
+
|
|
+define Package/wpad-mesh-mbedtls
|
|
+$(call Package/wpad-mesh,$(1))
|
|
+ TITLE+= (mbedTLS, 11s, SAE)
|
|
+ DEPENDS+=+PACKAGE_wpad-mesh-mbedtls:libmbedtls
|
|
+ VARIANT:=wpad-mesh-mbedtls
|
|
+endef
|
|
+
|
|
+Package/wpad-mesh-mbedtls/description = $(Package/wpad-mesh/description)
|
|
+
|
|
+
|
|
+define Package/wpa-supplicant/Default
|
|
+ SECTION:=net
|
|
+ CATEGORY:=Network
|
|
+ SUBMENU:=WirelessAPD
|
|
+ TITLE:=WPA Supplicant
|
|
+ URL:=http://hostap.epitest.fi/wpa_supplicant/
|
|
+ DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS)
|
|
+ EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE))
|
|
+ USERID:=network=101:network=101
|
|
+ PROVIDES:=wpa-supplicant
|
|
+ CONFLICTS:=$(SUPPLICANT_PROVIDERS)
|
|
+ SUPPLICANT_PROVIDERS+=$(1)
|
|
+endef
|
|
+
|
|
+define Package/wpa-supplicant
|
|
+$(call Package/wpa-supplicant/Default,$(1))
|
|
+ TITLE+= (built-in full)
|
|
+ VARIANT:=supplicant-full-internal
|
|
+endef
|
|
+
|
|
+define Package/wpa-supplicant-openssl
|
|
+$(call Package/wpa-supplicant/Default,$(1))
|
|
+ TITLE+= (OpenSSL full)
|
|
+ VARIANT:=supplicant-full-openssl
|
|
+ DEPENDS+=+PACKAGE_wpa-supplicant-openssl:libopenssl
|
|
+endef
|
|
+
|
|
+define Package/wpa-supplicant-wolfssl
|
|
+$(call Package/wpa-supplicant/Default,$(1))
|
|
+ TITLE+= (wolfSSL full)
|
|
+ VARIANT:=supplicant-full-wolfssl
|
|
+ DEPENDS+=+PACKAGE_wpa-supplicant-wolfssl:libwolfssl
|
|
+endef
|
|
+
|
|
+define Package/wpa-supplicant-mbedtls
|
|
+$(call Package/wpa-supplicant/Default,$(1))
|
|
+ TITLE+= (mbedTLS full)
|
|
+ VARIANT:=supplicant-full-mbedtls
|
|
+ DEPENDS+=+PACKAGE_wpa-supplicant-mbedtls:libmbedtls
|
|
+endef
|
|
+
|
|
+define Package/wpa-supplicant/config
|
|
+ source "$(SOURCE)/Config.in"
|
|
+endef
|
|
+
|
|
+define Package/wpa-supplicant-p2p
|
|
+$(call Package/wpa-supplicant/Default,$(1))
|
|
+ TITLE+= (Wi-Fi P2P support)
|
|
+ DEPENDS+=@PACKAGE_kmod-cfg80211
|
|
+ VARIANT:=supplicant-p2p-internal
|
|
+endef
|
|
+
|
|
+define Package/wpa-supplicant-mesh/Default
|
|
+$(call Package/wpa-supplicant/Default,$(1))
|
|
+ DEPENDS+=@PACKAGE_kmod-cfg80211 @(!TARGET_uml||BROKEN)
|
|
+ PROVIDES+=wpa-supplicant-mesh
|
|
+endef
|
|
+
|
|
+define Package/wpa-supplicant-mesh-openssl
|
|
+$(call Package/wpa-supplicant-mesh/Default,$(1))
|
|
+ TITLE+= (OpenSSL, 11s, SAE)
|
|
+ VARIANT:=supplicant-mesh-openssl
|
|
+ DEPENDS+=+PACKAGE_wpa-supplicant-mesh-openssl:libopenssl
|
|
+endef
|
|
+
|
|
+define Package/wpa-supplicant-mesh-wolfssl
|
|
+$(call Package/wpa-supplicant-mesh/Default,$(1))
|
|
+ TITLE+= (wolfSSL, 11s, SAE)
|
|
+ VARIANT:=supplicant-mesh-wolfssl
|
|
+ DEPENDS+=+PACKAGE_wpa-supplicant-mesh-wolfssl:libwolfssl
|
|
+endef
|
|
+
|
|
+define Package/wpa-supplicant-mesh-mbedtls
|
|
+$(call Package/wpa-supplicant-mesh/Default,$(1))
|
|
+ TITLE+= (mbedTLS, 11s, SAE)
|
|
+ VARIANT:=supplicant-mesh-mbedtls
|
|
+ DEPENDS+=+PACKAGE_wpa-supplicant-mesh-mbedtls:libmbedtls
|
|
+endef
|
|
+
|
|
+define Package/wpa-supplicant-basic
|
|
+$(call Package/wpa-supplicant/Default,$(1))
|
|
+ TITLE+= (11r, 11w)
|
|
+ VARIANT:=supplicant-basic
|
|
+endef
|
|
+
|
|
+define Package/wpa-supplicant-mini
|
|
+$(call Package/wpa-supplicant/Default,$(1))
|
|
+ TITLE+= (minimal)
|
|
+ VARIANT:=supplicant-mini
|
|
+endef
|
|
+
|
|
+
|
|
+define Package/hostapd-common
|
|
+ TITLE:=hostapd/wpa_supplicant common support files
|
|
+ SECTION:=net
|
|
+ CATEGORY:=Network
|
|
+ SUBMENU:=WirelessAPD
|
|
+endef
|
|
+
|
|
+define Package/hostapd-utils
|
|
+ SECTION:=net
|
|
+ CATEGORY:=Network
|
|
+ SUBMENU:=WirelessAPD
|
|
+ TITLE:=IEEE 802.1x Authenticator (utils)
|
|
+ URL:=http://hostap.epitest.fi/
|
|
+ DEPENDS:=@$(subst $(space),||,$(foreach pkg,$(HOSTAPD_PROVIDERS),PACKAGE_$(pkg)))
|
|
+ VARIANT:=*
|
|
+endef
|
|
+
|
|
+define Package/hostapd-utils/description
|
|
+ This package contains a command line utility to control the
|
|
+ IEEE 802.1x/WPA/EAP/RADIUS Authenticator.
|
|
+endef
|
|
+
|
|
+define Package/wpa-cli
|
|
+ SECTION:=net
|
|
+ CATEGORY:=Network
|
|
+ SUBMENU:=WirelessAPD
|
|
+ DEPENDS:=@$(subst $(space),||,$(foreach pkg,$(SUPPLICANT_PROVIDERS),PACKAGE_$(pkg)))
|
|
+ TITLE:=WPA Supplicant command line control utility
|
|
+ VARIANT:=*
|
|
+endef
|
|
+
|
|
+define Package/eapol-test/Default
|
|
+ TITLE:=802.1x auth test utility
|
|
+ SECTION:=net
|
|
+ SUBMENU:=WirelessAPD
|
|
+ CATEGORY:=Network
|
|
+ DEPENDS:=$(DRV_DEPENDS) $(CORE_DEPENDS)
|
|
+endef
|
|
+
|
|
+define Package/eapol-test
|
|
+ $(call Package/eapol-test/Default,$(1))
|
|
+ TITLE+= (built-in full)
|
|
+ VARIANT:=supplicant-full-internal
|
|
+endef
|
|
+
|
|
+define Package/eapol-test-openssl
|
|
+ $(call Package/eapol-test/Default,$(1))
|
|
+ TITLE+= (OpenSSL full)
|
|
+ VARIANT:=supplicant-full-openssl
|
|
+ CONFLICTS:=$(filter-out eapol-test-openssl ,$(EAPOL_TEST_PROVIDERS))
|
|
+ DEPENDS+=+PACKAGE_eapol-test-openssl:libopenssl
|
|
+ PROVIDES:=eapol-test
|
|
+endef
|
|
+
|
|
+define Package/eapol-test-wolfssl
|
|
+ $(call Package/eapol-test/Default,$(1))
|
|
+ TITLE+= (wolfSSL full)
|
|
+ VARIANT:=supplicant-full-wolfssl
|
|
+ CONFLICTS:=$(filter-out eapol-test-openssl ,$(filter-out eapol-test-wolfssl ,$(EAPOL_TEST_PROVIDERS)))
|
|
+ DEPENDS+=+PACKAGE_eapol-test-wolfssl:libwolfssl
|
|
+ PROVIDES:=eapol-test
|
|
+endef
|
|
+
|
|
+define Package/eapol-test-mbedtls
|
|
+ $(call Package/eapol-test/Default,$(1))
|
|
+ TITLE+= (mbedTLS full)
|
|
+ VARIANT:=supplicant-full-mbedtls
|
|
+ CONFLICTS:=$(filter-out eapol-test-openssl ,$(filter-out eapol-test-mbedtls ,$(EAPOL_TEST_PROVIDERS)))
|
|
+ DEPENDS+=+PACKAGE_eapol-test-mbedtls:libmbedtls
|
|
+ PROVIDES:=eapol-test
|
|
+endef
|
|
+
|
|
+
|
|
+ifneq ($(wildcard $(PKG_BUILD_DIR)/.config_*),$(subst .configured_,.config_,$(STAMP_CONFIGURED)))
|
|
+ define Build/Configure/rebuild
|
|
+ $(FIND) $(PKG_BUILD_DIR) -name \*.o -or -name \*.a | $(XARGS) rm -f
|
|
+ rm -f $(PKG_BUILD_DIR)/hostapd/hostapd
|
|
+ rm -f $(PKG_BUILD_DIR)/wpa_supplicant/wpa_supplicant
|
|
+ rm -f $(PKG_BUILD_DIR)/.config_*
|
|
+ touch $(subst .configured_,.config_,$(STAMP_CONFIGURED))
|
|
+ endef
|
|
+endif
|
|
+
|
|
+define Build/Configure
|
|
+ $(Build/Configure/rebuild)
|
|
+ $(if $(wildcard ./files/hostapd-$(CONFIG_VARIANT).config), \
|
|
+ $(CP) ./files/hostapd-$(CONFIG_VARIANT).config $(PKG_BUILD_DIR)/hostapd/.config \
|
|
+ )
|
|
+ $(if $(wildcard ./files/wpa_supplicant-$(CONFIG_VARIANT).config), \
|
|
+ $(CP) ./files/wpa_supplicant-$(CONFIG_VARIANT).config $(PKG_BUILD_DIR)/wpa_supplicant/.config
|
|
+ )
|
|
+endef
|
|
+
|
|
+TARGET_CPPFLAGS := \
|
|
+ -I$(STAGING_DIR)/usr/include/libnl-tiny \
|
|
+ -I$(PKG_BUILD_DIR)/src/crypto \
|
|
+ $(TARGET_CPPFLAGS) \
|
|
+ -DCONFIG_LIBNL20 \
|
|
+ -D_GNU_SOURCE \
|
|
+ $(if $(CONFIG_WPA_MSG_MIN_PRIORITY),-DCONFIG_MSG_MIN_PRIORITY=$(CONFIG_WPA_MSG_MIN_PRIORITY))
|
|
+
|
|
+TARGET_LDFLAGS += -lubox -lubus -lblobmsg_json -lucode
|
|
+
|
|
+ifdef CONFIG_PACKAGE_kmod-cfg80211
|
|
+ TARGET_LDFLAGS += -lm -lnl-tiny
|
|
+endif
|
|
+
|
|
+ifdef CONFIG_WPA_ENABLE_WEP
|
|
+ DRIVER_MAKEOPTS += CONFIG_WEP=y
|
|
+endif
|
|
+
|
|
+define Build/RunMake
|
|
+ CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \
|
|
+ $(MAKE) $(PKG_JOBS) -C $(PKG_BUILD_DIR)/$(1) \
|
|
+ $(TARGET_CONFIGURE_OPTS) \
|
|
+ $(DRIVER_MAKEOPTS) \
|
|
+ LIBS="$(TARGET_LDFLAGS)" \
|
|
+ LIBS_c="$(TARGET_LDFLAGS_C)" \
|
|
+ AR="$(TARGET_CROSS)gcc-ar" \
|
|
+ BCHECK= \
|
|
+ $(if $(findstring s,$(OPENWRT_VERBOSE)),V=1) \
|
|
+ $(2)
|
|
+endef
|
|
+
|
|
+define Build/Compile/wpad
|
|
+ echo ` \
|
|
+ $(call Build/RunMake,hostapd,-s MULTICALL=1 dump_cflags); \
|
|
+ $(call Build/RunMake,wpa_supplicant,-s MULTICALL=1 dump_cflags) | \
|
|
+ sed -e 's,-n ,,g' -e 's^$(TARGET_CFLAGS)^^' \
|
|
+ ` > $(PKG_BUILD_DIR)/.cflags
|
|
+ sed -i 's/"/\\"/g' $(PKG_BUILD_DIR)/.cflags
|
|
+ +$(call Build/RunMake,hostapd, \
|
|
+ CFLAGS="$$$$(cat $(PKG_BUILD_DIR)/.cflags)" \
|
|
+ MULTICALL=1 \
|
|
+ hostapd_cli hostapd_multi.a \
|
|
+ )
|
|
+ +$(call Build/RunMake,wpa_supplicant, \
|
|
+ CFLAGS="$$$$(cat $(PKG_BUILD_DIR)/.cflags)" \
|
|
+ MULTICALL=1 \
|
|
+ wpa_cli wpa_supplicant_multi.a \
|
|
+ )
|
|
+ +export MAKEFLAGS="$(MAKE_JOBSERVER)"; $(TARGET_CC) -o $(PKG_BUILD_DIR)/wpad \
|
|
+ $(TARGET_CFLAGS) \
|
|
+ ./files/multicall.c \
|
|
+ $(PKG_BUILD_DIR)/hostapd/hostapd_multi.a \
|
|
+ $(PKG_BUILD_DIR)/wpa_supplicant/wpa_supplicant_multi.a \
|
|
+ $(TARGET_LDFLAGS)
|
|
+endef
|
|
+
|
|
+define Build/Compile/hostapd
|
|
+ +$(call Build/RunMake,hostapd, \
|
|
+ hostapd hostapd_cli \
|
|
+ )
|
|
+endef
|
|
+
|
|
+define Build/Compile/supplicant
|
|
+ +$(call Build/RunMake,wpa_supplicant, \
|
|
+ wpa_cli wpa_supplicant \
|
|
+ )
|
|
+endef
|
|
+
|
|
+define Build/Compile/supplicant-full-internal
|
|
+ +$(call Build/RunMake,wpa_supplicant, \
|
|
+ eapol_test \
|
|
+ )
|
|
+endef
|
|
+
|
|
+define Build/Compile/supplicant-full-openssl
|
|
+ +$(call Build/RunMake,wpa_supplicant, \
|
|
+ eapol_test \
|
|
+ )
|
|
+endef
|
|
+
|
|
+define Build/Compile/supplicant-full-wolfssl
|
|
+ +$(call Build/RunMake,wpa_supplicant, \
|
|
+ eapol_test \
|
|
+ )
|
|
+endef
|
|
+
|
|
+define Build/Compile/supplicant-full-mbedtls
|
|
+ +$(call Build/RunMake,wpa_supplicant, \
|
|
+ eapol_test \
|
|
+ )
|
|
+endef
|
|
+
|
|
+define Build/Compile
|
|
+ $(Build/Compile/$(LOCAL_TYPE))
|
|
+ $(Build/Compile/$(BUILD_VARIANT))
|
|
+endef
|
|
+
|
|
+define Install/hostapd/full
|
|
+ $(INSTALL_DIR) $(1)/etc/init.d $(1)/etc/config $(1)/etc/radius
|
|
+ ln -sf hostapd $(1)/usr/sbin/hostapd-radius
|
|
+ $(INSTALL_BIN) ./files/radius.init $(1)/etc/init.d/radius
|
|
+ $(INSTALL_DATA) ./files/radius.config $(1)/etc/config/radius
|
|
+ $(INSTALL_DATA) ./files/radius.clients $(1)/etc/radius/clients
|
|
+ $(INSTALL_DATA) ./files/radius.users $(1)/etc/radius/users
|
|
+endef
|
|
+
|
|
+define Package/hostapd-full/conffiles
|
|
+/etc/config/radius
|
|
+/etc/radius
|
|
+endef
|
|
+
|
|
+ifeq ($(CONFIG_VARIANT),full)
|
|
+Package/wpad-mesh-openssl/conffiles = $(Package/hostapd-full/conffiles)
|
|
+Package/wpad-mesh-wolfssl/conffiles = $(Package/hostapd-full/conffiles)
|
|
+Package/wpad-mesh-mbedtls/conffiles = $(Package/hostapd-full/conffiles)
|
|
+Package/wpad/conffiles = $(Package/hostapd-full/conffiles)
|
|
+Package/wpad-openssl/conffiles = $(Package/hostapd-full/conffiles)
|
|
+Package/wpad-wolfssl/conffiles = $(Package/hostapd-full/conffiles)
|
|
+Package/wpad-mbedtls/conffiles = $(Package/hostapd-full/conffiles)
|
|
+Package/hostapd/conffiles = $(Package/hostapd-full/conffiles)
|
|
+Package/hostapd-openssl/conffiles = $(Package/hostapd-full/conffiles)
|
|
+Package/hostapd-wolfssl/conffiles = $(Package/hostapd-full/conffiles)
|
|
+Package/hostapd-mbedtls/conffiles = $(Package/hostapd-full/conffiles)
|
|
+endif
|
|
+
|
|
+define Install/hostapd
|
|
+ $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/hostap
|
|
+ $(INSTALL_DATA) ./files/hostapd.uc $(1)/usr/share/hostap/
|
|
+ $(if $(findstring full,$(CONFIG_VARIANT)),$(Install/hostapd/full))
|
|
+endef
|
|
+
|
|
+define Install/supplicant
|
|
+ $(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/hostap
|
|
+ $(INSTALL_DATA) ./files/wpa_supplicant.uc $(1)/usr/share/hostap/
|
|
+endef
|
|
+
|
|
+define Package/hostapd-common/install
|
|
+ $(INSTALL_DIR) $(1)/etc/capabilities $(1)/etc/rc.button $(1)/etc/hotplug.d/ieee80211 $(1)/etc/init.d $(1)/lib/netifd $(1)/usr/share/acl.d $(1)/usr/share/hostap
|
|
+ $(INSTALL_BIN) ./files/dhcp-get-server.sh $(1)/lib/netifd/dhcp-get-server.sh
|
|
+ $(INSTALL_DATA) ./files/hostapd.sh $(1)/lib/netifd/hostapd.sh
|
|
+ $(INSTALL_BIN) ./files/wpad.init $(1)/etc/init.d/wpad
|
|
+ $(INSTALL_BIN) ./files/wps-hotplug.sh $(1)/etc/rc.button/wps
|
|
+ $(INSTALL_DATA) ./files/wpad_acl.json $(1)/usr/share/acl.d
|
|
+ $(INSTALL_DATA) ./files/wpad.json $(1)/etc/capabilities
|
|
+ $(INSTALL_DATA) ./files/common.uc $(1)/usr/share/hostap/
|
|
+ $(INSTALL_DATA) ./files/wdev.uc $(1)/usr/share/hostap/
|
|
+endef
|
|
+
|
|
+define Package/hostapd/install
|
|
+ $(call Install/hostapd,$(1))
|
|
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostapd/hostapd $(1)/usr/sbin/
|
|
+endef
|
|
+Package/hostapd-basic/install = $(Package/hostapd/install)
|
|
+Package/hostapd-basic-openssl/install = $(Package/hostapd/install)
|
|
+Package/hostapd-basic-wolfssl/install = $(Package/hostapd/install)
|
|
+Package/hostapd-basic-mbedtls/install = $(Package/hostapd/install)
|
|
+Package/hostapd-mini/install = $(Package/hostapd/install)
|
|
+Package/hostapd-openssl/install = $(Package/hostapd/install)
|
|
+Package/hostapd-wolfssl/install = $(Package/hostapd/install)
|
|
+Package/hostapd-mbedtls/install = $(Package/hostapd/install)
|
|
+
|
|
+ifneq ($(LOCAL_TYPE),supplicant)
|
|
+ define Package/hostapd-utils/install
|
|
+ $(INSTALL_DIR) $(1)/usr/sbin
|
|
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/hostapd/hostapd_cli $(1)/usr/sbin/
|
|
+ endef
|
|
+endif
|
|
+
|
|
+define Package/wpad/install
|
|
+ $(call Install/hostapd,$(1))
|
|
+ $(call Install/supplicant,$(1))
|
|
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/wpad $(1)/usr/sbin/
|
|
+ $(LN) wpad $(1)/usr/sbin/hostapd
|
|
+ $(LN) wpad $(1)/usr/sbin/wpa_supplicant
|
|
+endef
|
|
+Package/wpad-basic/install = $(Package/wpad/install)
|
|
+Package/wpad-basic-openssl/install = $(Package/wpad/install)
|
|
+Package/wpad-basic-wolfssl/install = $(Package/wpad/install)
|
|
+Package/wpad-basic-mbedtls/install = $(Package/wpad/install)
|
|
+Package/wpad-mini/install = $(Package/wpad/install)
|
|
+Package/wpad-openssl/install = $(Package/wpad/install)
|
|
+Package/wpad-wolfssl/install = $(Package/wpad/install)
|
|
+Package/wpad-mbedtls/install = $(Package/wpad/install)
|
|
+Package/wpad-mesh-openssl/install = $(Package/wpad/install)
|
|
+Package/wpad-mesh-wolfssl/install = $(Package/wpad/install)
|
|
+Package/wpad-mesh-mbedtls/install = $(Package/wpad/install)
|
|
+
|
|
+define Package/wpa-supplicant/install
|
|
+ $(call Install/supplicant,$(1))
|
|
+ $(INSTALL_BIN) $(PKG_BUILD_DIR)/wpa_supplicant/wpa_supplicant $(1)/usr/sbin/
|
|
+endef
|
|
+Package/wpa-supplicant-basic/install = $(Package/wpa-supplicant/install)
|
|
+Package/wpa-supplicant-mini/install = $(Package/wpa-supplicant/install)
|
|
+Package/wpa-supplicant-p2p/install = $(Package/wpa-supplicant/install)
|
|
+Package/wpa-supplicant-openssl/install = $(Package/wpa-supplicant/install)
|
|
+Package/wpa-supplicant-wolfssl/install = $(Package/wpa-supplicant/install)
|
|
+Package/wpa-supplicant-mbedtls/install = $(Package/wpa-supplicant/install)
|
|
+Package/wpa-supplicant-mesh-openssl/install = $(Package/wpa-supplicant/install)
|
|
+Package/wpa-supplicant-mesh-wolfssl/install = $(Package/wpa-supplicant/install)
|
|
+Package/wpa-supplicant-mesh-mbedtls/install = $(Package/wpa-supplicant/install)
|
|
+
|
|
+ifneq ($(LOCAL_TYPE),hostapd)
|
|
+ define Package/wpa-cli/install
|
|
+ $(INSTALL_DIR) $(1)/usr/sbin
|
|
+ $(CP) $(PKG_BUILD_DIR)/wpa_supplicant/wpa_cli $(1)/usr/sbin/
|
|
+ endef
|
|
+endif
|
|
+
|
|
+ifeq ($(BUILD_VARIANT),supplicant-full-internal)
|
|
+ define Package/eapol-test/install
|
|
+ $(INSTALL_DIR) $(1)/usr/sbin
|
|
+ $(CP) $(PKG_BUILD_DIR)/wpa_supplicant/eapol_test $(1)/usr/sbin/
|
|
+ endef
|
|
+endif
|
|
+
|
|
+ifeq ($(BUILD_VARIANT),supplicant-full-openssl)
|
|
+ define Package/eapol-test-openssl/install
|
|
+ $(INSTALL_DIR) $(1)/usr/sbin
|
|
+ $(CP) $(PKG_BUILD_DIR)/wpa_supplicant/eapol_test $(1)/usr/sbin/
|
|
+ endef
|
|
+endif
|
|
+
|
|
+ifeq ($(BUILD_VARIANT),supplicant-full-wolfssl)
|
|
+ define Package/eapol-test-wolfssl/install
|
|
+ $(INSTALL_DIR) $(1)/usr/sbin
|
|
+ $(CP) $(PKG_BUILD_DIR)/wpa_supplicant/eapol_test $(1)/usr/sbin/
|
|
+ endef
|
|
+endif
|
|
+
|
|
+ifeq ($(BUILD_VARIANT),supplicant-full-mbedtls)
|
|
+ define Package/eapol-test-mbedtls/install
|
|
+ $(INSTALL_DIR) $(1)/usr/sbin
|
|
+ $(CP) $(PKG_BUILD_DIR)/wpa_supplicant/eapol_test $(1)/usr/sbin/
|
|
+ endef
|
|
+endif
|
|
+
|
|
+# Build hostapd-common before its dependents, to avoid
|
|
+# spurious rebuilds when building multiple variants.
|
|
+$(eval $(call BuildPackage,hostapd-common))
|
|
+$(eval $(call BuildPackage,hostapd))
|
|
+$(eval $(call BuildPackage,hostapd-basic))
|
|
+$(eval $(call BuildPackage,hostapd-basic-openssl))
|
|
+$(eval $(call BuildPackage,hostapd-basic-wolfssl))
|
|
+$(eval $(call BuildPackage,hostapd-basic-mbedtls))
|
|
+$(eval $(call BuildPackage,hostapd-mini))
|
|
+$(eval $(call BuildPackage,hostapd-openssl))
|
|
+$(eval $(call BuildPackage,hostapd-wolfssl))
|
|
+$(eval $(call BuildPackage,hostapd-mbedtls))
|
|
+$(eval $(call BuildPackage,wpad))
|
|
+$(eval $(call BuildPackage,wpad-mesh-openssl))
|
|
+$(eval $(call BuildPackage,wpad-mesh-wolfssl))
|
|
+$(eval $(call BuildPackage,wpad-mesh-mbedtls))
|
|
+$(eval $(call BuildPackage,wpad-basic))
|
|
+$(eval $(call BuildPackage,wpad-basic-openssl))
|
|
+$(eval $(call BuildPackage,wpad-basic-wolfssl))
|
|
+$(eval $(call BuildPackage,wpad-basic-mbedtls))
|
|
+$(eval $(call BuildPackage,wpad-mini))
|
|
+$(eval $(call BuildPackage,wpad-openssl))
|
|
+$(eval $(call BuildPackage,wpad-wolfssl))
|
|
+$(eval $(call BuildPackage,wpad-mbedtls))
|
|
+$(eval $(call BuildPackage,wpa-supplicant))
|
|
+$(eval $(call BuildPackage,wpa-supplicant-mesh-openssl))
|
|
+$(eval $(call BuildPackage,wpa-supplicant-mesh-wolfssl))
|
|
+$(eval $(call BuildPackage,wpa-supplicant-mesh-mbedtls))
|
|
+$(eval $(call BuildPackage,wpa-supplicant-basic))
|
|
+$(eval $(call BuildPackage,wpa-supplicant-mini))
|
|
+$(eval $(call BuildPackage,wpa-supplicant-p2p))
|
|
+$(eval $(call BuildPackage,wpa-supplicant-openssl))
|
|
+$(eval $(call BuildPackage,wpa-supplicant-wolfssl))
|
|
+$(eval $(call BuildPackage,wpa-supplicant-mbedtls))
|
|
+$(eval $(call BuildPackage,wpa-cli))
|
|
+$(eval $(call BuildPackage,hostapd-utils))
|
|
+$(eval $(call BuildPackage,eapol-test))
|
|
+$(eval $(call BuildPackage,eapol-test-openssl))
|
|
+$(eval $(call BuildPackage,eapol-test-wolfssl))
|
|
+$(eval $(call BuildPackage,eapol-test-mbedtls))
|
|
diff --git a/package/network/services/hostapd/README.md b/package/network/services/hostapd/README.md
|
|
new file mode 100644
|
|
index 0000000000..2150863306
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/README.md
|
|
@@ -0,0 +1,419 @@
|
|
+# UBUS methods - hostapd
|
|
+
|
|
+## bss_mgmt_enable
|
|
+Enable 802.11k/v features.
|
|
+
|
|
+### arguments
|
|
+| Name | Type | Required | Description |
|
|
+|---|---|---|---|
|
|
+| neighbor_report | bool | no | enable 802.11k neighbor reports |
|
|
+| beacon_report | bool | no | enable 802.11k beacon reports |
|
|
+| link_measurements | bool | no | enable 802.11k link measurements |
|
|
+| bss_transition | bool | no | enable 802.11v BSS transition support |
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb bss_mgmt_enable '{ "neighbor_report": true, "beacon_report": true, "link_measurements": true, "bss_transition": true
|
|
+}'`
|
|
+
|
|
+
|
|
+## bss_transition_request
|
|
+Initiate an 802.11v transition request.
|
|
+
|
|
+### arguments
|
|
+| Name | Type | Required | Description |
|
|
+|---|---|---|---|
|
|
+| addr | string | yes | client MAC address |
|
|
+| disassociation_imminent | bool | no | set Disassociation Imminent bit |
|
|
+| disassociation_timer | int32 | no | disassociate client if it doesn't roam after this time |
|
|
+| validity_period | int32 | no | validity of the BSS Transition Candiate List |
|
|
+| neighbors | array | no | BSS Transition Candidate List |
|
|
+| abridged | bool | no | prefer APs in the BSS Transition Candidate List |
|
|
+| dialog_token | int32 | no | identifier for the request/report transaction |
|
|
+| mbo_reason | int32 | no | MBO Transition Reason Code Attribute |
|
|
+| cell_pref | int32 | no | MBO Cellular Data Connection Preference Attribute |
|
|
+| reassoc_delay | int32 | no | MBO Re-association retry delay |
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb bss_transition_request '{ "addr": "68:2F:67:8B:98:ED", "disassociation_imminent": false, "disassociation_timer": 0, "validity_period": 30, "neighbors": ["b6a7b9cbeebabf5900008064090603026a00"], "abridged": 1 }'`
|
|
+
|
|
+
|
|
+## config_add
|
|
+Dynamically load a BSS configuration from a file. This is used by netifd's mac80211 support script to configure BSSes on multiple PHYs in a single hostapd instance.
|
|
+
|
|
+### arguments
|
|
+| Name | Type | Required | Description |
|
|
+|---|---|---|---|
|
|
+| iface | string | yes | WiFi interface name |
|
|
+| config | string | yes | path to hostapd config file |
|
|
+
|
|
+
|
|
+## config_remove
|
|
+Dynamically remove a BSS configuration.
|
|
+
|
|
+### arguments
|
|
+| Name | Type | Required | Description |
|
|
+|---|---|---|---|
|
|
+| iface | string | yes | WiFi interface name |
|
|
+
|
|
+
|
|
+## del_client
|
|
+Kick a client off the network.
|
|
+
|
|
+### arguments
|
|
+| Name | Type | Required | Description |
|
|
+|---|---|---|---|
|
|
+| addr | string | yes | client MAC address |
|
|
+| reason | int32 | no | 802.11 reason code |
|
|
+| deauth | bool | no | deauthenticates client instead of disassociating |
|
|
+| ban_time | int32 | no | ban client for N milliseconds |
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb del_client '{ "addr": "68:2f:67:8b:98:ed", "reason": 5, "deauth": true, "ban_time": 10000 }'`
|
|
+
|
|
+
|
|
+## get_clients
|
|
+Show associated clients.
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb get_clients`
|
|
+
|
|
+### output
|
|
+```json
|
|
+{
|
|
+ "freq": 5260,
|
|
+ "clients": {
|
|
+ "68:2f:67:8b:98:ed": {
|
|
+ "auth": true,
|
|
+ "assoc": true,
|
|
+ "authorized": true,
|
|
+ "preauth": false,
|
|
+ "wds": false,
|
|
+ "wmm": true,
|
|
+ "ht": true,
|
|
+ "vht": true,
|
|
+ "he": false,
|
|
+ "wps": false,
|
|
+ "mfp": true,
|
|
+ "rrm": [
|
|
+ 0,
|
|
+ 0,
|
|
+ 0,
|
|
+ 0,
|
|
+ 0
|
|
+ ],
|
|
+ "extended_capabilities": [
|
|
+ 0,
|
|
+ 0,
|
|
+ 0,
|
|
+ 0,
|
|
+ 0,
|
|
+ 0,
|
|
+ 0,
|
|
+ 64
|
|
+ ],
|
|
+ "aid": 3,
|
|
+ "signature": "wifi4|probe:0,1,45,127,107,191,221(0017f2,10),221(001018,2),htcap:006f,htagg:1b,htmcs:0000ffff,vhtcap:0f825832,vhtrxmcs:0000ffea,vhttxmcs:0000ffea,extcap:0000008000000040|assoc:0,1,33,36,48,45,127,191,221(0017f2,10),221(001018,2),221(0050f2,2),htcap:006f,htagg:1b,htmcs:0000ffff,vhtcap:0f825832,vhtrxmcs:0000ffea,vhttxmcs:0000ffea,txpow:14f9,extcap:0000000000000040",
|
|
+ "bytes": {
|
|
+ "rx": 1933667,
|
|
+ "tx": 746805
|
|
+ },
|
|
+ "airtime": {
|
|
+ "rx": 208863,
|
|
+ "tx": 9037883
|
|
+ },
|
|
+ "packets": {
|
|
+ "rx": 3587,
|
|
+ "tx": 2185
|
|
+ },
|
|
+ "rate": {
|
|
+ "rx": 866700,
|
|
+ "tx": 866700
|
|
+ },
|
|
+ "signal": -50,
|
|
+ "capabilities": {
|
|
+ "vht": {
|
|
+ "su_beamformee": true,
|
|
+ "mu_beamformee": false,
|
|
+ "mcs_map": {
|
|
+ "rx": {
|
|
+ "1ss": 9,
|
|
+ "2ss": 9,
|
|
+ "3ss": 9,
|
|
+ "4ss": -1,
|
|
+ "5ss": -1,
|
|
+ "6ss": -1,
|
|
+ "7ss": -1,
|
|
+ "8ss": -1
|
|
+ },
|
|
+ "tx": {
|
|
+ "1ss": 9,
|
|
+ "2ss": 9,
|
|
+ "3ss": 9,
|
|
+ "4ss": -1,
|
|
+ "5ss": -1,
|
|
+ "6ss": -1,
|
|
+ "7ss": -1,
|
|
+ "8ss": -1
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+}
|
|
+```
|
|
+
|
|
+
|
|
+## get_features
|
|
+Show HT/VHT support.
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb get_features`
|
|
+
|
|
+### output
|
|
+```json
|
|
+{
|
|
+ "ht_supported": true,
|
|
+ "vht_supported": true
|
|
+}
|
|
+```
|
|
+
|
|
+
|
|
+## get_status
|
|
+Get BSS status.
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb get_status`
|
|
+
|
|
+### output
|
|
+```json
|
|
+{
|
|
+ "status": "ENABLED",
|
|
+ "bssid": "b6:a7:b9:cb:ee:bc",
|
|
+ "ssid": "fb",
|
|
+ "freq": 5260,
|
|
+ "channel": 52,
|
|
+ "op_class": 128,
|
|
+ "beacon_interval": 100,
|
|
+ "phy": "wl5-lan",
|
|
+ "rrm": {
|
|
+ "neighbor_report_tx": 0
|
|
+ },
|
|
+ "wnm": {
|
|
+ "bss_transition_query_rx": 0,
|
|
+ "bss_transition_request_tx": 0,
|
|
+ "bss_transition_response_rx": 0
|
|
+ },
|
|
+ "airtime": {
|
|
+ "time": 259561738,
|
|
+ "time_busy": 2844249,
|
|
+ "utilization": 0
|
|
+ },
|
|
+ "dfs": {
|
|
+ "cac_seconds": 60,
|
|
+ "cac_active": false,
|
|
+ "cac_seconds_left": 0
|
|
+ }
|
|
+}
|
|
+```
|
|
+
|
|
+
|
|
+## link_measurement_req
|
|
+Initiate an 802.11k Link Measurement Request.
|
|
+
|
|
+### arguments
|
|
+| Name | Type | Required | Description |
|
|
+|---|---|---|---|
|
|
+| addr | string | yes | client MAC address |
|
|
+| tx-power-used | int32 | no | transmit power used to transmit the Link Measurement Request frame |
|
|
+| tx-power-max | int32 | no | upper limit of transmit power to be used by the client |
|
|
+
|
|
+
|
|
+## list_bans
|
|
+List banned clients.
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb list_bans`
|
|
+
|
|
+### output
|
|
+```json
|
|
+{
|
|
+ "clients": [
|
|
+ "68:2f:67:8b:98:ed"
|
|
+ ]
|
|
+}
|
|
+```
|
|
+
|
|
+
|
|
+## notify_response
|
|
+When enabled, hostapd will send a ubus notification and wait for a response before responding to various requests. This is used by e.g. usteer to make it possible to ignore probe requests.
|
|
+
|
|
+:warning: enabling this will cause hostapd to stop responding to probe requests unless a ubus subscriber responds to the ubus notifications.
|
|
+
|
|
+### arguments
|
|
+| Name | Type | Required | Description |
|
|
+|---|---|---|---|
|
|
+| notify_response | int32 | yes | disable (0) or enable (!0) |
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb notify_response '{ "notify_response": 1 }'`
|
|
+
|
|
+## reload
|
|
+Reload BSS configuration.
|
|
+
|
|
+:warning: this can cause problems for certain configurations:
|
|
+
|
|
+```
|
|
+Mon May 16 16:09:08 2022 daemon.warn hostapd: Failed to check if DFS is required; ret=-1
|
|
+Mon May 16 16:09:08 2022 daemon.warn hostapd: Failed to check if DFS is required; ret=-1
|
|
+Mon May 16 16:09:08 2022 daemon.err hostapd: Wrong coupling between HT and VHT/HE channel setting
|
|
+```
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb reload`
|
|
+
|
|
+
|
|
+## rrm_beacon_req
|
|
+Send a Beacon Measurement Request to a client.
|
|
+
|
|
+### arguments
|
|
+| Name | Type | Required | Description |
|
|
+|---|---|---|---|
|
|
+| addr | string | yes | client MAC address |
|
|
+| op_class | int32 | yes | the Regulatory Class for which this Measurement Request applies |
|
|
+| channel | int32 | yes | channel to measure |
|
|
+| duration | int32 | yes | compile Beacon Measurement Report after N TU |
|
|
+| mode | int32 | yes | mode to be used for measurement (0: passive, 1: active, 2: beacon table) |
|
|
+| bssid | string | no | filter BSSes in Beacon Measurement Report by BSSID |
|
|
+| ssid | string | no | filter BSSes in Beacon Measurement Report by SSID|
|
|
+
|
|
+
|
|
+## rrm_nr_get_own
|
|
+Show Neighbor Report Element for this BSS.
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb rrm_nr_get_own`
|
|
+
|
|
+### output
|
|
+```json
|
|
+{
|
|
+ "value": [
|
|
+ "b6:a7:b9:cb:ee:bc",
|
|
+ "fb",
|
|
+ "b6a7b9cbeebcaf5900008095090603029b00"
|
|
+ ]
|
|
+}
|
|
+```
|
|
+
|
|
+
|
|
+## rrm_nr_list
|
|
+Show Neighbor Report Elements for other BSSes in this ESS.
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb rrm_nr_list`
|
|
+
|
|
+### output
|
|
+```json
|
|
+{
|
|
+ "list": [
|
|
+ [
|
|
+ "b6:a7:b9:cb:ee:ba",
|
|
+ "fb",
|
|
+ "b6a7b9cbeebabf5900008064090603026a00"
|
|
+ ]
|
|
+ ]
|
|
+}
|
|
+```
|
|
+
|
|
+## rrm_nr_set
|
|
+Set the Neighbor Report Elements. An element for the node on which this command is executed will always be added.
|
|
+
|
|
+### arguments
|
|
+| Name | Type | Required | Description |
|
|
+|---|---|---|---|
|
|
+| list | array | yes | array of Neighbor Report Elements in the format of the rrm_nr_list output |
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb rrm_nr_set '{ "list": [ [ "b6:a7:b9:cb:ee:ba", "fb", "b6a7b9cbeebabf5900008064090603026a00" ] ] }'`
|
|
+
|
|
+
|
|
+## set_vendor_elements
|
|
+Configure Vendor-specific Information Elements for BSS.
|
|
+
|
|
+### arguments
|
|
+| Name | Type | Required | Description |
|
|
+|---|---|---|---|
|
|
+| vendor_elements | string | yes | Vendor-specific Information Elements as hex string |
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb set_vendor_elements '{ "vendor_elements": "dd054857dd6662" }'`
|
|
+
|
|
+
|
|
+## switch_chan
|
|
+Initiate a channel switch.
|
|
+
|
|
+:warning: trying to switch to the channel that is currently in use will fail: `Command failed: Operation not supported`
|
|
+
|
|
+### arguments
|
|
+| Name | Type | Required | Description |
|
|
+|---|---|---|---|
|
|
+| freq | int32 | yes | frequency in MHz to switch to |
|
|
+| bcn_count | int32 | no | count in Beacon frames (TBTT) to perform the switch |
|
|
+| center_freq1 | int32 | no | segment 0 center frequency in MHz (valid for HT and VHT) |
|
|
+| center_freq2 | int32 | no | segment 1 center frequency in MHz (valid only for 80 MHz channel width and an 80+80 channel) |
|
|
+| bandwidth | int32 | no | channel width to use |
|
|
+| sec_channel_offset| int32 | no | secondary channel offset for HT40 (0 = disabled, 1 = HT40+, -1 = HT40-) |
|
|
+| ht | bool | no | enable 802.11n |
|
|
+| vht | bool | no | enable 802.11ac |
|
|
+| he | bool | no | enable 802.11ax |
|
|
+| block_tx | bool | no | block transmission during CSA period |
|
|
+| csa_force | bool | no | restart the interface in case the CSA fails |
|
|
+
|
|
+## example
|
|
+`ubus call hostapd.wl5-fb switch_chan '{ "freq": 5180, "bcn_count": 10, "center_freq1": 5210, "bandwidth": 80, "he": 1, "block_tx": 1, "csa_force": 0 }'`
|
|
+
|
|
+
|
|
+## update_airtime
|
|
+Set dynamic airtime weight for client.
|
|
+
|
|
+### arguments
|
|
+| Name | Type | Required | Description |
|
|
+|---|---|---|---|
|
|
+| sta | string | yes | client MAC address |
|
|
+| weight | int32 | yes | airtime weight |
|
|
+
|
|
+
|
|
+## update_beacon
|
|
+Force beacon frame content to be updated and to start beaconing on an interface that uses start_disabled=1.
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb update_beacon`
|
|
+
|
|
+
|
|
+## wps_status
|
|
+Get WPS status for BSS.
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb wps_status`
|
|
+
|
|
+### output
|
|
+```json
|
|
+{
|
|
+ "pbc_status": "Disabled",
|
|
+ "last_wps_result": "None"
|
|
+}
|
|
+```
|
|
+
|
|
+
|
|
+## wps_cancel
|
|
+Cancel WPS Push Button Configuration.
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb wps_cancel`
|
|
+
|
|
+
|
|
+## wps_start
|
|
+Start WPS Push Button Configuration.
|
|
+
|
|
+### example
|
|
+`ubus call hostapd.wl5-fb wps_start`
|
|
diff --git a/package/network/services/hostapd/files/common.uc b/package/network/services/hostapd/files/common.uc
|
|
new file mode 100644
|
|
index 0000000000..9ece3b1af2
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/common.uc
|
|
@@ -0,0 +1,168 @@
|
|
+import * as nl80211 from "nl80211";
|
|
+import * as rtnl from "rtnl";
|
|
+import { readfile } from "fs";
|
|
+
|
|
+const iftypes = {
|
|
+ ap: nl80211.const.NL80211_IFTYPE_AP,
|
|
+ mesh: nl80211.const.NL80211_IFTYPE_MESH_POINT,
|
|
+ sta: nl80211.const.NL80211_IFTYPE_STATION,
|
|
+ adhoc: nl80211.const.NL80211_IFTYPE_ADHOC,
|
|
+ monitor: nl80211.const.NL80211_IFTYPE_MONITOR,
|
|
+};
|
|
+
|
|
+function wdev_remove(name)
|
|
+{
|
|
+ nl80211.request(nl80211.const.NL80211_CMD_DEL_INTERFACE, 0, { dev: name });
|
|
+}
|
|
+
|
|
+function __phy_is_fullmac(phyidx)
|
|
+{
|
|
+ let data = nl80211.request(nl80211.const.NL80211_CMD_GET_WIPHY, 0, { wiphy: phyidx });
|
|
+
|
|
+ return !data.software_iftypes.ap_vlan;
|
|
+}
|
|
+
|
|
+function phy_is_fullmac(phy)
|
|
+{
|
|
+ let phyidx = int(trim(readfile(`/sys/class/ieee80211/${phy}/index`)));
|
|
+
|
|
+ return __phy_is_fullmac(phyidx);
|
|
+}
|
|
+
|
|
+function find_reusable_wdev(phyidx)
|
|
+{
|
|
+ if (!__phy_is_fullmac(phyidx))
|
|
+ return null;
|
|
+
|
|
+ let data = nl80211.request(
|
|
+ nl80211.const.NL80211_CMD_GET_INTERFACE,
|
|
+ nl80211.const.NLM_F_DUMP,
|
|
+ { wiphy: phyidx });
|
|
+ for (let res in data)
|
|
+ if (trim(readfile(`/sys/class/net/${res.ifname}/operstate`)) == "down")
|
|
+ return res.ifname;
|
|
+ return null;
|
|
+}
|
|
+
|
|
+function wdev_create(phy, name, data)
|
|
+{
|
|
+ let phyidx = int(readfile(`/sys/class/ieee80211/${phy}/index`));
|
|
+
|
|
+ wdev_remove(name);
|
|
+
|
|
+ if (!iftypes[data.mode])
|
|
+ return `Invalid mode: ${data.mode}`;
|
|
+
|
|
+ let req = {
|
|
+ wiphy: phyidx,
|
|
+ ifname: name,
|
|
+ iftype: iftypes[data.mode],
|
|
+ };
|
|
+
|
|
+ if (data["4addr"])
|
|
+ req["4addr"] = data["4addr"];
|
|
+ if (data.macaddr)
|
|
+ req.mac = data.macaddr;
|
|
+
|
|
+ nl80211.error();
|
|
+
|
|
+ let reuse_ifname = find_reusable_wdev(phyidx);
|
|
+ if (reuse_ifname &&
|
|
+ (reuse_ifname == name ||
|
|
+ rtnl.request(rtnl.const.RTM_SETLINK, 0, { dev: reuse_ifname, ifname: name}) != false))
|
|
+ nl80211.request(
|
|
+ nl80211.const.NL80211_CMD_SET_INTERFACE, 0, {
|
|
+ wiphy: phyidx,
|
|
+ dev: name,
|
|
+ iftype: iftypes[data.mode],
|
|
+ });
|
|
+ else
|
|
+ nl80211.request(
|
|
+ nl80211.const.NL80211_CMD_NEW_INTERFACE,
|
|
+ nl80211.const.NLM_F_CREATE,
|
|
+ req);
|
|
+
|
|
+ let error = nl80211.error();
|
|
+ if (error)
|
|
+ return error;
|
|
+
|
|
+ if (data.powersave != null) {
|
|
+ nl80211.request(nl80211.const.NL80211_CMD_SET_POWER_SAVE, 0,
|
|
+ { dev: name, ps_state: data.powersave ? 1 : 0});
|
|
+ }
|
|
+
|
|
+ return null;
|
|
+}
|
|
+
|
|
+const vlist_proto = {
|
|
+ update: function(values, arg) {
|
|
+ let data = this.data;
|
|
+ let cb = this.cb;
|
|
+ let seq = { };
|
|
+ let new_data = {};
|
|
+ let old_data = {};
|
|
+
|
|
+ this.data = new_data;
|
|
+
|
|
+ if (type(values) == "object") {
|
|
+ for (let key in values) {
|
|
+ old_data[key] = data[key];
|
|
+ new_data[key] = values[key];
|
|
+ delete data[key];
|
|
+ }
|
|
+ } else {
|
|
+ for (let val in values) {
|
|
+ let cur_key = val[0];
|
|
+ let cur_obj = val[1];
|
|
+
|
|
+ old_data[cur_key] = data[cur_key];
|
|
+ new_data[cur_key] = val[1];
|
|
+ delete data[cur_key];
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (let key in data) {
|
|
+ cb(null, data[key], arg);
|
|
+ delete data[key];
|
|
+ }
|
|
+ for (let key in new_data)
|
|
+ cb(new_data[key], old_data[key], arg);
|
|
+ }
|
|
+};
|
|
+
|
|
+function is_equal(val1, val2) {
|
|
+ let t1 = type(val1);
|
|
+
|
|
+ if (t1 != type(val2))
|
|
+ return false;
|
|
+
|
|
+ if (t1 == "array") {
|
|
+ if (length(val1) != length(val2))
|
|
+ return false;
|
|
+
|
|
+ for (let i = 0; i < length(val1); i++)
|
|
+ if (!is_equal(val1[i], val2[i]))
|
|
+ return false;
|
|
+
|
|
+ return true;
|
|
+ } else if (t1 == "object") {
|
|
+ for (let key in val1)
|
|
+ if (!is_equal(val1[key], val2[key]))
|
|
+ return false;
|
|
+ for (let key in val2)
|
|
+ if (!val1[key])
|
|
+ return false;
|
|
+ return true;
|
|
+ } else {
|
|
+ return val1 == val2;
|
|
+ }
|
|
+}
|
|
+
|
|
+function vlist_new(cb) {
|
|
+ return proto({
|
|
+ cb: cb,
|
|
+ data: {}
|
|
+ }, vlist_proto);
|
|
+}
|
|
+
|
|
+export { wdev_remove, wdev_create, is_equal, vlist_new, phy_is_fullmac };
|
|
diff --git a/package/network/services/hostapd/files/dhcp-get-server.sh b/package/network/services/hostapd/files/dhcp-get-server.sh
|
|
new file mode 100644
|
|
index 0000000000..a1509ace2f
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/dhcp-get-server.sh
|
|
@@ -0,0 +1,2 @@
|
|
+#!/bin/sh
|
|
+[ "$1" = bound ] && echo "$serverid"
|
|
diff --git a/package/network/services/hostapd/files/hostapd-basic.config b/package/network/services/hostapd/files/hostapd-basic.config
|
|
new file mode 100644
|
|
index 0000000000..3d19d8f902
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/hostapd-basic.config
|
|
@@ -0,0 +1,404 @@
|
|
+# Example hostapd build time configuration
|
|
+#
|
|
+# This file lists the configuration options that are used when building the
|
|
+# hostapd binary. All lines starting with # are ignored. Configuration option
|
|
+# lines must be commented out complete, if they are not to be included, i.e.,
|
|
+# just setting VARIABLE=n is not disabling that variable.
|
|
+#
|
|
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
|
|
+# be modified from here. In most cass, these lines should use += in order not
|
|
+# to override previous values of the variables.
|
|
+
|
|
+# Driver interface for Host AP driver
|
|
+#CONFIG_DRIVER_HOSTAP=y
|
|
+
|
|
+# Driver interface for wired authenticator
|
|
+CONFIG_DRIVER_WIRED=y
|
|
+
|
|
+# Driver interface for drivers using the nl80211 kernel interface
|
|
+CONFIG_DRIVER_NL80211=y
|
|
+
|
|
+# QCA vendor extensions to nl80211
|
|
+#CONFIG_DRIVER_NL80211_QCA=y
|
|
+
|
|
+# driver_nl80211.c requires libnl. If you are compiling it yourself
|
|
+# you may need to point hostapd to your version of libnl.
|
|
+#
|
|
+#CFLAGS += -I$<path to libnl include files>
|
|
+#LIBS += -L$<path to libnl library files>
|
|
+
|
|
+# Use libnl v2.0 (or 3.0) libraries.
|
|
+#CONFIG_LIBNL20=y
|
|
+
|
|
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
|
|
+#CONFIG_LIBNL32=y
|
|
+
|
|
+
|
|
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
|
+#CONFIG_DRIVER_BSD=y
|
|
+#CFLAGS += -I/usr/local/include
|
|
+#LIBS += -L/usr/local/lib
|
|
+#LIBS_p += -L/usr/local/lib
|
|
+#LIBS_c += -L/usr/local/lib
|
|
+
|
|
+# Driver interface for no driver (e.g., RADIUS server only)
|
|
+#CONFIG_DRIVER_NONE=y
|
|
+
|
|
+# IEEE 802.11F/IAPP
|
|
+#CONFIG_IAPP=y
|
|
+
|
|
+# WPA2/IEEE 802.11i RSN pre-authentication
|
|
+CONFIG_RSN_PREAUTH=y
|
|
+
|
|
+# IEEE 802.11w (management frame protection)
|
|
+#CONFIG_IEEE80211W=y
|
|
+
|
|
+# Support Operating Channel Validation
|
|
+CONFIG_OCV=y
|
|
+
|
|
+# Integrated EAP server
|
|
+#CONFIG_EAP=y
|
|
+
|
|
+# EAP Re-authentication Protocol (ERP) in integrated EAP server
|
|
+#CONFIG_ERP=y
|
|
+
|
|
+# EAP-MD5 for the integrated EAP server
|
|
+#CONFIG_EAP_MD5=y
|
|
+
|
|
+# EAP-TLS for the integrated EAP server
|
|
+#CONFIG_EAP_TLS=y
|
|
+
|
|
+# EAP-MSCHAPv2 for the integrated EAP server
|
|
+#CONFIG_EAP_MSCHAPV2=y
|
|
+
|
|
+# EAP-PEAP for the integrated EAP server
|
|
+#CONFIG_EAP_PEAP=y
|
|
+
|
|
+# EAP-GTC for the integrated EAP server
|
|
+#CONFIG_EAP_GTC=y
|
|
+
|
|
+# EAP-TTLS for the integrated EAP server
|
|
+#CONFIG_EAP_TTLS=y
|
|
+
|
|
+# EAP-SIM for the integrated EAP server
|
|
+#CONFIG_EAP_SIM=y
|
|
+
|
|
+# EAP-AKA for the integrated EAP server
|
|
+#CONFIG_EAP_AKA=y
|
|
+
|
|
+# EAP-AKA' for the integrated EAP server
|
|
+# This requires CONFIG_EAP_AKA to be enabled, too.
|
|
+#CONFIG_EAP_AKA_PRIME=y
|
|
+
|
|
+# EAP-PAX for the integrated EAP server
|
|
+#CONFIG_EAP_PAX=y
|
|
+
|
|
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
|
|
+#CONFIG_EAP_PSK=y
|
|
+
|
|
+# EAP-pwd for the integrated EAP server (secure authentication with a password)
|
|
+#CONFIG_EAP_PWD=y
|
|
+
|
|
+# EAP-SAKE for the integrated EAP server
|
|
+#CONFIG_EAP_SAKE=y
|
|
+
|
|
+# EAP-GPSK for the integrated EAP server
|
|
+#CONFIG_EAP_GPSK=y
|
|
+# Include support for optional SHA256 cipher suite in EAP-GPSK
|
|
+#CONFIG_EAP_GPSK_SHA256=y
|
|
+
|
|
+# EAP-FAST for the integrated EAP server
|
|
+#CONFIG_EAP_FAST=y
|
|
+
|
|
+# EAP-TEAP for the integrated EAP server
|
|
+# Note: The current EAP-TEAP implementation is experimental and should not be
|
|
+# enabled for production use. The IETF RFC 7170 that defines EAP-TEAP has number
|
|
+# of conflicting statements and missing details and the implementation has
|
|
+# vendor specific workarounds for those and as such, may not interoperate with
|
|
+# any other implementation. This should not be used for anything else than
|
|
+# experimentation and interoperability testing until those issues has been
|
|
+# resolved.
|
|
+#CONFIG_EAP_TEAP=y
|
|
+
|
|
+# Wi-Fi Protected Setup (WPS)
|
|
+#CONFIG_WPS=y
|
|
+# Enable UPnP support for external WPS Registrars
|
|
+#CONFIG_WPS_UPNP=y
|
|
+# Enable WPS support with NFC config method
|
|
+#CONFIG_WPS_NFC=y
|
|
+
|
|
+# EAP-IKEv2
|
|
+#CONFIG_EAP_IKEV2=y
|
|
+
|
|
+# Trusted Network Connect (EAP-TNC)
|
|
+#CONFIG_EAP_TNC=y
|
|
+
|
|
+# EAP-EKE for the integrated EAP server
|
|
+#CONFIG_EAP_EKE=y
|
|
+
|
|
+# PKCS#12 (PFX) support (used to read private key and certificate file from
|
|
+# a file that usually has extension .p12 or .pfx)
|
|
+#CONFIG_PKCS12=y
|
|
+
|
|
+# RADIUS authentication server. This provides access to the integrated EAP
|
|
+# server from external hosts using RADIUS.
|
|
+#CONFIG_RADIUS_SERVER=y
|
|
+
|
|
+# Build IPv6 support for RADIUS operations
|
|
+#CONFIG_IPV6=y
|
|
+
|
|
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
|
|
+CONFIG_IEEE80211R=y
|
|
+
|
|
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
|
|
+# 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
|
|
+
|
|
+# IEEE 802.11ac (Very High Throughput) support
|
|
+CONFIG_IEEE80211AC=y
|
|
+
|
|
+# IEEE 802.11ax HE support
|
|
+# Note: This is experimental and work in progress. The definitions are still
|
|
+# subject to change and this should not be expected to interoperate with the
|
|
+# final IEEE 802.11ax version.
|
|
+#CONFIG_IEEE80211AX=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.
|
|
+#CONFIG_NO_STDOUT_DEBUG=y
|
|
+
|
|
+# Add support for writing debug log to a file: -f /tmp/hostapd.log
|
|
+# Disabled by default.
|
|
+#CONFIG_DEBUG_FILE=y
|
|
+
|
|
+# Send debug messages to syslog instead of stdout
|
|
+CONFIG_DEBUG_SYSLOG=y
|
|
+
|
|
+# Add support for sending all debug messages (regardless of debug verbosity)
|
|
+# to the Linux kernel tracing facility. This helps debug the entire stack by
|
|
+# making it easy to record everything happening from the driver up into the
|
|
+# same file, e.g., using trace-cmd.
|
|
+#CONFIG_DEBUG_LINUX_TRACING=y
|
|
+
|
|
+# Remove support for RADIUS accounting
|
|
+CONFIG_NO_ACCOUNTING=y
|
|
+
|
|
+# Remove support for RADIUS
|
|
+CONFIG_NO_RADIUS=y
|
|
+
|
|
+# Remove support for VLANs
|
|
+#CONFIG_NO_VLAN=y
|
|
+
|
|
+# Enable support for fully dynamic VLANs. This enables hostapd to
|
|
+# automatically create bridge and VLAN interfaces if necessary.
|
|
+#CONFIG_FULL_DYNAMIC_VLAN=y
|
|
+
|
|
+# Use netlink-based kernel API for VLAN operations instead of ioctl()
|
|
+# Note: This requires libnl 3.1 or newer.
|
|
+#CONFIG_VLAN_NETLINK=y
|
|
+
|
|
+# Remove support for dumping internal state through control interface commands
|
|
+# This can be used to reduce binary size at the cost of disabling a debugging
|
|
+# option.
|
|
+CONFIG_NO_DUMP_STATE=y
|
|
+
|
|
+# Enable tracing code for developer debugging
|
|
+# This tracks use of memory allocations and other registrations and reports
|
|
+# incorrect use with a backtrace of call (or allocation) location.
|
|
+#CONFIG_WPA_TRACE=y
|
|
+# For BSD, comment out these.
|
|
+#LIBS += -lexecinfo
|
|
+#LIBS_p += -lexecinfo
|
|
+#LIBS_c += -lexecinfo
|
|
+
|
|
+# Use libbfd to get more details for developer debugging
|
|
+# This enables use of libbfd to get more detailed symbols for the backtraces
|
|
+# generated by CONFIG_WPA_TRACE=y.
|
|
+#CONFIG_WPA_TRACE_BFD=y
|
|
+# For BSD, comment out these.
|
|
+#LIBS += -lbfd -liberty -lz
|
|
+#LIBS_p += -lbfd -liberty -lz
|
|
+#LIBS_c += -lbfd -liberty -lz
|
|
+
|
|
+# hostapd depends on strong random number generation being available from the
|
|
+# operating system. os_get_random() function is used to fetch random data when
|
|
+# needed, e.g., for key generation. On Linux and BSD systems, this works by
|
|
+# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
|
|
+# properly initialized before hostapd is started. This is important especially
|
|
+# on embedded devices that do not have a hardware random number generator and
|
|
+# may by default start up with minimal entropy available for random number
|
|
+# generation.
|
|
+#
|
|
+# As a safety net, hostapd is by default trying to internally collect
|
|
+# additional entropy for generating random data to mix in with the data
|
|
+# fetched from the OS. This by itself is not considered to be very strong, but
|
|
+# it may help in cases where the system pool is not initialized properly.
|
|
+# However, it is very strongly recommended that the system pool is initialized
|
|
+# with enough entropy either by using hardware assisted random number
|
|
+# generator or by storing state over device reboots.
|
|
+#
|
|
+# hostapd can be configured to maintain its own entropy store over restarts to
|
|
+# enhance random number generation. This is not perfect, but it is much more
|
|
+# secure than using the same sequence of random numbers after every reboot.
|
|
+# This can be enabled with -e<entropy file> command line option. The specified
|
|
+# file needs to be readable and writable by hostapd.
|
|
+#
|
|
+# If the os_get_random() is known to provide strong random data (e.g., on
|
|
+# Linux/BSD, the board in question is known to have reliable source of random
|
|
+# data from /dev/urandom), the internal hostapd random pool can be disabled.
|
|
+# This will save some in binary size and CPU use. However, this should only be
|
|
+# considered for builds that are known to be used on devices that meet the
|
|
+# requirements described above.
|
|
+CONFIG_NO_RANDOM_POOL=y
|
|
+
|
|
+# Should we attempt to use the getrandom(2) call that provides more reliable
|
|
+# yet secure randomness source than /dev/random on Linux 3.17 and newer.
|
|
+# Requires glibc 2.25 to build, falls back to /dev/random if unavailable.
|
|
+CONFIG_GETRANDOM=y
|
|
+
|
|
+# Should we use poll instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_POLL=y
|
|
+
|
|
+# Should we use epoll instead of select? Select is used by default.
|
|
+CONFIG_ELOOP_EPOLL=y
|
|
+
|
|
+# Should we use kqueue instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_KQUEUE=y
|
|
+
|
|
+# Select TLS implementation
|
|
+# openssl = OpenSSL (default)
|
|
+# gnutls = GnuTLS
|
|
+# internal = Internal TLSv1 implementation (experimental)
|
|
+# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
|
|
+# none = Empty template
|
|
+CONFIG_TLS=internal
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
|
+# can be enabled to get a stronger construction of messages when block ciphers
|
|
+# are used.
|
|
+#CONFIG_TLSV11=y
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
|
|
+# can be enabled to enable use of stronger crypto algorithms.
|
|
+#CONFIG_TLSV12=y
|
|
+
|
|
+# Select which ciphers to use by default with OpenSSL if the user does not
|
|
+# specify them.
|
|
+#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
|
|
+
|
|
+# If CONFIG_TLS=internal is used, additional library and include paths are
|
|
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
|
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
|
+# and drawbacks of this option.
|
|
+#CONFIG_INTERNAL_LIBTOMMATH=y
|
|
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
|
|
+#LTM_PATH=/usr/src/libtommath-0.39
|
|
+#CFLAGS += -I$(LTM_PATH)
|
|
+#LIBS += -L$(LTM_PATH)
|
|
+#LIBS_p += -L$(LTM_PATH)
|
|
+#endif
|
|
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
|
|
+# can be configured to include faster routines for exptmod, sqr, and div to
|
|
+# speed up DH and RSA calculation considerably
|
|
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
|
+
|
|
+# Interworking (IEEE 802.11u)
|
|
+# This can be used to enable functionality to improve interworking with
|
|
+# external networks.
|
|
+#CONFIG_INTERWORKING=y
|
|
+
|
|
+# Hotspot 2.0
|
|
+#CONFIG_HS20=y
|
|
+
|
|
+# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
|
|
+#CONFIG_SQLITE=y
|
|
+
|
|
+# Enable Fast Session Transfer (FST)
|
|
+#CONFIG_FST=y
|
|
+
|
|
+# Enable CLI commands for FST testing
|
|
+#CONFIG_FST_TEST=y
|
|
+
|
|
+# Testing options
|
|
+# This can be used to enable some testing options (see also the example
|
|
+# configuration file) that are really useful only for testing clients that
|
|
+# connect to this hostapd. These options allow, for example, to drop a
|
|
+# certain percentage of probe requests or auth/(re)assoc frames.
|
|
+#
|
|
+#CONFIG_TESTING_OPTIONS=y
|
|
+
|
|
+# Automatic Channel Selection
|
|
+# This will allow hostapd to pick the channel automatically when channel is set
|
|
+# to "acs_survey" or "0". Eventually, other ACS algorithms can be added in
|
|
+# similar way.
|
|
+#
|
|
+# Automatic selection is currently only done through initialization, later on
|
|
+# we hope to do background checks to keep us moving to more ideal channels as
|
|
+# time goes by. ACS is currently only supported through the nl80211 driver and
|
|
+# your driver must have survey dump capability that is filled by the driver
|
|
+# during scanning.
|
|
+#
|
|
+# You can customize the ACS survey algorithm with the hostapd.conf variable
|
|
+# acs_num_scans.
|
|
+#
|
|
+# Supported ACS drivers:
|
|
+# * ath9k
|
|
+# * ath5k
|
|
+# * ath10k
|
|
+#
|
|
+# For more details refer to:
|
|
+# http://wireless.kernel.org/en/users/Documentation/acs
|
|
+#
|
|
+#CONFIG_ACS=y
|
|
+
|
|
+# Multiband Operation support
|
|
+# These extentions facilitate efficient use of multiple frequency bands
|
|
+# available to the AP and the devices that may associate with it.
|
|
+#CONFIG_MBO=y
|
|
+
|
|
+# Client Taxonomy
|
|
+# Has the AP retain the Probe Request and (Re)Association Request frames from
|
|
+# a client, from which a signature can be produced which can identify the model
|
|
+# of client device like "Nexus 6P" or "iPhone 5s".
|
|
+#CONFIG_TAXONOMY=y
|
|
+
|
|
+# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
|
|
+#CONFIG_FILS=y
|
|
+# FILS shared key authentication with PFS
|
|
+#CONFIG_FILS_SK_PFS=y
|
|
+
|
|
+# Include internal line edit mode in hostapd_cli. This can be used to provide
|
|
+# limited command line editing and history support.
|
|
+#CONFIG_WPA_CLI_EDIT=y
|
|
+
|
|
+# Opportunistic Wireless Encryption (OWE)
|
|
+# Experimental implementation of draft-harkins-owe-07.txt
|
|
+#CONFIG_OWE=y
|
|
+
|
|
+# Airtime policy support
|
|
+CONFIG_AIRTIME_POLICY=y
|
|
+
|
|
+# Proxy ARP support
|
|
+#CONFIG_PROXYARP=y
|
|
+
|
|
+# Override default value for the wpa_disable_eapol_key_retries configuration
|
|
+# parameter. See that parameter in hostapd.conf for more details.
|
|
+#CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1
|
|
+
|
|
+# uBus IPC/RPC System
|
|
+# Services can connect to the bus and provide methods
|
|
+# that can be called by other services or clients.
|
|
+CONFIG_UBUS=y
|
|
+
|
|
+# OpenWrt patch 380-disable-ctrl-iface-mib.patch
|
|
+# leads to the MIB only being compiled in if
|
|
+# CONFIG_CTRL_IFACE_MIB is enabled.
|
|
+#CONFIG_CTRL_IFACE_MIB=y
|
|
diff --git a/package/network/services/hostapd/files/hostapd-full.config b/package/network/services/hostapd/files/hostapd-full.config
|
|
new file mode 100644
|
|
index 0000000000..9076ebc44f
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/hostapd-full.config
|
|
@@ -0,0 +1,404 @@
|
|
+# Example hostapd build time configuration
|
|
+#
|
|
+# This file lists the configuration options that are used when building the
|
|
+# hostapd binary. All lines starting with # are ignored. Configuration option
|
|
+# lines must be commented out complete, if they are not to be included, i.e.,
|
|
+# just setting VARIABLE=n is not disabling that variable.
|
|
+#
|
|
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
|
|
+# be modified from here. In most cass, these lines should use += in order not
|
|
+# to override previous values of the variables.
|
|
+
|
|
+# Driver interface for Host AP driver
|
|
+#CONFIG_DRIVER_HOSTAP=y
|
|
+
|
|
+# Driver interface for wired authenticator
|
|
+CONFIG_DRIVER_WIRED=y
|
|
+
|
|
+# Driver interface for drivers using the nl80211 kernel interface
|
|
+CONFIG_DRIVER_NL80211=y
|
|
+
|
|
+# QCA vendor extensions to nl80211
|
|
+#CONFIG_DRIVER_NL80211_QCA=y
|
|
+
|
|
+# driver_nl80211.c requires libnl. If you are compiling it yourself
|
|
+# you may need to point hostapd to your version of libnl.
|
|
+#
|
|
+#CFLAGS += -I$<path to libnl include files>
|
|
+#LIBS += -L$<path to libnl library files>
|
|
+
|
|
+# Use libnl v2.0 (or 3.0) libraries.
|
|
+#CONFIG_LIBNL20=y
|
|
+
|
|
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
|
|
+#CONFIG_LIBNL32=y
|
|
+
|
|
+
|
|
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
|
+#CONFIG_DRIVER_BSD=y
|
|
+#CFLAGS += -I/usr/local/include
|
|
+#LIBS += -L/usr/local/lib
|
|
+#LIBS_p += -L/usr/local/lib
|
|
+#LIBS_c += -L/usr/local/lib
|
|
+
|
|
+# Driver interface for no driver (e.g., RADIUS server only)
|
|
+#CONFIG_DRIVER_NONE=y
|
|
+
|
|
+# IEEE 802.11F/IAPP
|
|
+CONFIG_IAPP=y
|
|
+
|
|
+# WPA2/IEEE 802.11i RSN pre-authentication
|
|
+CONFIG_RSN_PREAUTH=y
|
|
+
|
|
+# IEEE 802.11w (management frame protection)
|
|
+#CONFIG_IEEE80211W=y
|
|
+
|
|
+# Support Operating Channel Validation
|
|
+CONFIG_OCV=y
|
|
+
|
|
+# Integrated EAP server
|
|
+CONFIG_EAP=y
|
|
+
|
|
+# EAP Re-authentication Protocol (ERP) in integrated EAP server
|
|
+CONFIG_ERP=y
|
|
+
|
|
+# EAP-MD5 for the integrated EAP server
|
|
+CONFIG_EAP_MD5=y
|
|
+
|
|
+# EAP-TLS for the integrated EAP server
|
|
+CONFIG_EAP_TLS=y
|
|
+
|
|
+# EAP-MSCHAPv2 for the integrated EAP server
|
|
+CONFIG_EAP_MSCHAPV2=y
|
|
+
|
|
+# EAP-PEAP for the integrated EAP server
|
|
+CONFIG_EAP_PEAP=y
|
|
+
|
|
+# EAP-GTC for the integrated EAP server
|
|
+CONFIG_EAP_GTC=y
|
|
+
|
|
+# EAP-TTLS for the integrated EAP server
|
|
+CONFIG_EAP_TTLS=y
|
|
+
|
|
+# EAP-SIM for the integrated EAP server
|
|
+#CONFIG_EAP_SIM=y
|
|
+
|
|
+# EAP-AKA for the integrated EAP server
|
|
+#CONFIG_EAP_AKA=y
|
|
+
|
|
+# EAP-AKA' for the integrated EAP server
|
|
+# This requires CONFIG_EAP_AKA to be enabled, too.
|
|
+#CONFIG_EAP_AKA_PRIME=y
|
|
+
|
|
+# EAP-PAX for the integrated EAP server
|
|
+#CONFIG_EAP_PAX=y
|
|
+
|
|
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
|
|
+#CONFIG_EAP_PSK=y
|
|
+
|
|
+# EAP-pwd for the integrated EAP server (secure authentication with a password)
|
|
+#CONFIG_EAP_PWD=y
|
|
+
|
|
+# EAP-SAKE for the integrated EAP server
|
|
+#CONFIG_EAP_SAKE=y
|
|
+
|
|
+# EAP-GPSK for the integrated EAP server
|
|
+#CONFIG_EAP_GPSK=y
|
|
+# Include support for optional SHA256 cipher suite in EAP-GPSK
|
|
+#CONFIG_EAP_GPSK_SHA256=y
|
|
+
|
|
+# EAP-FAST for the integrated EAP server
|
|
+CONFIG_EAP_FAST=y
|
|
+
|
|
+# EAP-TEAP for the integrated EAP server
|
|
+# Note: The current EAP-TEAP implementation is experimental and should not be
|
|
+# enabled for production use. The IETF RFC 7170 that defines EAP-TEAP has number
|
|
+# of conflicting statements and missing details and the implementation has
|
|
+# vendor specific workarounds for those and as such, may not interoperate with
|
|
+# any other implementation. This should not be used for anything else than
|
|
+# experimentation and interoperability testing until those issues has been
|
|
+# resolved.
|
|
+#CONFIG_EAP_TEAP=y
|
|
+
|
|
+# Wi-Fi Protected Setup (WPS)
|
|
+CONFIG_WPS=y
|
|
+# Enable UPnP support for external WPS Registrars
|
|
+#CONFIG_WPS_UPNP=y
|
|
+# Enable WPS support with NFC config method
|
|
+#CONFIG_WPS_NFC=y
|
|
+
|
|
+# EAP-IKEv2
|
|
+#CONFIG_EAP_IKEV2=y
|
|
+
|
|
+# Trusted Network Connect (EAP-TNC)
|
|
+#CONFIG_EAP_TNC=y
|
|
+
|
|
+# EAP-EKE for the integrated EAP server
|
|
+#CONFIG_EAP_EKE=y
|
|
+
|
|
+# PKCS#12 (PFX) support (used to read private key and certificate file from
|
|
+# a file that usually has extension .p12 or .pfx)
|
|
+CONFIG_PKCS12=y
|
|
+
|
|
+# RADIUS authentication server. This provides access to the integrated EAP
|
|
+# server from external hosts using RADIUS.
|
|
+CONFIG_RADIUS_SERVER=y
|
|
+
|
|
+# Build IPv6 support for RADIUS operations
|
|
+CONFIG_IPV6=y
|
|
+
|
|
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
|
|
+CONFIG_IEEE80211R=y
|
|
+
|
|
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
|
|
+# 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
|
|
+
|
|
+# IEEE 802.11ac (Very High Throughput) support
|
|
+CONFIG_IEEE80211AC=y
|
|
+
|
|
+# IEEE 802.11ax HE support
|
|
+# Note: This is experimental and work in progress. The definitions are still
|
|
+# subject to change and this should not be expected to interoperate with the
|
|
+# final IEEE 802.11ax version.
|
|
+#CONFIG_IEEE80211AX=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.
|
|
+#CONFIG_NO_STDOUT_DEBUG=y
|
|
+
|
|
+# Add support for writing debug log to a file: -f /tmp/hostapd.log
|
|
+# Disabled by default.
|
|
+#CONFIG_DEBUG_FILE=y
|
|
+
|
|
+# Send debug messages to syslog instead of stdout
|
|
+CONFIG_DEBUG_SYSLOG=y
|
|
+
|
|
+# Add support for sending all debug messages (regardless of debug verbosity)
|
|
+# to the Linux kernel tracing facility. This helps debug the entire stack by
|
|
+# making it easy to record everything happening from the driver up into the
|
|
+# same file, e.g., using trace-cmd.
|
|
+#CONFIG_DEBUG_LINUX_TRACING=y
|
|
+
|
|
+# Remove support for RADIUS accounting
|
|
+#CONFIG_NO_ACCOUNTING=y
|
|
+
|
|
+# Remove support for RADIUS
|
|
+#CONFIG_NO_RADIUS=y
|
|
+
|
|
+# Remove support for VLANs
|
|
+#CONFIG_NO_VLAN=y
|
|
+
|
|
+# Enable support for fully dynamic VLANs. This enables hostapd to
|
|
+# automatically create bridge and VLAN interfaces if necessary.
|
|
+CONFIG_FULL_DYNAMIC_VLAN=y
|
|
+
|
|
+# Use netlink-based kernel API for VLAN operations instead of ioctl()
|
|
+# Note: This requires libnl 3.1 or newer.
|
|
+#CONFIG_VLAN_NETLINK=y
|
|
+
|
|
+# Remove support for dumping internal state through control interface commands
|
|
+# This can be used to reduce binary size at the cost of disabling a debugging
|
|
+# option.
|
|
+CONFIG_NO_DUMP_STATE=y
|
|
+
|
|
+# Enable tracing code for developer debugging
|
|
+# This tracks use of memory allocations and other registrations and reports
|
|
+# incorrect use with a backtrace of call (or allocation) location.
|
|
+#CONFIG_WPA_TRACE=y
|
|
+# For BSD, comment out these.
|
|
+#LIBS += -lexecinfo
|
|
+#LIBS_p += -lexecinfo
|
|
+#LIBS_c += -lexecinfo
|
|
+
|
|
+# Use libbfd to get more details for developer debugging
|
|
+# This enables use of libbfd to get more detailed symbols for the backtraces
|
|
+# generated by CONFIG_WPA_TRACE=y.
|
|
+#CONFIG_WPA_TRACE_BFD=y
|
|
+# For BSD, comment out these.
|
|
+#LIBS += -lbfd -liberty -lz
|
|
+#LIBS_p += -lbfd -liberty -lz
|
|
+#LIBS_c += -lbfd -liberty -lz
|
|
+
|
|
+# hostapd depends on strong random number generation being available from the
|
|
+# operating system. os_get_random() function is used to fetch random data when
|
|
+# needed, e.g., for key generation. On Linux and BSD systems, this works by
|
|
+# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
|
|
+# properly initialized before hostapd is started. This is important especially
|
|
+# on embedded devices that do not have a hardware random number generator and
|
|
+# may by default start up with minimal entropy available for random number
|
|
+# generation.
|
|
+#
|
|
+# As a safety net, hostapd is by default trying to internally collect
|
|
+# additional entropy for generating random data to mix in with the data
|
|
+# fetched from the OS. This by itself is not considered to be very strong, but
|
|
+# it may help in cases where the system pool is not initialized properly.
|
|
+# However, it is very strongly recommended that the system pool is initialized
|
|
+# with enough entropy either by using hardware assisted random number
|
|
+# generator or by storing state over device reboots.
|
|
+#
|
|
+# hostapd can be configured to maintain its own entropy store over restarts to
|
|
+# enhance random number generation. This is not perfect, but it is much more
|
|
+# secure than using the same sequence of random numbers after every reboot.
|
|
+# This can be enabled with -e<entropy file> command line option. The specified
|
|
+# file needs to be readable and writable by hostapd.
|
|
+#
|
|
+# If the os_get_random() is known to provide strong random data (e.g., on
|
|
+# Linux/BSD, the board in question is known to have reliable source of random
|
|
+# data from /dev/urandom), the internal hostapd random pool can be disabled.
|
|
+# This will save some in binary size and CPU use. However, this should only be
|
|
+# considered for builds that are known to be used on devices that meet the
|
|
+# requirements described above.
|
|
+CONFIG_NO_RANDOM_POOL=y
|
|
+
|
|
+# Should we attempt to use the getrandom(2) call that provides more reliable
|
|
+# yet secure randomness source than /dev/random on Linux 3.17 and newer.
|
|
+# Requires glibc 2.25 to build, falls back to /dev/random if unavailable.
|
|
+CONFIG_GETRANDOM=y
|
|
+
|
|
+# Should we use poll instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_POLL=y
|
|
+
|
|
+# Should we use epoll instead of select? Select is used by default.
|
|
+CONFIG_ELOOP_EPOLL=y
|
|
+
|
|
+# Should we use kqueue instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_KQUEUE=y
|
|
+
|
|
+# Select TLS implementation
|
|
+# openssl = OpenSSL (default)
|
|
+# gnutls = GnuTLS
|
|
+# internal = Internal TLSv1 implementation (experimental)
|
|
+# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
|
|
+# none = Empty template
|
|
+CONFIG_TLS=internal
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
|
+# can be enabled to get a stronger construction of messages when block ciphers
|
|
+# are used.
|
|
+#CONFIG_TLSV11=y
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
|
|
+# can be enabled to enable use of stronger crypto algorithms.
|
|
+#CONFIG_TLSV12=y
|
|
+
|
|
+# Select which ciphers to use by default with OpenSSL if the user does not
|
|
+# specify them.
|
|
+#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
|
|
+
|
|
+# If CONFIG_TLS=internal is used, additional library and include paths are
|
|
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
|
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
|
+# and drawbacks of this option.
|
|
+CONFIG_INTERNAL_LIBTOMMATH=y
|
|
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
|
|
+#LTM_PATH=/usr/src/libtommath-0.39
|
|
+#CFLAGS += -I$(LTM_PATH)
|
|
+#LIBS += -L$(LTM_PATH)
|
|
+#LIBS_p += -L$(LTM_PATH)
|
|
+#endif
|
|
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
|
|
+# can be configured to include faster routines for exptmod, sqr, and div to
|
|
+# speed up DH and RSA calculation considerably
|
|
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
|
+
|
|
+# Interworking (IEEE 802.11u)
|
|
+# This can be used to enable functionality to improve interworking with
|
|
+# external networks.
|
|
+CONFIG_INTERWORKING=y
|
|
+
|
|
+# Hotspot 2.0
|
|
+CONFIG_HS20=y
|
|
+
|
|
+# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
|
|
+#CONFIG_SQLITE=y
|
|
+
|
|
+# Enable Fast Session Transfer (FST)
|
|
+#CONFIG_FST=y
|
|
+
|
|
+# Enable CLI commands for FST testing
|
|
+#CONFIG_FST_TEST=y
|
|
+
|
|
+# Testing options
|
|
+# This can be used to enable some testing options (see also the example
|
|
+# configuration file) that are really useful only for testing clients that
|
|
+# connect to this hostapd. These options allow, for example, to drop a
|
|
+# certain percentage of probe requests or auth/(re)assoc frames.
|
|
+#
|
|
+#CONFIG_TESTING_OPTIONS=y
|
|
+
|
|
+# Automatic Channel Selection
|
|
+# This will allow hostapd to pick the channel automatically when channel is set
|
|
+# to "acs_survey" or "0". Eventually, other ACS algorithms can be added in
|
|
+# similar way.
|
|
+#
|
|
+# Automatic selection is currently only done through initialization, later on
|
|
+# we hope to do background checks to keep us moving to more ideal channels as
|
|
+# time goes by. ACS is currently only supported through the nl80211 driver and
|
|
+# your driver must have survey dump capability that is filled by the driver
|
|
+# during scanning.
|
|
+#
|
|
+# You can customize the ACS survey algorithm with the hostapd.conf variable
|
|
+# acs_num_scans.
|
|
+#
|
|
+# Supported ACS drivers:
|
|
+# * ath9k
|
|
+# * ath5k
|
|
+# * ath10k
|
|
+#
|
|
+# For more details refer to:
|
|
+# http://wireless.kernel.org/en/users/Documentation/acs
|
|
+#
|
|
+#CONFIG_ACS=y
|
|
+
|
|
+# Multiband Operation support
|
|
+# These extentions facilitate efficient use of multiple frequency bands
|
|
+# available to the AP and the devices that may associate with it.
|
|
+#CONFIG_MBO=y
|
|
+
|
|
+# Client Taxonomy
|
|
+# Has the AP retain the Probe Request and (Re)Association Request frames from
|
|
+# a client, from which a signature can be produced which can identify the model
|
|
+# of client device like "Nexus 6P" or "iPhone 5s".
|
|
+CONFIG_TAXONOMY=y
|
|
+
|
|
+# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
|
|
+#CONFIG_FILS=y
|
|
+# FILS shared key authentication with PFS
|
|
+#CONFIG_FILS_SK_PFS=y
|
|
+
|
|
+# Include internal line edit mode in hostapd_cli. This can be used to provide
|
|
+# limited command line editing and history support.
|
|
+#CONFIG_WPA_CLI_EDIT=y
|
|
+
|
|
+# Opportunistic Wireless Encryption (OWE)
|
|
+# Experimental implementation of draft-harkins-owe-07.txt
|
|
+#CONFIG_OWE=y
|
|
+
|
|
+# Airtime policy support
|
|
+CONFIG_AIRTIME_POLICY=y
|
|
+
|
|
+# Proxy ARP support
|
|
+CONFIG_PROXYARP=y
|
|
+
|
|
+# Override default value for the wpa_disable_eapol_key_retries configuration
|
|
+# parameter. See that parameter in hostapd.conf for more details.
|
|
+#CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1
|
|
+
|
|
+# uBus IPC/RPC System
|
|
+# Services can connect to the bus and provide methods
|
|
+# that can be called by other services or clients.
|
|
+CONFIG_UBUS=y
|
|
+
|
|
+# OpenWrt patch 380-disable-ctrl-iface-mib.patch
|
|
+# leads to the MIB only being compiled in if
|
|
+# CONFIG_CTRL_IFACE_MIB is enabled.
|
|
+CONFIG_CTRL_IFACE_MIB=y
|
|
diff --git a/package/network/services/hostapd/files/hostapd-mini.config b/package/network/services/hostapd/files/hostapd-mini.config
|
|
new file mode 100644
|
|
index 0000000000..f2ed071ec0
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/hostapd-mini.config
|
|
@@ -0,0 +1,404 @@
|
|
+# Example hostapd build time configuration
|
|
+#
|
|
+# This file lists the configuration options that are used when building the
|
|
+# hostapd binary. All lines starting with # are ignored. Configuration option
|
|
+# lines must be commented out complete, if they are not to be included, i.e.,
|
|
+# just setting VARIABLE=n is not disabling that variable.
|
|
+#
|
|
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
|
|
+# be modified from here. In most cass, these lines should use += in order not
|
|
+# to override previous values of the variables.
|
|
+
|
|
+# Driver interface for Host AP driver
|
|
+#CONFIG_DRIVER_HOSTAP=y
|
|
+
|
|
+# Driver interface for wired authenticator
|
|
+CONFIG_DRIVER_WIRED=y
|
|
+
|
|
+# Driver interface for drivers using the nl80211 kernel interface
|
|
+CONFIG_DRIVER_NL80211=y
|
|
+
|
|
+# QCA vendor extensions to nl80211
|
|
+#CONFIG_DRIVER_NL80211_QCA=y
|
|
+
|
|
+# driver_nl80211.c requires libnl. If you are compiling it yourself
|
|
+# you may need to point hostapd to your version of libnl.
|
|
+#
|
|
+#CFLAGS += -I$<path to libnl include files>
|
|
+#LIBS += -L$<path to libnl library files>
|
|
+
|
|
+# Use libnl v2.0 (or 3.0) libraries.
|
|
+#CONFIG_LIBNL20=y
|
|
+
|
|
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
|
|
+#CONFIG_LIBNL32=y
|
|
+
|
|
+
|
|
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
|
+#CONFIG_DRIVER_BSD=y
|
|
+#CFLAGS += -I/usr/local/include
|
|
+#LIBS += -L/usr/local/lib
|
|
+#LIBS_p += -L/usr/local/lib
|
|
+#LIBS_c += -L/usr/local/lib
|
|
+
|
|
+# Driver interface for no driver (e.g., RADIUS server only)
|
|
+#CONFIG_DRIVER_NONE=y
|
|
+
|
|
+# IEEE 802.11F/IAPP
|
|
+#CONFIG_IAPP=y
|
|
+
|
|
+# WPA2/IEEE 802.11i RSN pre-authentication
|
|
+CONFIG_RSN_PREAUTH=y
|
|
+
|
|
+# IEEE 802.11w (management frame protection)
|
|
+#CONFIG_IEEE80211W=y
|
|
+
|
|
+# Support Operating Channel Validation
|
|
+#CONFIG_OCV=y
|
|
+
|
|
+# Integrated EAP server
|
|
+#CONFIG_EAP=y
|
|
+
|
|
+# EAP Re-authentication Protocol (ERP) in integrated EAP server
|
|
+#CONFIG_ERP=y
|
|
+
|
|
+# EAP-MD5 for the integrated EAP server
|
|
+#CONFIG_EAP_MD5=y
|
|
+
|
|
+# EAP-TLS for the integrated EAP server
|
|
+#CONFIG_EAP_TLS=y
|
|
+
|
|
+# EAP-MSCHAPv2 for the integrated EAP server
|
|
+#CONFIG_EAP_MSCHAPV2=y
|
|
+
|
|
+# EAP-PEAP for the integrated EAP server
|
|
+#CONFIG_EAP_PEAP=y
|
|
+
|
|
+# EAP-GTC for the integrated EAP server
|
|
+#CONFIG_EAP_GTC=y
|
|
+
|
|
+# EAP-TTLS for the integrated EAP server
|
|
+#CONFIG_EAP_TTLS=y
|
|
+
|
|
+# EAP-SIM for the integrated EAP server
|
|
+#CONFIG_EAP_SIM=y
|
|
+
|
|
+# EAP-AKA for the integrated EAP server
|
|
+#CONFIG_EAP_AKA=y
|
|
+
|
|
+# EAP-AKA' for the integrated EAP server
|
|
+# This requires CONFIG_EAP_AKA to be enabled, too.
|
|
+#CONFIG_EAP_AKA_PRIME=y
|
|
+
|
|
+# EAP-PAX for the integrated EAP server
|
|
+#CONFIG_EAP_PAX=y
|
|
+
|
|
+# EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK)
|
|
+#CONFIG_EAP_PSK=y
|
|
+
|
|
+# EAP-pwd for the integrated EAP server (secure authentication with a password)
|
|
+#CONFIG_EAP_PWD=y
|
|
+
|
|
+# EAP-SAKE for the integrated EAP server
|
|
+#CONFIG_EAP_SAKE=y
|
|
+
|
|
+# EAP-GPSK for the integrated EAP server
|
|
+#CONFIG_EAP_GPSK=y
|
|
+# Include support for optional SHA256 cipher suite in EAP-GPSK
|
|
+#CONFIG_EAP_GPSK_SHA256=y
|
|
+
|
|
+# EAP-FAST for the integrated EAP server
|
|
+#CONFIG_EAP_FAST=y
|
|
+
|
|
+# EAP-TEAP for the integrated EAP server
|
|
+# Note: The current EAP-TEAP implementation is experimental and should not be
|
|
+# enabled for production use. The IETF RFC 7170 that defines EAP-TEAP has number
|
|
+# of conflicting statements and missing details and the implementation has
|
|
+# vendor specific workarounds for those and as such, may not interoperate with
|
|
+# any other implementation. This should not be used for anything else than
|
|
+# experimentation and interoperability testing until those issues has been
|
|
+# resolved.
|
|
+#CONFIG_EAP_TEAP=y
|
|
+
|
|
+# Wi-Fi Protected Setup (WPS)
|
|
+#CONFIG_WPS=y
|
|
+# Enable UPnP support for external WPS Registrars
|
|
+#CONFIG_WPS_UPNP=y
|
|
+# Enable WPS support with NFC config method
|
|
+#CONFIG_WPS_NFC=y
|
|
+
|
|
+# EAP-IKEv2
|
|
+#CONFIG_EAP_IKEV2=y
|
|
+
|
|
+# Trusted Network Connect (EAP-TNC)
|
|
+#CONFIG_EAP_TNC=y
|
|
+
|
|
+# EAP-EKE for the integrated EAP server
|
|
+#CONFIG_EAP_EKE=y
|
|
+
|
|
+# PKCS#12 (PFX) support (used to read private key and certificate file from
|
|
+# a file that usually has extension .p12 or .pfx)
|
|
+#CONFIG_PKCS12=y
|
|
+
|
|
+# RADIUS authentication server. This provides access to the integrated EAP
|
|
+# server from external hosts using RADIUS.
|
|
+#CONFIG_RADIUS_SERVER=y
|
|
+
|
|
+# Build IPv6 support for RADIUS operations
|
|
+#CONFIG_IPV6=y
|
|
+
|
|
+# IEEE Std 802.11r-2008 (Fast BSS Transition)
|
|
+#CONFIG_IEEE80211R=y
|
|
+
|
|
+# Use the hostapd's IEEE 802.11 authentication (ACL), but without
|
|
+# 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
|
|
+
|
|
+# IEEE 802.11ac (Very High Throughput) support
|
|
+CONFIG_IEEE80211AC=y
|
|
+
|
|
+# IEEE 802.11ax HE support
|
|
+# Note: This is experimental and work in progress. The definitions are still
|
|
+# subject to change and this should not be expected to interoperate with the
|
|
+# final IEEE 802.11ax version.
|
|
+#CONFIG_IEEE80211AX=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.
|
|
+#CONFIG_NO_STDOUT_DEBUG=y
|
|
+
|
|
+# Add support for writing debug log to a file: -f /tmp/hostapd.log
|
|
+# Disabled by default.
|
|
+#CONFIG_DEBUG_FILE=y
|
|
+
|
|
+# Send debug messages to syslog instead of stdout
|
|
+CONFIG_DEBUG_SYSLOG=y
|
|
+
|
|
+# Add support for sending all debug messages (regardless of debug verbosity)
|
|
+# to the Linux kernel tracing facility. This helps debug the entire stack by
|
|
+# making it easy to record everything happening from the driver up into the
|
|
+# same file, e.g., using trace-cmd.
|
|
+#CONFIG_DEBUG_LINUX_TRACING=y
|
|
+
|
|
+# Remove support for RADIUS accounting
|
|
+CONFIG_NO_ACCOUNTING=y
|
|
+
|
|
+# Remove support for RADIUS
|
|
+CONFIG_NO_RADIUS=y
|
|
+
|
|
+# Remove support for VLANs
|
|
+#CONFIG_NO_VLAN=y
|
|
+
|
|
+# Enable support for fully dynamic VLANs. This enables hostapd to
|
|
+# automatically create bridge and VLAN interfaces if necessary.
|
|
+#CONFIG_FULL_DYNAMIC_VLAN=y
|
|
+
|
|
+# Use netlink-based kernel API for VLAN operations instead of ioctl()
|
|
+# Note: This requires libnl 3.1 or newer.
|
|
+#CONFIG_VLAN_NETLINK=y
|
|
+
|
|
+# Remove support for dumping internal state through control interface commands
|
|
+# This can be used to reduce binary size at the cost of disabling a debugging
|
|
+# option.
|
|
+CONFIG_NO_DUMP_STATE=y
|
|
+
|
|
+# Enable tracing code for developer debugging
|
|
+# This tracks use of memory allocations and other registrations and reports
|
|
+# incorrect use with a backtrace of call (or allocation) location.
|
|
+#CONFIG_WPA_TRACE=y
|
|
+# For BSD, comment out these.
|
|
+#LIBS += -lexecinfo
|
|
+#LIBS_p += -lexecinfo
|
|
+#LIBS_c += -lexecinfo
|
|
+
|
|
+# Use libbfd to get more details for developer debugging
|
|
+# This enables use of libbfd to get more detailed symbols for the backtraces
|
|
+# generated by CONFIG_WPA_TRACE=y.
|
|
+#CONFIG_WPA_TRACE_BFD=y
|
|
+# For BSD, comment out these.
|
|
+#LIBS += -lbfd -liberty -lz
|
|
+#LIBS_p += -lbfd -liberty -lz
|
|
+#LIBS_c += -lbfd -liberty -lz
|
|
+
|
|
+# hostapd depends on strong random number generation being available from the
|
|
+# operating system. os_get_random() function is used to fetch random data when
|
|
+# needed, e.g., for key generation. On Linux and BSD systems, this works by
|
|
+# reading /dev/urandom. It should be noted that the OS entropy pool needs to be
|
|
+# properly initialized before hostapd is started. This is important especially
|
|
+# on embedded devices that do not have a hardware random number generator and
|
|
+# may by default start up with minimal entropy available for random number
|
|
+# generation.
|
|
+#
|
|
+# As a safety net, hostapd is by default trying to internally collect
|
|
+# additional entropy for generating random data to mix in with the data
|
|
+# fetched from the OS. This by itself is not considered to be very strong, but
|
|
+# it may help in cases where the system pool is not initialized properly.
|
|
+# However, it is very strongly recommended that the system pool is initialized
|
|
+# with enough entropy either by using hardware assisted random number
|
|
+# generator or by storing state over device reboots.
|
|
+#
|
|
+# hostapd can be configured to maintain its own entropy store over restarts to
|
|
+# enhance random number generation. This is not perfect, but it is much more
|
|
+# secure than using the same sequence of random numbers after every reboot.
|
|
+# This can be enabled with -e<entropy file> command line option. The specified
|
|
+# file needs to be readable and writable by hostapd.
|
|
+#
|
|
+# If the os_get_random() is known to provide strong random data (e.g., on
|
|
+# Linux/BSD, the board in question is known to have reliable source of random
|
|
+# data from /dev/urandom), the internal hostapd random pool can be disabled.
|
|
+# This will save some in binary size and CPU use. However, this should only be
|
|
+# considered for builds that are known to be used on devices that meet the
|
|
+# requirements described above.
|
|
+CONFIG_NO_RANDOM_POOL=y
|
|
+
|
|
+# Should we attempt to use the getrandom(2) call that provides more reliable
|
|
+# yet secure randomness source than /dev/random on Linux 3.17 and newer.
|
|
+# Requires glibc 2.25 to build, falls back to /dev/random if unavailable.
|
|
+CONFIG_GETRANDOM=y
|
|
+
|
|
+# Should we use poll instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_POLL=y
|
|
+
|
|
+# Should we use epoll instead of select? Select is used by default.
|
|
+CONFIG_ELOOP_EPOLL=y
|
|
+
|
|
+# Should we use kqueue instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_KQUEUE=y
|
|
+
|
|
+# Select TLS implementation
|
|
+# openssl = OpenSSL (default)
|
|
+# gnutls = GnuTLS
|
|
+# internal = Internal TLSv1 implementation (experimental)
|
|
+# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
|
|
+# none = Empty template
|
|
+CONFIG_TLS=internal
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
|
+# can be enabled to get a stronger construction of messages when block ciphers
|
|
+# are used.
|
|
+#CONFIG_TLSV11=y
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
|
|
+# can be enabled to enable use of stronger crypto algorithms.
|
|
+#CONFIG_TLSV12=y
|
|
+
|
|
+# Select which ciphers to use by default with OpenSSL if the user does not
|
|
+# specify them.
|
|
+#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
|
|
+
|
|
+# If CONFIG_TLS=internal is used, additional library and include paths are
|
|
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
|
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
|
+# and drawbacks of this option.
|
|
+#CONFIG_INTERNAL_LIBTOMMATH=y
|
|
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
|
|
+#LTM_PATH=/usr/src/libtommath-0.39
|
|
+#CFLAGS += -I$(LTM_PATH)
|
|
+#LIBS += -L$(LTM_PATH)
|
|
+#LIBS_p += -L$(LTM_PATH)
|
|
+#endif
|
|
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
|
|
+# can be configured to include faster routines for exptmod, sqr, and div to
|
|
+# speed up DH and RSA calculation considerably
|
|
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
|
+
|
|
+# Interworking (IEEE 802.11u)
|
|
+# This can be used to enable functionality to improve interworking with
|
|
+# external networks.
|
|
+#CONFIG_INTERWORKING=y
|
|
+
|
|
+# Hotspot 2.0
|
|
+#CONFIG_HS20=y
|
|
+
|
|
+# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
|
|
+#CONFIG_SQLITE=y
|
|
+
|
|
+# Enable Fast Session Transfer (FST)
|
|
+#CONFIG_FST=y
|
|
+
|
|
+# Enable CLI commands for FST testing
|
|
+#CONFIG_FST_TEST=y
|
|
+
|
|
+# Testing options
|
|
+# This can be used to enable some testing options (see also the example
|
|
+# configuration file) that are really useful only for testing clients that
|
|
+# connect to this hostapd. These options allow, for example, to drop a
|
|
+# certain percentage of probe requests or auth/(re)assoc frames.
|
|
+#
|
|
+#CONFIG_TESTING_OPTIONS=y
|
|
+
|
|
+# Automatic Channel Selection
|
|
+# This will allow hostapd to pick the channel automatically when channel is set
|
|
+# to "acs_survey" or "0". Eventually, other ACS algorithms can be added in
|
|
+# similar way.
|
|
+#
|
|
+# Automatic selection is currently only done through initialization, later on
|
|
+# we hope to do background checks to keep us moving to more ideal channels as
|
|
+# time goes by. ACS is currently only supported through the nl80211 driver and
|
|
+# your driver must have survey dump capability that is filled by the driver
|
|
+# during scanning.
|
|
+#
|
|
+# You can customize the ACS survey algorithm with the hostapd.conf variable
|
|
+# acs_num_scans.
|
|
+#
|
|
+# Supported ACS drivers:
|
|
+# * ath9k
|
|
+# * ath5k
|
|
+# * ath10k
|
|
+#
|
|
+# For more details refer to:
|
|
+# http://wireless.kernel.org/en/users/Documentation/acs
|
|
+#
|
|
+#CONFIG_ACS=y
|
|
+
|
|
+# Multiband Operation support
|
|
+# These extentions facilitate efficient use of multiple frequency bands
|
|
+# available to the AP and the devices that may associate with it.
|
|
+#CONFIG_MBO=y
|
|
+
|
|
+# Client Taxonomy
|
|
+# Has the AP retain the Probe Request and (Re)Association Request frames from
|
|
+# a client, from which a signature can be produced which can identify the model
|
|
+# of client device like "Nexus 6P" or "iPhone 5s".
|
|
+#CONFIG_TAXONOMY=y
|
|
+
|
|
+# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
|
|
+#CONFIG_FILS=y
|
|
+# FILS shared key authentication with PFS
|
|
+#CONFIG_FILS_SK_PFS=y
|
|
+
|
|
+# Include internal line edit mode in hostapd_cli. This can be used to provide
|
|
+# limited command line editing and history support.
|
|
+#CONFIG_WPA_CLI_EDIT=y
|
|
+
|
|
+# Opportunistic Wireless Encryption (OWE)
|
|
+# Experimental implementation of draft-harkins-owe-07.txt
|
|
+#CONFIG_OWE=y
|
|
+
|
|
+# Airtime policy support
|
|
+#CONFIG_AIRTIME_POLICY=y
|
|
+
|
|
+# Proxy ARP support
|
|
+#CONFIG_PROXYARP=y
|
|
+
|
|
+# Override default value for the wpa_disable_eapol_key_retries configuration
|
|
+# parameter. See that parameter in hostapd.conf for more details.
|
|
+#CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1
|
|
+
|
|
+# uBus IPC/RPC System
|
|
+# Services can connect to the bus and provide methods
|
|
+# that can be called by other services or clients.
|
|
+CONFIG_UBUS=y
|
|
+
|
|
+# OpenWrt patch 380-disable-ctrl-iface-mib.patch
|
|
+# leads to the MIB only being compiled in if
|
|
+# CONFIG_CTRL_IFACE_MIB is enabled.
|
|
+#CONFIG_CTRL_IFACE_MIB=y
|
|
diff --git a/package/network/services/hostapd/files/hostapd.uc b/package/network/services/hostapd/files/hostapd.uc
|
|
new file mode 100644
|
|
index 0000000000..f9f0c31bab
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/hostapd.uc
|
|
@@ -0,0 +1,486 @@
|
|
+let libubus = require("ubus");
|
|
+import { open, readfile } from "fs";
|
|
+import { wdev_create, wdev_remove, is_equal, vlist_new, phy_is_fullmac } from "common";
|
|
+
|
|
+let ubus = libubus.connect();
|
|
+
|
|
+hostapd.data.config = {};
|
|
+
|
|
+hostapd.data.file_fields = {
|
|
+ vlan_file: true,
|
|
+ wpa_psk_file: true,
|
|
+ accept_mac_file: true,
|
|
+ deny_mac_file: true,
|
|
+ eap_user_file: true,
|
|
+ ca_cert: true,
|
|
+ server_cert: true,
|
|
+ server_cert2: true,
|
|
+ private_key: true,
|
|
+ private_key2: true,
|
|
+ dh_file: true,
|
|
+ eap_sim_db: true,
|
|
+};
|
|
+
|
|
+function iface_remove(cfg)
|
|
+{
|
|
+ if (!cfg || !cfg.bss || !cfg.bss[0] || !cfg.bss[0].ifname)
|
|
+ return;
|
|
+
|
|
+ hostapd.remove_iface(cfg.bss[0].ifname);
|
|
+ for (let bss in cfg.bss)
|
|
+ wdev_remove(bss.ifname);
|
|
+}
|
|
+
|
|
+function iface_gen_config(phy, config)
|
|
+{
|
|
+ let str = `data:
|
|
+${join("\n", config.radio.data)}
|
|
+channel=${config.radio.channel}
|
|
+`;
|
|
+
|
|
+ for (let i = 0; i < length(config.bss); i++) {
|
|
+ let bss = config.bss[i];
|
|
+ let type = i > 0 ? "bss" : "interface";
|
|
+
|
|
+ str += `
|
|
+${type}=${bss.ifname}
|
|
+${join("\n", bss.data)}
|
|
+`;
|
|
+ }
|
|
+
|
|
+ return str;
|
|
+}
|
|
+
|
|
+function iface_restart(phy, config, old_config)
|
|
+{
|
|
+ iface_remove(old_config);
|
|
+ iface_remove(config);
|
|
+
|
|
+ if (!config.bss || !config.bss[0]) {
|
|
+ hostapd.printf(`No bss for phy ${phy}`);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ let bss = config.bss[0];
|
|
+ let err = wdev_create(phy, bss.ifname, { mode: "ap" });
|
|
+ if (err)
|
|
+ hostapd.printf(`Failed to create ${bss.ifname} on phy ${phy}: ${err}`);
|
|
+ let config_inline = iface_gen_config(phy, config);
|
|
+
|
|
+ let ubus = hostapd.data.ubus;
|
|
+ ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: true });
|
|
+ if (hostapd.add_iface(`bss_config=${bss.ifname}:${config_inline}`) < 0)
|
|
+ hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`);
|
|
+ ubus.call("wpa_supplicant", "phy_set_state", { phy: phy, stop: false });
|
|
+}
|
|
+
|
|
+function array_to_obj(arr, key, start)
|
|
+{
|
|
+ let obj = {};
|
|
+
|
|
+ start ??= 0;
|
|
+ for (let i = start; i < length(arr); i++) {
|
|
+ let cur = arr[i];
|
|
+ obj[cur[key]] = cur;
|
|
+ }
|
|
+
|
|
+ return obj;
|
|
+}
|
|
+
|
|
+function find_array_idx(arr, key, val)
|
|
+{
|
|
+ for (let i = 0; i < length(arr); i++)
|
|
+ if (arr[i][key] == val)
|
|
+ return i;
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+function bss_reload_psk(bss, config, old_config)
|
|
+{
|
|
+ if (is_equal(old_config.hash.wpa_psk_file, config.hash.wpa_psk_file))
|
|
+ return;
|
|
+
|
|
+ old_config.hash.wpa_psk_file = config.hash.wpa_psk_file;
|
|
+ if (!is_equal(old_config, config))
|
|
+ return;
|
|
+
|
|
+ let ret = bss.ctrl("RELOAD_WPA_PSK");
|
|
+ ret ??= "failed";
|
|
+
|
|
+ hostapd.printf(`Reload WPA PSK file for bss ${config.ifname}: ${ret}`);
|
|
+}
|
|
+
|
|
+function iface_reload_config(phy, config, old_config)
|
|
+{
|
|
+ if (!old_config || !is_equal(old_config.radio, config.radio))
|
|
+ return false;
|
|
+
|
|
+ if (is_equal(old_config.bss, config.bss))
|
|
+ return true;
|
|
+
|
|
+ if (!old_config.bss || !old_config.bss[0])
|
|
+ return false;
|
|
+
|
|
+ if (config.bss[0].ifname != old_config.bss[0].ifname)
|
|
+ return false;
|
|
+
|
|
+ let iface_name = config.bss[0].ifname;
|
|
+ let iface = hostapd.interfaces[iface_name];
|
|
+ if (!iface)
|
|
+ return false;
|
|
+
|
|
+ let first_bss = hostapd.bss[iface_name];
|
|
+ if (!first_bss)
|
|
+ return false;
|
|
+
|
|
+ let config_inline = iface_gen_config(phy, config);
|
|
+
|
|
+ bss_reload_psk(first_bss, config.bss[0], old_config.bss[0]);
|
|
+ if (!is_equal(config.bss[0], old_config.bss[0])) {
|
|
+ if (phy_is_fullmac(phy))
|
|
+ return false;
|
|
+
|
|
+ if (config.bss[0].bssid != old_config.bss[0].bssid)
|
|
+ return false;
|
|
+
|
|
+ hostapd.printf(`Reload config for bss '${config.bss[0].ifname}' on phy '${phy}'`);
|
|
+ if (first_bss.set_config(config_inline, 0) < 0) {
|
|
+ hostapd.printf(`Failed to set config`);
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ let new_cfg = array_to_obj(config.bss, "ifname", 1);
|
|
+ let old_cfg = array_to_obj(old_config.bss, "ifname", 1);
|
|
+
|
|
+ for (let name in old_cfg) {
|
|
+ let bss = hostapd.bss[name];
|
|
+ if (!bss) {
|
|
+ hostapd.printf(`bss '${name}' not found`);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (!new_cfg[name]) {
|
|
+ hostapd.printf(`Remove bss '${name}' on phy '${phy}'`);
|
|
+ bss.delete();
|
|
+ wdev_remove(name);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ let new_cfg_data = new_cfg[name];
|
|
+ delete new_cfg[name];
|
|
+
|
|
+ if (is_equal(old_cfg[name], new_cfg_data))
|
|
+ continue;
|
|
+
|
|
+ hostapd.printf(`Reload config for bss '${name}' on phy '${phy}'`);
|
|
+ let idx = find_array_idx(config.bss, "ifname", name);
|
|
+ if (idx < 0) {
|
|
+ hostapd.printf(`bss index not found`);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (bss.set_config(config_inline, idx) < 0) {
|
|
+ hostapd.printf(`Failed to set config`);
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ for (let name in new_cfg) {
|
|
+ hostapd.printf(`Add bss '${name}' on phy '${phy}'`);
|
|
+
|
|
+ let idx = find_array_idx(config.bss, "ifname", name);
|
|
+ if (idx < 0) {
|
|
+ hostapd.printf(`bss index not found`);
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ if (iface.add_bss(config_inline, idx) < 0) {
|
|
+ hostapd.printf(`Failed to add bss`);
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+function iface_set_config(phy, config)
|
|
+{
|
|
+ let old_config = hostapd.data.config[phy];
|
|
+
|
|
+ hostapd.data.config[phy] = config;
|
|
+
|
|
+ if (!config)
|
|
+ return iface_remove(old_config);
|
|
+
|
|
+ let ret = iface_reload_config(phy, config, old_config);
|
|
+ if (ret) {
|
|
+ hostapd.printf(`Reloaded settings for phy ${phy}`);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ hostapd.printf(`Restart interface for phy ${phy}`);
|
|
+ return iface_restart(phy, config, old_config);
|
|
+}
|
|
+
|
|
+function config_add_bss(config, name)
|
|
+{
|
|
+ let bss = {
|
|
+ ifname: name,
|
|
+ data: [],
|
|
+ hash: {}
|
|
+ };
|
|
+
|
|
+ push(config.bss, bss);
|
|
+
|
|
+ return bss;
|
|
+}
|
|
+
|
|
+function iface_load_config(filename)
|
|
+{
|
|
+ let f = open(filename, "r");
|
|
+ if (!f)
|
|
+ return null;
|
|
+
|
|
+ let config = {
|
|
+ radio: {
|
|
+ data: []
|
|
+ },
|
|
+ bss: [],
|
|
+ orig_file: filename,
|
|
+ };
|
|
+
|
|
+ let bss;
|
|
+ let line;
|
|
+ while ((line = trim(f.read("line"))) != null) {
|
|
+ let val = split(line, "=", 2);
|
|
+ if (!val[0])
|
|
+ continue;
|
|
+
|
|
+ if (val[0] == "interface") {
|
|
+ bss = config_add_bss(config, val[1]);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (val[0] == "channel") {
|
|
+ config.radio.channel = val[1];
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ push(config.radio.data, line);
|
|
+ }
|
|
+
|
|
+ while ((line = trim(f.read("line"))) != null) {
|
|
+ let val = split(line, "=", 2);
|
|
+ if (!val[0])
|
|
+ continue;
|
|
+
|
|
+ if (val[0] == "bssid")
|
|
+ bss.bssid = val[1];
|
|
+
|
|
+ if (val[0] == "bss") {
|
|
+ bss = config_add_bss(config, val[1]);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ if (hostapd.data.file_fields[val[0]])
|
|
+ bss.hash[val[0]] = hostapd.sha1(readfile(val[1]));
|
|
+
|
|
+ push(bss.data, line);
|
|
+ }
|
|
+ f.close();
|
|
+
|
|
+ return config;
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+let main_obj = {
|
|
+ reload: {
|
|
+ args: {
|
|
+ phy: "",
|
|
+ },
|
|
+ call: function(req) {
|
|
+ try {
|
|
+ let phy_list = req.args.phy ? [ req.args.phy ] : keys(hostapd.data.config);
|
|
+ for (let phy_name in phy_list) {
|
|
+ let phy = hostapd.data.config[phy_name];
|
|
+ let config = iface_load_config(phy.orig_file);
|
|
+ iface_set_config(phy_name, config);
|
|
+ }
|
|
+ } catch(e) {
|
|
+ hostapd.printf(`Error reloading config: ${e}\n${e.stacktrace[0].context}`);
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+ },
|
|
+ apsta_state: {
|
|
+ args: {
|
|
+ phy: "",
|
|
+ up: true,
|
|
+ frequency: 0,
|
|
+ sec_chan_offset: 0,
|
|
+ csa: true,
|
|
+ csa_count: 0,
|
|
+ },
|
|
+ call: function(req) {
|
|
+ if (req.args.up == null || !req.args.phy)
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ let phy = req.args.phy;
|
|
+ let config = hostapd.data.config[phy];
|
|
+ if (!config || !config.bss || !config.bss[0] || !config.bss[0].ifname)
|
|
+ return 0;
|
|
+
|
|
+ let iface = hostapd.interfaces[config.bss[0].ifname];
|
|
+ if (!iface)
|
|
+ return 0;
|
|
+
|
|
+ if (!req.args.up) {
|
|
+ iface.stop();
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ let freq = req.args.frequency;
|
|
+ if (!freq)
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ let sec_offset = req.args.sec_chan_offset;
|
|
+ if (sec_offset != -1 && sec_offset != 1)
|
|
+ sec_offset = 0;
|
|
+
|
|
+ let width = 0;
|
|
+ for (let line in config.radio.data) {
|
|
+ if (!sec_offset && match(line, /^ht_capab=.*HT40/)) {
|
|
+ sec_offset = null; // auto-detect
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ let val = match(line, /^(vht_oper_chwidth|he_oper_chwidth)=(\d+)/);
|
|
+ if (!val)
|
|
+ continue;
|
|
+
|
|
+ val = int(val[2]);
|
|
+ if (val > width)
|
|
+ width = val;
|
|
+ }
|
|
+
|
|
+ if (freq < 4000)
|
|
+ width = 0;
|
|
+
|
|
+ let freq_info = hostapd.freq_info(freq, sec_offset, width);
|
|
+ if (!freq_info)
|
|
+ return libubus.STATUS_UNKNOWN_ERROR;
|
|
+
|
|
+ let ret;
|
|
+ if (req.args.csa) {
|
|
+ freq_info.csa_count = req.args.csa_count ?? 10;
|
|
+ ret = iface.switch_channel(freq_info);
|
|
+ } else {
|
|
+ iface.stop();
|
|
+ ret = iface.start(freq_info);
|
|
+ }
|
|
+ if (!ret)
|
|
+ return libubus.STATUS_UNKNOWN_ERROR;
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+ },
|
|
+ config_set: {
|
|
+ args: {
|
|
+ phy: "",
|
|
+ config: "",
|
|
+ prev_config: "",
|
|
+ },
|
|
+ call: function(req) {
|
|
+ let phy = req.args.phy;
|
|
+ let file = req.args.config;
|
|
+ let prev_file = req.args.prev_config;
|
|
+
|
|
+ if (!phy)
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ try {
|
|
+ if (prev_file && !hostapd.data.config[phy]) {
|
|
+ let config = iface_load_config(prev_file);
|
|
+ if (config)
|
|
+ config.radio.data = [];
|
|
+ hostapd.data.config[phy] = config;
|
|
+ }
|
|
+
|
|
+ let config = iface_load_config(file);
|
|
+
|
|
+ hostapd.printf(`Set new config for phy ${phy}: ${file}`);
|
|
+ iface_set_config(phy, config);
|
|
+ } catch(e) {
|
|
+ hostapd.printf(`Error loading config: ${e}\n${e.stacktrace[0].context}`);
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+ }
|
|
+
|
|
+ return {
|
|
+ pid: hostapd.getpid()
|
|
+ };
|
|
+ }
|
|
+ },
|
|
+ config_add: {
|
|
+ args: {
|
|
+ iface: "",
|
|
+ config: "",
|
|
+ },
|
|
+ call: function(req) {
|
|
+ if (!req.args.iface || !req.args.config)
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ if (hostapd.add_iface(`bss_config=${req.args.iface}:${req.args.config}`) < 0)
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ return {
|
|
+ pid: hostapd.getpid()
|
|
+ };
|
|
+ }
|
|
+ },
|
|
+ config_remove: {
|
|
+ args: {
|
|
+ iface: ""
|
|
+ },
|
|
+ call: function(req) {
|
|
+ if (!req.args.iface)
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ hostapd.remove_iface(req.args.iface);
|
|
+ return 0;
|
|
+ }
|
|
+ },
|
|
+};
|
|
+
|
|
+hostapd.data.ubus = ubus;
|
|
+hostapd.data.obj = ubus.publish("hostapd", main_obj);
|
|
+
|
|
+function bss_event(type, name, data) {
|
|
+ let ubus = hostapd.data.ubus;
|
|
+
|
|
+ data ??= {};
|
|
+ data.name = name;
|
|
+ hostapd.data.obj.notify(`bss.${type}`, data, null, null, null, -1);
|
|
+ ubus.call("service", "event", { type: `hostapd.${name}.${type}`, data: {} });
|
|
+}
|
|
+
|
|
+return {
|
|
+ shutdown: function() {
|
|
+ for (let phy in hostapd.data.config)
|
|
+ iface_set_config(phy, null);
|
|
+ hostapd.ubus.disconnect();
|
|
+ },
|
|
+ bss_add: function(name, obj) {
|
|
+ bss_event("add", name);
|
|
+ },
|
|
+ bss_reload: function(name, obj, reconf) {
|
|
+ bss_event("reload", name, { reconf: reconf != 0 });
|
|
+ },
|
|
+ bss_remove: function(name, obj) {
|
|
+ bss_event("remove", name);
|
|
+ }
|
|
+};
|
|
diff --git a/package/network/services/hostapd/files/multicall.c b/package/network/services/hostapd/files/multicall.c
|
|
new file mode 100644
|
|
index 0000000000..c8e814bb5c
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/multicall.c
|
|
@@ -0,0 +1,28 @@
|
|
+#include <stdio.h>
|
|
+#include <string.h>
|
|
+#include <stdbool.h>
|
|
+
|
|
+extern int hostapd_main(int argc, char **argv);
|
|
+extern int wpa_supplicant_main(int argc, char **argv);
|
|
+
|
|
+int main(int argc, char **argv)
|
|
+{
|
|
+ bool restart = false;
|
|
+ const char *prog = argv[0];
|
|
+
|
|
+restart:
|
|
+ if (strstr(argv[0], "hostapd"))
|
|
+ return hostapd_main(argc, argv);
|
|
+ else if (strstr(argv[0], "wpa_supplicant"))
|
|
+ return wpa_supplicant_main(argc, argv);
|
|
+
|
|
+ if (!restart && argc > 1) {
|
|
+ argv++;
|
|
+ argc--;
|
|
+ restart = true;
|
|
+ goto restart;
|
|
+ }
|
|
+
|
|
+ fprintf(stderr, "Invalid command.\nUsage: %s wpa_supplicant|hostapd [<arguments>]\n", prog);
|
|
+ return 255;
|
|
+}
|
|
diff --git a/package/network/services/hostapd/files/radius.clients b/package/network/services/hostapd/files/radius.clients
|
|
new file mode 100644
|
|
index 0000000000..3175dcfd04
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/radius.clients
|
|
@@ -0,0 +1 @@
|
|
+0.0.0.0/0 radius
|
|
diff --git a/package/network/services/hostapd/files/radius.config b/package/network/services/hostapd/files/radius.config
|
|
new file mode 100644
|
|
index 0000000000..ad8730748b
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/radius.config
|
|
@@ -0,0 +1,9 @@
|
|
+config radius
|
|
+ option disabled '1'
|
|
+ option ca_cert '/etc/radius/ca.pem'
|
|
+ option cert '/etc/radius/cert.pem'
|
|
+ option key '/etc/radius/key.pem'
|
|
+ option users '/etc/radius/users'
|
|
+ option clients '/etc/radius/clients'
|
|
+ option auth_port '1812'
|
|
+ option acct_port '1813'
|
|
diff --git a/package/network/services/hostapd/files/radius.init b/package/network/services/hostapd/files/radius.init
|
|
new file mode 100644
|
|
index 0000000000..4c562c2473
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/radius.init
|
|
@@ -0,0 +1,42 @@
|
|
+#!/bin/sh /etc/rc.common
|
|
+
|
|
+START=30
|
|
+
|
|
+USE_PROCD=1
|
|
+NAME=radius
|
|
+
|
|
+radius_start() {
|
|
+ local cfg="$1"
|
|
+
|
|
+ config_get_bool disabled "$cfg" disabled 0
|
|
+
|
|
+ [ "$disabled" -gt 0 ] && return
|
|
+
|
|
+ config_get ca "$cfg" ca_cert
|
|
+ config_get key "$cfg" key
|
|
+ config_get cert "$cfg" cert
|
|
+ config_get users "$cfg" users
|
|
+ config_get clients "$cfg" clients
|
|
+ config_get auth_port "$cfg" auth_port 1812
|
|
+ config_get acct_port "$cfg" acct_port 1813
|
|
+ config_get identity "$cfg" identity "$(cat /proc/sys/kernel/hostname)"
|
|
+
|
|
+ procd_open_instance $cfg
|
|
+ procd_set_param command /usr/sbin/hostapd-radius \
|
|
+ -C "$ca" \
|
|
+ -c "$cert" -k "$key" \
|
|
+ -s "$clients" -u "$users" \
|
|
+ -p "$auth_port" -P "$acct_port" \
|
|
+ -i "$identity"
|
|
+ procd_close_instance
|
|
+}
|
|
+
|
|
+start_service() {
|
|
+ config_load radius
|
|
+ config_foreach radius_start radius
|
|
+}
|
|
+
|
|
+service_triggers()
|
|
+{
|
|
+ procd_add_reload_trigger "radius"
|
|
+}
|
|
diff --git a/package/network/services/hostapd/files/radius.users b/package/network/services/hostapd/files/radius.users
|
|
new file mode 100644
|
|
index 0000000000..03e2fc8fae
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/radius.users
|
|
@@ -0,0 +1,14 @@
|
|
+{
|
|
+ "phase1": {
|
|
+ "wildcard": [
|
|
+ {
|
|
+ "name": "*",
|
|
+ "methods": [ "PEAP" ]
|
|
+ }
|
|
+ ]
|
|
+ },
|
|
+ "phase2": {
|
|
+ "users": {
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/package/network/services/hostapd/files/wdev.uc b/package/network/services/hostapd/files/wdev.uc
|
|
new file mode 100644
|
|
index 0000000000..5b321423eb
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/wdev.uc
|
|
@@ -0,0 +1,156 @@
|
|
+#!/usr/bin/env ucode
|
|
+'use strict';
|
|
+import { vlist_new, is_equal, wdev_create, wdev_remove } from "/usr/share/hostap/common.uc";
|
|
+import { readfile, writefile, basename, readlink, glob } from "fs";
|
|
+
|
|
+let keep_devices = {};
|
|
+let phy = shift(ARGV);
|
|
+let new_config = shift(ARGV);
|
|
+const mesh_params = [
|
|
+ "mesh_retry_timeout", "mesh_confirm_timeout", "mesh_holding_timeout", "mesh_max_peer_links",
|
|
+ "mesh_max_retries", "mesh_ttl", "mesh_element_ttl", "mesh_hwmp_max_preq_retries",
|
|
+ "mesh_path_refresh_time", "mesh_min_discovery_timeout", "mesh_hwmp_active_path_timeout",
|
|
+ "mesh_hwmp_preq_min_interval", "mesh_hwmp_net_diameter_traversal_time", "mesh_hwmp_rootmode",
|
|
+ "mesh_hwmp_rann_interval", "mesh_gate_announcements", "mesh_sync_offset_max_neighor",
|
|
+ "mesh_rssi_threshold", "mesh_hwmp_active_path_to_root_timeout", "mesh_hwmp_root_interval",
|
|
+ "mesh_hwmp_confirmation_interval", "mesh_awake_window", "mesh_plink_timeout",
|
|
+ "mesh_auto_open_plinks", "mesh_fwding", "mesh_power_mode"
|
|
+];
|
|
+
|
|
+function iface_stop(wdev)
|
|
+{
|
|
+ if (keep_devices[wdev.ifname])
|
|
+ return;
|
|
+
|
|
+ wdev_remove(wdev.ifname);
|
|
+}
|
|
+
|
|
+function iface_start(wdev)
|
|
+{
|
|
+ let ifname = wdev.ifname;
|
|
+
|
|
+ if (readfile(`/sys/class/net/${ifname}/ifindex`)) {
|
|
+ system([ "ip", "link", "set", "dev", ifname, "down" ]);
|
|
+ wdev_remove(ifname);
|
|
+ }
|
|
+ wdev_create(phy, ifname, wdev);
|
|
+ system([ "ip", "link", "set", "dev", ifname, "up" ]);
|
|
+ if (wdev.freq)
|
|
+ system(`iw dev ${ifname} set freq ${wdev.freq} ${wdev.htmode}`);
|
|
+ if (wdev.mode == "adhoc") {
|
|
+ let cmd = ["iw", "dev", ifname, "ibss", "join", wdev.ssid, wdev.freq, wdev.htmode, "fixed-freq" ];
|
|
+ if (wdev.bssid)
|
|
+ push(cmd, wdev.bssid);
|
|
+ for (let key in [ "beacon-interval", "basic-rates", "mcast-rate", "keys" ])
|
|
+ if (wdev[key])
|
|
+ push(cmd, key, wdev[key]);
|
|
+ system(cmd);
|
|
+ } else if (wdev.mode == "mesh") {
|
|
+ let cmd = [ "iw", "dev", ifname, "mesh", "join", wdev.ssid, "freq", wdev.freq, wdev.htmode ];
|
|
+ for (let key in [ "beacon-interval", "mcast-rate" ])
|
|
+ if (wdev[key])
|
|
+ push(cmd, key, wdev[key]);
|
|
+ system(cmd);
|
|
+
|
|
+ cmd = ["iw", "dev", ifname, "set", "mesh_param" ];
|
|
+ let len = length(cmd);
|
|
+
|
|
+ for (let param in mesh_params)
|
|
+ if (wdev[param])
|
|
+ push(cmd, param, wdev[param]);
|
|
+
|
|
+ if (len == length(cmd))
|
|
+ return;
|
|
+
|
|
+ system(cmd);
|
|
+ }
|
|
+
|
|
+}
|
|
+
|
|
+function iface_cb(new_if, old_if)
|
|
+{
|
|
+ if (old_if && new_if && is_equal(old_if, new_if))
|
|
+ return;
|
|
+
|
|
+ if (old_if)
|
|
+ iface_stop(old_if);
|
|
+ if (new_if)
|
|
+ iface_start(new_if);
|
|
+}
|
|
+
|
|
+function drop_inactive(config)
|
|
+{
|
|
+ for (let key in config) {
|
|
+ if (!readfile(`/sys/class/net/${key}/ifindex`))
|
|
+ delete config[key];
|
|
+ }
|
|
+}
|
|
+
|
|
+function add_ifname(config)
|
|
+{
|
|
+ for (let key in config)
|
|
+ config[key].ifname = key;
|
|
+}
|
|
+
|
|
+function delete_ifname(config)
|
|
+{
|
|
+ for (let key in config)
|
|
+ delete config[key].ifname;
|
|
+}
|
|
+
|
|
+function add_existing(phy, config)
|
|
+{
|
|
+ let wdevs = glob(`/sys/class/ieee80211/${phy}/device/net/*`);
|
|
+ wdevs = map(wdevs, (arg) => basename(arg));
|
|
+ for (let wdev in wdevs) {
|
|
+ if (config[wdev])
|
|
+ continue;
|
|
+
|
|
+ if (basename(readlink(`/sys/class/net/${wdev}/phy80211`)) != phy)
|
|
+ continue;
|
|
+
|
|
+ if (trim(readfile(`/sys/class/net/${wdev}/operstate`)) == "down")
|
|
+ config[wdev] = {};
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+let statefile = `/var/run/wdev-${phy}.json`;
|
|
+
|
|
+for (let dev in ARGV)
|
|
+ keep_devices[dev] = true;
|
|
+
|
|
+if (!phy || !new_config) {
|
|
+ warn(`Usage: ${basename(sourcepath())} <phy> <config> [<device]...]\n`);
|
|
+ exit(1);
|
|
+}
|
|
+
|
|
+if (!readfile(`/sys/class/ieee80211/${phy}/index`)) {
|
|
+ warn(`PHY ${phy} does not exist\n`);
|
|
+ exit(1);
|
|
+}
|
|
+
|
|
+new_config = json(new_config);
|
|
+if (!new_config) {
|
|
+ warn("Invalid configuration\n");
|
|
+ exit(1);
|
|
+}
|
|
+
|
|
+let old_config = readfile(statefile);
|
|
+if (old_config)
|
|
+ old_config = json(old_config);
|
|
+
|
|
+let config = vlist_new(iface_cb);
|
|
+if (type(old_config) == "object")
|
|
+ config.data = old_config;
|
|
+
|
|
+add_existing(phy, config.data);
|
|
+add_ifname(config.data);
|
|
+drop_inactive(config.data);
|
|
+
|
|
+add_ifname(new_config);
|
|
+config.update(new_config);
|
|
+
|
|
+drop_inactive(config.data);
|
|
+delete_ifname(config.data);
|
|
+writefile(statefile, sprintf("%J", config.data));
|
|
diff --git a/package/network/services/hostapd/files/wpa_supplicant-basic.config b/package/network/services/hostapd/files/wpa_supplicant-basic.config
|
|
new file mode 100644
|
|
index 0000000000..944b4d9287
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/wpa_supplicant-basic.config
|
|
@@ -0,0 +1,625 @@
|
|
+# Example wpa_supplicant build time configuration
|
|
+#
|
|
+# This file lists the configuration options that are used when building the
|
|
+# wpa_supplicant binary. All lines starting with # are ignored. Configuration
|
|
+# option lines must be commented out complete, if they are not to be included,
|
|
+# i.e., just setting VARIABLE=n is not disabling that variable.
|
|
+#
|
|
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
|
|
+# be modified from here. In most cases, these lines should use += in order not
|
|
+# to override previous values of the variables.
|
|
+
|
|
+
|
|
+# Uncomment following two lines and fix the paths if you have installed OpenSSL
|
|
+# or GnuTLS in non-default location
|
|
+#CFLAGS += -I/usr/local/openssl/include
|
|
+#LIBS += -L/usr/local/openssl/lib
|
|
+
|
|
+# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
|
|
+# the kerberos files are not in the default include path. Following line can be
|
|
+# used to fix build issues on such systems (krb5.h not found).
|
|
+#CFLAGS += -I/usr/include/kerberos
|
|
+
|
|
+# Driver interface for generic Linux wireless extensions
|
|
+# Note: WEXT is deprecated in the current Linux kernel version and no new
|
|
+# functionality is added to it. nl80211-based interface is the new
|
|
+# replacement for WEXT and its use allows wpa_supplicant to properly control
|
|
+# the driver to improve existing functionality like roaming and to support new
|
|
+# functionality.
|
|
+#CONFIG_DRIVER_WEXT=y
|
|
+
|
|
+# Driver interface for Linux drivers using the nl80211 kernel interface
|
|
+CONFIG_DRIVER_NL80211=y
|
|
+
|
|
+# QCA vendor extensions to nl80211
|
|
+#CONFIG_DRIVER_NL80211_QCA=y
|
|
+
|
|
+# driver_nl80211.c requires libnl. If you are compiling it yourself
|
|
+# you may need to point hostapd to your version of libnl.
|
|
+#
|
|
+#CFLAGS += -I$<path to libnl include files>
|
|
+#LIBS += -L$<path to libnl library files>
|
|
+
|
|
+# Use libnl v2.0 (or 3.0) libraries.
|
|
+#CONFIG_LIBNL20=y
|
|
+
|
|
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
|
|
+#CONFIG_LIBNL32=y
|
|
+
|
|
+
|
|
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
|
+#CONFIG_DRIVER_BSD=y
|
|
+#CFLAGS += -I/usr/local/include
|
|
+#LIBS += -L/usr/local/lib
|
|
+#LIBS_p += -L/usr/local/lib
|
|
+#LIBS_c += -L/usr/local/lib
|
|
+
|
|
+# Driver interface for Windows NDIS
|
|
+#CONFIG_DRIVER_NDIS=y
|
|
+#CFLAGS += -I/usr/include/w32api/ddk
|
|
+#LIBS += -L/usr/local/lib
|
|
+# For native build using mingw
|
|
+#CONFIG_NATIVE_WINDOWS=y
|
|
+# Additional directories for cross-compilation on Linux host for mingw target
|
|
+#CFLAGS += -I/opt/mingw/mingw32/include/ddk
|
|
+#LIBS += -L/opt/mingw/mingw32/lib
|
|
+#CC=mingw32-gcc
|
|
+# By default, driver_ndis uses WinPcap for low-level operations. This can be
|
|
+# replaced with the following option which replaces WinPcap calls with NDISUIO.
|
|
+# However, this requires that WZC is disabled (net stop wzcsvc) before starting
|
|
+# wpa_supplicant.
|
|
+# CONFIG_USE_NDISUIO=y
|
|
+
|
|
+# Driver interface for wired Ethernet drivers
|
|
+CONFIG_DRIVER_WIRED=y
|
|
+
|
|
+# Driver interface for MACsec capable Qualcomm Atheros drivers
|
|
+#CONFIG_DRIVER_MACSEC_QCA=y
|
|
+
|
|
+# Driver interface for Linux MACsec drivers
|
|
+#CONFIG_DRIVER_MACSEC_LINUX=y
|
|
+
|
|
+# Driver interface for the Broadcom RoboSwitch family
|
|
+#CONFIG_DRIVER_ROBOSWITCH=y
|
|
+
|
|
+# Driver interface for no driver (e.g., WPS ER only)
|
|
+#CONFIG_DRIVER_NONE=y
|
|
+
|
|
+# Solaris libraries
|
|
+#LIBS += -lsocket -ldlpi -lnsl
|
|
+#LIBS_c += -lsocket
|
|
+
|
|
+# Enable IEEE 802.1X Supplicant (automatically included if any EAP method or
|
|
+# MACsec is included)
|
|
+#CONFIG_IEEE8021X_EAPOL=y
|
|
+
|
|
+# EAP-MD5
|
|
+#CONFIG_EAP_MD5=y
|
|
+
|
|
+# EAP-MSCHAPv2
|
|
+#CONFIG_EAP_MSCHAPV2=y
|
|
+
|
|
+# EAP-TLS
|
|
+#CONFIG_EAP_TLS=y
|
|
+
|
|
+# EAL-PEAP
|
|
+#CONFIG_EAP_PEAP=y
|
|
+
|
|
+# EAP-TTLS
|
|
+#CONFIG_EAP_TTLS=y
|
|
+
|
|
+# EAP-FAST
|
|
+#CONFIG_EAP_FAST=y
|
|
+
|
|
+# EAP-TEAP
|
|
+# Note: The current EAP-TEAP implementation is experimental and should not be
|
|
+# enabled for production use. The IETF RFC 7170 that defines EAP-TEAP has number
|
|
+# of conflicting statements and missing details and the implementation has
|
|
+# vendor specific workarounds for those and as such, may not interoperate with
|
|
+# any other implementation. This should not be used for anything else than
|
|
+# experimentation and interoperability testing until those issues has been
|
|
+# resolved.
|
|
+#CONFIG_EAP_TEAP=y
|
|
+
|
|
+# EAP-GTC
|
|
+#CONFIG_EAP_GTC=y
|
|
+
|
|
+# EAP-OTP
|
|
+#CONFIG_EAP_OTP=y
|
|
+
|
|
+# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)
|
|
+#CONFIG_EAP_SIM=y
|
|
+
|
|
+# Enable SIM simulator (Milenage) for EAP-SIM
|
|
+#CONFIG_SIM_SIMULATOR=y
|
|
+
|
|
+# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
|
|
+#CONFIG_EAP_PSK=y
|
|
+
|
|
+# EAP-pwd (secure authentication using only a password)
|
|
+#CONFIG_EAP_PWD=y
|
|
+
|
|
+# EAP-PAX
|
|
+#CONFIG_EAP_PAX=y
|
|
+
|
|
+# LEAP
|
|
+#CONFIG_EAP_LEAP=y
|
|
+
|
|
+# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
|
|
+#CONFIG_EAP_AKA=y
|
|
+
|
|
+# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
|
|
+# This requires CONFIG_EAP_AKA to be enabled, too.
|
|
+#CONFIG_EAP_AKA_PRIME=y
|
|
+
|
|
+# Enable USIM simulator (Milenage) for EAP-AKA
|
|
+#CONFIG_USIM_SIMULATOR=y
|
|
+
|
|
+# EAP-SAKE
|
|
+#CONFIG_EAP_SAKE=y
|
|
+
|
|
+# EAP-GPSK
|
|
+#CONFIG_EAP_GPSK=y
|
|
+# Include support for optional SHA256 cipher suite in EAP-GPSK
|
|
+#CONFIG_EAP_GPSK_SHA256=y
|
|
+
|
|
+# EAP-TNC and related Trusted Network Connect support (experimental)
|
|
+#CONFIG_EAP_TNC=y
|
|
+
|
|
+# Wi-Fi Protected Setup (WPS)
|
|
+#CONFIG_WPS=y
|
|
+# Enable WPS external registrar functionality
|
|
+#CONFIG_WPS_ER=y
|
|
+# Disable credentials for an open network by default when acting as a WPS
|
|
+# registrar.
|
|
+#CONFIG_WPS_REG_DISABLE_OPEN=y
|
|
+# Enable WPS support with NFC config method
|
|
+#CONFIG_WPS_NFC=y
|
|
+
|
|
+# EAP-IKEv2
|
|
+#CONFIG_EAP_IKEV2=y
|
|
+
|
|
+# EAP-EKE
|
|
+#CONFIG_EAP_EKE=y
|
|
+
|
|
+# MACsec
|
|
+#CONFIG_MACSEC=y
|
|
+
|
|
+# PKCS#12 (PFX) support (used to read private key and certificate file from
|
|
+# a file that usually has extension .p12 or .pfx)
|
|
+#CONFIG_PKCS12=y
|
|
+
|
|
+# Smartcard support (i.e., private key on a smartcard), e.g., with openssl
|
|
+# engine.
|
|
+#CONFIG_SMARTCARD=y
|
|
+
|
|
+# PC/SC interface for smartcards (USIM, GSM SIM)
|
|
+# Enable this if EAP-SIM or EAP-AKA is included
|
|
+#CONFIG_PCSC=y
|
|
+
|
|
+# Support HT overrides (disable HT/HT40, mask MCS rates, etc.)
|
|
+CONFIG_HT_OVERRIDES=y
|
|
+
|
|
+# Support VHT overrides (disable VHT, mask MCS rates, etc.)
|
|
+CONFIG_VHT_OVERRIDES=y
|
|
+
|
|
+# Development testing
|
|
+#CONFIG_EAPOL_TEST=y
|
|
+
|
|
+# Select control interface backend for external programs, e.g, wpa_cli:
|
|
+# unix = UNIX domain sockets (default for Linux/*BSD)
|
|
+# udp = UDP sockets using localhost (127.0.0.1)
|
|
+# udp6 = UDP IPv6 sockets using localhost (::1)
|
|
+# named_pipe = Windows Named Pipe (default for Windows)
|
|
+# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
|
|
+# udp6-remote = UDP IPv6 sockets with remote access (only for tests purpose)
|
|
+# y = use default (backwards compatibility)
|
|
+# If this option is commented out, control interface is not included in the
|
|
+# build.
|
|
+CONFIG_CTRL_IFACE=y
|
|
+
|
|
+# Include support for GNU Readline and History Libraries in wpa_cli.
|
|
+# When building a wpa_cli binary for distribution, please note that these
|
|
+# libraries are licensed under GPL and as such, BSD license may not apply for
|
|
+# the resulting binary.
|
|
+#CONFIG_READLINE=y
|
|
+
|
|
+# Include internal line edit mode in wpa_cli. This can be used as a replacement
|
|
+# for GNU Readline to provide limited command line editing and history support.
|
|
+#CONFIG_WPA_CLI_EDIT=y
|
|
+
|
|
+# Remove debugging code that is printing out debug message to stdout.
|
|
+# This can be used to reduce the size of the wpa_supplicant considerably
|
|
+# if debugging code is not needed. The size reduction can be around 35%
|
|
+# (e.g., 90 kB).
|
|
+#CONFIG_NO_STDOUT_DEBUG=y
|
|
+
|
|
+# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save
|
|
+# 35-50 kB in code size.
|
|
+#CONFIG_NO_WPA=y
|
|
+
|
|
+# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
|
|
+# This option can be used to reduce code size by removing support for
|
|
+# converting ASCII passphrases into PSK. If this functionality is removed, the
|
|
+# PSK can only be configured as the 64-octet hexstring (e.g., from
|
|
+# wpa_passphrase). This saves about 0.5 kB in code size.
|
|
+#CONFIG_NO_WPA_PASSPHRASE=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.
|
|
+# This can be used if ap_scan=1 mode is never enabled.
|
|
+#CONFIG_NO_SCAN_PROCESSING=y
|
|
+
|
|
+# Select configuration backend:
|
|
+# file = text file (e.g., wpa_supplicant.conf; note: the configuration file
|
|
+# path is given on command line, not here; this option is just used to
|
|
+# select the backend that allows configuration files to be used)
|
|
+# winreg = Windows registry (see win_example.reg for an example)
|
|
+CONFIG_BACKEND=file
|
|
+
|
|
+# Remove configuration write functionality (i.e., to allow the configuration
|
|
+# file to be updated based on runtime configuration changes). The runtime
|
|
+# configuration can still be changed, the changes are just not going to be
|
|
+# persistent over restarts. This option can be used to reduce code size by
|
|
+# about 3.5 kB.
|
|
+CONFIG_NO_CONFIG_WRITE=y
|
|
+
|
|
+# Remove support for configuration blobs to reduce code size by about 1.5 kB.
|
|
+#CONFIG_NO_CONFIG_BLOBS=y
|
|
+
|
|
+# Select program entry point implementation:
|
|
+# main = UNIX/POSIX like main() function (default)
|
|
+# main_winsvc = Windows service (read parameters from registry)
|
|
+# main_none = Very basic example (development use only)
|
|
+#CONFIG_MAIN=main
|
|
+
|
|
+# Select wrapper for operating system and C library specific functions
|
|
+# unix = UNIX/POSIX like systems (default)
|
|
+# win32 = Windows systems
|
|
+# none = Empty template
|
|
+#CONFIG_OS=unix
|
|
+
|
|
+# Select event loop implementation
|
|
+# eloop = select() loop (default)
|
|
+# eloop_win = Windows events and WaitForMultipleObject() loop
|
|
+#CONFIG_ELOOP=eloop
|
|
+
|
|
+# Should we use poll instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_POLL=y
|
|
+
|
|
+# Should we use epoll instead of select? Select is used by default.
|
|
+CONFIG_ELOOP_EPOLL=y
|
|
+
|
|
+# Should we use kqueue instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_KQUEUE=y
|
|
+
|
|
+# Select layer 2 packet implementation
|
|
+# linux = Linux packet socket (default)
|
|
+# pcap = libpcap/libdnet/WinPcap
|
|
+# freebsd = FreeBSD libpcap
|
|
+# winpcap = WinPcap with receive thread
|
|
+# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)
|
|
+# none = Empty template
|
|
+#CONFIG_L2_PACKET=linux
|
|
+
|
|
+# Disable Linux packet socket workaround applicable for station interface
|
|
+# in a bridge for EAPOL frames. This should be uncommented only if the kernel
|
|
+# is known to not have the regression issue in packet socket behavior with
|
|
+# bridge interfaces (commit 'bridge: respect RFC2863 operational state')').
|
|
+CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
|
|
+
|
|
+# IEEE 802.11w (management frame protection), also known as PMF
|
|
+# Driver support is also needed for IEEE 802.11w.
|
|
+#CONFIG_IEEE80211W=y
|
|
+
|
|
+# Support Operating Channel Validation
|
|
+CONFIG_OCV=y
|
|
+
|
|
+# Select TLS implementation
|
|
+# openssl = OpenSSL (default)
|
|
+# gnutls = GnuTLS
|
|
+# internal = Internal TLSv1 implementation (experimental)
|
|
+# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
|
|
+# none = Empty template
|
|
+CONFIG_TLS=internal
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
|
+# can be enabled to get a stronger construction of messages when block ciphers
|
|
+# are used. It should be noted that some existing TLS v1.0 -based
|
|
+# implementation may not be compatible with TLS v1.1 message (ClientHello is
|
|
+# sent prior to negotiating which version will be used)
|
|
+#CONFIG_TLSV11=y
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
|
|
+# can be enabled to enable use of stronger crypto algorithms. It should be
|
|
+# noted that some existing TLS v1.0 -based implementation may not be compatible
|
|
+# with TLS v1.2 message (ClientHello is sent prior to negotiating which version
|
|
+# will be used)
|
|
+#CONFIG_TLSV12=y
|
|
+
|
|
+# Select which ciphers to use by default with OpenSSL if the user does not
|
|
+# specify them.
|
|
+#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
|
|
+
|
|
+# If CONFIG_TLS=internal is used, additional library and include paths are
|
|
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
|
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
|
+# and drawbacks of this option.
|
|
+#CONFIG_INTERNAL_LIBTOMMATH=y
|
|
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
|
|
+#LTM_PATH=/usr/src/libtommath-0.39
|
|
+#CFLAGS += -I$(LTM_PATH)
|
|
+#LIBS += -L$(LTM_PATH)
|
|
+#LIBS_p += -L$(LTM_PATH)
|
|
+#endif
|
|
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
|
|
+# can be configured to include faster routines for exptmod, sqr, and div to
|
|
+# speed up DH and RSA calculation considerably
|
|
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
|
+
|
|
+# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
|
|
+# This is only for Windows builds and requires WMI-related header files and
|
|
+# WbemUuid.Lib from Platform SDK even when building with MinGW.
|
|
+#CONFIG_NDIS_EVENTS_INTEGRATED=y
|
|
+#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
|
|
+
|
|
+# Add support for new DBus control interface
|
|
+# (fi.w1.hostap.wpa_supplicant1)
|
|
+#CONFIG_CTRL_IFACE_DBUS_NEW=y
|
|
+
|
|
+# Add introspection support for new DBus control interface
|
|
+#CONFIG_CTRL_IFACE_DBUS_INTRO=y
|
|
+
|
|
+# Add support for loading EAP methods dynamically as shared libraries.
|
|
+# When this option is enabled, each EAP method can be either included
|
|
+# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
|
|
+# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to
|
|
+# be loaded in the beginning of the wpa_supplicant configuration file
|
|
+# (see load_dynamic_eap parameter in the example file) before being used in
|
|
+# the network blocks.
|
|
+#
|
|
+# Note that some shared parts of EAP methods are included in the main program
|
|
+# and in order to be able to use dynamic EAP methods using these parts, the
|
|
+# main program must have been build with the EAP method enabled (=y or =dyn).
|
|
+# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries
|
|
+# unless at least one of them was included in the main build to force inclusion
|
|
+# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included
|
|
+# in the main build to be able to load these methods dynamically.
|
|
+#
|
|
+# Please also note that using dynamic libraries will increase the total binary
|
|
+# size. Thus, it may not be the best option for targets that have limited
|
|
+# amount of memory/flash.
|
|
+#CONFIG_DYNAMIC_EAP_METHODS=y
|
|
+
|
|
+# IEEE Std 802.11r-2008 (Fast BSS Transition) for station mode
|
|
+CONFIG_IEEE80211R=y
|
|
+
|
|
+# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
|
|
+#CONFIG_DEBUG_FILE=y
|
|
+
|
|
+# Send debug messages to syslog instead of stdout
|
|
+CONFIG_DEBUG_SYSLOG=y
|
|
+# Set syslog facility for debug messages
|
|
+CONFIG_DEBUG_SYSLOG_FACILITY=LOG_DAEMON
|
|
+
|
|
+# Add support for sending all debug messages (regardless of debug verbosity)
|
|
+# to the Linux kernel tracing facility. This helps debug the entire stack by
|
|
+# making it easy to record everything happening from the driver up into the
|
|
+# same file, e.g., using trace-cmd.
|
|
+#CONFIG_DEBUG_LINUX_TRACING=y
|
|
+
|
|
+# Add support for writing debug log to Android logcat instead of standard
|
|
+# output
|
|
+#CONFIG_ANDROID_LOG=y
|
|
+
|
|
+# Enable privilege separation (see README 'Privilege separation' for details)
|
|
+#CONFIG_PRIVSEP=y
|
|
+
|
|
+# Enable mitigation against certain attacks against TKIP by delaying Michael
|
|
+# MIC error reports by a random amount of time between 0 and 60 seconds
|
|
+#CONFIG_DELAYED_MIC_ERROR_REPORT=y
|
|
+
|
|
+# Enable tracing code for developer debugging
|
|
+# This tracks use of memory allocations and other registrations and reports
|
|
+# incorrect use with a backtrace of call (or allocation) location.
|
|
+#CONFIG_WPA_TRACE=y
|
|
+# For BSD, uncomment these.
|
|
+#LIBS += -lexecinfo
|
|
+#LIBS_p += -lexecinfo
|
|
+#LIBS_c += -lexecinfo
|
|
+
|
|
+# Use libbfd to get more details for developer debugging
|
|
+# This enables use of libbfd to get more detailed symbols for the backtraces
|
|
+# generated by CONFIG_WPA_TRACE=y.
|
|
+#CONFIG_WPA_TRACE_BFD=y
|
|
+# For BSD, uncomment these.
|
|
+#LIBS += -lbfd -liberty -lz
|
|
+#LIBS_p += -lbfd -liberty -lz
|
|
+#LIBS_c += -lbfd -liberty -lz
|
|
+
|
|
+# wpa_supplicant depends on strong random number generation being available
|
|
+# from the operating system. os_get_random() function is used to fetch random
|
|
+# data when needed, e.g., for key generation. On Linux and BSD systems, this
|
|
+# works by reading /dev/urandom. It should be noted that the OS entropy pool
|
|
+# needs to be properly initialized before wpa_supplicant is started. This is
|
|
+# important especially on embedded devices that do not have a hardware random
|
|
+# number generator and may by default start up with minimal entropy available
|
|
+# for random number generation.
|
|
+#
|
|
+# As a safety net, wpa_supplicant is by default trying to internally collect
|
|
+# additional entropy for generating random data to mix in with the data fetched
|
|
+# from the OS. This by itself is not considered to be very strong, but it may
|
|
+# help in cases where the system pool is not initialized properly. However, it
|
|
+# is very strongly recommended that the system pool is initialized with enough
|
|
+# entropy either by using hardware assisted random number generator or by
|
|
+# storing state over device reboots.
|
|
+#
|
|
+# wpa_supplicant can be configured to maintain its own entropy store over
|
|
+# restarts to enhance random number generation. This is not perfect, but it is
|
|
+# much more secure than using the same sequence of random numbers after every
|
|
+# reboot. This can be enabled with -e<entropy file> command line option. The
|
|
+# specified file needs to be readable and writable by wpa_supplicant.
|
|
+#
|
|
+# If the os_get_random() is known to provide strong random data (e.g., on
|
|
+# Linux/BSD, the board in question is known to have reliable source of random
|
|
+# data from /dev/urandom), the internal wpa_supplicant random pool can be
|
|
+# disabled. This will save some in binary size and CPU use. However, this
|
|
+# should only be considered for builds that are known to be used on devices
|
|
+# that meet the requirements described above.
|
|
+CONFIG_NO_RANDOM_POOL=y
|
|
+
|
|
+# Should we attempt to use the getrandom(2) call that provides more reliable
|
|
+# yet secure randomness source than /dev/random on Linux 3.17 and newer.
|
|
+# 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)
|
|
+# Note: This is experimental and not complete implementation.
|
|
+#CONFIG_WNM=y
|
|
+
|
|
+# Interworking (IEEE 802.11u)
|
|
+# This can be used to enable functionality to improve interworking with
|
|
+# external networks (GAS/ANQP to learn more about the networks and network
|
|
+# selection based on available credentials).
|
|
+#CONFIG_INTERWORKING=y
|
|
+
|
|
+# Hotspot 2.0
|
|
+#CONFIG_HS20=y
|
|
+
|
|
+# Enable interface matching in wpa_supplicant
|
|
+#CONFIG_MATCH_IFACE=y
|
|
+
|
|
+# Disable roaming in wpa_supplicant
|
|
+#CONFIG_NO_ROAMING=y
|
|
+
|
|
+# AP mode operations with wpa_supplicant
|
|
+# This can be used for controlling AP mode operations with wpa_supplicant. It
|
|
+# should be noted that this is mainly aimed at simple cases like
|
|
+# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
|
|
+# external RADIUS server can be supported with hostapd.
|
|
+#CONFIG_AP=y
|
|
+
|
|
+# P2P (Wi-Fi Direct)
|
|
+# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
|
|
+# more information on P2P operations.
|
|
+#CONFIG_P2P=y
|
|
+
|
|
+# Enable TDLS support
|
|
+#CONFIG_TDLS=y
|
|
+
|
|
+# Wi-Fi Display
|
|
+# This can be used to enable Wi-Fi Display extensions for P2P using an external
|
|
+# program to control the additional information exchanges in the messages.
|
|
+#CONFIG_WIFI_DISPLAY=y
|
|
+
|
|
+# Autoscan
|
|
+# This can be used to enable automatic scan support in wpa_supplicant.
|
|
+# See wpa_supplicant.conf for more information on autoscan usage.
|
|
+#
|
|
+# Enabling directly a module will enable autoscan support.
|
|
+# For exponential module:
|
|
+#CONFIG_AUTOSCAN_EXPONENTIAL=y
|
|
+# For periodic module:
|
|
+#CONFIG_AUTOSCAN_PERIODIC=y
|
|
+
|
|
+# Password (and passphrase, etc.) backend for external storage
|
|
+# These optional mechanisms can be used to add support for storing passwords
|
|
+# and other secrets in external (to wpa_supplicant) location. This allows, for
|
|
+# example, operating system specific key storage to be used
|
|
+#
|
|
+# External password backend for testing purposes (developer use)
|
|
+#CONFIG_EXT_PASSWORD_TEST=y
|
|
+
|
|
+# Enable Fast Session Transfer (FST)
|
|
+#CONFIG_FST=y
|
|
+
|
|
+# Enable CLI commands for FST testing
|
|
+#CONFIG_FST_TEST=y
|
|
+
|
|
+# OS X builds. This is only for building eapol_test.
|
|
+#CONFIG_OSX=y
|
|
+
|
|
+# Automatic Channel Selection
|
|
+# This will allow wpa_supplicant to pick the channel automatically when channel
|
|
+# is set to "0".
|
|
+#
|
|
+# TODO: Extend parser to be able to parse "channel=acs_survey" as an alternative
|
|
+# to "channel=0". This would enable us to eventually add other ACS algorithms in
|
|
+# similar way.
|
|
+#
|
|
+# Automatic selection is currently only done through initialization, later on
|
|
+# we hope to do background checks to keep us moving to more ideal channels as
|
|
+# time goes by. ACS is currently only supported through the nl80211 driver and
|
|
+# your driver must have survey dump capability that is filled by the driver
|
|
+# during scanning.
|
|
+#
|
|
+# TODO: In analogy to hostapd be able to customize the ACS survey algorithm with
|
|
+# a newly to create wpa_supplicant.conf variable acs_num_scans.
|
|
+#
|
|
+# Supported ACS drivers:
|
|
+# * ath9k
|
|
+# * ath5k
|
|
+# * ath10k
|
|
+#
|
|
+# For more details refer to:
|
|
+# http://wireless.kernel.org/en/users/Documentation/acs
|
|
+#CONFIG_ACS=y
|
|
+
|
|
+# Support Multi Band Operation
|
|
+#CONFIG_MBO=y
|
|
+
|
|
+# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
|
|
+#CONFIG_FILS=y
|
|
+# FILS shared key authentication with PFS
|
|
+#CONFIG_FILS_SK_PFS=y
|
|
+
|
|
+# Support RSN on IBSS networks
|
|
+# This is needed to be able to use mode=1 network profile with proto=RSN and
|
|
+# key_mgmt=WPA-PSK (i.e., full key management instead of WPA-None).
|
|
+#CONFIG_IBSS_RSN=y
|
|
+
|
|
+# External PMKSA cache control
|
|
+# This can be used to enable control interface commands that allow the current
|
|
+# PMKSA cache entries to be fetched and new entries to be added.
|
|
+#CONFIG_PMKSA_CACHE_EXTERNAL=y
|
|
+
|
|
+# Mesh Networking (IEEE 802.11s)
|
|
+#CONFIG_MESH=y
|
|
+
|
|
+# Background scanning modules
|
|
+# These can be used to request wpa_supplicant to perform background scanning
|
|
+# operations for roaming within an ESS (same SSID). See the bgscan parameter in
|
|
+# the wpa_supplicant.conf file for more details.
|
|
+# Periodic background scans based on signal strength
|
|
+#CONFIG_BGSCAN_SIMPLE=y
|
|
+# Learn channels used by the network and try to avoid bgscans on other
|
|
+# channels (experimental)
|
|
+#CONFIG_BGSCAN_LEARN=y
|
|
+
|
|
+# Opportunistic Wireless Encryption (OWE)
|
|
+# Experimental implementation of draft-harkins-owe-07.txt
|
|
+#CONFIG_OWE=y
|
|
+
|
|
+# Device Provisioning Protocol (DPP)
|
|
+# This requires CONFIG_IEEE80211W=y to be enabled, too. (see
|
|
+# wpa_supplicant/README-DPP for details)
|
|
+#CONFIG_DPP=y
|
|
+
|
|
+# uBus IPC/RPC System
|
|
+# Services can connect to the bus and provide methods
|
|
+# that can be called by other services or clients.
|
|
+CONFIG_UBUS=y
|
|
+
|
|
+# OpenWrt patch 380-disable-ctrl-iface-mib.patch
|
|
+# leads to the MIB only being compiled in if
|
|
+# CONFIG_CTRL_IFACE_MIB is enabled.
|
|
+#CONFIG_CTRL_IFACE_MIB=y
|
|
diff --git a/package/network/services/hostapd/files/wpa_supplicant-full.config b/package/network/services/hostapd/files/wpa_supplicant-full.config
|
|
new file mode 100644
|
|
index 0000000000..b39dabca06
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/wpa_supplicant-full.config
|
|
@@ -0,0 +1,625 @@
|
|
+# Example wpa_supplicant build time configuration
|
|
+#
|
|
+# This file lists the configuration options that are used when building the
|
|
+# wpa_supplicant binary. All lines starting with # are ignored. Configuration
|
|
+# option lines must be commented out complete, if they are not to be included,
|
|
+# i.e., just setting VARIABLE=n is not disabling that variable.
|
|
+#
|
|
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
|
|
+# be modified from here. In most cases, these lines should use += in order not
|
|
+# to override previous values of the variables.
|
|
+
|
|
+
|
|
+# Uncomment following two lines and fix the paths if you have installed OpenSSL
|
|
+# or GnuTLS in non-default location
|
|
+#CFLAGS += -I/usr/local/openssl/include
|
|
+#LIBS += -L/usr/local/openssl/lib
|
|
+
|
|
+# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
|
|
+# the kerberos files are not in the default include path. Following line can be
|
|
+# used to fix build issues on such systems (krb5.h not found).
|
|
+#CFLAGS += -I/usr/include/kerberos
|
|
+
|
|
+# Driver interface for generic Linux wireless extensions
|
|
+# Note: WEXT is deprecated in the current Linux kernel version and no new
|
|
+# functionality is added to it. nl80211-based interface is the new
|
|
+# replacement for WEXT and its use allows wpa_supplicant to properly control
|
|
+# the driver to improve existing functionality like roaming and to support new
|
|
+# functionality.
|
|
+#CONFIG_DRIVER_WEXT=y
|
|
+
|
|
+# Driver interface for Linux drivers using the nl80211 kernel interface
|
|
+CONFIG_DRIVER_NL80211=y
|
|
+
|
|
+# QCA vendor extensions to nl80211
|
|
+#CONFIG_DRIVER_NL80211_QCA=y
|
|
+
|
|
+# driver_nl80211.c requires libnl. If you are compiling it yourself
|
|
+# you may need to point hostapd to your version of libnl.
|
|
+#
|
|
+#CFLAGS += -I$<path to libnl include files>
|
|
+#LIBS += -L$<path to libnl library files>
|
|
+
|
|
+# Use libnl v2.0 (or 3.0) libraries.
|
|
+#CONFIG_LIBNL20=y
|
|
+
|
|
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
|
|
+#CONFIG_LIBNL32=y
|
|
+
|
|
+
|
|
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
|
+#CONFIG_DRIVER_BSD=y
|
|
+#CFLAGS += -I/usr/local/include
|
|
+#LIBS += -L/usr/local/lib
|
|
+#LIBS_p += -L/usr/local/lib
|
|
+#LIBS_c += -L/usr/local/lib
|
|
+
|
|
+# Driver interface for Windows NDIS
|
|
+#CONFIG_DRIVER_NDIS=y
|
|
+#CFLAGS += -I/usr/include/w32api/ddk
|
|
+#LIBS += -L/usr/local/lib
|
|
+# For native build using mingw
|
|
+#CONFIG_NATIVE_WINDOWS=y
|
|
+# Additional directories for cross-compilation on Linux host for mingw target
|
|
+#CFLAGS += -I/opt/mingw/mingw32/include/ddk
|
|
+#LIBS += -L/opt/mingw/mingw32/lib
|
|
+#CC=mingw32-gcc
|
|
+# By default, driver_ndis uses WinPcap for low-level operations. This can be
|
|
+# replaced with the following option which replaces WinPcap calls with NDISUIO.
|
|
+# However, this requires that WZC is disabled (net stop wzcsvc) before starting
|
|
+# wpa_supplicant.
|
|
+# CONFIG_USE_NDISUIO=y
|
|
+
|
|
+# Driver interface for wired Ethernet drivers
|
|
+CONFIG_DRIVER_WIRED=y
|
|
+
|
|
+# Driver interface for MACsec capable Qualcomm Atheros drivers
|
|
+#CONFIG_DRIVER_MACSEC_QCA=y
|
|
+
|
|
+# Driver interface for Linux MACsec drivers
|
|
+#CONFIG_DRIVER_MACSEC_LINUX=y
|
|
+
|
|
+# Driver interface for the Broadcom RoboSwitch family
|
|
+#CONFIG_DRIVER_ROBOSWITCH=y
|
|
+
|
|
+# Driver interface for no driver (e.g., WPS ER only)
|
|
+#CONFIG_DRIVER_NONE=y
|
|
+
|
|
+# Solaris libraries
|
|
+#LIBS += -lsocket -ldlpi -lnsl
|
|
+#LIBS_c += -lsocket
|
|
+
|
|
+# Enable IEEE 802.1X Supplicant (automatically included if any EAP method or
|
|
+# MACsec is included)
|
|
+CONFIG_IEEE8021X_EAPOL=y
|
|
+
|
|
+# EAP-MD5
|
|
+CONFIG_EAP_MD5=y
|
|
+
|
|
+# EAP-MSCHAPv2
|
|
+CONFIG_EAP_MSCHAPV2=y
|
|
+
|
|
+# EAP-TLS
|
|
+CONFIG_EAP_TLS=y
|
|
+
|
|
+# EAL-PEAP
|
|
+CONFIG_EAP_PEAP=y
|
|
+
|
|
+# EAP-TTLS
|
|
+CONFIG_EAP_TTLS=y
|
|
+
|
|
+# EAP-FAST
|
|
+CONFIG_EAP_FAST=y
|
|
+
|
|
+# EAP-TEAP
|
|
+# Note: The current EAP-TEAP implementation is experimental and should not be
|
|
+# enabled for production use. The IETF RFC 7170 that defines EAP-TEAP has number
|
|
+# of conflicting statements and missing details and the implementation has
|
|
+# vendor specific workarounds for those and as such, may not interoperate with
|
|
+# any other implementation. This should not be used for anything else than
|
|
+# experimentation and interoperability testing until those issues has been
|
|
+# resolved.
|
|
+#CONFIG_EAP_TEAP=y
|
|
+
|
|
+# EAP-GTC
|
|
+CONFIG_EAP_GTC=y
|
|
+
|
|
+# EAP-OTP
|
|
+CONFIG_EAP_OTP=y
|
|
+
|
|
+# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)
|
|
+#CONFIG_EAP_SIM=y
|
|
+
|
|
+# Enable SIM simulator (Milenage) for EAP-SIM
|
|
+#CONFIG_SIM_SIMULATOR=y
|
|
+
|
|
+# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
|
|
+#CONFIG_EAP_PSK=y
|
|
+
|
|
+# EAP-pwd (secure authentication using only a password)
|
|
+#CONFIG_EAP_PWD=y
|
|
+
|
|
+# EAP-PAX
|
|
+#CONFIG_EAP_PAX=y
|
|
+
|
|
+# LEAP
|
|
+CONFIG_EAP_LEAP=y
|
|
+
|
|
+# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
|
|
+#CONFIG_EAP_AKA=y
|
|
+
|
|
+# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
|
|
+# This requires CONFIG_EAP_AKA to be enabled, too.
|
|
+#CONFIG_EAP_AKA_PRIME=y
|
|
+
|
|
+# Enable USIM simulator (Milenage) for EAP-AKA
|
|
+#CONFIG_USIM_SIMULATOR=y
|
|
+
|
|
+# EAP-SAKE
|
|
+#CONFIG_EAP_SAKE=y
|
|
+
|
|
+# EAP-GPSK
|
|
+#CONFIG_EAP_GPSK=y
|
|
+# Include support for optional SHA256 cipher suite in EAP-GPSK
|
|
+#CONFIG_EAP_GPSK_SHA256=y
|
|
+
|
|
+# EAP-TNC and related Trusted Network Connect support (experimental)
|
|
+#CONFIG_EAP_TNC=y
|
|
+
|
|
+# Wi-Fi Protected Setup (WPS)
|
|
+CONFIG_WPS=y
|
|
+# Enable WPS external registrar functionality
|
|
+#CONFIG_WPS_ER=y
|
|
+# Disable credentials for an open network by default when acting as a WPS
|
|
+# registrar.
|
|
+#CONFIG_WPS_REG_DISABLE_OPEN=y
|
|
+# Enable WPS support with NFC config method
|
|
+#CONFIG_WPS_NFC=y
|
|
+
|
|
+# EAP-IKEv2
|
|
+#CONFIG_EAP_IKEV2=y
|
|
+
|
|
+# EAP-EKE
|
|
+#CONFIG_EAP_EKE=y
|
|
+
|
|
+# MACsec
|
|
+#CONFIG_MACSEC=y
|
|
+
|
|
+# PKCS#12 (PFX) support (used to read private key and certificate file from
|
|
+# a file that usually has extension .p12 or .pfx)
|
|
+CONFIG_PKCS12=y
|
|
+
|
|
+# Smartcard support (i.e., private key on a smartcard), e.g., with openssl
|
|
+# engine.
|
|
+CONFIG_SMARTCARD=y
|
|
+
|
|
+# PC/SC interface for smartcards (USIM, GSM SIM)
|
|
+# Enable this if EAP-SIM or EAP-AKA is included
|
|
+#CONFIG_PCSC=y
|
|
+
|
|
+# Support HT overrides (disable HT/HT40, mask MCS rates, etc.)
|
|
+CONFIG_HT_OVERRIDES=y
|
|
+
|
|
+# Support VHT overrides (disable VHT, mask MCS rates, etc.)
|
|
+CONFIG_VHT_OVERRIDES=y
|
|
+
|
|
+# Development testing
|
|
+#CONFIG_EAPOL_TEST=y
|
|
+
|
|
+# Select control interface backend for external programs, e.g, wpa_cli:
|
|
+# unix = UNIX domain sockets (default for Linux/*BSD)
|
|
+# udp = UDP sockets using localhost (127.0.0.1)
|
|
+# udp6 = UDP IPv6 sockets using localhost (::1)
|
|
+# named_pipe = Windows Named Pipe (default for Windows)
|
|
+# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
|
|
+# udp6-remote = UDP IPv6 sockets with remote access (only for tests purpose)
|
|
+# y = use default (backwards compatibility)
|
|
+# If this option is commented out, control interface is not included in the
|
|
+# build.
|
|
+CONFIG_CTRL_IFACE=y
|
|
+
|
|
+# Include support for GNU Readline and History Libraries in wpa_cli.
|
|
+# When building a wpa_cli binary for distribution, please note that these
|
|
+# libraries are licensed under GPL and as such, BSD license may not apply for
|
|
+# the resulting binary.
|
|
+#CONFIG_READLINE=y
|
|
+
|
|
+# Include internal line edit mode in wpa_cli. This can be used as a replacement
|
|
+# for GNU Readline to provide limited command line editing and history support.
|
|
+#CONFIG_WPA_CLI_EDIT=y
|
|
+
|
|
+# Remove debugging code that is printing out debug message to stdout.
|
|
+# This can be used to reduce the size of the wpa_supplicant considerably
|
|
+# if debugging code is not needed. The size reduction can be around 35%
|
|
+# (e.g., 90 kB).
|
|
+#CONFIG_NO_STDOUT_DEBUG=y
|
|
+
|
|
+# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save
|
|
+# 35-50 kB in code size.
|
|
+#CONFIG_NO_WPA=y
|
|
+
|
|
+# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
|
|
+# This option can be used to reduce code size by removing support for
|
|
+# converting ASCII passphrases into PSK. If this functionality is removed, the
|
|
+# PSK can only be configured as the 64-octet hexstring (e.g., from
|
|
+# wpa_passphrase). This saves about 0.5 kB in code size.
|
|
+#CONFIG_NO_WPA_PASSPHRASE=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.
|
|
+# This can be used if ap_scan=1 mode is never enabled.
|
|
+#CONFIG_NO_SCAN_PROCESSING=y
|
|
+
|
|
+# Select configuration backend:
|
|
+# file = text file (e.g., wpa_supplicant.conf; note: the configuration file
|
|
+# path is given on command line, not here; this option is just used to
|
|
+# select the backend that allows configuration files to be used)
|
|
+# winreg = Windows registry (see win_example.reg for an example)
|
|
+CONFIG_BACKEND=file
|
|
+
|
|
+# Remove configuration write functionality (i.e., to allow the configuration
|
|
+# file to be updated based on runtime configuration changes). The runtime
|
|
+# configuration can still be changed, the changes are just not going to be
|
|
+# persistent over restarts. This option can be used to reduce code size by
|
|
+# about 3.5 kB.
|
|
+#CONFIG_NO_CONFIG_WRITE=y
|
|
+
|
|
+# Remove support for configuration blobs to reduce code size by about 1.5 kB.
|
|
+#CONFIG_NO_CONFIG_BLOBS=y
|
|
+
|
|
+# Select program entry point implementation:
|
|
+# main = UNIX/POSIX like main() function (default)
|
|
+# main_winsvc = Windows service (read parameters from registry)
|
|
+# main_none = Very basic example (development use only)
|
|
+#CONFIG_MAIN=main
|
|
+
|
|
+# Select wrapper for operating system and C library specific functions
|
|
+# unix = UNIX/POSIX like systems (default)
|
|
+# win32 = Windows systems
|
|
+# none = Empty template
|
|
+#CONFIG_OS=unix
|
|
+
|
|
+# Select event loop implementation
|
|
+# eloop = select() loop (default)
|
|
+# eloop_win = Windows events and WaitForMultipleObject() loop
|
|
+#CONFIG_ELOOP=eloop
|
|
+
|
|
+# Should we use poll instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_POLL=y
|
|
+
|
|
+# Should we use epoll instead of select? Select is used by default.
|
|
+CONFIG_ELOOP_EPOLL=y
|
|
+
|
|
+# Should we use kqueue instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_KQUEUE=y
|
|
+
|
|
+# Select layer 2 packet implementation
|
|
+# linux = Linux packet socket (default)
|
|
+# pcap = libpcap/libdnet/WinPcap
|
|
+# freebsd = FreeBSD libpcap
|
|
+# winpcap = WinPcap with receive thread
|
|
+# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)
|
|
+# none = Empty template
|
|
+#CONFIG_L2_PACKET=linux
|
|
+
|
|
+# Disable Linux packet socket workaround applicable for station interface
|
|
+# in a bridge for EAPOL frames. This should be uncommented only if the kernel
|
|
+# is known to not have the regression issue in packet socket behavior with
|
|
+# bridge interfaces (commit 'bridge: respect RFC2863 operational state')').
|
|
+CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
|
|
+
|
|
+# IEEE 802.11w (management frame protection), also known as PMF
|
|
+# Driver support is also needed for IEEE 802.11w.
|
|
+#CONFIG_IEEE80211W=y
|
|
+
|
|
+# Support Operating Channel Validation
|
|
+CONFIG_OCV=y
|
|
+
|
|
+# Select TLS implementation
|
|
+# openssl = OpenSSL (default)
|
|
+# gnutls = GnuTLS
|
|
+# internal = Internal TLSv1 implementation (experimental)
|
|
+# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
|
|
+# none = Empty template
|
|
+CONFIG_TLS=internal
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
|
+# can be enabled to get a stronger construction of messages when block ciphers
|
|
+# are used. It should be noted that some existing TLS v1.0 -based
|
|
+# implementation may not be compatible with TLS v1.1 message (ClientHello is
|
|
+# sent prior to negotiating which version will be used)
|
|
+#CONFIG_TLSV11=y
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
|
|
+# can be enabled to enable use of stronger crypto algorithms. It should be
|
|
+# noted that some existing TLS v1.0 -based implementation may not be compatible
|
|
+# with TLS v1.2 message (ClientHello is sent prior to negotiating which version
|
|
+# will be used)
|
|
+#CONFIG_TLSV12=y
|
|
+
|
|
+# Select which ciphers to use by default with OpenSSL if the user does not
|
|
+# specify them.
|
|
+#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
|
|
+
|
|
+# If CONFIG_TLS=internal is used, additional library and include paths are
|
|
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
|
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
|
+# and drawbacks of this option.
|
|
+CONFIG_INTERNAL_LIBTOMMATH=y
|
|
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
|
|
+#LTM_PATH=/usr/src/libtommath-0.39
|
|
+#CFLAGS += -I$(LTM_PATH)
|
|
+#LIBS += -L$(LTM_PATH)
|
|
+#LIBS_p += -L$(LTM_PATH)
|
|
+#endif
|
|
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
|
|
+# can be configured to include faster routines for exptmod, sqr, and div to
|
|
+# speed up DH and RSA calculation considerably
|
|
+CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
|
+
|
|
+# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
|
|
+# This is only for Windows builds and requires WMI-related header files and
|
|
+# WbemUuid.Lib from Platform SDK even when building with MinGW.
|
|
+#CONFIG_NDIS_EVENTS_INTEGRATED=y
|
|
+#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
|
|
+
|
|
+# Add support for new DBus control interface
|
|
+# (fi.w1.hostap.wpa_supplicant1)
|
|
+#CONFIG_CTRL_IFACE_DBUS_NEW=y
|
|
+
|
|
+# Add introspection support for new DBus control interface
|
|
+#CONFIG_CTRL_IFACE_DBUS_INTRO=y
|
|
+
|
|
+# Add support for loading EAP methods dynamically as shared libraries.
|
|
+# When this option is enabled, each EAP method can be either included
|
|
+# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
|
|
+# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to
|
|
+# be loaded in the beginning of the wpa_supplicant configuration file
|
|
+# (see load_dynamic_eap parameter in the example file) before being used in
|
|
+# the network blocks.
|
|
+#
|
|
+# Note that some shared parts of EAP methods are included in the main program
|
|
+# and in order to be able to use dynamic EAP methods using these parts, the
|
|
+# main program must have been build with the EAP method enabled (=y or =dyn).
|
|
+# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries
|
|
+# unless at least one of them was included in the main build to force inclusion
|
|
+# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included
|
|
+# in the main build to be able to load these methods dynamically.
|
|
+#
|
|
+# Please also note that using dynamic libraries will increase the total binary
|
|
+# size. Thus, it may not be the best option for targets that have limited
|
|
+# amount of memory/flash.
|
|
+#CONFIG_DYNAMIC_EAP_METHODS=y
|
|
+
|
|
+# IEEE Std 802.11r-2008 (Fast BSS Transition) for station mode
|
|
+CONFIG_IEEE80211R=y
|
|
+
|
|
+# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
|
|
+#CONFIG_DEBUG_FILE=y
|
|
+
|
|
+# Send debug messages to syslog instead of stdout
|
|
+CONFIG_DEBUG_SYSLOG=y
|
|
+# Set syslog facility for debug messages
|
|
+CONFIG_DEBUG_SYSLOG_FACILITY=LOG_DAEMON
|
|
+
|
|
+# Add support for sending all debug messages (regardless of debug verbosity)
|
|
+# to the Linux kernel tracing facility. This helps debug the entire stack by
|
|
+# making it easy to record everything happening from the driver up into the
|
|
+# same file, e.g., using trace-cmd.
|
|
+#CONFIG_DEBUG_LINUX_TRACING=y
|
|
+
|
|
+# Add support for writing debug log to Android logcat instead of standard
|
|
+# output
|
|
+#CONFIG_ANDROID_LOG=y
|
|
+
|
|
+# Enable privilege separation (see README 'Privilege separation' for details)
|
|
+#CONFIG_PRIVSEP=y
|
|
+
|
|
+# Enable mitigation against certain attacks against TKIP by delaying Michael
|
|
+# MIC error reports by a random amount of time between 0 and 60 seconds
|
|
+#CONFIG_DELAYED_MIC_ERROR_REPORT=y
|
|
+
|
|
+# Enable tracing code for developer debugging
|
|
+# This tracks use of memory allocations and other registrations and reports
|
|
+# incorrect use with a backtrace of call (or allocation) location.
|
|
+#CONFIG_WPA_TRACE=y
|
|
+# For BSD, uncomment these.
|
|
+#LIBS += -lexecinfo
|
|
+#LIBS_p += -lexecinfo
|
|
+#LIBS_c += -lexecinfo
|
|
+
|
|
+# Use libbfd to get more details for developer debugging
|
|
+# This enables use of libbfd to get more detailed symbols for the backtraces
|
|
+# generated by CONFIG_WPA_TRACE=y.
|
|
+#CONFIG_WPA_TRACE_BFD=y
|
|
+# For BSD, uncomment these.
|
|
+#LIBS += -lbfd -liberty -lz
|
|
+#LIBS_p += -lbfd -liberty -lz
|
|
+#LIBS_c += -lbfd -liberty -lz
|
|
+
|
|
+# wpa_supplicant depends on strong random number generation being available
|
|
+# from the operating system. os_get_random() function is used to fetch random
|
|
+# data when needed, e.g., for key generation. On Linux and BSD systems, this
|
|
+# works by reading /dev/urandom. It should be noted that the OS entropy pool
|
|
+# needs to be properly initialized before wpa_supplicant is started. This is
|
|
+# important especially on embedded devices that do not have a hardware random
|
|
+# number generator and may by default start up with minimal entropy available
|
|
+# for random number generation.
|
|
+#
|
|
+# As a safety net, wpa_supplicant is by default trying to internally collect
|
|
+# additional entropy for generating random data to mix in with the data fetched
|
|
+# from the OS. This by itself is not considered to be very strong, but it may
|
|
+# help in cases where the system pool is not initialized properly. However, it
|
|
+# is very strongly recommended that the system pool is initialized with enough
|
|
+# entropy either by using hardware assisted random number generator or by
|
|
+# storing state over device reboots.
|
|
+#
|
|
+# wpa_supplicant can be configured to maintain its own entropy store over
|
|
+# restarts to enhance random number generation. This is not perfect, but it is
|
|
+# much more secure than using the same sequence of random numbers after every
|
|
+# reboot. This can be enabled with -e<entropy file> command line option. The
|
|
+# specified file needs to be readable and writable by wpa_supplicant.
|
|
+#
|
|
+# If the os_get_random() is known to provide strong random data (e.g., on
|
|
+# Linux/BSD, the board in question is known to have reliable source of random
|
|
+# data from /dev/urandom), the internal wpa_supplicant random pool can be
|
|
+# disabled. This will save some in binary size and CPU use. However, this
|
|
+# should only be considered for builds that are known to be used on devices
|
|
+# that meet the requirements described above.
|
|
+CONFIG_NO_RANDOM_POOL=y
|
|
+
|
|
+# Should we attempt to use the getrandom(2) call that provides more reliable
|
|
+# yet secure randomness source than /dev/random on Linux 3.17 and newer.
|
|
+# 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)
|
|
+# Note: This is experimental and not complete implementation.
|
|
+CONFIG_WNM=y
|
|
+
|
|
+# Interworking (IEEE 802.11u)
|
|
+# This can be used to enable functionality to improve interworking with
|
|
+# external networks (GAS/ANQP to learn more about the networks and network
|
|
+# selection based on available credentials).
|
|
+CONFIG_INTERWORKING=y
|
|
+
|
|
+# Hotspot 2.0
|
|
+CONFIG_HS20=y
|
|
+
|
|
+# Enable interface matching in wpa_supplicant
|
|
+#CONFIG_MATCH_IFACE=y
|
|
+
|
|
+# Disable roaming in wpa_supplicant
|
|
+#CONFIG_NO_ROAMING=y
|
|
+
|
|
+# AP mode operations with wpa_supplicant
|
|
+# This can be used for controlling AP mode operations with wpa_supplicant. It
|
|
+# should be noted that this is mainly aimed at simple cases like
|
|
+# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
|
|
+# external RADIUS server can be supported with hostapd.
|
|
+#CONFIG_AP=y
|
|
+
|
|
+# P2P (Wi-Fi Direct)
|
|
+# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
|
|
+# more information on P2P operations.
|
|
+#CONFIG_P2P=y
|
|
+
|
|
+# Enable TDLS support
|
|
+#CONFIG_TDLS=y
|
|
+
|
|
+# Wi-Fi Display
|
|
+# This can be used to enable Wi-Fi Display extensions for P2P using an external
|
|
+# program to control the additional information exchanges in the messages.
|
|
+#CONFIG_WIFI_DISPLAY=y
|
|
+
|
|
+# Autoscan
|
|
+# This can be used to enable automatic scan support in wpa_supplicant.
|
|
+# See wpa_supplicant.conf for more information on autoscan usage.
|
|
+#
|
|
+# Enabling directly a module will enable autoscan support.
|
|
+# For exponential module:
|
|
+#CONFIG_AUTOSCAN_EXPONENTIAL=y
|
|
+# For periodic module:
|
|
+#CONFIG_AUTOSCAN_PERIODIC=y
|
|
+
|
|
+# Password (and passphrase, etc.) backend for external storage
|
|
+# These optional mechanisms can be used to add support for storing passwords
|
|
+# and other secrets in external (to wpa_supplicant) location. This allows, for
|
|
+# example, operating system specific key storage to be used
|
|
+#
|
|
+# External password backend for testing purposes (developer use)
|
|
+#CONFIG_EXT_PASSWORD_TEST=y
|
|
+
|
|
+# Enable Fast Session Transfer (FST)
|
|
+#CONFIG_FST=y
|
|
+
|
|
+# Enable CLI commands for FST testing
|
|
+#CONFIG_FST_TEST=y
|
|
+
|
|
+# OS X builds. This is only for building eapol_test.
|
|
+#CONFIG_OSX=y
|
|
+
|
|
+# Automatic Channel Selection
|
|
+# This will allow wpa_supplicant to pick the channel automatically when channel
|
|
+# is set to "0".
|
|
+#
|
|
+# TODO: Extend parser to be able to parse "channel=acs_survey" as an alternative
|
|
+# to "channel=0". This would enable us to eventually add other ACS algorithms in
|
|
+# similar way.
|
|
+#
|
|
+# Automatic selection is currently only done through initialization, later on
|
|
+# we hope to do background checks to keep us moving to more ideal channels as
|
|
+# time goes by. ACS is currently only supported through the nl80211 driver and
|
|
+# your driver must have survey dump capability that is filled by the driver
|
|
+# during scanning.
|
|
+#
|
|
+# TODO: In analogy to hostapd be able to customize the ACS survey algorithm with
|
|
+# a newly to create wpa_supplicant.conf variable acs_num_scans.
|
|
+#
|
|
+# Supported ACS drivers:
|
|
+# * ath9k
|
|
+# * ath5k
|
|
+# * ath10k
|
|
+#
|
|
+# For more details refer to:
|
|
+# http://wireless.kernel.org/en/users/Documentation/acs
|
|
+#CONFIG_ACS=y
|
|
+
|
|
+# Support Multi Band Operation
|
|
+#CONFIG_MBO=y
|
|
+
|
|
+# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
|
|
+CONFIG_FILS=y
|
|
+# FILS shared key authentication with PFS
|
|
+#CONFIG_FILS_SK_PFS=y
|
|
+
|
|
+# Support RSN on IBSS networks
|
|
+# This is needed to be able to use mode=1 network profile with proto=RSN and
|
|
+# key_mgmt=WPA-PSK (i.e., full key management instead of WPA-None).
|
|
+CONFIG_IBSS_RSN=y
|
|
+
|
|
+# External PMKSA cache control
|
|
+# This can be used to enable control interface commands that allow the current
|
|
+# PMKSA cache entries to be fetched and new entries to be added.
|
|
+#CONFIG_PMKSA_CACHE_EXTERNAL=y
|
|
+
|
|
+# Mesh Networking (IEEE 802.11s)
|
|
+#CONFIG_MESH=y
|
|
+
|
|
+# Background scanning modules
|
|
+# These can be used to request wpa_supplicant to perform background scanning
|
|
+# operations for roaming within an ESS (same SSID). See the bgscan parameter in
|
|
+# the wpa_supplicant.conf file for more details.
|
|
+# Periodic background scans based on signal strength
|
|
+#CONFIG_BGSCAN_SIMPLE=y
|
|
+# Learn channels used by the network and try to avoid bgscans on other
|
|
+# channels (experimental)
|
|
+#CONFIG_BGSCAN_LEARN=y
|
|
+
|
|
+# Opportunistic Wireless Encryption (OWE)
|
|
+# Experimental implementation of draft-harkins-owe-07.txt
|
|
+#CONFIG_OWE=y
|
|
+
|
|
+# Device Provisioning Protocol (DPP)
|
|
+# This requires CONFIG_IEEE80211W=y to be enabled, too. (see
|
|
+# wpa_supplicant/README-DPP for details)
|
|
+#CONFIG_DPP=y
|
|
+
|
|
+# uBus IPC/RPC System
|
|
+# Services can connect to the bus and provide methods
|
|
+# that can be called by other services or clients.
|
|
+CONFIG_UBUS=y
|
|
+
|
|
+# OpenWrt patch 380-disable-ctrl-iface-mib.patch
|
|
+# leads to the MIB only being compiled in if
|
|
+# CONFIG_CTRL_IFACE_MIB is enabled.
|
|
+CONFIG_CTRL_IFACE_MIB=y
|
|
diff --git a/package/network/services/hostapd/files/wpa_supplicant-mini.config b/package/network/services/hostapd/files/wpa_supplicant-mini.config
|
|
new file mode 100644
|
|
index 0000000000..2a3f8fb69d
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/wpa_supplicant-mini.config
|
|
@@ -0,0 +1,625 @@
|
|
+# Example wpa_supplicant build time configuration
|
|
+#
|
|
+# This file lists the configuration options that are used when building the
|
|
+# wpa_supplicant binary. All lines starting with # are ignored. Configuration
|
|
+# option lines must be commented out complete, if they are not to be included,
|
|
+# i.e., just setting VARIABLE=n is not disabling that variable.
|
|
+#
|
|
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
|
|
+# be modified from here. In most cases, these lines should use += in order not
|
|
+# to override previous values of the variables.
|
|
+
|
|
+
|
|
+# Uncomment following two lines and fix the paths if you have installed OpenSSL
|
|
+# or GnuTLS in non-default location
|
|
+#CFLAGS += -I/usr/local/openssl/include
|
|
+#LIBS += -L/usr/local/openssl/lib
|
|
+
|
|
+# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
|
|
+# the kerberos files are not in the default include path. Following line can be
|
|
+# used to fix build issues on such systems (krb5.h not found).
|
|
+#CFLAGS += -I/usr/include/kerberos
|
|
+
|
|
+# Driver interface for generic Linux wireless extensions
|
|
+# Note: WEXT is deprecated in the current Linux kernel version and no new
|
|
+# functionality is added to it. nl80211-based interface is the new
|
|
+# replacement for WEXT and its use allows wpa_supplicant to properly control
|
|
+# the driver to improve existing functionality like roaming and to support new
|
|
+# functionality.
|
|
+#CONFIG_DRIVER_WEXT=y
|
|
+
|
|
+# Driver interface for Linux drivers using the nl80211 kernel interface
|
|
+CONFIG_DRIVER_NL80211=y
|
|
+
|
|
+# QCA vendor extensions to nl80211
|
|
+#CONFIG_DRIVER_NL80211_QCA=y
|
|
+
|
|
+# driver_nl80211.c requires libnl. If you are compiling it yourself
|
|
+# you may need to point hostapd to your version of libnl.
|
|
+#
|
|
+#CFLAGS += -I$<path to libnl include files>
|
|
+#LIBS += -L$<path to libnl library files>
|
|
+
|
|
+# Use libnl v2.0 (or 3.0) libraries.
|
|
+#CONFIG_LIBNL20=y
|
|
+
|
|
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
|
|
+#CONFIG_LIBNL32=y
|
|
+
|
|
+
|
|
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
|
+#CONFIG_DRIVER_BSD=y
|
|
+#CFLAGS += -I/usr/local/include
|
|
+#LIBS += -L/usr/local/lib
|
|
+#LIBS_p += -L/usr/local/lib
|
|
+#LIBS_c += -L/usr/local/lib
|
|
+
|
|
+# Driver interface for Windows NDIS
|
|
+#CONFIG_DRIVER_NDIS=y
|
|
+#CFLAGS += -I/usr/include/w32api/ddk
|
|
+#LIBS += -L/usr/local/lib
|
|
+# For native build using mingw
|
|
+#CONFIG_NATIVE_WINDOWS=y
|
|
+# Additional directories for cross-compilation on Linux host for mingw target
|
|
+#CFLAGS += -I/opt/mingw/mingw32/include/ddk
|
|
+#LIBS += -L/opt/mingw/mingw32/lib
|
|
+#CC=mingw32-gcc
|
|
+# By default, driver_ndis uses WinPcap for low-level operations. This can be
|
|
+# replaced with the following option which replaces WinPcap calls with NDISUIO.
|
|
+# However, this requires that WZC is disabled (net stop wzcsvc) before starting
|
|
+# wpa_supplicant.
|
|
+# CONFIG_USE_NDISUIO=y
|
|
+
|
|
+# Driver interface for wired Ethernet drivers
|
|
+CONFIG_DRIVER_WIRED=y
|
|
+
|
|
+# Driver interface for MACsec capable Qualcomm Atheros drivers
|
|
+#CONFIG_DRIVER_MACSEC_QCA=y
|
|
+
|
|
+# Driver interface for Linux MACsec drivers
|
|
+#CONFIG_DRIVER_MACSEC_LINUX=y
|
|
+
|
|
+# Driver interface for the Broadcom RoboSwitch family
|
|
+#CONFIG_DRIVER_ROBOSWITCH=y
|
|
+
|
|
+# Driver interface for no driver (e.g., WPS ER only)
|
|
+#CONFIG_DRIVER_NONE=y
|
|
+
|
|
+# Solaris libraries
|
|
+#LIBS += -lsocket -ldlpi -lnsl
|
|
+#LIBS_c += -lsocket
|
|
+
|
|
+# Enable IEEE 802.1X Supplicant (automatically included if any EAP method or
|
|
+# MACsec is included)
|
|
+#CONFIG_IEEE8021X_EAPOL=y
|
|
+
|
|
+# EAP-MD5
|
|
+#CONFIG_EAP_MD5=y
|
|
+
|
|
+# EAP-MSCHAPv2
|
|
+#CONFIG_EAP_MSCHAPV2=y
|
|
+
|
|
+# EAP-TLS
|
|
+#CONFIG_EAP_TLS=y
|
|
+
|
|
+# EAL-PEAP
|
|
+#CONFIG_EAP_PEAP=y
|
|
+
|
|
+# EAP-TTLS
|
|
+#CONFIG_EAP_TTLS=y
|
|
+
|
|
+# EAP-FAST
|
|
+#CONFIG_EAP_FAST=y
|
|
+
|
|
+# EAP-TEAP
|
|
+# Note: The current EAP-TEAP implementation is experimental and should not be
|
|
+# enabled for production use. The IETF RFC 7170 that defines EAP-TEAP has number
|
|
+# of conflicting statements and missing details and the implementation has
|
|
+# vendor specific workarounds for those and as such, may not interoperate with
|
|
+# any other implementation. This should not be used for anything else than
|
|
+# experimentation and interoperability testing until those issues has been
|
|
+# resolved.
|
|
+#CONFIG_EAP_TEAP=y
|
|
+
|
|
+# EAP-GTC
|
|
+#CONFIG_EAP_GTC=y
|
|
+
|
|
+# EAP-OTP
|
|
+#CONFIG_EAP_OTP=y
|
|
+
|
|
+# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)
|
|
+#CONFIG_EAP_SIM=y
|
|
+
|
|
+# Enable SIM simulator (Milenage) for EAP-SIM
|
|
+#CONFIG_SIM_SIMULATOR=y
|
|
+
|
|
+# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
|
|
+#CONFIG_EAP_PSK=y
|
|
+
|
|
+# EAP-pwd (secure authentication using only a password)
|
|
+#CONFIG_EAP_PWD=y
|
|
+
|
|
+# EAP-PAX
|
|
+#CONFIG_EAP_PAX=y
|
|
+
|
|
+# LEAP
|
|
+#CONFIG_EAP_LEAP=y
|
|
+
|
|
+# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
|
|
+#CONFIG_EAP_AKA=y
|
|
+
|
|
+# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
|
|
+# This requires CONFIG_EAP_AKA to be enabled, too.
|
|
+#CONFIG_EAP_AKA_PRIME=y
|
|
+
|
|
+# Enable USIM simulator (Milenage) for EAP-AKA
|
|
+#CONFIG_USIM_SIMULATOR=y
|
|
+
|
|
+# EAP-SAKE
|
|
+#CONFIG_EAP_SAKE=y
|
|
+
|
|
+# EAP-GPSK
|
|
+#CONFIG_EAP_GPSK=y
|
|
+# Include support for optional SHA256 cipher suite in EAP-GPSK
|
|
+#CONFIG_EAP_GPSK_SHA256=y
|
|
+
|
|
+# EAP-TNC and related Trusted Network Connect support (experimental)
|
|
+#CONFIG_EAP_TNC=y
|
|
+
|
|
+# Wi-Fi Protected Setup (WPS)
|
|
+#CONFIG_WPS=y
|
|
+# Enable WPS external registrar functionality
|
|
+#CONFIG_WPS_ER=y
|
|
+# Disable credentials for an open network by default when acting as a WPS
|
|
+# registrar.
|
|
+#CONFIG_WPS_REG_DISABLE_OPEN=y
|
|
+# Enable WPS support with NFC config method
|
|
+#CONFIG_WPS_NFC=y
|
|
+
|
|
+# EAP-IKEv2
|
|
+#CONFIG_EAP_IKEV2=y
|
|
+
|
|
+# EAP-EKE
|
|
+#CONFIG_EAP_EKE=y
|
|
+
|
|
+# MACsec
|
|
+#CONFIG_MACSEC=y
|
|
+
|
|
+# PKCS#12 (PFX) support (used to read private key and certificate file from
|
|
+# a file that usually has extension .p12 or .pfx)
|
|
+#CONFIG_PKCS12=y
|
|
+
|
|
+# Smartcard support (i.e., private key on a smartcard), e.g., with openssl
|
|
+# engine.
|
|
+#CONFIG_SMARTCARD=y
|
|
+
|
|
+# PC/SC interface for smartcards (USIM, GSM SIM)
|
|
+# Enable this if EAP-SIM or EAP-AKA is included
|
|
+#CONFIG_PCSC=y
|
|
+
|
|
+# Support HT overrides (disable HT/HT40, mask MCS rates, etc.)
|
|
+CONFIG_HT_OVERRIDES=y
|
|
+
|
|
+# Support VHT overrides (disable VHT, mask MCS rates, etc.)
|
|
+CONFIG_VHT_OVERRIDES=y
|
|
+
|
|
+# Development testing
|
|
+#CONFIG_EAPOL_TEST=y
|
|
+
|
|
+# Select control interface backend for external programs, e.g, wpa_cli:
|
|
+# unix = UNIX domain sockets (default for Linux/*BSD)
|
|
+# udp = UDP sockets using localhost (127.0.0.1)
|
|
+# udp6 = UDP IPv6 sockets using localhost (::1)
|
|
+# named_pipe = Windows Named Pipe (default for Windows)
|
|
+# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
|
|
+# udp6-remote = UDP IPv6 sockets with remote access (only for tests purpose)
|
|
+# y = use default (backwards compatibility)
|
|
+# If this option is commented out, control interface is not included in the
|
|
+# build.
|
|
+CONFIG_CTRL_IFACE=y
|
|
+
|
|
+# Include support for GNU Readline and History Libraries in wpa_cli.
|
|
+# When building a wpa_cli binary for distribution, please note that these
|
|
+# libraries are licensed under GPL and as such, BSD license may not apply for
|
|
+# the resulting binary.
|
|
+#CONFIG_READLINE=y
|
|
+
|
|
+# Include internal line edit mode in wpa_cli. This can be used as a replacement
|
|
+# for GNU Readline to provide limited command line editing and history support.
|
|
+#CONFIG_WPA_CLI_EDIT=y
|
|
+
|
|
+# Remove debugging code that is printing out debug message to stdout.
|
|
+# This can be used to reduce the size of the wpa_supplicant considerably
|
|
+# if debugging code is not needed. The size reduction can be around 35%
|
|
+# (e.g., 90 kB).
|
|
+#CONFIG_NO_STDOUT_DEBUG=y
|
|
+
|
|
+# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save
|
|
+# 35-50 kB in code size.
|
|
+#CONFIG_NO_WPA=y
|
|
+
|
|
+# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
|
|
+# This option can be used to reduce code size by removing support for
|
|
+# converting ASCII passphrases into PSK. If this functionality is removed, the
|
|
+# PSK can only be configured as the 64-octet hexstring (e.g., from
|
|
+# wpa_passphrase). This saves about 0.5 kB in code size.
|
|
+#CONFIG_NO_WPA_PASSPHRASE=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.
|
|
+# This can be used if ap_scan=1 mode is never enabled.
|
|
+#CONFIG_NO_SCAN_PROCESSING=y
|
|
+
|
|
+# Select configuration backend:
|
|
+# file = text file (e.g., wpa_supplicant.conf; note: the configuration file
|
|
+# path is given on command line, not here; this option is just used to
|
|
+# select the backend that allows configuration files to be used)
|
|
+# winreg = Windows registry (see win_example.reg for an example)
|
|
+CONFIG_BACKEND=file
|
|
+
|
|
+# Remove configuration write functionality (i.e., to allow the configuration
|
|
+# file to be updated based on runtime configuration changes). The runtime
|
|
+# configuration can still be changed, the changes are just not going to be
|
|
+# persistent over restarts. This option can be used to reduce code size by
|
|
+# about 3.5 kB.
|
|
+CONFIG_NO_CONFIG_WRITE=y
|
|
+
|
|
+# Remove support for configuration blobs to reduce code size by about 1.5 kB.
|
|
+#CONFIG_NO_CONFIG_BLOBS=y
|
|
+
|
|
+# Select program entry point implementation:
|
|
+# main = UNIX/POSIX like main() function (default)
|
|
+# main_winsvc = Windows service (read parameters from registry)
|
|
+# main_none = Very basic example (development use only)
|
|
+#CONFIG_MAIN=main
|
|
+
|
|
+# Select wrapper for operating system and C library specific functions
|
|
+# unix = UNIX/POSIX like systems (default)
|
|
+# win32 = Windows systems
|
|
+# none = Empty template
|
|
+#CONFIG_OS=unix
|
|
+
|
|
+# Select event loop implementation
|
|
+# eloop = select() loop (default)
|
|
+# eloop_win = Windows events and WaitForMultipleObject() loop
|
|
+#CONFIG_ELOOP=eloop
|
|
+
|
|
+# Should we use poll instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_POLL=y
|
|
+
|
|
+# Should we use epoll instead of select? Select is used by default.
|
|
+CONFIG_ELOOP_EPOLL=y
|
|
+
|
|
+# Should we use kqueue instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_KQUEUE=y
|
|
+
|
|
+# Select layer 2 packet implementation
|
|
+# linux = Linux packet socket (default)
|
|
+# pcap = libpcap/libdnet/WinPcap
|
|
+# freebsd = FreeBSD libpcap
|
|
+# winpcap = WinPcap with receive thread
|
|
+# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)
|
|
+# none = Empty template
|
|
+#CONFIG_L2_PACKET=linux
|
|
+
|
|
+# Disable Linux packet socket workaround applicable for station interface
|
|
+# in a bridge for EAPOL frames. This should be uncommented only if the kernel
|
|
+# is known to not have the regression issue in packet socket behavior with
|
|
+# bridge interfaces (commit 'bridge: respect RFC2863 operational state')').
|
|
+CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
|
|
+
|
|
+# IEEE 802.11w (management frame protection), also known as PMF
|
|
+# Driver support is also needed for IEEE 802.11w.
|
|
+#CONFIG_IEEE80211W=y
|
|
+
|
|
+# Support Operating Channel Validation
|
|
+#CONFIG_OCV=y
|
|
+
|
|
+# Select TLS implementation
|
|
+# openssl = OpenSSL (default)
|
|
+# gnutls = GnuTLS
|
|
+# internal = Internal TLSv1 implementation (experimental)
|
|
+# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
|
|
+# none = Empty template
|
|
+CONFIG_TLS=internal
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
|
+# can be enabled to get a stronger construction of messages when block ciphers
|
|
+# are used. It should be noted that some existing TLS v1.0 -based
|
|
+# implementation may not be compatible with TLS v1.1 message (ClientHello is
|
|
+# sent prior to negotiating which version will be used)
|
|
+#CONFIG_TLSV11=y
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
|
|
+# can be enabled to enable use of stronger crypto algorithms. It should be
|
|
+# noted that some existing TLS v1.0 -based implementation may not be compatible
|
|
+# with TLS v1.2 message (ClientHello is sent prior to negotiating which version
|
|
+# will be used)
|
|
+#CONFIG_TLSV12=y
|
|
+
|
|
+# Select which ciphers to use by default with OpenSSL if the user does not
|
|
+# specify them.
|
|
+#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
|
|
+
|
|
+# If CONFIG_TLS=internal is used, additional library and include paths are
|
|
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
|
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
|
+# and drawbacks of this option.
|
|
+#CONFIG_INTERNAL_LIBTOMMATH=y
|
|
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
|
|
+#LTM_PATH=/usr/src/libtommath-0.39
|
|
+#CFLAGS += -I$(LTM_PATH)
|
|
+#LIBS += -L$(LTM_PATH)
|
|
+#LIBS_p += -L$(LTM_PATH)
|
|
+#endif
|
|
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
|
|
+# can be configured to include faster routines for exptmod, sqr, and div to
|
|
+# speed up DH and RSA calculation considerably
|
|
+#CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
|
+
|
|
+# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
|
|
+# This is only for Windows builds and requires WMI-related header files and
|
|
+# WbemUuid.Lib from Platform SDK even when building with MinGW.
|
|
+#CONFIG_NDIS_EVENTS_INTEGRATED=y
|
|
+#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
|
|
+
|
|
+# Add support for new DBus control interface
|
|
+# (fi.w1.hostap.wpa_supplicant1)
|
|
+#CONFIG_CTRL_IFACE_DBUS_NEW=y
|
|
+
|
|
+# Add introspection support for new DBus control interface
|
|
+#CONFIG_CTRL_IFACE_DBUS_INTRO=y
|
|
+
|
|
+# Add support for loading EAP methods dynamically as shared libraries.
|
|
+# When this option is enabled, each EAP method can be either included
|
|
+# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
|
|
+# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to
|
|
+# be loaded in the beginning of the wpa_supplicant configuration file
|
|
+# (see load_dynamic_eap parameter in the example file) before being used in
|
|
+# the network blocks.
|
|
+#
|
|
+# Note that some shared parts of EAP methods are included in the main program
|
|
+# and in order to be able to use dynamic EAP methods using these parts, the
|
|
+# main program must have been build with the EAP method enabled (=y or =dyn).
|
|
+# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries
|
|
+# unless at least one of them was included in the main build to force inclusion
|
|
+# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included
|
|
+# in the main build to be able to load these methods dynamically.
|
|
+#
|
|
+# Please also note that using dynamic libraries will increase the total binary
|
|
+# size. Thus, it may not be the best option for targets that have limited
|
|
+# amount of memory/flash.
|
|
+#CONFIG_DYNAMIC_EAP_METHODS=y
|
|
+
|
|
+# IEEE Std 802.11r-2008 (Fast BSS Transition) for station mode
|
|
+#CONFIG_IEEE80211R=y
|
|
+
|
|
+# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
|
|
+#CONFIG_DEBUG_FILE=y
|
|
+
|
|
+# Send debug messages to syslog instead of stdout
|
|
+CONFIG_DEBUG_SYSLOG=y
|
|
+# Set syslog facility for debug messages
|
|
+CONFIG_DEBUG_SYSLOG_FACILITY=LOG_DAEMON
|
|
+
|
|
+# Add support for sending all debug messages (regardless of debug verbosity)
|
|
+# to the Linux kernel tracing facility. This helps debug the entire stack by
|
|
+# making it easy to record everything happening from the driver up into the
|
|
+# same file, e.g., using trace-cmd.
|
|
+#CONFIG_DEBUG_LINUX_TRACING=y
|
|
+
|
|
+# Add support for writing debug log to Android logcat instead of standard
|
|
+# output
|
|
+#CONFIG_ANDROID_LOG=y
|
|
+
|
|
+# Enable privilege separation (see README 'Privilege separation' for details)
|
|
+#CONFIG_PRIVSEP=y
|
|
+
|
|
+# Enable mitigation against certain attacks against TKIP by delaying Michael
|
|
+# MIC error reports by a random amount of time between 0 and 60 seconds
|
|
+#CONFIG_DELAYED_MIC_ERROR_REPORT=y
|
|
+
|
|
+# Enable tracing code for developer debugging
|
|
+# This tracks use of memory allocations and other registrations and reports
|
|
+# incorrect use with a backtrace of call (or allocation) location.
|
|
+#CONFIG_WPA_TRACE=y
|
|
+# For BSD, uncomment these.
|
|
+#LIBS += -lexecinfo
|
|
+#LIBS_p += -lexecinfo
|
|
+#LIBS_c += -lexecinfo
|
|
+
|
|
+# Use libbfd to get more details for developer debugging
|
|
+# This enables use of libbfd to get more detailed symbols for the backtraces
|
|
+# generated by CONFIG_WPA_TRACE=y.
|
|
+#CONFIG_WPA_TRACE_BFD=y
|
|
+# For BSD, uncomment these.
|
|
+#LIBS += -lbfd -liberty -lz
|
|
+#LIBS_p += -lbfd -liberty -lz
|
|
+#LIBS_c += -lbfd -liberty -lz
|
|
+
|
|
+# wpa_supplicant depends on strong random number generation being available
|
|
+# from the operating system. os_get_random() function is used to fetch random
|
|
+# data when needed, e.g., for key generation. On Linux and BSD systems, this
|
|
+# works by reading /dev/urandom. It should be noted that the OS entropy pool
|
|
+# needs to be properly initialized before wpa_supplicant is started. This is
|
|
+# important especially on embedded devices that do not have a hardware random
|
|
+# number generator and may by default start up with minimal entropy available
|
|
+# for random number generation.
|
|
+#
|
|
+# As a safety net, wpa_supplicant is by default trying to internally collect
|
|
+# additional entropy for generating random data to mix in with the data fetched
|
|
+# from the OS. This by itself is not considered to be very strong, but it may
|
|
+# help in cases where the system pool is not initialized properly. However, it
|
|
+# is very strongly recommended that the system pool is initialized with enough
|
|
+# entropy either by using hardware assisted random number generator or by
|
|
+# storing state over device reboots.
|
|
+#
|
|
+# wpa_supplicant can be configured to maintain its own entropy store over
|
|
+# restarts to enhance random number generation. This is not perfect, but it is
|
|
+# much more secure than using the same sequence of random numbers after every
|
|
+# reboot. This can be enabled with -e<entropy file> command line option. The
|
|
+# specified file needs to be readable and writable by wpa_supplicant.
|
|
+#
|
|
+# If the os_get_random() is known to provide strong random data (e.g., on
|
|
+# Linux/BSD, the board in question is known to have reliable source of random
|
|
+# data from /dev/urandom), the internal wpa_supplicant random pool can be
|
|
+# disabled. This will save some in binary size and CPU use. However, this
|
|
+# should only be considered for builds that are known to be used on devices
|
|
+# that meet the requirements described above.
|
|
+CONFIG_NO_RANDOM_POOL=y
|
|
+
|
|
+# Should we attempt to use the getrandom(2) call that provides more reliable
|
|
+# yet secure randomness source than /dev/random on Linux 3.17 and newer.
|
|
+# 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)
|
|
+# Note: This is experimental and not complete implementation.
|
|
+#CONFIG_WNM=y
|
|
+
|
|
+# Interworking (IEEE 802.11u)
|
|
+# This can be used to enable functionality to improve interworking with
|
|
+# external networks (GAS/ANQP to learn more about the networks and network
|
|
+# selection based on available credentials).
|
|
+#CONFIG_INTERWORKING=y
|
|
+
|
|
+# Hotspot 2.0
|
|
+#CONFIG_HS20=y
|
|
+
|
|
+# Enable interface matching in wpa_supplicant
|
|
+#CONFIG_MATCH_IFACE=y
|
|
+
|
|
+# Disable roaming in wpa_supplicant
|
|
+#CONFIG_NO_ROAMING=y
|
|
+
|
|
+# AP mode operations with wpa_supplicant
|
|
+# This can be used for controlling AP mode operations with wpa_supplicant. It
|
|
+# should be noted that this is mainly aimed at simple cases like
|
|
+# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
|
|
+# external RADIUS server can be supported with hostapd.
|
|
+#CONFIG_AP=y
|
|
+
|
|
+# P2P (Wi-Fi Direct)
|
|
+# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
|
|
+# more information on P2P operations.
|
|
+#CONFIG_P2P=y
|
|
+
|
|
+# Enable TDLS support
|
|
+#CONFIG_TDLS=y
|
|
+
|
|
+# Wi-Fi Display
|
|
+# This can be used to enable Wi-Fi Display extensions for P2P using an external
|
|
+# program to control the additional information exchanges in the messages.
|
|
+#CONFIG_WIFI_DISPLAY=y
|
|
+
|
|
+# Autoscan
|
|
+# This can be used to enable automatic scan support in wpa_supplicant.
|
|
+# See wpa_supplicant.conf for more information on autoscan usage.
|
|
+#
|
|
+# Enabling directly a module will enable autoscan support.
|
|
+# For exponential module:
|
|
+#CONFIG_AUTOSCAN_EXPONENTIAL=y
|
|
+# For periodic module:
|
|
+#CONFIG_AUTOSCAN_PERIODIC=y
|
|
+
|
|
+# Password (and passphrase, etc.) backend for external storage
|
|
+# These optional mechanisms can be used to add support for storing passwords
|
|
+# and other secrets in external (to wpa_supplicant) location. This allows, for
|
|
+# example, operating system specific key storage to be used
|
|
+#
|
|
+# External password backend for testing purposes (developer use)
|
|
+#CONFIG_EXT_PASSWORD_TEST=y
|
|
+
|
|
+# Enable Fast Session Transfer (FST)
|
|
+#CONFIG_FST=y
|
|
+
|
|
+# Enable CLI commands for FST testing
|
|
+#CONFIG_FST_TEST=y
|
|
+
|
|
+# OS X builds. This is only for building eapol_test.
|
|
+#CONFIG_OSX=y
|
|
+
|
|
+# Automatic Channel Selection
|
|
+# This will allow wpa_supplicant to pick the channel automatically when channel
|
|
+# is set to "0".
|
|
+#
|
|
+# TODO: Extend parser to be able to parse "channel=acs_survey" as an alternative
|
|
+# to "channel=0". This would enable us to eventually add other ACS algorithms in
|
|
+# similar way.
|
|
+#
|
|
+# Automatic selection is currently only done through initialization, later on
|
|
+# we hope to do background checks to keep us moving to more ideal channels as
|
|
+# time goes by. ACS is currently only supported through the nl80211 driver and
|
|
+# your driver must have survey dump capability that is filled by the driver
|
|
+# during scanning.
|
|
+#
|
|
+# TODO: In analogy to hostapd be able to customize the ACS survey algorithm with
|
|
+# a newly to create wpa_supplicant.conf variable acs_num_scans.
|
|
+#
|
|
+# Supported ACS drivers:
|
|
+# * ath9k
|
|
+# * ath5k
|
|
+# * ath10k
|
|
+#
|
|
+# For more details refer to:
|
|
+# http://wireless.kernel.org/en/users/Documentation/acs
|
|
+#CONFIG_ACS=y
|
|
+
|
|
+# Support Multi Band Operation
|
|
+#CONFIG_MBO=y
|
|
+
|
|
+# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
|
|
+#CONFIG_FILS=y
|
|
+# FILS shared key authentication with PFS
|
|
+#CONFIG_FILS_SK_PFS=y
|
|
+
|
|
+# Support RSN on IBSS networks
|
|
+# This is needed to be able to use mode=1 network profile with proto=RSN and
|
|
+# key_mgmt=WPA-PSK (i.e., full key management instead of WPA-None).
|
|
+#CONFIG_IBSS_RSN=y
|
|
+
|
|
+# External PMKSA cache control
|
|
+# This can be used to enable control interface commands that allow the current
|
|
+# PMKSA cache entries to be fetched and new entries to be added.
|
|
+#CONFIG_PMKSA_CACHE_EXTERNAL=y
|
|
+
|
|
+# Mesh Networking (IEEE 802.11s)
|
|
+#CONFIG_MESH=y
|
|
+
|
|
+# Background scanning modules
|
|
+# These can be used to request wpa_supplicant to perform background scanning
|
|
+# operations for roaming within an ESS (same SSID). See the bgscan parameter in
|
|
+# the wpa_supplicant.conf file for more details.
|
|
+# Periodic background scans based on signal strength
|
|
+#CONFIG_BGSCAN_SIMPLE=y
|
|
+# Learn channels used by the network and try to avoid bgscans on other
|
|
+# channels (experimental)
|
|
+#CONFIG_BGSCAN_LEARN=y
|
|
+
|
|
+# Opportunistic Wireless Encryption (OWE)
|
|
+# Experimental implementation of draft-harkins-owe-07.txt
|
|
+#CONFIG_OWE=y
|
|
+
|
|
+# Device Provisioning Protocol (DPP)
|
|
+# This requires CONFIG_IEEE80211W=y to be enabled, too. (see
|
|
+# wpa_supplicant/README-DPP for details)
|
|
+#CONFIG_DPP=y
|
|
+
|
|
+# uBus IPC/RPC System
|
|
+# Services can connect to the bus and provide methods
|
|
+# that can be called by other services or clients.
|
|
+CONFIG_UBUS=y
|
|
+
|
|
+# OpenWrt patch 380-disable-ctrl-iface-mib.patch
|
|
+# leads to the MIB only being compiled in if
|
|
+# CONFIG_CTRL_IFACE_MIB is enabled.
|
|
+#CONFIG_CTRL_IFACE_MIB=y
|
|
diff --git a/package/network/services/hostapd/files/wpa_supplicant-p2p.config b/package/network/services/hostapd/files/wpa_supplicant-p2p.config
|
|
new file mode 100644
|
|
index 0000000000..7f5140622c
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/wpa_supplicant-p2p.config
|
|
@@ -0,0 +1,625 @@
|
|
+# Example wpa_supplicant build time configuration
|
|
+#
|
|
+# This file lists the configuration options that are used when building the
|
|
+# wpa_supplicant binary. All lines starting with # are ignored. Configuration
|
|
+# option lines must be commented out complete, if they are not to be included,
|
|
+# i.e., just setting VARIABLE=n is not disabling that variable.
|
|
+#
|
|
+# This file is included in Makefile, so variables like CFLAGS and LIBS can also
|
|
+# be modified from here. In most cases, these lines should use += in order not
|
|
+# to override previous values of the variables.
|
|
+
|
|
+
|
|
+# Uncomment following two lines and fix the paths if you have installed OpenSSL
|
|
+# or GnuTLS in non-default location
|
|
+#CFLAGS += -I/usr/local/openssl/include
|
|
+#LIBS += -L/usr/local/openssl/lib
|
|
+
|
|
+# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
|
|
+# the kerberos files are not in the default include path. Following line can be
|
|
+# used to fix build issues on such systems (krb5.h not found).
|
|
+#CFLAGS += -I/usr/include/kerberos
|
|
+
|
|
+# Driver interface for generic Linux wireless extensions
|
|
+# Note: WEXT is deprecated in the current Linux kernel version and no new
|
|
+# functionality is added to it. nl80211-based interface is the new
|
|
+# replacement for WEXT and its use allows wpa_supplicant to properly control
|
|
+# the driver to improve existing functionality like roaming and to support new
|
|
+# functionality.
|
|
+#CONFIG_DRIVER_WEXT=y
|
|
+
|
|
+# Driver interface for Linux drivers using the nl80211 kernel interface
|
|
+CONFIG_DRIVER_NL80211=y
|
|
+
|
|
+# QCA vendor extensions to nl80211
|
|
+#CONFIG_DRIVER_NL80211_QCA=y
|
|
+
|
|
+# driver_nl80211.c requires libnl. If you are compiling it yourself
|
|
+# you may need to point hostapd to your version of libnl.
|
|
+#
|
|
+#CFLAGS += -I$<path to libnl include files>
|
|
+#LIBS += -L$<path to libnl library files>
|
|
+
|
|
+# Use libnl v2.0 (or 3.0) libraries.
|
|
+#CONFIG_LIBNL20=y
|
|
+
|
|
+# Use libnl 3.2 libraries (if this is selected, CONFIG_LIBNL20 is ignored)
|
|
+#CONFIG_LIBNL32=y
|
|
+
|
|
+
|
|
+# Driver interface for FreeBSD net80211 layer (e.g., Atheros driver)
|
|
+#CONFIG_DRIVER_BSD=y
|
|
+#CFLAGS += -I/usr/local/include
|
|
+#LIBS += -L/usr/local/lib
|
|
+#LIBS_p += -L/usr/local/lib
|
|
+#LIBS_c += -L/usr/local/lib
|
|
+
|
|
+# Driver interface for Windows NDIS
|
|
+#CONFIG_DRIVER_NDIS=y
|
|
+#CFLAGS += -I/usr/include/w32api/ddk
|
|
+#LIBS += -L/usr/local/lib
|
|
+# For native build using mingw
|
|
+#CONFIG_NATIVE_WINDOWS=y
|
|
+# Additional directories for cross-compilation on Linux host for mingw target
|
|
+#CFLAGS += -I/opt/mingw/mingw32/include/ddk
|
|
+#LIBS += -L/opt/mingw/mingw32/lib
|
|
+#CC=mingw32-gcc
|
|
+# By default, driver_ndis uses WinPcap for low-level operations. This can be
|
|
+# replaced with the following option which replaces WinPcap calls with NDISUIO.
|
|
+# However, this requires that WZC is disabled (net stop wzcsvc) before starting
|
|
+# wpa_supplicant.
|
|
+# CONFIG_USE_NDISUIO=y
|
|
+
|
|
+# Driver interface for wired Ethernet drivers
|
|
+CONFIG_DRIVER_WIRED=y
|
|
+
|
|
+# Driver interface for MACsec capable Qualcomm Atheros drivers
|
|
+#CONFIG_DRIVER_MACSEC_QCA=y
|
|
+
|
|
+# Driver interface for Linux MACsec drivers
|
|
+#CONFIG_DRIVER_MACSEC_LINUX=y
|
|
+
|
|
+# Driver interface for the Broadcom RoboSwitch family
|
|
+#CONFIG_DRIVER_ROBOSWITCH=y
|
|
+
|
|
+# Driver interface for no driver (e.g., WPS ER only)
|
|
+#CONFIG_DRIVER_NONE=y
|
|
+
|
|
+# Solaris libraries
|
|
+#LIBS += -lsocket -ldlpi -lnsl
|
|
+#LIBS_c += -lsocket
|
|
+
|
|
+# Enable IEEE 802.1X Supplicant (automatically included if any EAP method or
|
|
+# MACsec is included)
|
|
+CONFIG_IEEE8021X_EAPOL=y
|
|
+
|
|
+# EAP-MD5
|
|
+CONFIG_EAP_MD5=y
|
|
+
|
|
+# EAP-MSCHAPv2
|
|
+CONFIG_EAP_MSCHAPV2=y
|
|
+
|
|
+# EAP-TLS
|
|
+CONFIG_EAP_TLS=y
|
|
+
|
|
+# EAL-PEAP
|
|
+CONFIG_EAP_PEAP=y
|
|
+
|
|
+# EAP-TTLS
|
|
+CONFIG_EAP_TTLS=y
|
|
+
|
|
+# EAP-FAST
|
|
+CONFIG_EAP_FAST=y
|
|
+
|
|
+# EAP-TEAP
|
|
+# Note: The current EAP-TEAP implementation is experimental and should not be
|
|
+# enabled for production use. The IETF RFC 7170 that defines EAP-TEAP has number
|
|
+# of conflicting statements and missing details and the implementation has
|
|
+# vendor specific workarounds for those and as such, may not interoperate with
|
|
+# any other implementation. This should not be used for anything else than
|
|
+# experimentation and interoperability testing until those issues has been
|
|
+# resolved.
|
|
+#CONFIG_EAP_TEAP=y
|
|
+
|
|
+# EAP-GTC
|
|
+CONFIG_EAP_GTC=y
|
|
+
|
|
+# EAP-OTP
|
|
+CONFIG_EAP_OTP=y
|
|
+
|
|
+# EAP-SIM (enable CONFIG_PCSC, if EAP-SIM is used)
|
|
+#CONFIG_EAP_SIM=y
|
|
+
|
|
+# Enable SIM simulator (Milenage) for EAP-SIM
|
|
+#CONFIG_SIM_SIMULATOR=y
|
|
+
|
|
+# EAP-PSK (experimental; this is _not_ needed for WPA-PSK)
|
|
+#CONFIG_EAP_PSK=y
|
|
+
|
|
+# EAP-pwd (secure authentication using only a password)
|
|
+#CONFIG_EAP_PWD=y
|
|
+
|
|
+# EAP-PAX
|
|
+#CONFIG_EAP_PAX=y
|
|
+
|
|
+# LEAP
|
|
+CONFIG_EAP_LEAP=y
|
|
+
|
|
+# EAP-AKA (enable CONFIG_PCSC, if EAP-AKA is used)
|
|
+#CONFIG_EAP_AKA=y
|
|
+
|
|
+# EAP-AKA' (enable CONFIG_PCSC, if EAP-AKA' is used).
|
|
+# This requires CONFIG_EAP_AKA to be enabled, too.
|
|
+#CONFIG_EAP_AKA_PRIME=y
|
|
+
|
|
+# Enable USIM simulator (Milenage) for EAP-AKA
|
|
+#CONFIG_USIM_SIMULATOR=y
|
|
+
|
|
+# EAP-SAKE
|
|
+#CONFIG_EAP_SAKE=y
|
|
+
|
|
+# EAP-GPSK
|
|
+#CONFIG_EAP_GPSK=y
|
|
+# Include support for optional SHA256 cipher suite in EAP-GPSK
|
|
+#CONFIG_EAP_GPSK_SHA256=y
|
|
+
|
|
+# EAP-TNC and related Trusted Network Connect support (experimental)
|
|
+#CONFIG_EAP_TNC=y
|
|
+
|
|
+# Wi-Fi Protected Setup (WPS)
|
|
+CONFIG_WPS=y
|
|
+# Enable WPS external registrar functionality
|
|
+#CONFIG_WPS_ER=y
|
|
+# Disable credentials for an open network by default when acting as a WPS
|
|
+# registrar.
|
|
+#CONFIG_WPS_REG_DISABLE_OPEN=y
|
|
+# Enable WPS support with NFC config method
|
|
+#CONFIG_WPS_NFC=y
|
|
+
|
|
+# EAP-IKEv2
|
|
+#CONFIG_EAP_IKEV2=y
|
|
+
|
|
+# EAP-EKE
|
|
+#CONFIG_EAP_EKE=y
|
|
+
|
|
+# MACsec
|
|
+#CONFIG_MACSEC=y
|
|
+
|
|
+# PKCS#12 (PFX) support (used to read private key and certificate file from
|
|
+# a file that usually has extension .p12 or .pfx)
|
|
+CONFIG_PKCS12=y
|
|
+
|
|
+# Smartcard support (i.e., private key on a smartcard), e.g., with openssl
|
|
+# engine.
|
|
+CONFIG_SMARTCARD=y
|
|
+
|
|
+# PC/SC interface for smartcards (USIM, GSM SIM)
|
|
+# Enable this if EAP-SIM or EAP-AKA is included
|
|
+#CONFIG_PCSC=y
|
|
+
|
|
+# Support HT overrides (disable HT/HT40, mask MCS rates, etc.)
|
|
+CONFIG_HT_OVERRIDES=y
|
|
+
|
|
+# Support VHT overrides (disable VHT, mask MCS rates, etc.)
|
|
+CONFIG_VHT_OVERRIDES=y
|
|
+
|
|
+# Development testing
|
|
+#CONFIG_EAPOL_TEST=y
|
|
+
|
|
+# Select control interface backend for external programs, e.g, wpa_cli:
|
|
+# unix = UNIX domain sockets (default for Linux/*BSD)
|
|
+# udp = UDP sockets using localhost (127.0.0.1)
|
|
+# udp6 = UDP IPv6 sockets using localhost (::1)
|
|
+# named_pipe = Windows Named Pipe (default for Windows)
|
|
+# udp-remote = UDP sockets with remote access (only for tests systems/purpose)
|
|
+# udp6-remote = UDP IPv6 sockets with remote access (only for tests purpose)
|
|
+# y = use default (backwards compatibility)
|
|
+# If this option is commented out, control interface is not included in the
|
|
+# build.
|
|
+CONFIG_CTRL_IFACE=y
|
|
+
|
|
+# Include support for GNU Readline and History Libraries in wpa_cli.
|
|
+# When building a wpa_cli binary for distribution, please note that these
|
|
+# libraries are licensed under GPL and as such, BSD license may not apply for
|
|
+# the resulting binary.
|
|
+#CONFIG_READLINE=y
|
|
+
|
|
+# Include internal line edit mode in wpa_cli. This can be used as a replacement
|
|
+# for GNU Readline to provide limited command line editing and history support.
|
|
+#CONFIG_WPA_CLI_EDIT=y
|
|
+
|
|
+# Remove debugging code that is printing out debug message to stdout.
|
|
+# This can be used to reduce the size of the wpa_supplicant considerably
|
|
+# if debugging code is not needed. The size reduction can be around 35%
|
|
+# (e.g., 90 kB).
|
|
+#CONFIG_NO_STDOUT_DEBUG=y
|
|
+
|
|
+# Remove WPA support, e.g., for wired-only IEEE 802.1X supplicant, to save
|
|
+# 35-50 kB in code size.
|
|
+#CONFIG_NO_WPA=y
|
|
+
|
|
+# Remove IEEE 802.11i/WPA-Personal ASCII passphrase support
|
|
+# This option can be used to reduce code size by removing support for
|
|
+# converting ASCII passphrases into PSK. If this functionality is removed, the
|
|
+# PSK can only be configured as the 64-octet hexstring (e.g., from
|
|
+# wpa_passphrase). This saves about 0.5 kB in code size.
|
|
+#CONFIG_NO_WPA_PASSPHRASE=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.
|
|
+# This can be used if ap_scan=1 mode is never enabled.
|
|
+#CONFIG_NO_SCAN_PROCESSING=y
|
|
+
|
|
+# Select configuration backend:
|
|
+# file = text file (e.g., wpa_supplicant.conf; note: the configuration file
|
|
+# path is given on command line, not here; this option is just used to
|
|
+# select the backend that allows configuration files to be used)
|
|
+# winreg = Windows registry (see win_example.reg for an example)
|
|
+CONFIG_BACKEND=file
|
|
+
|
|
+# Remove configuration write functionality (i.e., to allow the configuration
|
|
+# file to be updated based on runtime configuration changes). The runtime
|
|
+# configuration can still be changed, the changes are just not going to be
|
|
+# persistent over restarts. This option can be used to reduce code size by
|
|
+# about 3.5 kB.
|
|
+#CONFIG_NO_CONFIG_WRITE=y
|
|
+
|
|
+# Remove support for configuration blobs to reduce code size by about 1.5 kB.
|
|
+#CONFIG_NO_CONFIG_BLOBS=y
|
|
+
|
|
+# Select program entry point implementation:
|
|
+# main = UNIX/POSIX like main() function (default)
|
|
+# main_winsvc = Windows service (read parameters from registry)
|
|
+# main_none = Very basic example (development use only)
|
|
+#CONFIG_MAIN=main
|
|
+
|
|
+# Select wrapper for operating system and C library specific functions
|
|
+# unix = UNIX/POSIX like systems (default)
|
|
+# win32 = Windows systems
|
|
+# none = Empty template
|
|
+#CONFIG_OS=unix
|
|
+
|
|
+# Select event loop implementation
|
|
+# eloop = select() loop (default)
|
|
+# eloop_win = Windows events and WaitForMultipleObject() loop
|
|
+#CONFIG_ELOOP=eloop
|
|
+
|
|
+# Should we use poll instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_POLL=y
|
|
+
|
|
+# Should we use epoll instead of select? Select is used by default.
|
|
+CONFIG_ELOOP_EPOLL=y
|
|
+
|
|
+# Should we use kqueue instead of select? Select is used by default.
|
|
+#CONFIG_ELOOP_KQUEUE=y
|
|
+
|
|
+# Select layer 2 packet implementation
|
|
+# linux = Linux packet socket (default)
|
|
+# pcap = libpcap/libdnet/WinPcap
|
|
+# freebsd = FreeBSD libpcap
|
|
+# winpcap = WinPcap with receive thread
|
|
+# ndis = Windows NDISUIO (note: requires CONFIG_USE_NDISUIO=y)
|
|
+# none = Empty template
|
|
+#CONFIG_L2_PACKET=linux
|
|
+
|
|
+# Disable Linux packet socket workaround applicable for station interface
|
|
+# in a bridge for EAPOL frames. This should be uncommented only if the kernel
|
|
+# is known to not have the regression issue in packet socket behavior with
|
|
+# bridge interfaces (commit 'bridge: respect RFC2863 operational state')').
|
|
+CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
|
|
+
|
|
+# IEEE 802.11w (management frame protection), also known as PMF
|
|
+# Driver support is also needed for IEEE 802.11w.
|
|
+CONFIG_IEEE80211W=y
|
|
+
|
|
+# Support Operating Channel Validation
|
|
+#CONFIG_OCV=y
|
|
+
|
|
+# Select TLS implementation
|
|
+# openssl = OpenSSL (default)
|
|
+# gnutls = GnuTLS
|
|
+# internal = Internal TLSv1 implementation (experimental)
|
|
+# linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
|
|
+# none = Empty template
|
|
+CONFIG_TLS=internal
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1)
|
|
+# can be enabled to get a stronger construction of messages when block ciphers
|
|
+# are used. It should be noted that some existing TLS v1.0 -based
|
|
+# implementation may not be compatible with TLS v1.1 message (ClientHello is
|
|
+# sent prior to negotiating which version will be used)
|
|
+#CONFIG_TLSV11=y
|
|
+
|
|
+# TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2)
|
|
+# can be enabled to enable use of stronger crypto algorithms. It should be
|
|
+# noted that some existing TLS v1.0 -based implementation may not be compatible
|
|
+# with TLS v1.2 message (ClientHello is sent prior to negotiating which version
|
|
+# will be used)
|
|
+#CONFIG_TLSV12=y
|
|
+
|
|
+# Select which ciphers to use by default with OpenSSL if the user does not
|
|
+# specify them.
|
|
+#CONFIG_TLS_DEFAULT_CIPHERS="DEFAULT:!EXP:!LOW"
|
|
+
|
|
+# If CONFIG_TLS=internal is used, additional library and include paths are
|
|
+# needed for LibTomMath. Alternatively, an integrated, minimal version of
|
|
+# LibTomMath can be used. See beginning of libtommath.c for details on benefits
|
|
+# and drawbacks of this option.
|
|
+CONFIG_INTERNAL_LIBTOMMATH=y
|
|
+#ifndef CONFIG_INTERNAL_LIBTOMMATH
|
|
+#LTM_PATH=/usr/src/libtommath-0.39
|
|
+#CFLAGS += -I$(LTM_PATH)
|
|
+#LIBS += -L$(LTM_PATH)
|
|
+#LIBS_p += -L$(LTM_PATH)
|
|
+#endif
|
|
+# At the cost of about 4 kB of additional binary size, the internal LibTomMath
|
|
+# can be configured to include faster routines for exptmod, sqr, and div to
|
|
+# speed up DH and RSA calculation considerably
|
|
+CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
|
+
|
|
+# Include NDIS event processing through WMI into wpa_supplicant/wpasvc.
|
|
+# This is only for Windows builds and requires WMI-related header files and
|
|
+# WbemUuid.Lib from Platform SDK even when building with MinGW.
|
|
+#CONFIG_NDIS_EVENTS_INTEGRATED=y
|
|
+#PLATFORMSDKLIB="/opt/Program Files/Microsoft Platform SDK/Lib"
|
|
+
|
|
+# Add support for new DBus control interface
|
|
+# (fi.w1.hostap.wpa_supplicant1)
|
|
+#CONFIG_CTRL_IFACE_DBUS_NEW=y
|
|
+
|
|
+# Add introspection support for new DBus control interface
|
|
+#CONFIG_CTRL_IFACE_DBUS_INTRO=y
|
|
+
|
|
+# Add support for loading EAP methods dynamically as shared libraries.
|
|
+# When this option is enabled, each EAP method can be either included
|
|
+# statically (CONFIG_EAP_<method>=y) or dynamically (CONFIG_EAP_<method>=dyn).
|
|
+# Dynamic EAP methods are build as shared objects (eap_*.so) and they need to
|
|
+# be loaded in the beginning of the wpa_supplicant configuration file
|
|
+# (see load_dynamic_eap parameter in the example file) before being used in
|
|
+# the network blocks.
|
|
+#
|
|
+# Note that some shared parts of EAP methods are included in the main program
|
|
+# and in order to be able to use dynamic EAP methods using these parts, the
|
|
+# main program must have been build with the EAP method enabled (=y or =dyn).
|
|
+# This means that EAP-TLS/PEAP/TTLS/FAST cannot be added as dynamic libraries
|
|
+# unless at least one of them was included in the main build to force inclusion
|
|
+# of the shared code. Similarly, at least one of EAP-SIM/AKA must be included
|
|
+# in the main build to be able to load these methods dynamically.
|
|
+#
|
|
+# Please also note that using dynamic libraries will increase the total binary
|
|
+# size. Thus, it may not be the best option for targets that have limited
|
|
+# amount of memory/flash.
|
|
+#CONFIG_DYNAMIC_EAP_METHODS=y
|
|
+
|
|
+# IEEE Std 802.11r-2008 (Fast BSS Transition) for station mode
|
|
+#CONFIG_IEEE80211R=y
|
|
+
|
|
+# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt)
|
|
+#CONFIG_DEBUG_FILE=y
|
|
+
|
|
+# Send debug messages to syslog instead of stdout
|
|
+CONFIG_DEBUG_SYSLOG=y
|
|
+# Set syslog facility for debug messages
|
|
+CONFIG_DEBUG_SYSLOG_FACILITY=LOG_DAEMON
|
|
+
|
|
+# Add support for sending all debug messages (regardless of debug verbosity)
|
|
+# to the Linux kernel tracing facility. This helps debug the entire stack by
|
|
+# making it easy to record everything happening from the driver up into the
|
|
+# same file, e.g., using trace-cmd.
|
|
+#CONFIG_DEBUG_LINUX_TRACING=y
|
|
+
|
|
+# Add support for writing debug log to Android logcat instead of standard
|
|
+# output
|
|
+#CONFIG_ANDROID_LOG=y
|
|
+
|
|
+# Enable privilege separation (see README 'Privilege separation' for details)
|
|
+#CONFIG_PRIVSEP=y
|
|
+
|
|
+# Enable mitigation against certain attacks against TKIP by delaying Michael
|
|
+# MIC error reports by a random amount of time between 0 and 60 seconds
|
|
+#CONFIG_DELAYED_MIC_ERROR_REPORT=y
|
|
+
|
|
+# Enable tracing code for developer debugging
|
|
+# This tracks use of memory allocations and other registrations and reports
|
|
+# incorrect use with a backtrace of call (or allocation) location.
|
|
+#CONFIG_WPA_TRACE=y
|
|
+# For BSD, uncomment these.
|
|
+#LIBS += -lexecinfo
|
|
+#LIBS_p += -lexecinfo
|
|
+#LIBS_c += -lexecinfo
|
|
+
|
|
+# Use libbfd to get more details for developer debugging
|
|
+# This enables use of libbfd to get more detailed symbols for the backtraces
|
|
+# generated by CONFIG_WPA_TRACE=y.
|
|
+#CONFIG_WPA_TRACE_BFD=y
|
|
+# For BSD, uncomment these.
|
|
+#LIBS += -lbfd -liberty -lz
|
|
+#LIBS_p += -lbfd -liberty -lz
|
|
+#LIBS_c += -lbfd -liberty -lz
|
|
+
|
|
+# wpa_supplicant depends on strong random number generation being available
|
|
+# from the operating system. os_get_random() function is used to fetch random
|
|
+# data when needed, e.g., for key generation. On Linux and BSD systems, this
|
|
+# works by reading /dev/urandom. It should be noted that the OS entropy pool
|
|
+# needs to be properly initialized before wpa_supplicant is started. This is
|
|
+# important especially on embedded devices that do not have a hardware random
|
|
+# number generator and may by default start up with minimal entropy available
|
|
+# for random number generation.
|
|
+#
|
|
+# As a safety net, wpa_supplicant is by default trying to internally collect
|
|
+# additional entropy for generating random data to mix in with the data fetched
|
|
+# from the OS. This by itself is not considered to be very strong, but it may
|
|
+# help in cases where the system pool is not initialized properly. However, it
|
|
+# is very strongly recommended that the system pool is initialized with enough
|
|
+# entropy either by using hardware assisted random number generator or by
|
|
+# storing state over device reboots.
|
|
+#
|
|
+# wpa_supplicant can be configured to maintain its own entropy store over
|
|
+# restarts to enhance random number generation. This is not perfect, but it is
|
|
+# much more secure than using the same sequence of random numbers after every
|
|
+# reboot. This can be enabled with -e<entropy file> command line option. The
|
|
+# specified file needs to be readable and writable by wpa_supplicant.
|
|
+#
|
|
+# If the os_get_random() is known to provide strong random data (e.g., on
|
|
+# Linux/BSD, the board in question is known to have reliable source of random
|
|
+# data from /dev/urandom), the internal wpa_supplicant random pool can be
|
|
+# disabled. This will save some in binary size and CPU use. However, this
|
|
+# should only be considered for builds that are known to be used on devices
|
|
+# that meet the requirements described above.
|
|
+CONFIG_NO_RANDOM_POOL=y
|
|
+
|
|
+# Should we attempt to use the getrandom(2) call that provides more reliable
|
|
+# yet secure randomness source than /dev/random on Linux 3.17 and newer.
|
|
+# 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)
|
|
+# Note: This is experimental and not complete implementation.
|
|
+#CONFIG_WNM=y
|
|
+
|
|
+# Interworking (IEEE 802.11u)
|
|
+# This can be used to enable functionality to improve interworking with
|
|
+# external networks (GAS/ANQP to learn more about the networks and network
|
|
+# selection based on available credentials).
|
|
+#CONFIG_INTERWORKING=y
|
|
+
|
|
+# Hotspot 2.0
|
|
+#CONFIG_HS20=y
|
|
+
|
|
+# Enable interface matching in wpa_supplicant
|
|
+#CONFIG_MATCH_IFACE=y
|
|
+
|
|
+# Disable roaming in wpa_supplicant
|
|
+#CONFIG_NO_ROAMING=y
|
|
+
|
|
+# AP mode operations with wpa_supplicant
|
|
+# This can be used for controlling AP mode operations with wpa_supplicant. It
|
|
+# should be noted that this is mainly aimed at simple cases like
|
|
+# WPA2-Personal while more complex configurations like WPA2-Enterprise with an
|
|
+# external RADIUS server can be supported with hostapd.
|
|
+CONFIG_AP=y
|
|
+
|
|
+# P2P (Wi-Fi Direct)
|
|
+# This can be used to enable P2P support in wpa_supplicant. See README-P2P for
|
|
+# more information on P2P operations.
|
|
+CONFIG_P2P=y
|
|
+
|
|
+# Enable TDLS support
|
|
+#CONFIG_TDLS=y
|
|
+
|
|
+# Wi-Fi Display
|
|
+# This can be used to enable Wi-Fi Display extensions for P2P using an external
|
|
+# program to control the additional information exchanges in the messages.
|
|
+#CONFIG_WIFI_DISPLAY=y
|
|
+
|
|
+# Autoscan
|
|
+# This can be used to enable automatic scan support in wpa_supplicant.
|
|
+# See wpa_supplicant.conf for more information on autoscan usage.
|
|
+#
|
|
+# Enabling directly a module will enable autoscan support.
|
|
+# For exponential module:
|
|
+#CONFIG_AUTOSCAN_EXPONENTIAL=y
|
|
+# For periodic module:
|
|
+#CONFIG_AUTOSCAN_PERIODIC=y
|
|
+
|
|
+# Password (and passphrase, etc.) backend for external storage
|
|
+# These optional mechanisms can be used to add support for storing passwords
|
|
+# and other secrets in external (to wpa_supplicant) location. This allows, for
|
|
+# example, operating system specific key storage to be used
|
|
+#
|
|
+# External password backend for testing purposes (developer use)
|
|
+#CONFIG_EXT_PASSWORD_TEST=y
|
|
+
|
|
+# Enable Fast Session Transfer (FST)
|
|
+#CONFIG_FST=y
|
|
+
|
|
+# Enable CLI commands for FST testing
|
|
+#CONFIG_FST_TEST=y
|
|
+
|
|
+# OS X builds. This is only for building eapol_test.
|
|
+#CONFIG_OSX=y
|
|
+
|
|
+# Automatic Channel Selection
|
|
+# This will allow wpa_supplicant to pick the channel automatically when channel
|
|
+# is set to "0".
|
|
+#
|
|
+# TODO: Extend parser to be able to parse "channel=acs_survey" as an alternative
|
|
+# to "channel=0". This would enable us to eventually add other ACS algorithms in
|
|
+# similar way.
|
|
+#
|
|
+# Automatic selection is currently only done through initialization, later on
|
|
+# we hope to do background checks to keep us moving to more ideal channels as
|
|
+# time goes by. ACS is currently only supported through the nl80211 driver and
|
|
+# your driver must have survey dump capability that is filled by the driver
|
|
+# during scanning.
|
|
+#
|
|
+# TODO: In analogy to hostapd be able to customize the ACS survey algorithm with
|
|
+# a newly to create wpa_supplicant.conf variable acs_num_scans.
|
|
+#
|
|
+# Supported ACS drivers:
|
|
+# * ath9k
|
|
+# * ath5k
|
|
+# * ath10k
|
|
+#
|
|
+# For more details refer to:
|
|
+# http://wireless.kernel.org/en/users/Documentation/acs
|
|
+#CONFIG_ACS=y
|
|
+
|
|
+# Support Multi Band Operation
|
|
+#CONFIG_MBO=y
|
|
+
|
|
+# Fast Initial Link Setup (FILS) (IEEE 802.11ai)
|
|
+CONFIG_FILS=y
|
|
+# FILS shared key authentication with PFS
|
|
+#CONFIG_FILS_SK_PFS=y
|
|
+
|
|
+# Support RSN on IBSS networks
|
|
+# This is needed to be able to use mode=1 network profile with proto=RSN and
|
|
+# key_mgmt=WPA-PSK (i.e., full key management instead of WPA-None).
|
|
+CONFIG_IBSS_RSN=y
|
|
+
|
|
+# External PMKSA cache control
|
|
+# This can be used to enable control interface commands that allow the current
|
|
+# PMKSA cache entries to be fetched and new entries to be added.
|
|
+#CONFIG_PMKSA_CACHE_EXTERNAL=y
|
|
+
|
|
+# Mesh Networking (IEEE 802.11s)
|
|
+#CONFIG_MESH=y
|
|
+
|
|
+# Background scanning modules
|
|
+# These can be used to request wpa_supplicant to perform background scanning
|
|
+# operations for roaming within an ESS (same SSID). See the bgscan parameter in
|
|
+# the wpa_supplicant.conf file for more details.
|
|
+# Periodic background scans based on signal strength
|
|
+#CONFIG_BGSCAN_SIMPLE=y
|
|
+# Learn channels used by the network and try to avoid bgscans on other
|
|
+# channels (experimental)
|
|
+#CONFIG_BGSCAN_LEARN=y
|
|
+
|
|
+# Opportunistic Wireless Encryption (OWE)
|
|
+# Experimental implementation of draft-harkins-owe-07.txt
|
|
+#CONFIG_OWE=y
|
|
+
|
|
+# Device Provisioning Protocol (DPP)
|
|
+# This requires CONFIG_IEEE80211W=y to be enabled, too. (see
|
|
+# wpa_supplicant/README-DPP for details)
|
|
+#CONFIG_DPP=y
|
|
+
|
|
+# uBus IPC/RPC System
|
|
+# Services can connect to the bus and provide methods
|
|
+# that can be called by other services or clients.
|
|
+CONFIG_UBUS=y
|
|
+
|
|
+# OpenWrt patch 380-disable-ctrl-iface-mib.patch
|
|
+# leads to the MIB only being compiled in if
|
|
+# CONFIG_CTRL_IFACE_MIB is enabled.
|
|
+CONFIG_CTRL_IFACE_MIB=y
|
|
diff --git a/package/network/services/hostapd/files/wpa_supplicant.uc b/package/network/services/hostapd/files/wpa_supplicant.uc
|
|
new file mode 100644
|
|
index 0000000000..e3a3afcff2
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/wpa_supplicant.uc
|
|
@@ -0,0 +1,253 @@
|
|
+let libubus = require("ubus");
|
|
+import { open, readfile } from "fs";
|
|
+import { wdev_create, wdev_remove, is_equal, vlist_new } from "common";
|
|
+
|
|
+let ubus = libubus.connect();
|
|
+
|
|
+wpas.data.config = {};
|
|
+wpas.data.iface_phy = {};
|
|
+
|
|
+function iface_stop(iface)
|
|
+{
|
|
+ let ifname = iface.config.iface;
|
|
+
|
|
+ if (!iface.running)
|
|
+ return;
|
|
+
|
|
+ delete wpas.data.iface_phy[ifname];
|
|
+ wpas.remove_iface(ifname);
|
|
+ wdev_remove(ifname);
|
|
+ iface.running = false;
|
|
+}
|
|
+
|
|
+function iface_start(phy, iface)
|
|
+{
|
|
+ if (iface.running)
|
|
+ return;
|
|
+
|
|
+ let ifname = iface.config.iface;
|
|
+
|
|
+ wpas.data.iface_phy[ifname] = phy;
|
|
+ wdev_remove(ifname);
|
|
+ let ret = wdev_create(phy, ifname, iface.config);
|
|
+ if (ret)
|
|
+ wpas.printf(`Failed to create device ${ifname}: ${ret}`);
|
|
+ wpas.add_iface(iface.config);
|
|
+ iface.running = true;
|
|
+}
|
|
+
|
|
+function iface_cb(new_if, old_if)
|
|
+{
|
|
+ if (old_if && new_if && is_equal(old_if.config, new_if.config)) {
|
|
+ new_if.running = old_if.running;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (old_if)
|
|
+ iface_stop(old_if);
|
|
+}
|
|
+
|
|
+function prepare_config(config)
|
|
+{
|
|
+ config.config_data = readfile(config.config);
|
|
+
|
|
+ return { config: config };
|
|
+}
|
|
+
|
|
+function set_config(phy_name, config_list)
|
|
+{
|
|
+ let phy = wpas.data.config[phy_name];
|
|
+
|
|
+ if (!phy) {
|
|
+ phy = vlist_new(iface_cb, false);
|
|
+ wpas.data.config[phy_name] = phy;
|
|
+ }
|
|
+
|
|
+ let values = [];
|
|
+ for (let config in config_list)
|
|
+ push(values, [ config.iface, prepare_config(config) ]);
|
|
+
|
|
+ phy.update(values);
|
|
+}
|
|
+
|
|
+function start_pending(phy_name)
|
|
+{
|
|
+ let phy = wpas.data.config[phy_name];
|
|
+
|
|
+ for (let ifname in phy.data)
|
|
+ iface_start(phy_name, phy.data[ifname]);
|
|
+}
|
|
+
|
|
+let main_obj = {
|
|
+ phy_set_state: {
|
|
+ args: {
|
|
+ phy: "",
|
|
+ stop: true,
|
|
+ },
|
|
+ call: function(req) {
|
|
+ if (!req.args.phy || req.args.stop == null)
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ let phy = wpas.data.config[req.args.phy];
|
|
+ if (!phy)
|
|
+ return libubus.STATUS_NOT_FOUND;
|
|
+
|
|
+ try {
|
|
+ if (req.args.stop) {
|
|
+ for (let ifname in phy.data)
|
|
+ iface_stop(phy.data[ifname]);
|
|
+ } else {
|
|
+ start_pending(req.args.phy);
|
|
+ }
|
|
+ } catch (e) {
|
|
+ wpas.printf(`Error chaging state: ${e}\n${e.stacktrace[0].context}`);
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+ },
|
|
+ config_set: {
|
|
+ args: {
|
|
+ phy: "",
|
|
+ config: [],
|
|
+ defer: true,
|
|
+ },
|
|
+ call: function(req) {
|
|
+ if (!req.args.phy)
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ try {
|
|
+ if (req.args.config)
|
|
+ set_config(req.args.phy, req.args.config);
|
|
+
|
|
+ if (!req.args.defer)
|
|
+ start_pending(req.args.phy);
|
|
+ } catch (e) {
|
|
+ wpas.printf(`Error loading config: ${e}\n${e.stacktrace[0].context}`);
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+ }
|
|
+
|
|
+ return {
|
|
+ pid: wpas.getpid()
|
|
+ };
|
|
+ }
|
|
+ },
|
|
+ config_add: {
|
|
+ args: {
|
|
+ driver: "",
|
|
+ iface: "",
|
|
+ bridge: "",
|
|
+ hostapd_ctrl: "",
|
|
+ ctrl: "",
|
|
+ config: "",
|
|
+ },
|
|
+ call: function(req) {
|
|
+ if (!req.args.iface || !req.args.config)
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ if (wpas.add_iface(req.args) < 0)
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ return {
|
|
+ pid: wpas.getpid()
|
|
+ };
|
|
+ }
|
|
+ },
|
|
+ config_remove: {
|
|
+ args: {
|
|
+ iface: ""
|
|
+ },
|
|
+ call: function(req) {
|
|
+ if (!req.args.iface)
|
|
+ return libubus.STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ wpas.remove_iface(req.args.iface);
|
|
+ return 0;
|
|
+ }
|
|
+ },
|
|
+};
|
|
+
|
|
+wpas.data.ubus = ubus;
|
|
+wpas.data.obj = ubus.publish("wpa_supplicant", main_obj);
|
|
+
|
|
+function iface_event(type, name, data) {
|
|
+ let ubus = wpas.data.ubus;
|
|
+
|
|
+ data ??= {};
|
|
+ data.name = name;
|
|
+ wpas.data.obj.notify(`iface.${type}`, data, null, null, null, -1);
|
|
+ ubus.call("service", "event", { type: `wpa_supplicant.${name}.${type}`, data: {} });
|
|
+}
|
|
+
|
|
+function iface_hostapd_notify(phy, ifname, iface, state)
|
|
+{
|
|
+ let ubus = wpas.data.ubus;
|
|
+ let status = iface.status();
|
|
+ let msg = { phy: phy };
|
|
+
|
|
+ switch (state) {
|
|
+ case "DISCONNECTED":
|
|
+ case "AUTHENTICATING":
|
|
+ msg.up = false;
|
|
+ break;
|
|
+ case "INTERFACE_DISABLED":
|
|
+ case "INACTIVE":
|
|
+ msg.up = true;
|
|
+ break;
|
|
+ case "COMPLETED":
|
|
+ msg.up = true;
|
|
+ msg.frequency = status.frequency;
|
|
+ msg.sec_chan_offset = status.sec_chan_offset;
|
|
+ break;
|
|
+ default:
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ubus.call("hostapd", "apsta_state", msg);
|
|
+}
|
|
+
|
|
+function iface_channel_switch(phy, ifname, iface, info)
|
|
+{
|
|
+ let msg = {
|
|
+ phy: phy,
|
|
+ up: true,
|
|
+ csa: true,
|
|
+ csa_count: info.csa_count ? info.csa_count - 1 : 0,
|
|
+ frequency: info.frequency,
|
|
+ sec_chan_offset: info.sec_chan_offset,
|
|
+ };
|
|
+ ubus.call("hostapd", "apsta_state", msg);
|
|
+}
|
|
+
|
|
+return {
|
|
+ shutdown: function() {
|
|
+ for (let phy in wpas.data.config)
|
|
+ set_config(phy, []);
|
|
+ wpas.ubus.disconnect();
|
|
+ },
|
|
+ iface_add: function(name, obj) {
|
|
+ iface_event("add", name);
|
|
+ },
|
|
+ iface_remove: function(name, obj) {
|
|
+ iface_event("remove", name);
|
|
+ },
|
|
+ state: function(ifname, iface, state) {
|
|
+ let phy = wpas.data.iface_phy[ifname];
|
|
+ if (!phy) {
|
|
+ wpas.printf(`no PHY for ifname ${ifname}`);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ iface_hostapd_notify(phy, ifname, iface, state);
|
|
+ },
|
|
+ event: function(ifname, iface, ev, info) {
|
|
+ let phy = wpas.data.iface_phy[ifname];
|
|
+ if (!phy) {
|
|
+ wpas.printf(`no PHY for ifname ${ifname}`);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (ev == "CH_SWITCH_STARTED")
|
|
+ iface_channel_switch(phy, ifname, iface, info);
|
|
+ }
|
|
+};
|
|
diff --git a/package/network/services/hostapd/files/wpad.init b/package/network/services/hostapd/files/wpad.init
|
|
new file mode 100644
|
|
index 0000000000..65d46df982
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/wpad.init
|
|
@@ -0,0 +1,43 @@
|
|
+#!/bin/sh /etc/rc.common
|
|
+
|
|
+START=19
|
|
+STOP=21
|
|
+
|
|
+USE_PROCD=1
|
|
+NAME=wpad
|
|
+
|
|
+start_service() {
|
|
+ if [ -x "/usr/sbin/hostapd" ]; then
|
|
+ mkdir -p /var/run/hostapd
|
|
+ chown network:network /var/run/hostapd
|
|
+ procd_open_instance hostapd
|
|
+ procd_set_param command /usr/sbin/hostapd -s -g /var/run/hostapd/global
|
|
+ procd_set_param respawn 3600 1 0
|
|
+ procd_set_param limits core="unlimited"
|
|
+ [ -x /sbin/ujail -a -e /etc/capabilities/wpad.json ] && {
|
|
+ procd_add_jail hostapd
|
|
+ procd_set_param capabilities /etc/capabilities/wpad.json
|
|
+ procd_set_param user network
|
|
+ procd_set_param group network
|
|
+ procd_set_param no_new_privs 1
|
|
+ }
|
|
+ procd_close_instance
|
|
+ fi
|
|
+
|
|
+ if [ -x "/usr/sbin/wpa_supplicant" ]; then
|
|
+ mkdir -p /var/run/wpa_supplicant
|
|
+ chown network:network /var/run/wpa_supplicant
|
|
+ procd_open_instance supplicant
|
|
+ procd_set_param command /usr/sbin/wpa_supplicant -n -s -g /var/run/wpa_supplicant/global
|
|
+ procd_set_param respawn 3600 1 0
|
|
+ procd_set_param limits core="unlimited"
|
|
+ [ -x /sbin/ujail -a -e /etc/capabilities/wpad.json ] && {
|
|
+ procd_add_jail wpa_supplicant
|
|
+ procd_set_param capabilities /etc/capabilities/wpad.json
|
|
+ procd_set_param user network
|
|
+ procd_set_param group network
|
|
+ procd_set_param no_new_privs 1
|
|
+ }
|
|
+ procd_close_instance
|
|
+ fi
|
|
+}
|
|
diff --git a/package/network/services/hostapd/files/wpad.json b/package/network/services/hostapd/files/wpad.json
|
|
new file mode 100644
|
|
index 0000000000..c73f3d98bd
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/wpad.json
|
|
@@ -0,0 +1,22 @@
|
|
+{
|
|
+ "bounding": [
|
|
+ "CAP_NET_ADMIN",
|
|
+ "CAP_NET_RAW"
|
|
+ ],
|
|
+ "effective": [
|
|
+ "CAP_NET_ADMIN",
|
|
+ "CAP_NET_RAW"
|
|
+ ],
|
|
+ "ambient": [
|
|
+ "CAP_NET_ADMIN",
|
|
+ "CAP_NET_RAW"
|
|
+ ],
|
|
+ "permitted": [
|
|
+ "CAP_NET_ADMIN",
|
|
+ "CAP_NET_RAW"
|
|
+ ],
|
|
+ "inheritable": [
|
|
+ "CAP_NET_ADMIN",
|
|
+ "CAP_NET_RAW"
|
|
+ ]
|
|
+}
|
|
diff --git a/package/network/services/hostapd/files/wpad_acl.json b/package/network/services/hostapd/files/wpad_acl.json
|
|
new file mode 100644
|
|
index 0000000000..c77ccd8ea0
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/wpad_acl.json
|
|
@@ -0,0 +1,10 @@
|
|
+{
|
|
+ "user": "network",
|
|
+ "access": {
|
|
+ "service": {
|
|
+ "methods": [ "event" ]
|
|
+ }
|
|
+ },
|
|
+ "publish": [ "hostapd", "hostapd.*", "wpa_supplicant", "wpa_supplicant.*" ],
|
|
+ "send": [ "bss.*", "wps_credentials" ]
|
|
+}
|
|
diff --git a/package/network/services/hostapd/files/wps-hotplug.sh b/package/network/services/hostapd/files/wps-hotplug.sh
|
|
new file mode 100644
|
|
index 0000000000..073bdd1868
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/wps-hotplug.sh
|
|
@@ -0,0 +1,69 @@
|
|
+#!/bin/sh
|
|
+
|
|
+wps_catch_credentials() {
|
|
+ local iface ifaces ifc ifname ssid encryption key radio radios
|
|
+ local found=0
|
|
+
|
|
+ . /usr/share/libubox/jshn.sh
|
|
+ ubus -S -t 30 listen wps_credentials | while read creds; do
|
|
+ json_init
|
|
+ json_load "$creds"
|
|
+ json_select wps_credentials || continue
|
|
+ json_get_vars ifname ssid key encryption
|
|
+ local ifcname="$ifname"
|
|
+ json_init
|
|
+ json_load "$(ubus -S call network.wireless status)"
|
|
+ json_get_keys radios
|
|
+ for radio in $radios; do
|
|
+ json_select $radio
|
|
+ json_select interfaces
|
|
+ json_get_keys ifaces
|
|
+ for ifc in $ifaces; do
|
|
+ json_select $ifc
|
|
+ json_get_vars ifname
|
|
+ [ "$ifname" = "$ifcname" ] && {
|
|
+ ubus -S call uci set "{\"config\":\"wireless\", \"type\":\"wifi-iface\", \
|
|
+ \"match\": { \"device\": \"$radio\", \"encryption\": \"wps\" }, \
|
|
+ \"values\": { \"encryption\": \"$encryption\", \
|
|
+ \"ssid\": \"$ssid\", \
|
|
+ \"key\": \"$key\" } }"
|
|
+ ubus -S call uci commit '{"config": "wireless"}'
|
|
+ ubus -S call uci apply
|
|
+ }
|
|
+ json_select ..
|
|
+ done
|
|
+ json_select ..
|
|
+ json_select ..
|
|
+ done
|
|
+ done
|
|
+}
|
|
+
|
|
+if [ "$ACTION" = "released" ] && [ "$BUTTON" = "wps" ]; then
|
|
+ # If the button was pressed for 3 seconds or more, trigger WPS on
|
|
+ # wpa_supplicant only, no matter if hostapd is running or not. If
|
|
+ # was pressed for less than 3 seconds, try triggering on
|
|
+ # hostapd. If there is no hostapd instance to trigger it on or WPS
|
|
+ # is not enabled on them, trigger it on wpa_supplicant.
|
|
+ if [ "$SEEN" -lt 3 ] ; then
|
|
+ wps_done=0
|
|
+ ubusobjs="$( ubus -S list hostapd.* )"
|
|
+ for ubusobj in $ubusobjs; do
|
|
+ ubus -S call $ubusobj wps_start && wps_done=1
|
|
+ done
|
|
+ [ $wps_done = 0 ] || return 0
|
|
+ fi
|
|
+ wps_done=0
|
|
+ ubusobjs="$( ubus -S list wpa_supplicant.* )"
|
|
+ for ubusobj in $ubusobjs; do
|
|
+ ifname="$(echo $ubusobj | cut -d'.' -f2 )"
|
|
+ multi_ap=""
|
|
+ if [ -e "/var/run/wpa_supplicant-${ifname}.conf.is_multiap" ]; then
|
|
+ ubus -S call $ubusobj wps_start '{ "multi_ap": true }' && wps_done=1
|
|
+ else
|
|
+ ubus -S call $ubusobj wps_start && wps_done=1
|
|
+ fi
|
|
+ done
|
|
+ [ $wps_done = 0 ] || wps_catch_credentials &
|
|
+fi
|
|
+
|
|
+return 0
|
|
diff --git a/package/network/services/hostapd/patches/001-wolfssl-init-RNG-with-ECC-key.patch b/package/network/services/hostapd/patches/001-wolfssl-init-RNG-with-ECC-key.patch
|
|
new file mode 100644
|
|
index 0000000000..269dcaac75
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/001-wolfssl-init-RNG-with-ECC-key.patch
|
|
@@ -0,0 +1,43 @@
|
|
+From 21ce83b4ae2b9563175fdb4fc4312096cc399cf8 Mon Sep 17 00:00:00 2001
|
|
+From: David Bauer <mail@david-bauer.net>
|
|
+Date: Wed, 5 May 2021 00:44:34 +0200
|
|
+Subject: [PATCH] wolfssl: add RNG to EC key
|
|
+
|
|
+Since upstream commit 6467de5a8840 ("Randomize z ordinates in
|
|
+scalar mult when timing resistant") WolfSSL requires a RNG for
|
|
+the EC key when built hardened which is the default.
|
|
+
|
|
+Set the RNG for the EC key to fix connections for OWE clients.
|
|
+
|
|
+Signed-off-by: David Bauer <mail@david-bauer.net>
|
|
+---
|
|
+ src/crypto/crypto_wolfssl.c | 4 ++++
|
|
+ 1 file changed, 4 insertions(+)
|
|
+
|
|
+--- a/src/crypto/crypto_wolfssl.c
|
|
++++ b/src/crypto/crypto_wolfssl.c
|
|
+@@ -1340,6 +1340,7 @@ int ecc_projective_add_point(ecc_point *
|
|
+
|
|
+ struct crypto_ec {
|
|
+ ecc_key key;
|
|
++ WC_RNG rng;
|
|
+ mp_int a;
|
|
+ mp_int prime;
|
|
+ mp_int order;
|
|
+@@ -1394,6 +1395,8 @@ struct crypto_ec * crypto_ec_init(int gr
|
|
+ return NULL;
|
|
+
|
|
+ if (wc_ecc_init(&e->key) != 0 ||
|
|
++ wc_InitRng(&e->rng) != 0 ||
|
|
++ wc_ecc_set_rng(&e->key, &e->rng) != 0 ||
|
|
+ wc_ecc_set_curve(&e->key, 0, curve_id) != 0 ||
|
|
+ mp_init(&e->a) != MP_OKAY ||
|
|
+ mp_init(&e->prime) != MP_OKAY ||
|
|
+@@ -1425,6 +1428,7 @@ void crypto_ec_deinit(struct crypto_ec*
|
|
+ mp_clear(&e->order);
|
|
+ mp_clear(&e->prime);
|
|
+ mp_clear(&e->a);
|
|
++ wc_FreeRng(&e->rng);
|
|
+ wc_ecc_free(&e->key);
|
|
+ os_free(e);
|
|
+ }
|
|
diff --git a/package/network/services/hostapd/patches/010-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch b/package/network/services/hostapd/patches/010-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch
|
|
new file mode 100644
|
|
index 0000000000..0a51c84d21
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/010-mesh-Allow-DFS-channels-to-be-selected-if-dfs-is-ena.patch
|
|
@@ -0,0 +1,135 @@
|
|
+From 8de8cd8380af0c43d4fde67a668d79ef73b26b26 Mon Sep 17 00:00:00 2001
|
|
+From: Peter Oh <peter.oh@bowerswilkins.com>
|
|
+Date: Tue, 30 Jun 2020 14:18:58 +0200
|
|
+Subject: [PATCH 10/19] mesh: Allow DFS channels to be selected if dfs is
|
|
+ enabled
|
|
+
|
|
+Note: DFS is assumed to be usable if a country code has been set
|
|
+
|
|
+Signed-off-by: Benjamin Berg <benjamin@sipsolutions.net>
|
|
+Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
|
|
+---
|
|
+ wpa_supplicant/wpa_supplicant.c | 25 +++++++++++++++++++------
|
|
+ 1 file changed, 19 insertions(+), 6 deletions(-)
|
|
+
|
|
+--- a/wpa_supplicant/wpa_supplicant.c
|
|
++++ b/wpa_supplicant/wpa_supplicant.c
|
|
+@@ -2638,7 +2638,7 @@ static int drv_supports_vht(struct wpa_s
|
|
+ }
|
|
+
|
|
+
|
|
+-static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode)
|
|
++static bool ibss_mesh_is_80mhz_avail(int channel, struct hostapd_hw_modes *mode, bool dfs_enabled)
|
|
+ {
|
|
+ int i;
|
|
+
|
|
+@@ -2647,7 +2647,10 @@ static bool ibss_mesh_is_80mhz_avail(int
|
|
+
|
|
+ chan = hw_get_channel_chan(mode, i, NULL);
|
|
+ if (!chan ||
|
|
+- chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
|
|
++ chan->flag & HOSTAPD_CHAN_DISABLED)
|
|
++ return false;
|
|
++
|
|
++ if (!dfs_enabled && chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+@@ -2774,7 +2777,7 @@ static void ibss_mesh_select_40mhz(struc
|
|
+ const struct wpa_ssid *ssid,
|
|
+ struct hostapd_hw_modes *mode,
|
|
+ struct hostapd_freq_params *freq,
|
|
+- int obss_scan) {
|
|
++ int obss_scan, bool dfs_enabled) {
|
|
+ int chan_idx;
|
|
+ struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
|
|
+ int i, res;
|
|
+@@ -2798,8 +2801,11 @@ static void ibss_mesh_select_40mhz(struc
|
|
+ return;
|
|
+
|
|
+ /* Check primary channel flags */
|
|
+- if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
|
|
++ if (pri_chan->flag & HOSTAPD_CHAN_DISABLED)
|
|
+ return;
|
|
++ if (pri_chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
|
|
++ if (!dfs_enabled)
|
|
++ return;
|
|
+
|
|
+ #ifdef CONFIG_HT_OVERRIDES
|
|
+ if (ssid->disable_ht40)
|
|
+@@ -2825,8 +2831,11 @@ static void ibss_mesh_select_40mhz(struc
|
|
+ return;
|
|
+
|
|
+ /* Check secondary channel flags */
|
|
+- if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR))
|
|
++ if (sec_chan->flag & HOSTAPD_CHAN_DISABLED)
|
|
+ return;
|
|
++ if (sec_chan->flag & (HOSTAPD_CHAN_RADAR | HOSTAPD_CHAN_NO_IR))
|
|
++ if (!dfs_enabled)
|
|
++ return;
|
|
+
|
|
+ if (ht40 == -1) {
|
|
+ if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
|
|
+@@ -2880,7 +2889,7 @@ static bool ibss_mesh_select_80_160mhz(s
|
|
+ const struct wpa_ssid *ssid,
|
|
+ struct hostapd_hw_modes *mode,
|
|
+ struct hostapd_freq_params *freq,
|
|
+- int ieee80211_mode, bool is_6ghz) {
|
|
++ int ieee80211_mode, bool is_6ghz, bool dfs_enabled) {
|
|
+ static const int bw80[] = {
|
|
+ 5180, 5260, 5500, 5580, 5660, 5745, 5825,
|
|
+ 5955, 6035, 6115, 6195, 6275, 6355, 6435,
|
|
+@@ -2925,7 +2934,7 @@ static bool ibss_mesh_select_80_160mhz(s
|
|
+ goto skip_80mhz;
|
|
+
|
|
+ /* Use 40 MHz if channel not usable */
|
|
+- if (!ibss_mesh_is_80mhz_avail(channel, mode))
|
|
++ if (!ibss_mesh_is_80mhz_avail(channel, mode, dfs_enabled))
|
|
+ goto skip_80mhz;
|
|
+
|
|
+ chwidth = CONF_OPER_CHWIDTH_80MHZ;
|
|
+@@ -2939,7 +2948,7 @@ static bool ibss_mesh_select_80_160mhz(s
|
|
+ if ((mode->he_capab[ieee80211_mode].phy_cap[
|
|
+ HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &
|
|
+ HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G) && is_6ghz &&
|
|
+- ibss_mesh_is_80mhz_avail(channel + 16, mode)) {
|
|
++ ibss_mesh_is_80mhz_avail(channel + 16, mode, dfs_enabled)) {
|
|
+ for (j = 0; j < ARRAY_SIZE(bw160); j++) {
|
|
+ if (freq->freq == bw160[j]) {
|
|
+ chwidth = CONF_OPER_CHWIDTH_160MHZ;
|
|
+@@ -2967,10 +2976,12 @@ static bool ibss_mesh_select_80_160mhz(s
|
|
+ if (!chan)
|
|
+ continue;
|
|
+
|
|
+- if (chan->flag & (HOSTAPD_CHAN_DISABLED |
|
|
+- HOSTAPD_CHAN_NO_IR |
|
|
+- HOSTAPD_CHAN_RADAR))
|
|
++ if (chan->flag & HOSTAPD_CHAN_DISABLED)
|
|
+ continue;
|
|
++ if (chan->flag & (HOSTAPD_CHAN_RADAR |
|
|
++ HOSTAPD_CHAN_NO_IR))
|
|
++ if (!dfs_enabled)
|
|
++ continue;
|
|
+
|
|
+ /* Found a suitable second segment for 80+80 */
|
|
+ chwidth = CONF_OPER_CHWIDTH_80P80MHZ;
|
|
+@@ -3025,6 +3036,7 @@ void ibss_mesh_setup_freq(struct wpa_sup
|
|
+ int i, obss_scan = 1;
|
|
+ u8 channel;
|
|
+ bool is_6ghz;
|
|
++ bool dfs_enabled = wpa_s->conf->country[0] && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_RADAR);
|
|
+
|
|
+ freq->freq = ssid->frequency;
|
|
+
|
|
+@@ -3070,9 +3082,9 @@ void ibss_mesh_setup_freq(struct wpa_sup
|
|
+ freq->channel = channel;
|
|
+ /* Setup higher BW only for 5 GHz */
|
|
+ if (mode->mode == HOSTAPD_MODE_IEEE80211A) {
|
|
+- ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan);
|
|
++ ibss_mesh_select_40mhz(wpa_s, ssid, mode, freq, obss_scan, dfs_enabled);
|
|
+ if (!ibss_mesh_select_80_160mhz(wpa_s, ssid, mode, freq,
|
|
+- ieee80211_mode, is_6ghz))
|
|
++ ieee80211_mode, is_6ghz, dfs_enabled))
|
|
+ freq->he_enabled = freq->vht_enabled = false;
|
|
+ }
|
|
+
|
|
diff --git a/package/network/services/hostapd/patches/011-mesh-use-deterministic-channel-on-channel-switch.patch b/package/network/services/hostapd/patches/011-mesh-use-deterministic-channel-on-channel-switch.patch
|
|
new file mode 100644
|
|
index 0000000000..9b11f0e803
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/011-mesh-use-deterministic-channel-on-channel-switch.patch
|
|
@@ -0,0 +1,81 @@
|
|
+From fc8ea40f6130ac18d9c66797de2cf1d5af55d496 Mon Sep 17 00:00:00 2001
|
|
+From: Markus Theil <markus.theil@tu-ilmenau.de>
|
|
+Date: Tue, 30 Jun 2020 14:19:07 +0200
|
|
+Subject: [PATCH 19/19] mesh: use deterministic channel on channel switch
|
|
+
|
|
+This patch uses a deterministic channel on DFS channel switch
|
|
+in mesh networks. Otherwise, when switching to a usable but not
|
|
+available channel, no CSA can be sent and a random channel is choosen
|
|
+without notification of other nodes. It is then quite likely, that
|
|
+the mesh network gets disconnected.
|
|
+
|
|
+Fix this by using a deterministic number, based on the sha256 hash
|
|
+of the mesh ID, in order to use at least a different number in each
|
|
+mesh network.
|
|
+
|
|
+Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
|
|
+---
|
|
+ src/ap/dfs.c | 20 +++++++++++++++++++-
|
|
+ src/drivers/driver_nl80211.c | 4 ++++
|
|
+ 2 files changed, 23 insertions(+), 1 deletion(-)
|
|
+
|
|
+--- a/src/ap/dfs.c
|
|
++++ b/src/ap/dfs.c
|
|
+@@ -17,6 +17,7 @@
|
|
+ #include "ap_drv_ops.h"
|
|
+ #include "drivers/driver.h"
|
|
+ #include "dfs.h"
|
|
++#include "crypto/crypto.h"
|
|
+
|
|
+
|
|
+ enum dfs_channel_type {
|
|
+@@ -521,9 +522,14 @@ dfs_get_valid_channel(struct hostapd_ifa
|
|
+ int num_available_chandefs;
|
|
+ int chan_idx, chan_idx2;
|
|
+ int sec_chan_idx_80p80 = -1;
|
|
++ bool is_mesh = false;
|
|
+ int i;
|
|
+ u32 _rand;
|
|
+
|
|
++#ifdef CONFIG_MESH
|
|
++ is_mesh = iface->mconf;
|
|
++#endif
|
|
++
|
|
+ wpa_printf(MSG_DEBUG, "DFS: Selecting random channel");
|
|
+ *secondary_channel = 0;
|
|
+ *oper_centr_freq_seg0_idx = 0;
|
|
+@@ -543,8 +549,20 @@ dfs_get_valid_channel(struct hostapd_ifa
|
|
+ if (num_available_chandefs == 0)
|
|
+ return NULL;
|
|
+
|
|
+- if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
|
|
++ /* try to use deterministic channel in mesh, so that both sides
|
|
++ * have a chance to switch to the same channel */
|
|
++ if (is_mesh) {
|
|
++#ifdef CONFIG_MESH
|
|
++ u64 hash[4];
|
|
++ const u8 *meshid[1] = { &iface->mconf->meshid[0] };
|
|
++ const size_t meshid_len = iface->mconf->meshid_len;
|
|
++
|
|
++ sha256_vector(1, meshid, &meshid_len, (u8 *)&hash[0]);
|
|
++ _rand = hash[0] + hash[1] + hash[2] + hash[3];
|
|
++#endif
|
|
++ } else if (os_get_random((u8 *) &_rand, sizeof(_rand)) < 0)
|
|
+ return NULL;
|
|
++
|
|
+ chan_idx = _rand % num_available_chandefs;
|
|
+ dfs_find_channel(iface, &chan, chan_idx, type);
|
|
+ if (!chan) {
|
|
+--- a/src/drivers/driver_nl80211.c
|
|
++++ b/src/drivers/driver_nl80211.c
|
|
+@@ -10977,6 +10977,10 @@ static int nl80211_switch_channel(void *
|
|
+ if (ret)
|
|
+ goto error;
|
|
+
|
|
++ if (drv->nlmode == NL80211_IFTYPE_MESH_POINT) {
|
|
++ nla_put_flag(msg, NL80211_ATTR_HANDLE_DFS);
|
|
++ }
|
|
++
|
|
+ /* beacon_csa params */
|
|
+ beacon_csa = nla_nest_start(msg, NL80211_ATTR_CSA_IES);
|
|
+ if (!beacon_csa)
|
|
diff --git a/package/network/services/hostapd/patches/021-fix-sta-add-after-previous-connection.patch b/package/network/services/hostapd/patches/021-fix-sta-add-after-previous-connection.patch
|
|
new file mode 100644
|
|
index 0000000000..4ee43b5186
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/021-fix-sta-add-after-previous-connection.patch
|
|
@@ -0,0 +1,26 @@
|
|
+--- a/src/ap/ieee802_11.c
|
|
++++ b/src/ap/ieee802_11.c
|
|
+@@ -4601,6 +4601,13 @@ static int add_associated_sta(struct hos
|
|
+ * drivers to accept the STA parameter configuration. Since this is
|
|
+ * after a new FT-over-DS exchange, a new TK has been derived, so key
|
|
+ * reinstallation is not a concern for this case.
|
|
++ *
|
|
++ * If the STA was associated and authorized earlier, but came for a new
|
|
++ * connection (!added_unassoc + !reassoc), remove the existing STA entry
|
|
++ * so that it can be re-added. This case is rarely seen when the AP could
|
|
++ * not receive the deauth/disassoc frame from the STA. And the STA comes
|
|
++ * back with new connection within a short period or before the inactive
|
|
++ * STA entry is removed from the list.
|
|
+ */
|
|
+ wpa_printf(MSG_DEBUG, "Add associated STA " MACSTR
|
|
+ " (added_unassoc=%d auth_alg=%u ft_over_ds=%u reassoc=%d authorized=%d ft_tk=%d fils_tk=%d)",
|
|
+@@ -4614,7 +4621,8 @@ static int add_associated_sta(struct hos
|
|
+ (!(sta->flags & WLAN_STA_AUTHORIZED) ||
|
|
+ (reassoc && sta->ft_over_ds && sta->auth_alg == WLAN_AUTH_FT) ||
|
|
+ (!wpa_auth_sta_ft_tk_already_set(sta->wpa_sm) &&
|
|
+- !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)))) {
|
|
++ !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)) ||
|
|
++ (!reassoc && (sta->flags & WLAN_STA_AUTHORIZED)))) {
|
|
+ hostapd_drv_sta_remove(hapd, sta->addr);
|
|
+ wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED);
|
|
+ set = 0;
|
|
diff --git a/package/network/services/hostapd/patches/022-hostapd-fix-use-of-uninitialized-stack-variables.patch b/package/network/services/hostapd/patches/022-hostapd-fix-use-of-uninitialized-stack-variables.patch
|
|
new file mode 100644
|
|
index 0000000000..8dec325c98
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/022-hostapd-fix-use-of-uninitialized-stack-variables.patch
|
|
@@ -0,0 +1,25 @@
|
|
+From: Felix Fietkau <nbd@nbd.name>
|
|
+Date: Thu, 8 Jul 2021 16:33:03 +0200
|
|
+Subject: [PATCH] hostapd: fix use of uninitialized stack variables
|
|
+
|
|
+When a CSA is performed on an 80 MHz channel, hostapd_change_config_freq
|
|
+unconditionally calls hostapd_set_oper_centr_freq_seg0/1_idx with seg0/1
|
|
+filled by ieee80211_freq_to_chan.
|
|
+However, if ieee80211_freq_to_chan fails (because the freq is 0 or invalid),
|
|
+seg0/1 remains uninitialized and filled with stack garbage, causing errors
|
|
+such as "hostapd: 80 MHz: center segment 1 configured"
|
|
+
|
|
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
+---
|
|
+
|
|
+--- a/src/ap/hostapd.c
|
|
++++ b/src/ap/hostapd.c
|
|
+@@ -3764,7 +3764,7 @@ static int hostapd_change_config_freq(st
|
|
+ struct hostapd_freq_params *old_params)
|
|
+ {
|
|
+ int channel;
|
|
+- u8 seg0, seg1;
|
|
++ u8 seg0 = 0, seg1 = 0;
|
|
+ struct hostapd_hw_modes *mode;
|
|
+
|
|
+ if (!params->channel) {
|
|
diff --git a/package/network/services/hostapd/patches/023-ndisc_snoop-call-dl_list_del-before-freeing-ipv6-add.patch b/package/network/services/hostapd/patches/023-ndisc_snoop-call-dl_list_del-before-freeing-ipv6-add.patch
|
|
new file mode 100644
|
|
index 0000000000..9ff9b2398d
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/023-ndisc_snoop-call-dl_list_del-before-freeing-ipv6-add.patch
|
|
@@ -0,0 +1,19 @@
|
|
+From: Felix Fietkau <nbd@nbd.name>
|
|
+Date: Wed, 28 Jul 2021 05:43:29 +0200
|
|
+Subject: [PATCH] ndisc_snoop: call dl_list_del before freeing ipv6 addresses
|
|
+
|
|
+Fixes a segmentation fault on sta disconnect
|
|
+
|
|
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
+---
|
|
+
|
|
+--- a/src/ap/ndisc_snoop.c
|
|
++++ b/src/ap/ndisc_snoop.c
|
|
+@@ -61,6 +61,7 @@ void sta_ip6addr_del(struct hostapd_data
|
|
+ dl_list_for_each_safe(ip6addr, prev, &sta->ip6addr, struct ip6addr,
|
|
+ list) {
|
|
+ hostapd_drv_br_delete_ip_neigh(hapd, 6, (u8 *) &ip6addr->addr);
|
|
++ dl_list_del(&ip6addr->list);
|
|
+ os_free(ip6addr);
|
|
+ }
|
|
+ }
|
|
diff --git a/package/network/services/hostapd/patches/030-driver_nl80211-rewrite-neigh-code-to-not-depend-on-l.patch b/package/network/services/hostapd/patches/030-driver_nl80211-rewrite-neigh-code-to-not-depend-on-l.patch
|
|
new file mode 100644
|
|
index 0000000000..19248e80d8
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/030-driver_nl80211-rewrite-neigh-code-to-not-depend-on-l.patch
|
|
@@ -0,0 +1,275 @@
|
|
+From: Felix Fietkau <nbd@nbd.name>
|
|
+Date: Wed, 28 Jul 2021 05:49:46 +0200
|
|
+Subject: [PATCH] driver_nl80211: rewrite neigh code to not depend on
|
|
+ libnl3-route
|
|
+
|
|
+Removes an unnecessary dependency and also makes the code smaller
|
|
+
|
|
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
+---
|
|
+
|
|
+--- a/src/drivers/driver_nl80211.c
|
|
++++ b/src/drivers/driver_nl80211.c
|
|
+@@ -16,9 +16,6 @@
|
|
+ #include <net/if.h>
|
|
+ #include <netlink/genl/genl.h>
|
|
+ #include <netlink/genl/ctrl.h>
|
|
+-#ifdef CONFIG_LIBNL3_ROUTE
|
|
+-#include <netlink/route/neighbour.h>
|
|
+-#endif /* CONFIG_LIBNL3_ROUTE */
|
|
+ #include <linux/rtnetlink.h>
|
|
+ #include <netpacket/packet.h>
|
|
+ #include <linux/errqueue.h>
|
|
+@@ -5783,26 +5780,29 @@ fail:
|
|
+
|
|
+ static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr)
|
|
+ {
|
|
+-#ifdef CONFIG_LIBNL3_ROUTE
|
|
+ struct wpa_driver_nl80211_data *drv = bss->drv;
|
|
+- struct rtnl_neigh *rn;
|
|
+- struct nl_addr *nl_addr;
|
|
++ struct ndmsg nhdr = {
|
|
++ .ndm_state = NUD_PERMANENT,
|
|
++ .ndm_ifindex = bss->ifindex,
|
|
++ .ndm_family = AF_BRIDGE,
|
|
++ };
|
|
++ struct nl_msg *msg;
|
|
+ int err;
|
|
+
|
|
+- rn = rtnl_neigh_alloc();
|
|
+- if (!rn)
|
|
++ msg = nlmsg_alloc_simple(RTM_DELNEIGH, NLM_F_CREATE);
|
|
++ if (!msg)
|
|
+ return;
|
|
+
|
|
+- rtnl_neigh_set_family(rn, AF_BRIDGE);
|
|
+- rtnl_neigh_set_ifindex(rn, bss->ifindex);
|
|
+- nl_addr = nl_addr_build(AF_BRIDGE, (void *) addr, ETH_ALEN);
|
|
+- if (!nl_addr) {
|
|
+- rtnl_neigh_put(rn);
|
|
+- return;
|
|
+- }
|
|
+- rtnl_neigh_set_lladdr(rn, nl_addr);
|
|
++ if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0)
|
|
++ goto errout;
|
|
++
|
|
++ if (nla_put(msg, NDA_LLADDR, ETH_ALEN, (void *)addr))
|
|
++ goto errout;
|
|
++
|
|
++ if (nl_send_auto_complete(drv->rtnl_sk, msg) < 0)
|
|
++ goto errout;
|
|
+
|
|
+- err = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
|
|
++ err = nl_wait_for_ack(drv->rtnl_sk);
|
|
+ if (err < 0) {
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for "
|
|
+ MACSTR " ifindex=%d failed: %s", MAC2STR(addr),
|
|
+@@ -5812,9 +5812,8 @@ static void rtnl_neigh_delete_fdb_entry(
|
|
+ MACSTR, MAC2STR(addr));
|
|
+ }
|
|
+
|
|
+- nl_addr_put(nl_addr);
|
|
+- rtnl_neigh_put(rn);
|
|
+-#endif /* CONFIG_LIBNL3_ROUTE */
|
|
++errout:
|
|
++ nlmsg_free(msg);
|
|
+ }
|
|
+
|
|
+
|
|
+@@ -8492,7 +8491,6 @@ static void *i802_init(struct hostapd_da
|
|
+ (params->num_bridge == 0 || !params->bridge[0]))
|
|
+ add_ifidx(drv, br_ifindex, drv->ifindex);
|
|
+
|
|
+-#ifdef CONFIG_LIBNL3_ROUTE
|
|
+ if (bss->added_if_into_bridge || bss->already_in_bridge) {
|
|
+ int err;
|
|
+
|
|
+@@ -8509,7 +8507,6 @@ static void *i802_init(struct hostapd_da
|
|
+ goto failed;
|
|
+ }
|
|
+ }
|
|
+-#endif /* CONFIG_LIBNL3_ROUTE */
|
|
+
|
|
+ if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) {
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+@@ -11843,13 +11840,14 @@ static int wpa_driver_br_add_ip_neigh(vo
|
|
+ const u8 *ipaddr, int prefixlen,
|
|
+ const u8 *addr)
|
|
+ {
|
|
+-#ifdef CONFIG_LIBNL3_ROUTE
|
|
+ struct i802_bss *bss = priv;
|
|
+ struct wpa_driver_nl80211_data *drv = bss->drv;
|
|
+- struct rtnl_neigh *rn;
|
|
+- struct nl_addr *nl_ipaddr = NULL;
|
|
+- struct nl_addr *nl_lladdr = NULL;
|
|
+- int family, addrsize;
|
|
++ struct ndmsg nhdr = {
|
|
++ .ndm_state = NUD_PERMANENT,
|
|
++ .ndm_ifindex = bss->br_ifindex,
|
|
++ };
|
|
++ struct nl_msg *msg;
|
|
++ int addrsize;
|
|
+ int res;
|
|
+
|
|
+ if (!ipaddr || prefixlen == 0 || !addr)
|
|
+@@ -11868,85 +11866,66 @@ static int wpa_driver_br_add_ip_neigh(vo
|
|
+ }
|
|
+
|
|
+ if (version == 4) {
|
|
+- family = AF_INET;
|
|
++ nhdr.ndm_family = AF_INET;
|
|
+ addrsize = 4;
|
|
+ } else if (version == 6) {
|
|
+- family = AF_INET6;
|
|
++ nhdr.ndm_family = AF_INET6;
|
|
+ addrsize = 16;
|
|
+ } else {
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+- rn = rtnl_neigh_alloc();
|
|
+- if (rn == NULL)
|
|
++ msg = nlmsg_alloc_simple(RTM_NEWNEIGH, NLM_F_CREATE);
|
|
++ if (!msg)
|
|
+ return -ENOMEM;
|
|
+
|
|
+- /* set the destination ip address for neigh */
|
|
+- nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
|
|
+- if (nl_ipaddr == NULL) {
|
|
+- wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
|
|
+- res = -ENOMEM;
|
|
++ res = -ENOMEM;
|
|
++ if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0)
|
|
+ goto errout;
|
|
+- }
|
|
+- nl_addr_set_prefixlen(nl_ipaddr, prefixlen);
|
|
+- res = rtnl_neigh_set_dst(rn, nl_ipaddr);
|
|
+- if (res) {
|
|
+- wpa_printf(MSG_DEBUG,
|
|
+- "nl80211: neigh set destination addr failed");
|
|
++
|
|
++ if (nla_put(msg, NDA_DST, addrsize, (void *)ipaddr))
|
|
+ goto errout;
|
|
+- }
|
|
+
|
|
+- /* set the corresponding lladdr for neigh */
|
|
+- nl_lladdr = nl_addr_build(AF_BRIDGE, (u8 *) addr, ETH_ALEN);
|
|
+- if (nl_lladdr == NULL) {
|
|
+- wpa_printf(MSG_DEBUG, "nl80211: neigh set lladdr failed");
|
|
+- res = -ENOMEM;
|
|
++ if (nla_put(msg, NDA_LLADDR, ETH_ALEN, (void *)addr))
|
|
+ goto errout;
|
|
+- }
|
|
+- rtnl_neigh_set_lladdr(rn, nl_lladdr);
|
|
+
|
|
+- rtnl_neigh_set_ifindex(rn, bss->br_ifindex);
|
|
+- rtnl_neigh_set_state(rn, NUD_PERMANENT);
|
|
++ res = nl_send_auto_complete(drv->rtnl_sk, msg);
|
|
++ if (res < 0)
|
|
++ goto errout;
|
|
+
|
|
+- res = rtnl_neigh_add(drv->rtnl_sk, rn, NLM_F_CREATE);
|
|
++ res = nl_wait_for_ack(drv->rtnl_sk);
|
|
+ if (res) {
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "nl80211: Adding bridge ip neigh failed: %s",
|
|
+ nl_geterror(res));
|
|
+ }
|
|
+ errout:
|
|
+- if (nl_lladdr)
|
|
+- nl_addr_put(nl_lladdr);
|
|
+- if (nl_ipaddr)
|
|
+- nl_addr_put(nl_ipaddr);
|
|
+- if (rn)
|
|
+- rtnl_neigh_put(rn);
|
|
++ nlmsg_free(msg);
|
|
+ return res;
|
|
+-#else /* CONFIG_LIBNL3_ROUTE */
|
|
+- return -1;
|
|
+-#endif /* CONFIG_LIBNL3_ROUTE */
|
|
+ }
|
|
+
|
|
+
|
|
+ static int wpa_driver_br_delete_ip_neigh(void *priv, u8 version,
|
|
+ const u8 *ipaddr)
|
|
+ {
|
|
+-#ifdef CONFIG_LIBNL3_ROUTE
|
|
+ struct i802_bss *bss = priv;
|
|
+ struct wpa_driver_nl80211_data *drv = bss->drv;
|
|
+- struct rtnl_neigh *rn;
|
|
+- struct nl_addr *nl_ipaddr;
|
|
+- int family, addrsize;
|
|
++ struct ndmsg nhdr = {
|
|
++ .ndm_state = NUD_PERMANENT,
|
|
++ .ndm_ifindex = bss->br_ifindex,
|
|
++ };
|
|
++ struct nl_msg *msg;
|
|
++ int addrsize;
|
|
+ int res;
|
|
+
|
|
+ if (!ipaddr)
|
|
+ return -EINVAL;
|
|
+
|
|
+ if (version == 4) {
|
|
+- family = AF_INET;
|
|
++ nhdr.ndm_family = AF_INET;
|
|
+ addrsize = 4;
|
|
+ } else if (version == 6) {
|
|
+- family = AF_INET6;
|
|
++ nhdr.ndm_family = AF_INET6;
|
|
+ addrsize = 16;
|
|
+ } else {
|
|
+ return -EINVAL;
|
|
+@@ -11964,41 +11943,30 @@ static int wpa_driver_br_delete_ip_neigh
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+- rn = rtnl_neigh_alloc();
|
|
+- if (rn == NULL)
|
|
++ msg = nlmsg_alloc_simple(RTM_DELNEIGH, NLM_F_CREATE);
|
|
++ if (!msg)
|
|
+ return -ENOMEM;
|
|
+
|
|
+- /* set the destination ip address for neigh */
|
|
+- nl_ipaddr = nl_addr_build(family, (void *) ipaddr, addrsize);
|
|
+- if (nl_ipaddr == NULL) {
|
|
+- wpa_printf(MSG_DEBUG, "nl80211: nl_ipaddr build failed");
|
|
+- res = -ENOMEM;
|
|
++ res = -ENOMEM;
|
|
++ if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0)
|
|
+ goto errout;
|
|
+- }
|
|
+- res = rtnl_neigh_set_dst(rn, nl_ipaddr);
|
|
+- if (res) {
|
|
+- wpa_printf(MSG_DEBUG,
|
|
+- "nl80211: neigh set destination addr failed");
|
|
++
|
|
++ if (nla_put(msg, NDA_DST, addrsize, (void *)ipaddr))
|
|
+ goto errout;
|
|
+- }
|
|
+
|
|
+- rtnl_neigh_set_ifindex(rn, bss->br_ifindex);
|
|
++ res = nl_send_auto_complete(drv->rtnl_sk, msg);
|
|
++ if (res < 0)
|
|
++ goto errout;
|
|
+
|
|
+- res = rtnl_neigh_delete(drv->rtnl_sk, rn, 0);
|
|
++ res = nl_wait_for_ack(drv->rtnl_sk);
|
|
+ if (res) {
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "nl80211: Deleting bridge ip neigh failed: %s",
|
|
+ nl_geterror(res));
|
|
+ }
|
|
+ errout:
|
|
+- if (nl_ipaddr)
|
|
+- nl_addr_put(nl_ipaddr);
|
|
+- if (rn)
|
|
+- rtnl_neigh_put(rn);
|
|
++ nlmsg_free(msg);
|
|
+ return res;
|
|
+-#else /* CONFIG_LIBNL3_ROUTE */
|
|
+- return -1;
|
|
+-#endif /* CONFIG_LIBNL3_ROUTE */
|
|
+ }
|
|
+
|
|
+
|
|
diff --git a/package/network/services/hostapd/patches/040-mesh-allow-processing-authentication-frames-in-block.patch b/package/network/services/hostapd/patches/040-mesh-allow-processing-authentication-frames-in-block.patch
|
|
new file mode 100644
|
|
index 0000000000..f98d3806dc
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/040-mesh-allow-processing-authentication-frames-in-block.patch
|
|
@@ -0,0 +1,34 @@
|
|
+From: Felix Fietkau <nbd@nbd.name>
|
|
+Date: Mon, 18 Feb 2019 12:57:11 +0100
|
|
+Subject: [PATCH] mesh: allow processing authentication frames in blocked state
|
|
+
|
|
+If authentication fails repeatedly e.g. because of a weak signal, the link
|
|
+can end up in blocked state. If one of the nodes tries to establish a link
|
|
+again before it is unblocked on the other side, it will block the link to
|
|
+that other side. The same happens on the other side when it unblocks the
|
|
+link. In that scenario, the link never recovers on its own.
|
|
+
|
|
+To fix this, allow restarting authentication even if the link is in blocked
|
|
+state, but don't initiate the attempt until the blocked period is over.
|
|
+
|
|
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
+---
|
|
+
|
|
+--- a/src/ap/ieee802_11.c
|
|
++++ b/src/ap/ieee802_11.c
|
|
+@@ -3012,15 +3012,6 @@ static void handle_auth(struct hostapd_d
|
|
+ seq_ctrl);
|
|
+ return;
|
|
+ }
|
|
+-#ifdef CONFIG_MESH
|
|
+- if ((hapd->conf->mesh & MESH_ENABLED) &&
|
|
+- sta->plink_state == PLINK_BLOCKED) {
|
|
+- wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
|
|
+- " is blocked - drop Authentication frame",
|
|
+- MAC2STR(sa));
|
|
+- return;
|
|
+- }
|
|
+-#endif /* CONFIG_MESH */
|
|
+ #ifdef CONFIG_PASN
|
|
+ if (auth_alg == WLAN_AUTH_PASN &&
|
|
+ (sta->flags & WLAN_STA_ASSOC)) {
|
|
diff --git a/package/network/services/hostapd/patches/050-build_fix.patch b/package/network/services/hostapd/patches/050-build_fix.patch
|
|
new file mode 100644
|
|
index 0000000000..8680b07c66
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/050-build_fix.patch
|
|
@@ -0,0 +1,20 @@
|
|
+--- a/hostapd/Makefile
|
|
++++ b/hostapd/Makefile
|
|
+@@ -324,6 +324,7 @@ ifdef CONFIG_FILS
|
|
+ CFLAGS += -DCONFIG_FILS
|
|
+ OBJS += ../src/ap/fils_hlp.o
|
|
+ NEED_SHA384=y
|
|
++NEED_HMAC_SHA384_KDF=y
|
|
+ NEED_AES_SIV=y
|
|
+ ifdef CONFIG_FILS_SK_PFS
|
|
+ CFLAGS += -DCONFIG_FILS_SK_PFS
|
|
+--- a/wpa_supplicant/Makefile
|
|
++++ b/wpa_supplicant/Makefile
|
|
+@@ -331,6 +331,7 @@ endif
|
|
+ ifdef CONFIG_FILS
|
|
+ CFLAGS += -DCONFIG_FILS
|
|
+ NEED_SHA384=y
|
|
++NEED_HMAC_SHA384_KDF=y
|
|
+ NEED_AES_SIV=y
|
|
+ ifdef CONFIG_FILS_SK_PFS
|
|
+ CFLAGS += -DCONFIG_FILS_SK_PFS
|
|
diff --git a/package/network/services/hostapd/patches/100-daemonize_fix.patch b/package/network/services/hostapd/patches/100-daemonize_fix.patch
|
|
new file mode 100644
|
|
index 0000000000..687bd4082d
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/100-daemonize_fix.patch
|
|
@@ -0,0 +1,97 @@
|
|
+--- a/src/utils/os_unix.c
|
|
++++ b/src/utils/os_unix.c
|
|
+@@ -10,6 +10,7 @@
|
|
+
|
|
+ #include <time.h>
|
|
+ #include <sys/wait.h>
|
|
++#include <fcntl.h>
|
|
+
|
|
+ #ifdef ANDROID
|
|
+ #include <sys/capability.h>
|
|
+@@ -188,59 +189,46 @@ int os_gmtime(os_time_t t, struct os_tm
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+-
|
|
+-#ifdef __APPLE__
|
|
+-#include <fcntl.h>
|
|
+-static int os_daemon(int nochdir, int noclose)
|
|
++int os_daemonize(const char *pid_file)
|
|
+ {
|
|
+- int devnull;
|
|
++ int pid = 0, i, devnull;
|
|
+
|
|
+- if (chdir("/") < 0)
|
|
+- return -1;
|
|
++#if defined(__uClinux__) || defined(__sun__)
|
|
++ return -1;
|
|
++#else /* defined(__uClinux__) || defined(__sun__) */
|
|
+
|
|
+- devnull = open("/dev/null", O_RDWR);
|
|
+- if (devnull < 0)
|
|
++#ifndef __APPLE__
|
|
++ pid = fork();
|
|
++ if (pid < 0)
|
|
+ return -1;
|
|
++#endif
|
|
+
|
|
+- if (dup2(devnull, STDIN_FILENO) < 0) {
|
|
+- close(devnull);
|
|
+- return -1;
|
|
++ if (pid > 0) {
|
|
++ if (pid_file) {
|
|
++ FILE *f = fopen(pid_file, "w");
|
|
++ if (f) {
|
|
++ fprintf(f, "%u\n", pid);
|
|
++ fclose(f);
|
|
++ }
|
|
++ }
|
|
++ _exit(0);
|
|
+ }
|
|
+
|
|
+- if (dup2(devnull, STDOUT_FILENO) < 0) {
|
|
+- close(devnull);
|
|
++ if (setsid() < 0)
|
|
+ return -1;
|
|
+- }
|
|
+
|
|
+- if (dup2(devnull, STDERR_FILENO) < 0) {
|
|
+- close(devnull);
|
|
++ if (chdir("/") < 0)
|
|
+ return -1;
|
|
+- }
|
|
+-
|
|
+- return 0;
|
|
+-}
|
|
+-#else /* __APPLE__ */
|
|
+-#define os_daemon daemon
|
|
+-#endif /* __APPLE__ */
|
|
+
|
|
+-
|
|
+-int os_daemonize(const char *pid_file)
|
|
+-{
|
|
+-#if defined(__uClinux__) || defined(__sun__)
|
|
+- return -1;
|
|
+-#else /* defined(__uClinux__) || defined(__sun__) */
|
|
+- if (os_daemon(0, 0)) {
|
|
+- perror("daemon");
|
|
++ devnull = open("/dev/null", O_RDWR);
|
|
++ if (devnull < 0)
|
|
+ return -1;
|
|
+- }
|
|
+
|
|
+- if (pid_file) {
|
|
+- FILE *f = fopen(pid_file, "w");
|
|
+- if (f) {
|
|
+- fprintf(f, "%u\n", getpid());
|
|
+- fclose(f);
|
|
+- }
|
|
+- }
|
|
++ for (i = 0; i <= STDERR_FILENO; i++)
|
|
++ dup2(devnull, i);
|
|
++
|
|
++ if (devnull > 2)
|
|
++ close(devnull);
|
|
+
|
|
+ return -0;
|
|
+ #endif /* defined(__uClinux__) || defined(__sun__) */
|
|
diff --git a/package/network/services/hostapd/patches/110-mbedtls-TLS-crypto-option-initial-port.patch b/package/network/services/hostapd/patches/110-mbedtls-TLS-crypto-option-initial-port.patch
|
|
new file mode 100644
|
|
index 0000000000..22107944dc
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/110-mbedtls-TLS-crypto-option-initial-port.patch
|
|
@@ -0,0 +1,8051 @@
|
|
+From e16f200dc1d2f69efc78c7c55af0d7b410a981f9 Mon Sep 17 00:00:00 2001
|
|
+From: Glenn Strauss <gstrauss@gluelogic.com>
|
|
+Date: Tue, 5 Jul 2022 02:49:50 -0400
|
|
+Subject: [PATCH 1/7] mbedtls: TLS/crypto option (initial port)
|
|
+
|
|
+Signed-off-by: Glenn Strauss <gstrauss@gluelogic.com>
|
|
+---
|
|
+ hostapd/Makefile | 91 +
|
|
+ hostapd/defconfig | 15 +-
|
|
+ src/crypto/crypto_mbedtls.c | 4043 +++++++++++++++++
|
|
+ src/crypto/tls_mbedtls.c | 3313 ++++++++++++++
|
|
+ .../build/build-wpa_supplicant-mbedtls.config | 24 +
|
|
+ tests/hwsim/example-hostapd.config | 4 +
|
|
+ tests/hwsim/example-wpa_supplicant.config | 4 +
|
|
+ wpa_supplicant/Makefile | 74 +
|
|
+ wpa_supplicant/defconfig | 6 +-
|
|
+ 9 files changed, 7571 insertions(+), 3 deletions(-)
|
|
+ create mode 100644 src/crypto/crypto_mbedtls.c
|
|
+ create mode 100644 src/crypto/tls_mbedtls.c
|
|
+ create mode 100644 tests/build/build-wpa_supplicant-mbedtls.config
|
|
+
|
|
+--- a/hostapd/Makefile
|
|
++++ b/hostapd/Makefile
|
|
+@@ -745,6 +745,40 @@ endif
|
|
+ CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\"
|
|
+ endif
|
|
+
|
|
++ifeq ($(CONFIG_TLS), mbedtls)
|
|
++ifndef CONFIG_CRYPTO
|
|
++CONFIG_CRYPTO=mbedtls
|
|
++endif
|
|
++ifdef TLS_FUNCS
|
|
++OBJS += ../src/crypto/tls_mbedtls.o
|
|
++LIBS += -lmbedtls
|
|
++ifndef CONFIG_DPP
|
|
++LIBS += -lmbedx509
|
|
++endif
|
|
++endif
|
|
++OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
|
|
++HOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
|
|
++SOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
|
|
++ifdef NEED_FIPS186_2_PRF
|
|
++OBJS += ../src/crypto/fips_prf_internal.o
|
|
++SHA1OBJS += ../src/crypto/sha1-internal.o
|
|
++endif
|
|
++ifeq ($(CONFIG_CRYPTO), mbedtls)
|
|
++ifdef CONFIG_DPP
|
|
++LIBS += -lmbedx509
|
|
++LIBS_h += -lmbedx509
|
|
++LIBS_n += -lmbedx509
|
|
++LIBS_s += -lmbedx509
|
|
++endif
|
|
++LIBS += -lmbedcrypto
|
|
++LIBS_h += -lmbedcrypto
|
|
++LIBS_n += -lmbedcrypto
|
|
++LIBS_s += -lmbedcrypto
|
|
++# XXX: create a config option?
|
|
++CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
|
|
++endif
|
|
++endif
|
|
++
|
|
+ ifeq ($(CONFIG_TLS), gnutls)
|
|
+ ifndef CONFIG_CRYPTO
|
|
+ # default to libgcrypt
|
|
+@@ -924,9 +958,11 @@ endif
|
|
+
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ AESOBJS += ../src/crypto/aes-wrap.o
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_AES_EAX
|
|
+ AESOBJS += ../src/crypto/aes-eax.o
|
|
+ NEED_AES_CTR=y
|
|
+@@ -936,38 +972,48 @@ AESOBJS += ../src/crypto/aes-siv.o
|
|
+ NEED_AES_CTR=y
|
|
+ endif
|
|
+ ifdef NEED_AES_CTR
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ AESOBJS += ../src/crypto/aes-ctr.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_AES_ENCBLOCK
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ AESOBJS += ../src/crypto/aes-encblock.o
|
|
+ endif
|
|
++endif
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ AESOBJS += ../src/crypto/aes-omac1.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_AES_UNWRAP
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ NEED_AES_DEC=y
|
|
+ AESOBJS += ../src/crypto/aes-unwrap.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_AES_CBC
|
|
+ NEED_AES_DEC=y
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ AESOBJS += ../src/crypto/aes-cbc.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_AES_DEC
|
|
+ ifdef CONFIG_INTERNAL_AES
|
|
+ AESOBJS += ../src/crypto/aes-internal-dec.o
|
|
+@@ -982,12 +1028,16 @@ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), gnutls)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA1OBJS += ../src/crypto/sha1.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA1OBJS += ../src/crypto/sha1-prf.o
|
|
++endif
|
|
+ ifdef CONFIG_INTERNAL_SHA1
|
|
+ SHA1OBJS += ../src/crypto/sha1-internal.o
|
|
+ ifdef NEED_FIPS186_2_PRF
|
|
+@@ -996,16 +1046,22 @@ endif
|
|
+ endif
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_T_PRF
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA1OBJS += ../src/crypto/sha1-tprf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_TLS_PRF
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA1OBJS += ../src/crypto/sha1-tlsprf.o
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+
|
|
+ ifdef NEED_SHA1
|
|
+ OBJS += $(SHA1OBJS)
|
|
+@@ -1015,11 +1071,13 @@ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), gnutls)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/md5.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+
|
|
+ ifdef NEED_MD5
|
|
+ ifdef CONFIG_INTERNAL_MD5
|
|
+@@ -1058,56 +1116,81 @@ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), gnutls)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha256.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha256-prf.o
|
|
++endif
|
|
+ ifdef CONFIG_INTERNAL_SHA256
|
|
+ OBJS += ../src/crypto/sha256-internal.o
|
|
+ endif
|
|
+ ifdef NEED_TLS_PRF_SHA256
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha256-tlsprf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_TLS_PRF_SHA384
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha384-tlsprf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_HMAC_SHA256_KDF
|
|
++CFLAGS += -DCONFIG_HMAC_SHA256_KDF
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha256-kdf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_HMAC_SHA384_KDF
|
|
++CFLAGS += -DCONFIG_HMAC_SHA384_KDF
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha384-kdf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_HMAC_SHA512_KDF
|
|
++CFLAGS += -DCONFIG_HMAC_SHA512_KDF
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha512-kdf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_SHA384
|
|
+ CFLAGS += -DCONFIG_SHA384
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), gnutls)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha384.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha384-prf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_SHA512
|
|
+ CFLAGS += -DCONFIG_SHA512
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), gnutls)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha512.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha512-prf.o
|
|
+ endif
|
|
++endif
|
|
+
|
|
+ ifdef CONFIG_INTERNAL_SHA384
|
|
+ CFLAGS += -DCONFIG_INTERNAL_SHA384
|
|
+@@ -1152,11 +1235,13 @@ HOBJS += $(SHA1OBJS)
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ HOBJS += ../src/crypto/md5.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+
|
|
+ ifdef CONFIG_RADIUS_SERVER
|
|
+ CFLAGS += -DRADIUS_SERVER
|
|
+@@ -1329,7 +1414,9 @@ NOBJS += ../src/utils/trace.o
|
|
+ endif
|
|
+
|
|
+ HOBJS += hlr_auc_gw.o ../src/utils/common.o ../src/utils/wpa_debug.o ../src/utils/os_$(CONFIG_OS).o ../src/utils/wpabuf.o ../src/crypto/milenage.o
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ HOBJS += ../src/crypto/aes-encblock.o
|
|
++endif
|
|
+ ifdef CONFIG_INTERNAL_AES
|
|
+ HOBJS += ../src/crypto/aes-internal.o
|
|
+ HOBJS += ../src/crypto/aes-internal-enc.o
|
|
+@@ -1352,13 +1439,17 @@ SOBJS += ../src/common/sae.o
|
|
+ SOBJS += ../src/common/sae_pk.o
|
|
+ SOBJS += ../src/common/dragonfly.o
|
|
+ SOBJS += $(AESOBJS)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SOBJS += ../src/crypto/sha256-prf.o
|
|
+ SOBJS += ../src/crypto/sha384-prf.o
|
|
+ SOBJS += ../src/crypto/sha512-prf.o
|
|
++endif
|
|
+ SOBJS += ../src/crypto/dh_groups.o
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SOBJS += ../src/crypto/sha256-kdf.o
|
|
+ SOBJS += ../src/crypto/sha384-kdf.o
|
|
+ SOBJS += ../src/crypto/sha512-kdf.o
|
|
++endif
|
|
+
|
|
+ _OBJS_VAR := NOBJS
|
|
+ include ../src/objs.mk
|
|
+--- a/hostapd/defconfig
|
|
++++ b/hostapd/defconfig
|
|
+@@ -6,9 +6,21 @@
|
|
+ # just setting VARIABLE=n is not disabling that variable.
|
|
+ #
|
|
+ # This file is included in Makefile, so variables like CFLAGS and LIBS can also
|
|
+-# be modified from here. In most cass, these lines should use += in order not
|
|
++# be modified from here. In most cases, these lines should use += in order not
|
|
+ # to override previous values of the variables.
|
|
+
|
|
++
|
|
++# Uncomment following two lines and fix the paths if you have installed TLS
|
|
++# libraries in a non-default location
|
|
++#CFLAGS += -I/usr/local/openssl/include
|
|
++#LIBS += -L/usr/local/openssl/lib
|
|
++
|
|
++# Some Red Hat versions seem to include kerberos header files from OpenSSL, but
|
|
++# the kerberos files are not in the default include path. Following line can be
|
|
++# used to fix build issues on such systems (krb5.h not found).
|
|
++#CFLAGS += -I/usr/include/kerberos
|
|
++
|
|
++
|
|
+ # Driver interface for Host AP driver
|
|
+ CONFIG_DRIVER_HOSTAP=y
|
|
+
|
|
+@@ -278,6 +290,7 @@ CONFIG_IPV6=y
|
|
+ # openssl = OpenSSL (default)
|
|
+ # gnutls = GnuTLS
|
|
+ # internal = Internal TLSv1 implementation (experimental)
|
|
++# mbedtls = mbed TLS
|
|
+ # linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
|
|
+ # none = Empty template
|
|
+ #CONFIG_TLS=openssl
|
|
+--- /dev/null
|
|
++++ b/src/crypto/crypto_mbedtls.c
|
|
+@@ -0,0 +1,4043 @@
|
|
++/*
|
|
++ * crypto wrapper functions for mbed TLS
|
|
++ *
|
|
++ * SPDX-FileCopyrightText: 2022 Glenn Strauss <gstrauss@gluelogic.com>
|
|
++ * SPDX-License-Identifier: BSD-3-Clause
|
|
++ */
|
|
++
|
|
++#include "utils/includes.h"
|
|
++#include "utils/common.h"
|
|
++
|
|
++#include <mbedtls/version.h>
|
|
++#include <mbedtls/entropy.h>
|
|
++#include <mbedtls/ctr_drbg.h>
|
|
++#include <mbedtls/platform_util.h> /* mbedtls_platform_zeroize() */
|
|
++#include <mbedtls/asn1.h>
|
|
++#include <mbedtls/asn1write.h>
|
|
++#include <mbedtls/aes.h>
|
|
++#include <mbedtls/md.h>
|
|
++#include <mbedtls/md5.h>
|
|
++#include <mbedtls/sha1.h>
|
|
++#include <mbedtls/sha256.h>
|
|
++#include <mbedtls/sha512.h>
|
|
++
|
|
++#ifndef MBEDTLS_PRIVATE
|
|
++#define MBEDTLS_PRIVATE(x) x
|
|
++#endif
|
|
++
|
|
++/* hostapd/wpa_supplicant provides forced_memzero(),
|
|
++ * but prefer mbedtls_platform_zeroize() */
|
|
++#define forced_memzero(ptr,sz) mbedtls_platform_zeroize(ptr,sz)
|
|
++
|
|
++#ifndef __has_attribute
|
|
++#define __has_attribute(x) 0
|
|
++#endif
|
|
++
|
|
++#ifndef __GNUC_PREREQ
|
|
++#define __GNUC_PREREQ(maj,min) 0
|
|
++#endif
|
|
++
|
|
++#ifndef __attribute_cold__
|
|
++#if __has_attribute(cold) \
|
|
++ || __GNUC_PREREQ(4,3)
|
|
++#define __attribute_cold__ __attribute__((__cold__))
|
|
++#else
|
|
++#define __attribute_cold__
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++#ifndef __attribute_noinline__
|
|
++#if __has_attribute(noinline) \
|
|
++ || __GNUC_PREREQ(3,1)
|
|
++#define __attribute_noinline__ __attribute__((__noinline__))
|
|
++#else
|
|
++#define __attribute_noinline__
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++#include "crypto.h"
|
|
++#include "aes_wrap.h"
|
|
++#include "aes.h"
|
|
++#include "md5.h"
|
|
++#include "sha1.h"
|
|
++#include "sha256.h"
|
|
++#include "sha384.h"
|
|
++#include "sha512.h"
|
|
++
|
|
++
|
|
++/*
|
|
++ * selective code inclusion based on preprocessor defines
|
|
++ *
|
|
++ * future: additional code could be wrapped with preprocessor checks if
|
|
++ * wpa_supplicant/Makefile and hostap/Makefile were more consistent with
|
|
++ * setting preprocessor defines for named groups of functionality
|
|
++ */
|
|
++
|
|
++#if defined(CONFIG_FIPS)
|
|
++#undef MBEDTLS_MD4_C /* omit md4_vector() */
|
|
++#undef MBEDTLS_MD5_C /* omit md5_vector() hmac_md5_vector() hmac_md5() */
|
|
++#undef MBEDTLS_DES_C /* omit des_encrypt() */
|
|
++#undef MBEDTLS_NIST_KW_C /* omit aes_wrap() aes_unwrap() */
|
|
++#define CRYPTO_MBEDTLS_CONFIG_FIPS
|
|
++#endif
|
|
++
|
|
++#if !defined(CONFIG_FIPS)
|
|
++#if defined(EAP_PWD) \
|
|
++ || defined(EAP_LEAP) || defined(EAP_LEAP_DYNAMIC) \
|
|
++ || defined(EAP_TTLS) || defined(EAP_TTLS_DYNAMIC) \
|
|
++ || defined(EAP_MSCHAPv2) || defined(EAP_MSCHAPv2_DYNAMIC) \
|
|
++ || defined(EAP_SERVER_MSCHAPV2)
|
|
++#ifndef MBEDTLS_MD4_C /* (MD4 not in mbedtls 3.x) */
|
|
++#include "md4-internal.c"/* pull in hostap local implementation */
|
|
++#endif /* md4_vector() */
|
|
++#else
|
|
++#undef MBEDTLS_MD4_C /* omit md4_vector() */
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++#if !defined(CONFIG_NO_RC4) && !defined(CONFIG_NO_WPA)
|
|
++#ifndef MBEDTLS_ARC4_C /* (RC4 not in mbedtls 3.x) */
|
|
++#include "rc4.c" /* pull in hostap local implementation */
|
|
++#endif /* rc4_skip() */
|
|
++#else
|
|
++#undef MBEDTLS_ARC4_C /* omit rc4_skip() */
|
|
++#endif
|
|
++
|
|
++#if defined(CONFIG_MACSEC) \
|
|
++ || defined(CONFIG_NO_RADIUS) \
|
|
++ || defined(CONFIG_IEEE80211R) \
|
|
++ || defined(EAP_SERVER_FAST) \
|
|
++ || defined(EAP_SERVER_TEAP) \
|
|
++ || !defined(CONFIG_NO_WPA)
|
|
++ /* aes_wrap() aes_unwrap() */
|
|
++#else
|
|
++#undef MBEDTLS_NIST_KW_C /* omit aes_wrap() aes_unwrap() */
|
|
++#endif
|
|
++
|
|
++#if !defined(CONFIG_SHA256)
|
|
++#undef MBEDTLS_SHA256_C
|
|
++#endif
|
|
++
|
|
++#if !defined(CONFIG_SHA384) && !defined(CONFIG_SHA512)
|
|
++#undef MBEDTLS_SHA512_C
|
|
++#endif
|
|
++
|
|
++#if defined(CONFIG_HMAC_SHA256_KDF)
|
|
++#define CRYPTO_MBEDTLS_HMAC_KDF_SHA256
|
|
++#endif
|
|
++#if defined(CONFIG_HMAC_SHA384_KDF)
|
|
++#define CRYPTO_MBEDTLS_HMAC_KDF_SHA384
|
|
++#endif
|
|
++#if defined(CONFIG_HMAC_SHA512_KDF)
|
|
++#define CRYPTO_MBEDTLS_HMAC_KDF_SHA512
|
|
++#endif
|
|
++
|
|
++#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) \
|
|
++ || defined(EAP_TEAP) || defined(EAP_TEAP_DYNAMIC) || defined(EAP_SERVER_FAST)
|
|
++#define CRYPTO_MBEDTLS_SHA1_T_PRF
|
|
++#endif
|
|
++
|
|
++#if defined(CONFIG_DES)
|
|
++#define CRYPTO_MBEDTLS_DES_ENCRYPT
|
|
++#endif /* des_encrypt() */
|
|
++
|
|
++#if !defined(CONFIG_NO_PBKDF2)
|
|
++#define CRYPTO_MBEDTLS_PBKDF2_SHA1
|
|
++#endif /* pbkdf2_sha1() */
|
|
++
|
|
++#if defined(EAP_IKEV2) \
|
|
++ || defined(EAP_IKEV2_DYNAMIC) \
|
|
++ || defined(EAP_SERVER_IKEV2) /* CONFIG_EAP_IKEV2=y */
|
|
++#define CRYPTO_MBEDTLS_CRYPTO_CIPHER
|
|
++#endif /* crypto_cipher_*() */
|
|
++
|
|
++#if defined(EAP_PWD) || defined(EAP_SERVER_PWD) /* CONFIG_EAP_PWD=y */
|
|
++#define CRYPTO_MBEDTLS_CRYPTO_HASH
|
|
++#endif /* crypto_hash_*() */
|
|
++
|
|
++#if defined(EAP_PWD) || defined(EAP_SERVER_PWD) /* CONFIG_EAP_PWD=y */ \
|
|
++ || defined(CONFIG_SAE) /* CONFIG_SAE=y */
|
|
++#define CRYPTO_MBEDTLS_CRYPTO_BIGNUM
|
|
++#endif /* crypto_bignum_*() */
|
|
++
|
|
++#if defined(EAP_PWD) /* CONFIG_EAP_PWD=y */ \
|
|
++ || defined(EAP_EKE) /* CONFIG_EAP_EKE=y */ \
|
|
++ || defined(EAP_EKE_DYNAMIC) /* CONFIG_EAP_EKE=y */ \
|
|
++ || defined(EAP_SERVER_EKE) /* CONFIG_EAP_EKE=y */ \
|
|
++ || defined(EAP_IKEV2) /* CONFIG_EAP_IKEV2y */ \
|
|
++ || defined(EAP_IKEV2_DYNAMIC)/* CONFIG_EAP_IKEV2=y */ \
|
|
++ || defined(EAP_SERVER_IKEV2) /* CONFIG_EAP_IKEV2=y */ \
|
|
++ || defined(CONFIG_SAE) /* CONFIG_SAE=y */ \
|
|
++ || defined(CONFIG_WPS) /* CONFIG_WPS=y */
|
|
++#define CRYPTO_MBEDTLS_CRYPTO_DH
|
|
++#if defined(CONFIG_WPS_NFC)
|
|
++#define CRYPTO_MBEDTLS_DH5_INIT_FIXED
|
|
++#endif /* dh5_init_fixed() */
|
|
++#endif /* crypto_dh_*() */
|
|
++
|
|
++#if !defined(CONFIG_NO_WPA) /* CONFIG_NO_WPA= */
|
|
++#define CRYPTO_MBEDTLS_CRYPTO_ECDH
|
|
++#endif /* crypto_ecdh_*() */
|
|
++
|
|
++#if defined(CONFIG_ECC)
|
|
++#define CRYPTO_MBEDTLS_CRYPTO_BIGNUM
|
|
++#define CRYPTO_MBEDTLS_CRYPTO_EC
|
|
++#endif /* crypto_ec_*() crypto_ec_key_*() */
|
|
++
|
|
++#if defined(CONFIG_DPP) /* CONFIG_DPP=y */
|
|
++#define CRYPTO_MBEDTLS_CRYPTO_EC_DPP /* extra for DPP */
|
|
++#define CRYPTO_MBEDTLS_CRYPTO_CSR
|
|
++#endif /* crypto_csr_*() */
|
|
++
|
|
++#if defined(CONFIG_DPP3) /* CONFIG_DPP3=y */
|
|
++#define CRYPTO_MBEDTLS_CRYPTO_HPKE
|
|
++#endif
|
|
++
|
|
++#if defined(CONFIG_DPP2) /* CONFIG_DPP2=y */
|
|
++#define CRYPTO_MBEDTLS_CRYPTO_PKCS7
|
|
++#endif /* crypto_pkcs7_*() */
|
|
++
|
|
++#if defined(EAP_SIM) || defined(EAP_SIM_DYNAMIC) || defined(EAP_SERVER_SIM) \
|
|
++ || defined(EAP_AKA) || defined(EAP_AKA_DYNAMIC) || defined(EAP_SERVER_AKA) \
|
|
++ || defined(CONFIG_AP) || defined(HOSTAPD)
|
|
++/* CONFIG_EAP_SIM=y CONFIG_EAP_AKA=y CONFIG_AP=y HOSTAPD */
|
|
++#if defined(CRYPTO_RSA_OAEP_SHA256)
|
|
++#define CRYPTO_MBEDTLS_CRYPTO_RSA
|
|
++#endif
|
|
++#endif /* crypto_rsa_*() */
|
|
++
|
|
++
|
|
++static int ctr_drbg_init_state;
|
|
++static mbedtls_ctr_drbg_context ctr_drbg;
|
|
++static mbedtls_entropy_context entropy;
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM
|
|
++#include <mbedtls/bignum.h>
|
|
++static mbedtls_mpi mpi_sw_A;
|
|
++#endif
|
|
++
|
|
++__attribute_cold__
|
|
++__attribute_noinline__
|
|
++static mbedtls_ctr_drbg_context * ctr_drbg_init(void)
|
|
++{
|
|
++ mbedtls_ctr_drbg_init(&ctr_drbg);
|
|
++ mbedtls_entropy_init(&entropy);
|
|
++ if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
|
|
++ NULL, 0)) {
|
|
++ wpa_printf(MSG_ERROR, "Init of random number generator failed");
|
|
++ /* XXX: abort? */
|
|
++ }
|
|
++ else
|
|
++ ctr_drbg_init_state = 1;
|
|
++
|
|
++ return &ctr_drbg;
|
|
++}
|
|
++
|
|
++__attribute_cold__
|
|
++void crypto_unload(void)
|
|
++{
|
|
++ if (ctr_drbg_init_state) {
|
|
++ mbedtls_ctr_drbg_free(&ctr_drbg);
|
|
++ mbedtls_entropy_free(&entropy);
|
|
++ #ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM
|
|
++ mbedtls_mpi_free(&mpi_sw_A);
|
|
++ #endif
|
|
++ ctr_drbg_init_state = 0;
|
|
++ }
|
|
++}
|
|
++
|
|
++/* init ctr_drbg on first use
|
|
++ * crypto_global_init() and crypto_global_deinit() are not available here
|
|
++ * (available only when CONFIG_TLS=internal, which is not CONFIG_TLS=mbedtls) */
|
|
++mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void); /*(not in header)*/
|
|
++inline
|
|
++mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void)
|
|
++{
|
|
++ return ctr_drbg_init_state ? &ctr_drbg : ctr_drbg_init();
|
|
++}
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CONFIG_FIPS
|
|
++int crypto_get_random(void *buf, size_t len)
|
|
++{
|
|
++ return mbedtls_ctr_drbg_random(crypto_mbedtls_ctr_drbg(),buf,len) ? -1 : 0;
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++#if 1
|
|
++
|
|
++/* tradeoff: slightly smaller code size here at cost of slight increase
|
|
++ * in instructions and function calls at runtime versus the expanded
|
|
++ * per-message-digest code that follows in #else (~0.5 kib .text larger) */
|
|
++
|
|
++__attribute_noinline__
|
|
++static int md_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
|
++ u8 *mac, mbedtls_md_type_t md_type)
|
|
++{
|
|
++ mbedtls_md_context_t ctx;
|
|
++ mbedtls_md_init(&ctx);
|
|
++ if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0) != 0){
|
|
++ mbedtls_md_free(&ctx);
|
|
++ return -1;
|
|
++ }
|
|
++ mbedtls_md_starts(&ctx);
|
|
++ for (size_t i = 0; i < num_elem; ++i)
|
|
++ mbedtls_md_update(&ctx, addr[i], len[i]);
|
|
++ mbedtls_md_finish(&ctx, mac);
|
|
++ mbedtls_md_free(&ctx);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++#ifdef MBEDTLS_SHA512_C
|
|
++int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA512);
|
|
++}
|
|
++
|
|
++int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA384);
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_SHA256_C
|
|
++int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA256);
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_SHA1_C
|
|
++int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_SHA1);
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_MD5_C
|
|
++int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_MD5);
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_MD4_C
|
|
++#include <mbedtls/md4.h>
|
|
++int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return md_vector(num_elem, addr, len, mac, MBEDTLS_MD_MD4);
|
|
++}
|
|
++#endif
|
|
++
|
|
++#else /* expanded per-message-digest functions */
|
|
++
|
|
++#ifdef MBEDTLS_SHA512_C
|
|
++#include <mbedtls/sha512.h>
|
|
++__attribute_noinline__
|
|
++static int sha384_512_vector(size_t num_elem, const u8 *addr[],
|
|
++ const size_t *len, u8 *mac, int is384)
|
|
++{
|
|
++ struct mbedtls_sha512_context ctx;
|
|
++ mbedtls_sha512_init(&ctx);
|
|
++ #if MBEDTLS_VERSION_MAJOR >= 3
|
|
++ mbedtls_sha512_starts(&ctx, is384);
|
|
++ for (size_t i = 0; i < num_elem; ++i)
|
|
++ mbedtls_sha512_update(&ctx, addr[i], len[i]);
|
|
++ mbedtls_sha512_finish(&ctx, mac);
|
|
++ #else
|
|
++ mbedtls_sha512_starts_ret(&ctx, is384);
|
|
++ for (size_t i = 0; i < num_elem; ++i)
|
|
++ mbedtls_sha512_update_ret(&ctx, addr[i], len[i]);
|
|
++ mbedtls_sha512_finish_ret(&ctx, mac);
|
|
++ #endif
|
|
++ mbedtls_sha512_free(&ctx);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++int sha512_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return sha384_512_vector(num_elem, addr, len, mac, 0);
|
|
++}
|
|
++
|
|
++int sha384_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return sha384_512_vector(num_elem, addr, len, mac, 1);
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_SHA256_C
|
|
++#include <mbedtls/sha256.h>
|
|
++int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ struct mbedtls_sha256_context ctx;
|
|
++ mbedtls_sha256_init(&ctx);
|
|
++ #if MBEDTLS_VERSION_MAJOR >= 3
|
|
++ mbedtls_sha256_starts(&ctx, 0);
|
|
++ for (size_t i = 0; i < num_elem; ++i)
|
|
++ mbedtls_sha256_update(&ctx, addr[i], len[i]);
|
|
++ mbedtls_sha256_finish(&ctx, mac);
|
|
++ #else
|
|
++ mbedtls_sha256_starts_ret(&ctx, 0);
|
|
++ for (size_t i = 0; i < num_elem; ++i)
|
|
++ mbedtls_sha256_update_ret(&ctx, addr[i], len[i]);
|
|
++ mbedtls_sha256_finish_ret(&ctx, mac);
|
|
++ #endif
|
|
++ mbedtls_sha256_free(&ctx);
|
|
++ return 0;
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_SHA1_C
|
|
++#include <mbedtls/sha1.h>
|
|
++int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ struct mbedtls_sha1_context ctx;
|
|
++ mbedtls_sha1_init(&ctx);
|
|
++ #if MBEDTLS_VERSION_MAJOR >= 3
|
|
++ mbedtls_sha1_starts(&ctx);
|
|
++ for (size_t i = 0; i < num_elem; ++i)
|
|
++ mbedtls_sha1_update(&ctx, addr[i], len[i]);
|
|
++ mbedtls_sha1_finish(&ctx, mac);
|
|
++ #else
|
|
++ mbedtls_sha1_starts_ret(&ctx);
|
|
++ for (size_t i = 0; i < num_elem; ++i)
|
|
++ mbedtls_sha1_update_ret(&ctx, addr[i], len[i]);
|
|
++ mbedtls_sha1_finish_ret(&ctx, mac);
|
|
++ #endif
|
|
++ mbedtls_sha1_free(&ctx);
|
|
++ return 0;
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_MD5_C
|
|
++#include <mbedtls/md5.h>
|
|
++int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ struct mbedtls_md5_context ctx;
|
|
++ mbedtls_md5_init(&ctx);
|
|
++ #if MBEDTLS_VERSION_MAJOR >= 3
|
|
++ mbedtls_md5_starts(&ctx);
|
|
++ for (size_t i = 0; i < num_elem; ++i)
|
|
++ mbedtls_md5_update(&ctx, addr[i], len[i]);
|
|
++ mbedtls_md5_finish(&ctx, mac);
|
|
++ #else
|
|
++ mbedtls_md5_starts_ret(&ctx);
|
|
++ for (size_t i = 0; i < num_elem; ++i)
|
|
++ mbedtls_md5_update_ret(&ctx, addr[i], len[i]);
|
|
++ mbedtls_md5_finish_ret(&ctx, mac);
|
|
++ #endif
|
|
++ mbedtls_md5_free(&ctx);
|
|
++ return 0;
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_MD4_C
|
|
++#include <mbedtls/md4.h>
|
|
++int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ struct mbedtls_md4_context ctx;
|
|
++ mbedtls_md4_init(&ctx);
|
|
++ mbedtls_md4_starts_ret(&ctx);
|
|
++ for (size_t i = 0; i < num_elem; ++i)
|
|
++ mbedtls_md4_update_ret(&ctx, addr[i], len[i]);
|
|
++ mbedtls_md4_finish_ret(&ctx, mac);
|
|
++ mbedtls_md4_free(&ctx);
|
|
++ return 0;
|
|
++}
|
|
++#endif
|
|
++
|
|
++#endif /* expanded per-message-digest functions */
|
|
++
|
|
++
|
|
++__attribute_noinline__
|
|
++static int hmac_vector(const u8 *key, size_t key_len, size_t num_elem,
|
|
++ const u8 *addr[], const size_t *len, u8 *mac,
|
|
++ mbedtls_md_type_t md_type)
|
|
++{
|
|
++ mbedtls_md_context_t ctx;
|
|
++ mbedtls_md_init(&ctx);
|
|
++ if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1) != 0){
|
|
++ mbedtls_md_free(&ctx);
|
|
++ return -1;
|
|
++ }
|
|
++ mbedtls_md_hmac_starts(&ctx, key, key_len);
|
|
++ for (size_t i = 0; i < num_elem; ++i)
|
|
++ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
|
|
++ mbedtls_md_hmac_finish(&ctx, mac);
|
|
++ mbedtls_md_free(&ctx);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++#ifdef MBEDTLS_SHA512_C
|
|
++int hmac_sha512_vector(const u8 *key, size_t key_len, size_t num_elem,
|
|
++ const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return hmac_vector(key, key_len, num_elem, addr, len, mac,
|
|
++ MBEDTLS_MD_SHA512);
|
|
++}
|
|
++
|
|
++int hmac_sha512(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
|
|
++ u8 *mac)
|
|
++{
|
|
++ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
|
|
++ MBEDTLS_MD_SHA512);
|
|
++}
|
|
++
|
|
++int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem,
|
|
++ const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return hmac_vector(key, key_len, num_elem, addr, len, mac,
|
|
++ MBEDTLS_MD_SHA384);
|
|
++}
|
|
++
|
|
++int hmac_sha384(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
|
|
++ u8 *mac)
|
|
++{
|
|
++ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
|
|
++ MBEDTLS_MD_SHA384);
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_SHA256_C
|
|
++int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
|
|
++ const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return hmac_vector(key, key_len, num_elem, addr, len, mac,
|
|
++ MBEDTLS_MD_SHA256);
|
|
++}
|
|
++
|
|
++int hmac_sha256(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
|
|
++ u8 *mac)
|
|
++{
|
|
++ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
|
|
++ MBEDTLS_MD_SHA256);
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_SHA1_C
|
|
++int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
|
|
++ const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return hmac_vector(key, key_len, num_elem, addr, len, mac,
|
|
++ MBEDTLS_MD_SHA1);
|
|
++}
|
|
++
|
|
++int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
|
|
++ u8 *mac)
|
|
++{
|
|
++ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
|
|
++ MBEDTLS_MD_SHA1);
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_MD5_C
|
|
++int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
|
|
++ const u8 *addr[], const size_t *len, u8 *mac)
|
|
++{
|
|
++ return hmac_vector(key, key_len, num_elem, addr, len, mac,
|
|
++ MBEDTLS_MD_MD5);
|
|
++}
|
|
++
|
|
++int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
|
|
++ u8 *mac)
|
|
++{
|
|
++ return hmac_vector(key, key_len, 1, &data, &data_len, mac,
|
|
++ MBEDTLS_MD_MD5);
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C)
|
|
++
|
|
++#if defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA256) \
|
|
++ || defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA384) \
|
|
++ || defined(CRYPTO_MBEDTLS_HMAC_KDF_SHA512)
|
|
++
|
|
++#include <mbedtls/hkdf.h>
|
|
++
|
|
++/* sha256-kdf.c sha384-kdf.c sha512-kdf.c */
|
|
++
|
|
++/* HMAC-SHA256 KDF (RFC 5295) and HKDF-Expand(SHA256) (RFC 5869) */
|
|
++/* HMAC-SHA384 KDF (RFC 5295) and HKDF-Expand(SHA384) (RFC 5869) */
|
|
++/* HMAC-SHA512 KDF (RFC 5295) and HKDF-Expand(SHA512) (RFC 5869) */
|
|
++__attribute_noinline__
|
|
++static int hmac_kdf_expand(const u8 *prk, size_t prk_len,
|
|
++ const char *label, const u8 *info, size_t info_len,
|
|
++ u8 *okm, size_t okm_len, mbedtls_md_type_t md_type)
|
|
++{
|
|
++ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
|
|
++ #ifdef MBEDTLS_HKDF_C
|
|
++ if (label == NULL) /* RFC 5869 HKDF-Expand when (label == NULL) */
|
|
++ return mbedtls_hkdf_expand(md_info, prk, prk_len, info,
|
|
++ info_len, okm, okm_len) ? -1 : 0;
|
|
++ #endif
|
|
++
|
|
++ const size_t mac_len = mbedtls_md_get_size(md_info);
|
|
++ /* okm_len must not exceed 255 times hash len (RFC 5869 Section 2.3) */
|
|
++ if (okm_len > ((mac_len << 8) - mac_len))
|
|
++ return -1;
|
|
++
|
|
++ mbedtls_md_context_t ctx;
|
|
++ mbedtls_md_init(&ctx);
|
|
++ if (mbedtls_md_setup(&ctx, md_info, 1) != 0) {
|
|
++ mbedtls_md_free(&ctx);
|
|
++ return -1;
|
|
++ }
|
|
++ mbedtls_md_hmac_starts(&ctx, prk, prk_len);
|
|
++
|
|
++ u8 iter = 1;
|
|
++ const u8 *addr[4] = { okm, (const u8 *)label, info, &iter };
|
|
++ size_t len[4] = { 0, label ? os_strlen(label)+1 : 0, info_len, 1 };
|
|
++
|
|
++ for (; okm_len >= mac_len; okm_len -= mac_len, ++iter) {
|
|
++ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i)
|
|
++ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
|
|
++ mbedtls_md_hmac_finish(&ctx, okm);
|
|
++ mbedtls_md_hmac_reset(&ctx);
|
|
++ addr[0] = okm;
|
|
++ okm += mac_len;
|
|
++ len[0] = mac_len; /*(include digest in subsequent rounds)*/
|
|
++ }
|
|
++
|
|
++ if (okm_len) {
|
|
++ u8 hash[MBEDTLS_MD_MAX_SIZE];
|
|
++ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i)
|
|
++ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
|
|
++ mbedtls_md_hmac_finish(&ctx, hash);
|
|
++ os_memcpy(okm, hash, okm_len);
|
|
++ forced_memzero(hash, mac_len);
|
|
++ }
|
|
++
|
|
++ mbedtls_md_free(&ctx);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++#ifdef MBEDTLS_SHA512_C
|
|
++#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA512
|
|
++int hmac_sha512_kdf(const u8 *secret, size_t secret_len,
|
|
++ const char *label, const u8 *seed, size_t seed_len,
|
|
++ u8 *out, size_t outlen)
|
|
++{
|
|
++ return hmac_kdf_expand(secret, secret_len, label, seed, seed_len,
|
|
++ out, outlen, MBEDTLS_MD_SHA512);
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA384
|
|
++int hmac_sha384_kdf(const u8 *secret, size_t secret_len,
|
|
++ const char *label, const u8 *seed, size_t seed_len,
|
|
++ u8 *out, size_t outlen)
|
|
++{
|
|
++ return hmac_kdf_expand(secret, secret_len, label, seed, seed_len,
|
|
++ out, outlen, MBEDTLS_MD_SHA384);
|
|
++}
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_SHA256_C
|
|
++#ifdef CRYPTO_MBEDTLS_HMAC_KDF_SHA256
|
|
++int hmac_sha256_kdf(const u8 *secret, size_t secret_len,
|
|
++ const char *label, const u8 *seed, size_t seed_len,
|
|
++ u8 *out, size_t outlen)
|
|
++{
|
|
++ return hmac_kdf_expand(secret, secret_len, label, seed, seed_len,
|
|
++ out, outlen, MBEDTLS_MD_SHA256);
|
|
++}
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_HMAC_KDF_* */
|
|
++
|
|
++
|
|
++/* sha256-prf.c sha384-prf.c sha512-prf.c */
|
|
++
|
|
++/* hmac_prf_bits - IEEE Std 802.11ac-2013, 11.6.1.7.2 Key derivation function */
|
|
++__attribute_noinline__
|
|
++static int hmac_prf_bits(const u8 *key, size_t key_len, const char *label,
|
|
++ const u8 *data, size_t data_len, u8 *buf,
|
|
++ size_t buf_len_bits, mbedtls_md_type_t md_type)
|
|
++{
|
|
++ mbedtls_md_context_t ctx;
|
|
++ mbedtls_md_init(&ctx);
|
|
++ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
|
|
++ if (mbedtls_md_setup(&ctx, md_info, 1) != 0) {
|
|
++ mbedtls_md_free(&ctx);
|
|
++ return -1;
|
|
++ }
|
|
++ mbedtls_md_hmac_starts(&ctx, key, key_len);
|
|
++
|
|
++ u16 ctr, n_le = host_to_le16(buf_len_bits);
|
|
++ const u8 * const addr[] = { (u8 *)&ctr,(u8 *)label,data,(u8 *)&n_le };
|
|
++ const size_t len[] = { 2, os_strlen(label), data_len, 2 };
|
|
++ const size_t mac_len = mbedtls_md_get_size(md_info);
|
|
++ size_t buf_len = (buf_len_bits + 7) / 8;
|
|
++ for (ctr = 1; buf_len >= mac_len; buf_len -= mac_len, ++ctr) {
|
|
++ #if __BYTE_ORDER == __BIG_ENDIAN
|
|
++ ctr = host_to_le16(ctr);
|
|
++ #endif
|
|
++ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i)
|
|
++ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
|
|
++ mbedtls_md_hmac_finish(&ctx, buf);
|
|
++ mbedtls_md_hmac_reset(&ctx);
|
|
++ buf += mac_len;
|
|
++ #if __BYTE_ORDER == __BIG_ENDIAN
|
|
++ ctr = le_to_host16(ctr);
|
|
++ #endif
|
|
++ }
|
|
++
|
|
++ if (buf_len) {
|
|
++ u8 hash[MBEDTLS_MD_MAX_SIZE];
|
|
++ #if __BYTE_ORDER == __BIG_ENDIAN
|
|
++ ctr = host_to_le16(ctr);
|
|
++ #endif
|
|
++ for (size_t i = 0; i < ARRAY_SIZE(addr); ++i)
|
|
++ mbedtls_md_hmac_update(&ctx, addr[i], len[i]);
|
|
++ mbedtls_md_hmac_finish(&ctx, hash);
|
|
++ os_memcpy(buf, hash, buf_len);
|
|
++ buf += buf_len;
|
|
++ forced_memzero(hash, mac_len);
|
|
++ }
|
|
++
|
|
++ /* Mask out unused bits in last octet if it does not use all the bits */
|
|
++ if ((buf_len_bits &= 0x7))
|
|
++ buf[-1] &= (u8)(0xff << (8 - buf_len_bits));
|
|
++
|
|
++ mbedtls_md_free(&ctx);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++#ifdef MBEDTLS_SHA512_C
|
|
++int sha512_prf(const u8 *key, size_t key_len, const char *label,
|
|
++ const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
|
|
++{
|
|
++ return hmac_prf_bits(key, key_len, label, data, data_len, buf,
|
|
++ buf_len * 8, MBEDTLS_MD_SHA512);
|
|
++}
|
|
++
|
|
++int sha384_prf(const u8 *key, size_t key_len, const char *label,
|
|
++ const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
|
|
++{
|
|
++ return hmac_prf_bits(key, key_len, label, data, data_len, buf,
|
|
++ buf_len * 8, MBEDTLS_MD_SHA384);
|
|
++}
|
|
++#endif
|
|
++
|
|
++#ifdef MBEDTLS_SHA256_C
|
|
++int sha256_prf(const u8 *key, size_t key_len, const char *label,
|
|
++ const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
|
|
++{
|
|
++ return hmac_prf_bits(key, key_len, label, data, data_len, buf,
|
|
++ buf_len * 8, MBEDTLS_MD_SHA256);
|
|
++}
|
|
++
|
|
++int sha256_prf_bits(const u8 *key, size_t key_len, const char *label,
|
|
++ const u8 *data, size_t data_len, u8 *buf,
|
|
++ size_t buf_len_bits)
|
|
++{
|
|
++ return hmac_prf_bits(key, key_len, label, data, data_len, buf,
|
|
++ buf_len_bits, MBEDTLS_MD_SHA256);
|
|
++}
|
|
++#endif
|
|
++
|
|
++#endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA512_C */
|
|
++
|
|
++
|
|
++#ifdef MBEDTLS_SHA1_C
|
|
++
|
|
++/* sha1-prf.c */
|
|
++
|
|
++/* sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) */
|
|
++
|
|
++int sha1_prf(const u8 *key, size_t key_len, const char *label,
|
|
++ const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
|
|
++{
|
|
++ /*(note: algorithm differs from hmac_prf_bits() */
|
|
++ /*(note: smaller code size instead of expanding hmac_sha1_vector()
|
|
++ * as is done in hmac_prf_bits(); not expecting large num of loops) */
|
|
++ u8 counter = 0;
|
|
++ const u8 *addr[] = { (u8 *)label, data, &counter };
|
|
++ const size_t len[] = { os_strlen(label)+1, data_len, 1 };
|
|
++
|
|
++ for (; buf_len >= SHA1_MAC_LEN; buf_len -= SHA1_MAC_LEN, ++counter) {
|
|
++ if (hmac_sha1_vector(key, key_len, 3, addr, len, buf))
|
|
++ return -1;
|
|
++ buf += SHA1_MAC_LEN;
|
|
++ }
|
|
++
|
|
++ if (buf_len) {
|
|
++ u8 hash[SHA1_MAC_LEN];
|
|
++ if (hmac_sha1_vector(key, key_len, 3, addr, len, hash))
|
|
++ return -1;
|
|
++ os_memcpy(buf, hash, buf_len);
|
|
++ forced_memzero(hash, sizeof(hash));
|
|
++ }
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_SHA1_T_PRF
|
|
++
|
|
++/* sha1-tprf.c */
|
|
++
|
|
++/* sha1_t_prf - EAP-FAST Pseudo-Random Function (T-PRF) (RFC 4851,Section 5.5)*/
|
|
++
|
|
++int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
|
|
++ const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len)
|
|
++{
|
|
++ /*(note: algorithm differs from hmac_prf_bits() and hmac_kdf() above)*/
|
|
++ /*(note: smaller code size instead of expanding hmac_sha1_vector()
|
|
++ * as is done in hmac_prf_bits(); not expecting large num of loops) */
|
|
++ u8 ctr;
|
|
++ u16 olen = host_to_be16(buf_len);
|
|
++ const u8 *addr[] = { buf, (u8 *)label, seed, (u8 *)&olen, &ctr };
|
|
++ size_t len[] = { 0, os_strlen(label)+1, seed_len, 2, 1 };
|
|
++
|
|
++ for (ctr = 1; buf_len >= SHA1_MAC_LEN; buf_len -= SHA1_MAC_LEN, ++ctr) {
|
|
++ if (hmac_sha1_vector(key, key_len, 5, addr, len, buf))
|
|
++ return -1;
|
|
++ addr[0] = buf;
|
|
++ buf += SHA1_MAC_LEN;
|
|
++ len[0] = SHA1_MAC_LEN; /*(include digest in subsequent rounds)*/
|
|
++ }
|
|
++
|
|
++ if (buf_len) {
|
|
++ u8 hash[SHA1_MAC_LEN];
|
|
++ if (hmac_sha1_vector(key, key_len, 5, addr, len, hash))
|
|
++ return -1;
|
|
++ os_memcpy(buf, hash, buf_len);
|
|
++ forced_memzero(hash, sizeof(hash));
|
|
++ }
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_SHA1_T_PRF */
|
|
++
|
|
++#endif /* MBEDTLS_SHA1_C */
|
|
++
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_DES_ENCRYPT
|
|
++#ifdef MBEDTLS_DES_C
|
|
++#include <mbedtls/des.h>
|
|
++int des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
|
|
++{
|
|
++ u8 pkey[8], next, tmp;
|
|
++ int i;
|
|
++
|
|
++ /* Add parity bits to the key */
|
|
++ next = 0;
|
|
++ for (i = 0; i < 7; i++) {
|
|
++ tmp = key[i];
|
|
++ pkey[i] = (tmp >> i) | next | 1;
|
|
++ next = tmp << (7 - i);
|
|
++ }
|
|
++ pkey[i] = next | 1;
|
|
++
|
|
++ mbedtls_des_context des;
|
|
++ mbedtls_des_init(&des);
|
|
++ int ret = mbedtls_des_setkey_enc(&des, pkey)
|
|
++ || mbedtls_des_crypt_ecb(&des, clear, cypher) ? -1 : 0;
|
|
++ mbedtls_des_free(&des);
|
|
++ return ret;
|
|
++}
|
|
++#else
|
|
++#include "des-internal.c"/* pull in hostap local implementation */
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_PBKDF2_SHA1
|
|
++/* sha1-pbkdf2.c */
|
|
++#include <mbedtls/pkcs5.h>
|
|
++int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len,
|
|
++ int iterations, u8 *buf, size_t buflen)
|
|
++{
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03020200 /* mbedtls 3.2.2 */
|
|
++ return mbedtls_pkcs5_pbkdf2_hmac_ext(MBEDTLS_MD_SHA1,
|
|
++ (const u8 *)passphrase, os_strlen(passphrase),
|
|
++ ssid, ssid_len, iterations, 32, buf) ? -1 : 0;
|
|
++ #else
|
|
++ const mbedtls_md_info_t *md_info;
|
|
++ md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
|
|
++ if (md_info == NULL)
|
|
++ return -1;
|
|
++ mbedtls_md_context_t ctx;
|
|
++ mbedtls_md_init(&ctx);
|
|
++ int ret = mbedtls_md_setup(&ctx, md_info, 1)
|
|
++ || mbedtls_pkcs5_pbkdf2_hmac(&ctx,
|
|
++ (const u8 *)passphrase, os_strlen(passphrase),
|
|
++ ssid, ssid_len, iterations, 32, buf) ? -1 : 0;
|
|
++ mbedtls_md_free(&ctx);
|
|
++ return ret;
|
|
++ #endif
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++/*#include "aes.h"*/ /* prototypes also included in "crypto.h" */
|
|
++
|
|
++static void *aes_crypt_init_mode(const u8 *key, size_t len, int mode)
|
|
++{
|
|
++ mbedtls_aes_context *aes = os_malloc(sizeof(*aes));
|
|
++ if (!aes)
|
|
++ return NULL;
|
|
++
|
|
++ mbedtls_aes_init(aes);
|
|
++ if ((mode == MBEDTLS_AES_ENCRYPT
|
|
++ ? mbedtls_aes_setkey_enc(aes, key, len * 8)
|
|
++ : mbedtls_aes_setkey_dec(aes, key, len * 8)) == 0)
|
|
++ return aes;
|
|
++
|
|
++ mbedtls_aes_free(aes);
|
|
++ os_free(aes);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++void *aes_encrypt_init(const u8 *key, size_t len)
|
|
++{
|
|
++ return aes_crypt_init_mode(key, len, MBEDTLS_AES_ENCRYPT);
|
|
++}
|
|
++
|
|
++int aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
|
|
++{
|
|
++ return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, plain, crypt);
|
|
++}
|
|
++
|
|
++void aes_encrypt_deinit(void *ctx)
|
|
++{
|
|
++ mbedtls_aes_free(ctx);
|
|
++ os_free(ctx);
|
|
++}
|
|
++
|
|
++void *aes_decrypt_init(const u8 *key, size_t len)
|
|
++{
|
|
++ return aes_crypt_init_mode(key, len, MBEDTLS_AES_DECRYPT);
|
|
++}
|
|
++
|
|
++int aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
|
|
++{
|
|
++ return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_DECRYPT, crypt, plain);
|
|
++}
|
|
++
|
|
++void aes_decrypt_deinit(void *ctx)
|
|
++{
|
|
++ mbedtls_aes_free(ctx);
|
|
++ os_free(ctx);
|
|
++}
|
|
++
|
|
++
|
|
++#include "aes_wrap.h"
|
|
++
|
|
++
|
|
++#ifdef MBEDTLS_NIST_KW_C
|
|
++
|
|
++#include <mbedtls/nist_kw.h>
|
|
++
|
|
++/* aes-wrap.c */
|
|
++int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
|
|
++{
|
|
++ mbedtls_nist_kw_context ctx;
|
|
++ mbedtls_nist_kw_init(&ctx);
|
|
++ size_t olen;
|
|
++ int ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
|
|
++ kek, kek_len*8, 1)
|
|
++ || mbedtls_nist_kw_wrap(&ctx, MBEDTLS_KW_MODE_KW, plain, n*8,
|
|
++ cipher, &olen, (n+1)*8) ? -1 : 0;
|
|
++ mbedtls_nist_kw_free(&ctx);
|
|
++ return ret;
|
|
++}
|
|
++
|
|
++/* aes-unwrap.c */
|
|
++int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, u8 *plain)
|
|
++{
|
|
++ mbedtls_nist_kw_context ctx;
|
|
++ mbedtls_nist_kw_init(&ctx);
|
|
++ size_t olen;
|
|
++ int ret = mbedtls_nist_kw_setkey(&ctx, MBEDTLS_CIPHER_ID_AES,
|
|
++ kek, kek_len*8, 0)
|
|
++ || mbedtls_nist_kw_unwrap(&ctx, MBEDTLS_KW_MODE_KW, cipher,
|
|
++ (n+1)*8, plain, &olen, n*8) ? -1 : 0;
|
|
++ mbedtls_nist_kw_free(&ctx);
|
|
++ return ret;
|
|
++}
|
|
++
|
|
++#else
|
|
++
|
|
++#ifndef CRYPTO_MBEDTLS_CONFIG_FIPS
|
|
++#include "aes-wrap.c" /* pull in hostap local implementation */
|
|
++#include "aes-unwrap.c" /* pull in hostap local implementation */
|
|
++#endif
|
|
++
|
|
++#endif /* MBEDTLS_NIST_KW_C */
|
|
++
|
|
++
|
|
++#ifdef MBEDTLS_CMAC_C
|
|
++
|
|
++/* aes-omac1.c */
|
|
++
|
|
++#include <mbedtls/cmac.h>
|
|
++
|
|
++int omac1_aes_vector(
|
|
++ const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[],
|
|
++ const size_t *len, u8 *mac)
|
|
++{
|
|
++ mbedtls_cipher_type_t cipher_type;
|
|
++ switch (key_len) {
|
|
++ case 16: cipher_type = MBEDTLS_CIPHER_AES_128_ECB; break;
|
|
++ case 24: cipher_type = MBEDTLS_CIPHER_AES_192_ECB; break;
|
|
++ case 32: cipher_type = MBEDTLS_CIPHER_AES_256_ECB; break;
|
|
++ default: return -1;
|
|
++ }
|
|
++ const mbedtls_cipher_info_t *cipher_info;
|
|
++ cipher_info = mbedtls_cipher_info_from_type(cipher_type);
|
|
++ if (cipher_info == NULL)
|
|
++ return -1;
|
|
++
|
|
++ mbedtls_cipher_context_t ctx;
|
|
++ mbedtls_cipher_init(&ctx);
|
|
++ int ret = -1;
|
|
++ if (mbedtls_cipher_setup(&ctx, cipher_info) == 0
|
|
++ && mbedtls_cipher_cmac_starts(&ctx, key, key_len*8) == 0) {
|
|
++ ret = 0;
|
|
++ for (size_t i = 0; i < num_elem && ret == 0; ++i)
|
|
++ ret = mbedtls_cipher_cmac_update(&ctx, addr[i], len[i]);
|
|
++ }
|
|
++ if (ret == 0)
|
|
++ ret = mbedtls_cipher_cmac_finish(&ctx, mac);
|
|
++ mbedtls_cipher_free(&ctx);
|
|
++ return ret ? -1 : 0;
|
|
++}
|
|
++
|
|
++int omac1_aes_128_vector(const u8 *key, size_t num_elem,
|
|
++ const u8 *addr[], const size_t *len,
|
|
++ u8 *mac)
|
|
++{
|
|
++ return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
|
|
++}
|
|
++
|
|
++int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
|
|
++{
|
|
++ return omac1_aes_vector(key, 16, 1, &data, &data_len, mac);
|
|
++}
|
|
++
|
|
++int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
|
|
++{
|
|
++ return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
|
|
++}
|
|
++
|
|
++#else
|
|
++
|
|
++#include "aes-omac1.c" /* pull in hostap local implementation */
|
|
++
|
|
++#ifndef MBEDTLS_AES_BLOCK_SIZE
|
|
++#define MBEDTLS_AES_BLOCK_SIZE 16
|
|
++#endif
|
|
++
|
|
++#endif /* MBEDTLS_CMAC_C */
|
|
++
|
|
++
|
|
++/* These interfaces can be inefficient when used in loops, as the overhead of
|
|
++ * initialization each call is large for each block input (e.g. 16 bytes) */
|
|
++
|
|
++
|
|
++/* aes-encblock.c */
|
|
++int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out)
|
|
++{
|
|
++ mbedtls_aes_context aes;
|
|
++ mbedtls_aes_init(&aes);
|
|
++ int ret = mbedtls_aes_setkey_enc(&aes, key, 128)
|
|
++ || mbedtls_aes_crypt_ecb(&aes, MBEDTLS_AES_ENCRYPT, in, out)
|
|
++ ? -1
|
|
++ : 0;
|
|
++ mbedtls_aes_free(&aes);
|
|
++ return ret;
|
|
++}
|
|
++
|
|
++
|
|
++/* aes-ctr.c */
|
|
++int aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce,
|
|
++ u8 *data, size_t data_len)
|
|
++{
|
|
++ unsigned char counter[MBEDTLS_AES_BLOCK_SIZE];
|
|
++ unsigned char stream_block[MBEDTLS_AES_BLOCK_SIZE];
|
|
++ os_memcpy(counter, nonce, MBEDTLS_AES_BLOCK_SIZE);/*(must be writable)*/
|
|
++
|
|
++ mbedtls_aes_context ctx;
|
|
++ mbedtls_aes_init(&ctx);
|
|
++ size_t nc_off = 0;
|
|
++ int ret = mbedtls_aes_setkey_enc(&ctx, key, key_len*8)
|
|
++ || mbedtls_aes_crypt_ctr(&ctx, data_len, &nc_off,
|
|
++ counter, stream_block,
|
|
++ data, data) ? -1 : 0;
|
|
++ forced_memzero(stream_block, sizeof(stream_block));
|
|
++ mbedtls_aes_free(&ctx);
|
|
++ return ret;
|
|
++}
|
|
++
|
|
++int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,
|
|
++ u8 *data, size_t data_len)
|
|
++{
|
|
++ return aes_ctr_encrypt(key, 16, nonce, data, data_len);
|
|
++}
|
|
++
|
|
++
|
|
++/* aes-cbc.c */
|
|
++static int aes_128_cbc_oper(const u8 *key, const u8 *iv,
|
|
++ u8 *data, size_t data_len, int mode)
|
|
++{
|
|
++ unsigned char ivec[MBEDTLS_AES_BLOCK_SIZE];
|
|
++ os_memcpy(ivec, iv, MBEDTLS_AES_BLOCK_SIZE); /*(must be writable)*/
|
|
++
|
|
++ mbedtls_aes_context ctx;
|
|
++ mbedtls_aes_init(&ctx);
|
|
++ int ret = (mode == MBEDTLS_AES_ENCRYPT
|
|
++ ? mbedtls_aes_setkey_enc(&ctx, key, 128)
|
|
++ : mbedtls_aes_setkey_dec(&ctx, key, 128))
|
|
++ || mbedtls_aes_crypt_cbc(&ctx, mode, data_len, ivec, data, data);
|
|
++ mbedtls_aes_free(&ctx);
|
|
++ return ret ? -1 : 0;
|
|
++}
|
|
++
|
|
++int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
|
|
++{
|
|
++ return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_ENCRYPT);
|
|
++}
|
|
++
|
|
++int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
|
|
++{
|
|
++ return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_DECRYPT);
|
|
++}
|
|
++
|
|
++
|
|
++/*
|
|
++ * Much of the following is documented in crypto.h as for CONFIG_TLS=internal
|
|
++ * but such comments are not accurate:
|
|
++ *
|
|
++ * "This function is only used with internal TLSv1 implementation
|
|
++ * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
|
++ * to implement this."
|
|
++ */
|
|
++
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_CIPHER
|
|
++
|
|
++#include <mbedtls/cipher.h>
|
|
++
|
|
++struct crypto_cipher
|
|
++{
|
|
++ mbedtls_cipher_context_t ctx_enc;
|
|
++ mbedtls_cipher_context_t ctx_dec;
|
|
++};
|
|
++
|
|
++struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
|
|
++ const u8 *iv, const u8 *key,
|
|
++ size_t key_len)
|
|
++{
|
|
++ /* IKEv2 src/eap_common/ikev2_common.c:ikev2_{encr,decr}_encrypt()
|
|
++ * uses one of CRYPTO_CIPHER_ALG_AES or CRYPTO_CIPHER_ALG_3DES */
|
|
++
|
|
++ mbedtls_cipher_type_t cipher_type;
|
|
++ size_t iv_len;
|
|
++ switch (alg) {
|
|
++ #ifdef MBEDTLS_ARC4_C
|
|
++ #if 0
|
|
++ case CRYPTO_CIPHER_ALG_RC4:
|
|
++ cipher_type = MBEDTLS_CIPHER_ARC4_128;
|
|
++ iv_len = 0;
|
|
++ break;
|
|
++ #endif
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_AES_C
|
|
++ case CRYPTO_CIPHER_ALG_AES:
|
|
++ if (key_len == 16) cipher_type = MBEDTLS_CIPHER_AES_128_CTR;
|
|
++ if (key_len == 24) cipher_type = MBEDTLS_CIPHER_AES_192_CTR;
|
|
++ if (key_len == 32) cipher_type = MBEDTLS_CIPHER_AES_256_CTR;
|
|
++ iv_len = 16;
|
|
++ break;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_DES_C
|
|
++ case CRYPTO_CIPHER_ALG_3DES:
|
|
++ cipher_type = MBEDTLS_CIPHER_DES_EDE3_CBC;
|
|
++ iv_len = 8;
|
|
++ break;
|
|
++ #if 0
|
|
++ case CRYPTO_CIPHER_ALG_DES:
|
|
++ cipher_type = MBEDTLS_CIPHER_DES_CBC;
|
|
++ iv_len = 8;
|
|
++ break;
|
|
++ #endif
|
|
++ #endif
|
|
++ default:
|
|
++ return NULL;
|
|
++ }
|
|
++
|
|
++ const mbedtls_cipher_info_t *cipher_info;
|
|
++ cipher_info = mbedtls_cipher_info_from_type(cipher_type);
|
|
++ if (cipher_info == NULL)
|
|
++ return NULL;
|
|
++
|
|
++ key_len *= 8; /* key_bitlen */
|
|
++ #if 0 /*(were key_bitlen not already available)*/
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03010000 /* mbedtls 3.1.0 */
|
|
++ key_len = mbedtls_cipher_info_get_key_bitlen(cipher_info);
|
|
++ #else
|
|
++ key_len = cipher_info->MBEDTLS_PRIVATE(key_bitlen);
|
|
++ #endif
|
|
++ #endif
|
|
++
|
|
++ #if 0 /*(were iv_len not known above, would need MBEDTLS_PRIVATE(iv_size))*/
|
|
++ iv_len = cipher_info->MBEDTLS_PRIVATE(iv_size);
|
|
++ #endif
|
|
++
|
|
++ struct crypto_cipher *ctx = os_malloc(sizeof(*ctx));
|
|
++ if (!ctx)
|
|
++ return NULL;
|
|
++
|
|
++ mbedtls_cipher_init(&ctx->ctx_enc);
|
|
++ mbedtls_cipher_init(&ctx->ctx_dec);
|
|
++ if ( mbedtls_cipher_setup(&ctx->ctx_enc,cipher_info) == 0
|
|
++ && mbedtls_cipher_setup(&ctx->ctx_dec,cipher_info) == 0
|
|
++ && mbedtls_cipher_setkey(&ctx->ctx_enc,key,key_len,MBEDTLS_ENCRYPT) == 0
|
|
++ && mbedtls_cipher_setkey(&ctx->ctx_dec,key,key_len,MBEDTLS_DECRYPT) == 0
|
|
++ && mbedtls_cipher_set_iv(&ctx->ctx_enc,iv,iv_len) == 0
|
|
++ && mbedtls_cipher_set_iv(&ctx->ctx_dec,iv,iv_len) == 0
|
|
++ && mbedtls_cipher_reset(&ctx->ctx_enc) == 0
|
|
++ && mbedtls_cipher_reset(&ctx->ctx_dec) == 0) {
|
|
++ return ctx;
|
|
++ }
|
|
++
|
|
++ mbedtls_cipher_free(&ctx->ctx_enc);
|
|
++ mbedtls_cipher_free(&ctx->ctx_dec);
|
|
++ os_free(ctx);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++int crypto_cipher_encrypt(struct crypto_cipher *ctx,
|
|
++ const u8 *plain, u8 *crypt, size_t len)
|
|
++{
|
|
++ size_t olen = 0; /*(poor interface above; unknown size of u8 *crypt)*/
|
|
++ return (mbedtls_cipher_update(&ctx->ctx_enc, plain, len, crypt, &olen)
|
|
++ || mbedtls_cipher_finish(&ctx->ctx_enc, crypt + olen, &olen)) ? -1 : 0;
|
|
++}
|
|
++
|
|
++int crypto_cipher_decrypt(struct crypto_cipher *ctx,
|
|
++ const u8 *crypt, u8 *plain, size_t len)
|
|
++{
|
|
++ size_t olen = 0; /*(poor interface above; unknown size of u8 *plain)*/
|
|
++ return (mbedtls_cipher_update(&ctx->ctx_dec, crypt, len, plain, &olen)
|
|
++ || mbedtls_cipher_finish(&ctx->ctx_dec, plain + olen, &olen)) ? -1 : 0;
|
|
++}
|
|
++
|
|
++void crypto_cipher_deinit(struct crypto_cipher *ctx)
|
|
++{
|
|
++ mbedtls_cipher_free(&ctx->ctx_enc);
|
|
++ mbedtls_cipher_free(&ctx->ctx_dec);
|
|
++ os_free(ctx);
|
|
++}
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_CIPHER */
|
|
++
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_HASH
|
|
++
|
|
++struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
|
|
++ size_t key_len)
|
|
++{
|
|
++ mbedtls_md_type_t md_type;
|
|
++ int is_hmac = 0;
|
|
++
|
|
++ switch (alg) {
|
|
++ #ifdef MBEDTLS_MD5_C
|
|
++ case CRYPTO_HASH_ALG_MD5:
|
|
++ md_type = MBEDTLS_MD_MD5;
|
|
++ break;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_SHA1_C
|
|
++ case CRYPTO_HASH_ALG_SHA1:
|
|
++ md_type = MBEDTLS_MD_SHA1;
|
|
++ break;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_MD5_C
|
|
++ case CRYPTO_HASH_ALG_HMAC_MD5:
|
|
++ md_type = MBEDTLS_MD_MD5;
|
|
++ is_hmac = 1;
|
|
++ break;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_SHA1_C
|
|
++ case CRYPTO_HASH_ALG_HMAC_SHA1:
|
|
++ md_type = MBEDTLS_MD_SHA1;
|
|
++ is_hmac = 1;
|
|
++ break;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_SHA256_C
|
|
++ case CRYPTO_HASH_ALG_SHA256:
|
|
++ md_type = MBEDTLS_MD_SHA256;
|
|
++ break;
|
|
++ case CRYPTO_HASH_ALG_HMAC_SHA256:
|
|
++ md_type = MBEDTLS_MD_SHA256;
|
|
++ is_hmac = 1;
|
|
++ break;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_SHA512_C
|
|
++ case CRYPTO_HASH_ALG_SHA384:
|
|
++ md_type = MBEDTLS_MD_SHA384;
|
|
++ break;
|
|
++ case CRYPTO_HASH_ALG_SHA512:
|
|
++ md_type = MBEDTLS_MD_SHA512;
|
|
++ break;
|
|
++ #endif
|
|
++ default:
|
|
++ return NULL;
|
|
++ }
|
|
++
|
|
++ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
|
|
++ if (!md_info)
|
|
++ return NULL;
|
|
++
|
|
++ mbedtls_md_context_t *mctx = os_malloc(sizeof(*mctx));
|
|
++ if (mctx == NULL)
|
|
++ return NULL;
|
|
++
|
|
++ mbedtls_md_init(mctx);
|
|
++ if (mbedtls_md_setup(mctx, md_info, is_hmac) != 0) {
|
|
++ os_free(mctx);
|
|
++ return NULL;
|
|
++ }
|
|
++
|
|
++ if (is_hmac)
|
|
++ mbedtls_md_hmac_starts(mctx, key, key_len);
|
|
++ else
|
|
++ mbedtls_md_starts(mctx);
|
|
++ return (struct crypto_hash *)((uintptr_t)mctx | is_hmac);
|
|
++}
|
|
++
|
|
++void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
|
|
++{
|
|
++ mbedtls_md_context_t *mctx = (mbedtls_md_context_t*)((uintptr_t)ctx & ~1uL);
|
|
++ #if 0
|
|
++ /*(mbedtls_md_hmac_update() and mbedtls_md_update()
|
|
++ * make same modifications under the hood in mbedtls)*/
|
|
++ if ((uintptr_t)ctx & 1uL)
|
|
++ mbedtls_md_hmac_update(mctx, data, len);
|
|
++ else
|
|
++ #endif
|
|
++ mbedtls_md_update(mctx, data, len);
|
|
++}
|
|
++
|
|
++int crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
|
|
++{
|
|
++ mbedtls_md_context_t *mctx = (mbedtls_md_context_t*)((uintptr_t)ctx & ~1uL);
|
|
++ if (mac != NULL && len != NULL) { /*(NULL if caller just freeing context)*/
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */
|
|
++ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_ctx(mctx);
|
|
++ #else
|
|
++ const mbedtls_md_info_t *md_info = mctx->MBEDTLS_PRIVATE(md_info);
|
|
++ #endif
|
|
++ size_t maclen = mbedtls_md_get_size(md_info);
|
|
++ if (*len < maclen) {
|
|
++ *len = maclen;
|
|
++ /*(note: ctx not freed; can call again with larger *len)*/
|
|
++ return -1;
|
|
++ }
|
|
++ *len = maclen;
|
|
++ if ((uintptr_t)ctx & 1uL)
|
|
++ mbedtls_md_hmac_finish(mctx, mac);
|
|
++ else
|
|
++ mbedtls_md_finish(mctx, mac);
|
|
++ }
|
|
++ mbedtls_md_free(mctx);
|
|
++ os_free(mctx);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_HASH */
|
|
++
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_BIGNUM
|
|
++
|
|
++#include <mbedtls/bignum.h>
|
|
++
|
|
++/* crypto.h bignum interfaces */
|
|
++
|
|
++struct crypto_bignum *crypto_bignum_init(void)
|
|
++{
|
|
++ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
|
|
++ if (bn)
|
|
++ mbedtls_mpi_init(bn);
|
|
++ return (struct crypto_bignum *)bn;
|
|
++}
|
|
++
|
|
++struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len)
|
|
++{
|
|
++ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
|
|
++ if (bn) {
|
|
++ mbedtls_mpi_init(bn);
|
|
++ if (mbedtls_mpi_read_binary(bn, buf, len) == 0)
|
|
++ return (struct crypto_bignum *)bn;
|
|
++ }
|
|
++
|
|
++ os_free(bn);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++struct crypto_bignum *crypto_bignum_init_uint(unsigned int val)
|
|
++{
|
|
++ #if 0 /*(hostap use of this interface passes int, not uint)*/
|
|
++ val = host_to_be32(val);
|
|
++ return crypto_bignum_init_set((const u8 *)&val, sizeof(val));
|
|
++ #else
|
|
++ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
|
|
++ if (bn) {
|
|
++ mbedtls_mpi_init(bn);
|
|
++ if (mbedtls_mpi_lset(bn, (int)val) == 0)
|
|
++ return (struct crypto_bignum *)bn;
|
|
++ }
|
|
++
|
|
++ os_free(bn);
|
|
++ return NULL;
|
|
++ #endif
|
|
++}
|
|
++
|
|
++void crypto_bignum_deinit(struct crypto_bignum *n, int clear)
|
|
++{
|
|
++ mbedtls_mpi_free((mbedtls_mpi *)n);
|
|
++ os_free(n);
|
|
++}
|
|
++
|
|
++int crypto_bignum_to_bin(const struct crypto_bignum *a,
|
|
++ u8 *buf, size_t buflen, size_t padlen)
|
|
++{
|
|
++ size_t n = mbedtls_mpi_size((mbedtls_mpi *)a);
|
|
++ if (n < padlen)
|
|
++ n = padlen;
|
|
++ return n > buflen || mbedtls_mpi_write_binary((mbedtls_mpi *)a, buf, n)
|
|
++ ? -1
|
|
++ : (int)(n);
|
|
++}
|
|
++
|
|
++int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
|
|
++{
|
|
++ /*assert(r != m);*//* r must not be same as m for mbedtls_mpi_random()*/
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x021B0000 /* mbedtls 2.27.0 */
|
|
++ return mbedtls_mpi_random((mbedtls_mpi *)r, 0, (mbedtls_mpi *)m,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg()) ? -1 : 0;
|
|
++ #else
|
|
++ /* (needed by EAP_PWD, SAE, DPP) */
|
|
++ wpa_printf(MSG_ERROR,
|
|
++ "mbedtls 2.27.0 or later required for mbedtls_mpi_random()");
|
|
++ return -1;
|
|
++ #endif
|
|
++}
|
|
++
|
|
++int crypto_bignum_add(const struct crypto_bignum *a,
|
|
++ const struct crypto_bignum *b,
|
|
++ struct crypto_bignum *c)
|
|
++{
|
|
++ return mbedtls_mpi_add_mpi((mbedtls_mpi *)c,
|
|
++ (const mbedtls_mpi *)a,
|
|
++ (const mbedtls_mpi *)b) ? -1 : 0;
|
|
++}
|
|
++
|
|
++int crypto_bignum_mod(const struct crypto_bignum *a,
|
|
++ const struct crypto_bignum *b,
|
|
++ struct crypto_bignum *c)
|
|
++{
|
|
++ return mbedtls_mpi_mod_mpi((mbedtls_mpi *)c,
|
|
++ (const mbedtls_mpi *)a,
|
|
++ (const mbedtls_mpi *)b) ? -1 : 0;
|
|
++}
|
|
++
|
|
++int crypto_bignum_exptmod(const struct crypto_bignum *a,
|
|
++ const struct crypto_bignum *b,
|
|
++ const struct crypto_bignum *c,
|
|
++ struct crypto_bignum *d)
|
|
++{
|
|
++ /* (check if input params match d; d is the result) */
|
|
++ /* (a == d) is ok in current mbedtls implementation */
|
|
++ if (b == d || c == d) { /*(not ok; store result in intermediate)*/
|
|
++ mbedtls_mpi R;
|
|
++ mbedtls_mpi_init(&R);
|
|
++ int rc = mbedtls_mpi_exp_mod(&R,
|
|
++ (const mbedtls_mpi *)a,
|
|
++ (const mbedtls_mpi *)b,
|
|
++ (const mbedtls_mpi *)c,
|
|
++ NULL)
|
|
++ || mbedtls_mpi_copy((mbedtls_mpi *)d, &R) ? -1 : 0;
|
|
++ mbedtls_mpi_free(&R);
|
|
++ return rc;
|
|
++ }
|
|
++ else {
|
|
++ return mbedtls_mpi_exp_mod((mbedtls_mpi *)d,
|
|
++ (const mbedtls_mpi *)a,
|
|
++ (const mbedtls_mpi *)b,
|
|
++ (const mbedtls_mpi *)c,
|
|
++ NULL) ? -1 : 0;
|
|
++ }
|
|
++}
|
|
++
|
|
++int crypto_bignum_inverse(const struct crypto_bignum *a,
|
|
++ const struct crypto_bignum *b,
|
|
++ struct crypto_bignum *c)
|
|
++{
|
|
++ return mbedtls_mpi_inv_mod((mbedtls_mpi *)c,
|
|
++ (const mbedtls_mpi *)a,
|
|
++ (const mbedtls_mpi *)b) ? -1 : 0;
|
|
++}
|
|
++
|
|
++int crypto_bignum_sub(const struct crypto_bignum *a,
|
|
++ const struct crypto_bignum *b,
|
|
++ struct crypto_bignum *c)
|
|
++{
|
|
++ return mbedtls_mpi_sub_mpi((mbedtls_mpi *)c,
|
|
++ (const mbedtls_mpi *)a,
|
|
++ (const mbedtls_mpi *)b) ? -1 : 0;
|
|
++}
|
|
++
|
|
++int crypto_bignum_div(const struct crypto_bignum *a,
|
|
++ const struct crypto_bignum *b,
|
|
++ struct crypto_bignum *c)
|
|
++{
|
|
++ /*(most current use of this crypto.h interface has a == c (result),
|
|
++ * so store result in an intermediate to avoid overwritten input)*/
|
|
++ mbedtls_mpi R;
|
|
++ mbedtls_mpi_init(&R);
|
|
++ int rc = mbedtls_mpi_div_mpi(&R, NULL,
|
|
++ (const mbedtls_mpi *)a,
|
|
++ (const mbedtls_mpi *)b)
|
|
++ || mbedtls_mpi_copy((mbedtls_mpi *)c, &R) ? -1 : 0;
|
|
++ mbedtls_mpi_free(&R);
|
|
++ return rc;
|
|
++}
|
|
++
|
|
++int crypto_bignum_addmod(const struct crypto_bignum *a,
|
|
++ const struct crypto_bignum *b,
|
|
++ const struct crypto_bignum *c,
|
|
++ struct crypto_bignum *d)
|
|
++{
|
|
++ return mbedtls_mpi_add_mpi((mbedtls_mpi *)d,
|
|
++ (const mbedtls_mpi *)a,
|
|
++ (const mbedtls_mpi *)b)
|
|
++ || mbedtls_mpi_mod_mpi((mbedtls_mpi *)d,
|
|
++ (mbedtls_mpi *)d,
|
|
++ (const mbedtls_mpi *)c) ? -1 : 0;
|
|
++}
|
|
++
|
|
++int crypto_bignum_mulmod(const struct crypto_bignum *a,
|
|
++ const struct crypto_bignum *b,
|
|
++ const struct crypto_bignum *c,
|
|
++ struct crypto_bignum *d)
|
|
++{
|
|
++ return mbedtls_mpi_mul_mpi((mbedtls_mpi *)d,
|
|
++ (const mbedtls_mpi *)a,
|
|
++ (const mbedtls_mpi *)b)
|
|
++ || mbedtls_mpi_mod_mpi((mbedtls_mpi *)d,
|
|
++ (mbedtls_mpi *)d,
|
|
++ (const mbedtls_mpi *)c) ? -1 : 0;
|
|
++}
|
|
++
|
|
++int crypto_bignum_sqrmod(const struct crypto_bignum *a,
|
|
++ const struct crypto_bignum *b,
|
|
++ struct crypto_bignum *c)
|
|
++{
|
|
++ #if 1
|
|
++ return crypto_bignum_mulmod(a, a, b, c);
|
|
++ #else
|
|
++ mbedtls_mpi bn;
|
|
++ mbedtls_mpi_init(&bn);
|
|
++ if (mbedtls_mpi_lset(&bn, 2)) /* alt?: mbedtls_mpi_set_bit(&bn, 1) */
|
|
++ return -1;
|
|
++ int ret = mbedtls_mpi_exp_mod((mbedtls_mpi *)c,
|
|
++ (const mbedtls_mpi *)a, &bn,
|
|
++ (const mbedtls_mpi *)b, NULL) ? -1 : 0;
|
|
++ mbedtls_mpi_free(&bn);
|
|
++ return ret;
|
|
++ #endif
|
|
++}
|
|
++
|
|
++int crypto_bignum_rshift(const struct crypto_bignum *a, int n,
|
|
++ struct crypto_bignum *r)
|
|
++{
|
|
++ return mbedtls_mpi_copy((mbedtls_mpi *)r, (const mbedtls_mpi *)a)
|
|
++ || mbedtls_mpi_shift_r((mbedtls_mpi *)r, n) ? -1 : 0;
|
|
++}
|
|
++
|
|
++int crypto_bignum_cmp(const struct crypto_bignum *a,
|
|
++ const struct crypto_bignum *b)
|
|
++{
|
|
++ return mbedtls_mpi_cmp_mpi((const mbedtls_mpi *)a, (const mbedtls_mpi *)b);
|
|
++}
|
|
++
|
|
++int crypto_bignum_is_zero(const struct crypto_bignum *a)
|
|
++{
|
|
++ /* XXX: src/common/sae.c:sswu() contains comment:
|
|
++ * "TODO: Make sure crypto_bignum_is_zero() is constant time"
|
|
++ * Note: mbedtls_mpi_cmp_int() *is not* constant time */
|
|
++ return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 0) == 0);
|
|
++}
|
|
++
|
|
++int crypto_bignum_is_one(const struct crypto_bignum *a)
|
|
++{
|
|
++ return (mbedtls_mpi_cmp_int((const mbedtls_mpi *)a, 1) == 0);
|
|
++}
|
|
++
|
|
++int crypto_bignum_is_odd(const struct crypto_bignum *a)
|
|
++{
|
|
++ return mbedtls_mpi_get_bit((const mbedtls_mpi *)a, 0);
|
|
++}
|
|
++
|
|
++#include "utils/const_time.h"
|
|
++int crypto_bignum_legendre(const struct crypto_bignum *a,
|
|
++ const struct crypto_bignum *p)
|
|
++{
|
|
++ /* Security Note:
|
|
++ * mbedtls_mpi_exp_mod() is not documented to run in constant time,
|
|
++ * though mbedtls/library/bignum.c uses constant_time_internal.h funcs.
|
|
++ * Compare to crypto_openssl.c:crypto_bignum_legendre()
|
|
++ * which uses openssl BN_mod_exp_mont_consttime()
|
|
++ * mbedtls/library/ecp.c has further countermeasures to timing attacks,
|
|
++ * (but ecp.c funcs are not used here) */
|
|
++
|
|
++ mbedtls_mpi exp, tmp;
|
|
++ mbedtls_mpi_init(&exp);
|
|
++ mbedtls_mpi_init(&tmp);
|
|
++
|
|
++ /* exp = (p-1) / 2 */
|
|
++ int res;
|
|
++ if (mbedtls_mpi_sub_int(&exp, (const mbedtls_mpi *)p, 1) == 0
|
|
++ && mbedtls_mpi_shift_r(&exp, 1) == 0
|
|
++ && mbedtls_mpi_exp_mod(&tmp, (const mbedtls_mpi *)a, &exp,
|
|
++ (const mbedtls_mpi *)p, NULL) == 0) {
|
|
++ /*(modified from crypto_openssl.c:crypto_bignum_legendre())*/
|
|
++ /* Return 1 if tmp == 1, 0 if tmp == 0, or -1 otherwise. Need
|
|
++ * to use constant time selection to avoid branches here. */
|
|
++ unsigned int mask;
|
|
++ res = -1;
|
|
++ mask = const_time_eq((mbedtls_mpi_cmp_int(&tmp, 1) == 0), 1);
|
|
++ res = const_time_select_int(mask, 1, res);
|
|
++ mask = const_time_eq((mbedtls_mpi_cmp_int(&tmp, 0) == 0), 1);
|
|
++ res = const_time_select_int(mask, 0, res);
|
|
++ } else {
|
|
++ res = -2;
|
|
++ }
|
|
++
|
|
++ mbedtls_mpi_free(&tmp);
|
|
++ mbedtls_mpi_free(&exp);
|
|
++ return res;
|
|
++}
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_BIGNUM */
|
|
++
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_DH
|
|
++
|
|
++/* crypto_internal-modexp.c */
|
|
++
|
|
++#include <mbedtls/bignum.h>
|
|
++#include <mbedtls/dhm.h>
|
|
++
|
|
++#if 0 /* crypto_dh_init() and crypto_dh_derive_secret() prefer to use mbedtls */
|
|
++int crypto_mod_exp(const u8 *base, size_t base_len,
|
|
++ const u8 *power, size_t power_len,
|
|
++ const u8 *modulus, size_t modulus_len,
|
|
++ u8 *result, size_t *result_len)
|
|
++{
|
|
++ mbedtls_mpi bn_base, bn_exp, bn_modulus, bn_result;
|
|
++ mbedtls_mpi_init(&bn_base);
|
|
++ mbedtls_mpi_init(&bn_exp);
|
|
++ mbedtls_mpi_init(&bn_modulus);
|
|
++ mbedtls_mpi_init(&bn_result);
|
|
++
|
|
++ size_t len;
|
|
++ int ret = mbedtls_mpi_read_binary(&bn_base, base, base_len)
|
|
++ || mbedtls_mpi_read_binary(&bn_exp, power, power_len)
|
|
++ || mbedtls_mpi_read_binary(&bn_modulus, modulus, modulus_len)
|
|
++ || mbedtls_mpi_exp_mod(&bn_result,&bn_base,&bn_exp,&bn_modulus,NULL)
|
|
++ || (len = mbedtls_mpi_size(&bn_result)) > *result_len
|
|
++ || mbedtls_mpi_write_binary(&bn_result, result, (*result_len = len))
|
|
++ ? -1
|
|
++ : 0;
|
|
++
|
|
++ mbedtls_mpi_free(&bn_base);
|
|
++ mbedtls_mpi_free(&bn_exp);
|
|
++ mbedtls_mpi_free(&bn_modulus);
|
|
++ mbedtls_mpi_free(&bn_result);
|
|
++ return ret;
|
|
++}
|
|
++#endif
|
|
++
|
|
++static int crypto_mbedtls_dh_set_bin_pg(mbedtls_dhm_context *ctx, u8 generator,
|
|
++ const u8 *prime, size_t prime_len)
|
|
++{
|
|
++ /*(could set these directly in MBEDTLS_PRIVATE members)*/
|
|
++ mbedtls_mpi P, G;
|
|
++ mbedtls_mpi_init(&P);
|
|
++ mbedtls_mpi_init(&G);
|
|
++ int ret = mbedtls_mpi_lset(&G, generator)
|
|
++ || mbedtls_mpi_read_binary(&P, prime, prime_len)
|
|
++ || mbedtls_dhm_set_group(ctx, &P, &G);
|
|
++ mbedtls_mpi_free(&P);
|
|
++ mbedtls_mpi_free(&G);
|
|
++ return ret;
|
|
++}
|
|
++
|
|
++__attribute_noinline__
|
|
++static int crypto_mbedtls_dh_init_public(mbedtls_dhm_context *ctx, u8 generator,
|
|
++ const u8 *prime, size_t prime_len,
|
|
++ u8 *privkey, u8 *pubkey)
|
|
++{
|
|
++ if (crypto_mbedtls_dh_set_bin_pg(ctx, generator, prime, prime_len)
|
|
++ || mbedtls_dhm_make_public(ctx, (int)prime_len, pubkey, prime_len,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg()))
|
|
++ return -1;
|
|
++
|
|
++ /*(enable later when upstream mbedtls interface changes require)*/
|
|
++ #if 0 && MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++ mbedtls_mpi X;
|
|
++ mbedtls_mpi_init(&X);
|
|
++ int ret = mbedtls_dhm_get_value(ctx, MBEDTLS_DHM_PARAM_X, &X)
|
|
++ || mbedtls_mpi_write_binary(&X, privkey, prime_len) ? -1 : 0;
|
|
++ mbedtls_mpi_free(&X);
|
|
++ return ret;
|
|
++ #else
|
|
++ return mbedtls_mpi_write_binary(&ctx->MBEDTLS_PRIVATE(X),
|
|
++ privkey, prime_len) ? -1 : 0;
|
|
++ #endif
|
|
++}
|
|
++
|
|
++int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
|
|
++ u8 *pubkey)
|
|
++{
|
|
++ #if 0 /*(crypto_dh_init() duplicated (and identical) in crypto_*.c modules)*/
|
|
++ size_t pubkey_len, pad;
|
|
++
|
|
++ if (os_get_random(privkey, prime_len) < 0)
|
|
++ return -1;
|
|
++ if (os_memcmp(privkey, prime, prime_len) > 0) {
|
|
++ /* Make sure private value is smaller than prime */
|
|
++ privkey[0] = 0;
|
|
++ }
|
|
++
|
|
++ pubkey_len = prime_len;
|
|
++ if (crypto_mod_exp(&generator, 1, privkey, prime_len, prime, prime_len,
|
|
++ pubkey, &pubkey_len) < 0)
|
|
++ return -1;
|
|
++ if (pubkey_len < prime_len) {
|
|
++ pad = prime_len - pubkey_len;
|
|
++ os_memmove(pubkey + pad, pubkey, pubkey_len);
|
|
++ os_memset(pubkey, 0, pad);
|
|
++ }
|
|
++
|
|
++ return 0;
|
|
++ #else
|
|
++ /* Prefer to use mbedtls to derive our public/private key, as doing so
|
|
++ * leverages mbedtls to properly format output and to perform blinding*/
|
|
++ mbedtls_dhm_context ctx;
|
|
++ mbedtls_dhm_init(&ctx);
|
|
++ int ret = crypto_mbedtls_dh_init_public(&ctx, generator, prime,
|
|
++ prime_len, privkey, pubkey);
|
|
++ mbedtls_dhm_free(&ctx);
|
|
++ return ret;
|
|
++ #endif
|
|
++}
|
|
++
|
|
++/*(crypto_dh_derive_secret() could be implemented using crypto.h APIs
|
|
++ * instead of being reimplemented in each crypto_*.c)*/
|
|
++int crypto_dh_derive_secret(u8 generator, const u8 *prime, size_t prime_len,
|
|
++ const u8 *order, size_t order_len,
|
|
++ const u8 *privkey, size_t privkey_len,
|
|
++ const u8 *pubkey, size_t pubkey_len,
|
|
++ u8 *secret, size_t *len)
|
|
++{
|
|
++ #if 0
|
|
++ if (pubkey_len > prime_len ||
|
|
++ (pubkey_len == prime_len &&
|
|
++ os_memcmp(pubkey, prime, prime_len) >= 0))
|
|
++ return -1;
|
|
++
|
|
++ int res = 0;
|
|
++ mbedtls_mpi pub;
|
|
++ mbedtls_mpi_init(&pub);
|
|
++ if (mbedtls_mpi_read_binary(&pub, pubkey, pubkey_len)
|
|
++ || mbedtls_mpi_cmp_int(&pub, 1) <= 0) {
|
|
++ res = -1;
|
|
++ } else if (order) {
|
|
++ mbedtls_mpi p, q, tmp;
|
|
++ mbedtls_mpi_init(&p);
|
|
++ mbedtls_mpi_init(&q);
|
|
++ mbedtls_mpi_init(&tmp);
|
|
++
|
|
++ /* verify: pubkey^q == 1 mod p */
|
|
++ res = (mbedtls_mpi_read_binary(&p, prime, prime_len)
|
|
++ || mbedtls_mpi_read_binary(&q, order, order_len)
|
|
++ || mbedtls_mpi_exp_mod(&tmp, &pub, &q, &p, NULL)
|
|
++ || mbedtls_mpi_cmp_int(&tmp, 1) != 0);
|
|
++
|
|
++ mbedtls_mpi_free(&p);
|
|
++ mbedtls_mpi_free(&q);
|
|
++ mbedtls_mpi_free(&tmp);
|
|
++ }
|
|
++ mbedtls_mpi_free(&pub);
|
|
++
|
|
++ return (res == 0)
|
|
++ ? crypto_mod_exp(pubkey, pubkey_len, privkey, privkey_len,
|
|
++ prime, prime_len, secret, len)
|
|
++ : -1;
|
|
++ #else
|
|
++ /* Prefer to use mbedtls to derive DH shared secret, as doing so
|
|
++ * leverages mbedtls to validate params and to perform blinding.
|
|
++ *
|
|
++ * Attempt to reconstitute DH context to derive shared secret
|
|
++ * (due to limitations of the interface, which ought to pass context).
|
|
++ * Force provided G (our private key) into context without validation.
|
|
++ * Regenerating GX (our public key) not needed to derive shared secret.
|
|
++ */
|
|
++ /*(older compilers might not support VLAs)*/
|
|
++ /*unsigned char buf[2+prime_len+2+1+2+pubkey_len];*/
|
|
++ unsigned char buf[2+MBEDTLS_MPI_MAX_SIZE+2+1+2+MBEDTLS_MPI_MAX_SIZE];
|
|
++ unsigned char *p = buf + 2 + prime_len;
|
|
++ if (2+prime_len+2+1+2+pubkey_len > sizeof(buf))
|
|
++ return -1;
|
|
++ WPA_PUT_BE16(buf, prime_len); /*(2-byte big-endian size of prime)*/
|
|
++ p[0] = 0; /*(2-byte big-endian size of generator)*/
|
|
++ p[1] = 1;
|
|
++ p[2] = generator;
|
|
++ WPA_PUT_BE16(p+3, pubkey_len); /*(2-byte big-endian size of pubkey)*/
|
|
++ os_memcpy(p+5, pubkey, pubkey_len);
|
|
++ os_memcpy(buf+2, prime, prime_len);
|
|
++
|
|
++ mbedtls_dhm_context ctx;
|
|
++ mbedtls_dhm_init(&ctx);
|
|
++ p = buf;
|
|
++ int ret = mbedtls_dhm_read_params(&ctx, &p, p+2+prime_len+5+pubkey_len)
|
|
++ || mbedtls_mpi_read_binary(&ctx.MBEDTLS_PRIVATE(X),
|
|
++ privkey, privkey_len)
|
|
++ || mbedtls_dhm_calc_secret(&ctx, secret, *len, len,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg()) ? -1 : 0;
|
|
++ mbedtls_dhm_free(&ctx);
|
|
++ return ret;
|
|
++ #endif
|
|
++}
|
|
++
|
|
++/* dh_group5.c */
|
|
++
|
|
++#include "dh_group5.h"
|
|
++
|
|
++/* RFC3526_PRIME_1536[] and RFC3526_GENERATOR_1536[] from crypto_wolfssl.c */
|
|
++
|
|
++static const unsigned char RFC3526_PRIME_1536[] = {
|
|
++ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
|
++ 0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
|
++ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
|
++ 0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
|
++ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
|
++ 0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
|
++ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
|
++ 0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
|
++ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
|
|
++ 0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
|
++ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
|
|
++ 0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
|
++ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
|
|
++ 0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
|
++ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
|
|
++ 0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
|
++};
|
|
++
|
|
++static const unsigned char RFC3526_GENERATOR_1536[] = {
|
|
++ 0x02
|
|
++};
|
|
++
|
|
++void * dh5_init(struct wpabuf **priv, struct wpabuf **publ)
|
|
++{
|
|
++ const unsigned char * const prime = RFC3526_PRIME_1536;
|
|
++ const size_t prime_len = sizeof(RFC3526_PRIME_1536);
|
|
++ const u8 generator = *RFC3526_GENERATOR_1536;
|
|
++ struct wpabuf *wpubl = NULL, *wpriv = NULL;
|
|
++
|
|
++ mbedtls_dhm_context *ctx = os_malloc(sizeof(*ctx));
|
|
++ if (ctx == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_dhm_init(ctx);
|
|
++
|
|
++ if ( (wpubl = wpabuf_alloc(prime_len))
|
|
++ && (wpriv = wpabuf_alloc(prime_len))
|
|
++ && crypto_mbedtls_dh_init_public(ctx, generator, prime, prime_len,
|
|
++ wpabuf_put(wpriv, prime_len),
|
|
++ wpabuf_put(wpubl, prime_len))==0) {
|
|
++ wpabuf_free(*publ);
|
|
++ wpabuf_clear_free(*priv);
|
|
++ *publ = wpubl;
|
|
++ *priv = wpriv;
|
|
++ return ctx;
|
|
++ }
|
|
++
|
|
++ wpabuf_clear_free(wpriv);
|
|
++ wpabuf_free(wpubl);
|
|
++ mbedtls_dhm_free(ctx);
|
|
++ os_free(ctx);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_DH5_INIT_FIXED
|
|
++void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ)
|
|
++{
|
|
++ const unsigned char * const prime = RFC3526_PRIME_1536;
|
|
++ const size_t prime_len = sizeof(RFC3526_PRIME_1536);
|
|
++ const u8 generator = *RFC3526_GENERATOR_1536;
|
|
++
|
|
++ mbedtls_dhm_context *ctx = os_malloc(sizeof(*ctx));
|
|
++ if (ctx == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_dhm_init(ctx);
|
|
++
|
|
++ if (crypto_mbedtls_dh_set_bin_pg(ctx, generator, prime, prime_len)==0
|
|
++ #if 0 /*(ignore; not required to derive shared secret)*/
|
|
++ && mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(GX),
|
|
++ wpabuf_head(publ),wpabuf_len(publ))==0
|
|
++ #endif
|
|
++ && mbedtls_mpi_read_binary(&ctx->MBEDTLS_PRIVATE(X),
|
|
++ wpabuf_head(priv),wpabuf_len(priv))==0) {
|
|
++ return ctx;
|
|
++ }
|
|
++
|
|
++ mbedtls_dhm_free(ctx);
|
|
++ os_free(ctx);
|
|
++ return NULL;
|
|
++}
|
|
++#endif
|
|
++
|
|
++struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
|
|
++ const struct wpabuf *own_private)
|
|
++{
|
|
++ /*((mbedtls_dhm_context *)ctx must already contain own_private)*/
|
|
++ /* mbedtls 2.x: prime_len = ctx->len; */
|
|
++ /* mbedtls 3.x: prime_len = mbedtls_dhm_get_len(ctx); */
|
|
++ size_t olen = sizeof(RFC3526_PRIME_1536); /*(sizeof(); prime known)*/
|
|
++ struct wpabuf *buf = wpabuf_alloc(olen);
|
|
++ if (buf == NULL)
|
|
++ return NULL;
|
|
++ if (mbedtls_dhm_read_public((mbedtls_dhm_context *)ctx,
|
|
++ wpabuf_head(peer_public),
|
|
++ wpabuf_len(peer_public)) == 0
|
|
++ && mbedtls_dhm_calc_secret(ctx, wpabuf_mhead(buf), olen, &olen,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg()) == 0) {
|
|
++ wpabuf_put(buf, olen);
|
|
++ return buf;
|
|
++ }
|
|
++
|
|
++ wpabuf_free(buf);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++void dh5_free(void *ctx)
|
|
++{
|
|
++ mbedtls_dhm_free(ctx);
|
|
++ os_free(ctx);
|
|
++}
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_DH */
|
|
++
|
|
++
|
|
++#if defined(CRYPTO_MBEDTLS_CRYPTO_ECDH) || defined(CRYPTO_MBEDTLS_CRYPTO_EC)
|
|
++
|
|
++#include <mbedtls/ecp.h>
|
|
++
|
|
++#define CRYPTO_EC_pbits(e) (((mbedtls_ecp_group *)(e))->pbits)
|
|
++#define CRYPTO_EC_plen(e) ((((mbedtls_ecp_group *)(e))->pbits+7)>>3)
|
|
++#define CRYPTO_EC_P(e) (&((mbedtls_ecp_group *)(e))->P)
|
|
++#define CRYPTO_EC_N(e) (&((mbedtls_ecp_group *)(e))->N)
|
|
++#define CRYPTO_EC_A(e) (&((mbedtls_ecp_group *)(e))->A)
|
|
++#define CRYPTO_EC_B(e) (&((mbedtls_ecp_group *)(e))->B)
|
|
++#define CRYPTO_EC_G(e) (&((mbedtls_ecp_group *)(e))->G)
|
|
++
|
|
++static mbedtls_ecp_group_id crypto_mbedtls_ecp_group_id_from_ike_id(int group)
|
|
++{
|
|
++ /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml */
|
|
++ switch (group) {
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
|
++ case 19: return MBEDTLS_ECP_DP_SECP256R1;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
|
++ case 20: return MBEDTLS_ECP_DP_SECP384R1;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
|
++ case 21: return MBEDTLS_ECP_DP_SECP521R1;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
|
++ case 25: return MBEDTLS_ECP_DP_SECP192R1;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED
|
|
++ case 26: return MBEDTLS_ECP_DP_SECP224R1;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED
|
|
++ case 28: return MBEDTLS_ECP_DP_BP256R1;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED
|
|
++ case 29: return MBEDTLS_ECP_DP_BP384R1;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED
|
|
++ case 30: return MBEDTLS_ECP_DP_BP512R1;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
|
|
++ case 31: return MBEDTLS_ECP_DP_CURVE25519;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
|
|
++ case 32: return MBEDTLS_ECP_DP_CURVE448;
|
|
++ #endif
|
|
++ default: return MBEDTLS_ECP_DP_NONE;
|
|
++ }
|
|
++}
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC
|
|
++static int crypto_mbedtls_ike_id_from_ecp_group_id(mbedtls_ecp_group_id grp_id)
|
|
++{
|
|
++ /* https://www.iana.org/assignments/ikev2-parameters/ikev2-parameters.xhtml */
|
|
++ /*(for crypto_ec_key_group())*/
|
|
++ switch (grp_id) {
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_SECP256R1: return 19;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_SECP384R1: return 20;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_SECP521R1: return 21;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_SECP192R1: return 25;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_SECP224R1: return 26;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_BP256R1: return 28;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_BP384R1: return 29;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_BP512R1: return 30;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
|
|
++ case MBEDTLS_ECP_DP_CURVE25519: return 31;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
|
|
++ case MBEDTLS_ECP_DP_CURVE448: return 32;
|
|
++ #endif
|
|
++ default: return -1;
|
|
++ }
|
|
++}
|
|
++#endif
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_ECDH || CRYPTO_MBEDTLS_CRYPTO_EC */
|
|
++
|
|
++
|
|
++#if defined(CRYPTO_MBEDTLS_CRYPTO_ECDH) || defined(CRYPTO_MBEDTLS_CRYPTO_EC_DPP)
|
|
++
|
|
++#include <mbedtls/ecp.h>
|
|
++#include <mbedtls/pk.h>
|
|
++
|
|
++static int crypto_mbedtls_keypair_gen(int group, mbedtls_pk_context *pk)
|
|
++{
|
|
++ mbedtls_ecp_group_id grp_id =
|
|
++ crypto_mbedtls_ecp_group_id_from_ike_id(group);
|
|
++ if (grp_id == MBEDTLS_ECP_DP_NONE)
|
|
++ return -1;
|
|
++ const mbedtls_pk_info_t *pk_info =
|
|
++ mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
|
|
++ if (pk_info == NULL)
|
|
++ return -1;
|
|
++ return mbedtls_pk_setup(pk, pk_info)
|
|
++ || mbedtls_ecp_gen_key(grp_id, mbedtls_pk_ec(*pk),
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg()) ? -1 : 0;
|
|
++}
|
|
++
|
|
++#endif
|
|
++
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_ECDH
|
|
++
|
|
++#include <mbedtls/ecdh.h>
|
|
++#include <mbedtls/ecdsa.h>
|
|
++#include <mbedtls/ecp.h>
|
|
++#include <mbedtls/pk.h>
|
|
++
|
|
++/* wrap mbedtls_ecdh_context for more future-proof direct access to components
|
|
++ * (mbedtls_ecdh_context internal implementation may change between releases)
|
|
++ *
|
|
++ * If mbedtls_pk_context -- specifically underlying mbedtls_ecp_keypair --
|
|
++ * lifetime were guaranteed to be longer than that of mbedtls_ecdh_context,
|
|
++ * then mbedtls_pk_context or mbedtls_ecp_keypair could be stored in crypto_ecdh
|
|
++ * (or crypto_ec_key could be stored in crypto_ecdh, and crypto_ec_key could
|
|
++ * wrap mbedtls_ecp_keypair and components, to avoid MBEDTLS_PRIVATE access) */
|
|
++struct crypto_ecdh {
|
|
++ mbedtls_ecdh_context ctx;
|
|
++ mbedtls_ecp_group grp;
|
|
++ mbedtls_ecp_point Q;
|
|
++};
|
|
++
|
|
++struct crypto_ecdh * crypto_ecdh_init(int group)
|
|
++{
|
|
++ mbedtls_pk_context pk;
|
|
++ mbedtls_pk_init(&pk);
|
|
++ struct crypto_ecdh *ecdh = crypto_mbedtls_keypair_gen(group, &pk) == 0
|
|
++ ? crypto_ecdh_init2(group, (struct crypto_ec_key *)&pk)
|
|
++ : NULL;
|
|
++ mbedtls_pk_free(&pk);
|
|
++ return ecdh;
|
|
++}
|
|
++
|
|
++struct crypto_ecdh * crypto_ecdh_init2(int group,
|
|
++ struct crypto_ec_key *own_key)
|
|
++{
|
|
++ mbedtls_ecp_group_id grp_id =
|
|
++ crypto_mbedtls_ecp_group_id_from_ike_id(group);
|
|
++ if (grp_id == MBEDTLS_ECP_DP_NONE)
|
|
++ return NULL;
|
|
++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)own_key);
|
|
++ struct crypto_ecdh *ecdh = os_malloc(sizeof(*ecdh));
|
|
++ if (ecdh == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_ecdh_init(&ecdh->ctx);
|
|
++ mbedtls_ecp_group_init(&ecdh->grp);
|
|
++ mbedtls_ecp_point_init(&ecdh->Q);
|
|
++ if (mbedtls_ecdh_setup(&ecdh->ctx, grp_id) == 0
|
|
++ && mbedtls_ecdh_get_params(&ecdh->ctx,ecp_kp,MBEDTLS_ECDH_OURS) == 0) {
|
|
++ /* copy grp and Q for later use
|
|
++ * (retrieving this info later is more convoluted
|
|
++ * even if mbedtls_ecdh_make_public() is considered)*/
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */
|
|
++ mbedtls_mpi d;
|
|
++ mbedtls_mpi_init(&d);
|
|
++ if (mbedtls_ecp_export(ecp_kp, &ecdh->grp, &d, &ecdh->Q) == 0) {
|
|
++ mbedtls_mpi_free(&d);
|
|
++ return ecdh;
|
|
++ }
|
|
++ mbedtls_mpi_free(&d);
|
|
++ #else
|
|
++ if (mbedtls_ecp_group_load(&ecdh->grp, grp_id) == 0
|
|
++ && mbedtls_ecp_copy(&ecdh->Q, &ecp_kp->MBEDTLS_PRIVATE(Q)) == 0)
|
|
++ return ecdh;
|
|
++ #endif
|
|
++ }
|
|
++
|
|
++ mbedtls_ecp_point_free(&ecdh->Q);
|
|
++ mbedtls_ecp_group_free(&ecdh->grp);
|
|
++ mbedtls_ecdh_free(&ecdh->ctx);
|
|
++ os_free(ecdh);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int inc_y)
|
|
++{
|
|
++ mbedtls_ecp_group *grp = &ecdh->grp;
|
|
++ size_t len = CRYPTO_EC_plen(grp);
|
|
++ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
|
|
++ /* len */
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
|
|
++ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS)
|
|
++ len = inc_y ? len*2+1 : len+1;
|
|
++ #endif
|
|
++ struct wpabuf *buf = wpabuf_alloc(len);
|
|
++ if (buf == NULL)
|
|
++ return NULL;
|
|
++ inc_y = inc_y ? MBEDTLS_ECP_PF_UNCOMPRESSED : MBEDTLS_ECP_PF_COMPRESSED;
|
|
++ if (mbedtls_ecp_point_write_binary(grp, &ecdh->Q, inc_y, &len,
|
|
++ wpabuf_mhead_u8(buf), len) == 0) {
|
|
++ wpabuf_put(buf, len);
|
|
++ return buf;
|
|
++ }
|
|
++
|
|
++ wpabuf_free(buf);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++#if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
|
|
++static int crypto_mbedtls_short_weierstrass_derive_y(mbedtls_ecp_group *grp,
|
|
++ mbedtls_mpi *bn,
|
|
++ int parity_bit)
|
|
++{
|
|
++ /* y^2 = x^3 + ax + b
|
|
++ * sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4) */
|
|
++ mbedtls_mpi *cy2 = (mbedtls_mpi *)
|
|
++ crypto_ec_point_compute_y_sqr((struct crypto_ec *)grp,
|
|
++ (const struct crypto_bignum *)bn); /*x*/
|
|
++ if (cy2 == NULL)
|
|
++ return -1;
|
|
++
|
|
++ /*mbedtls_mpi_free(bn);*/
|
|
++ /*(reuse bn to store result (y))*/
|
|
++
|
|
++ mbedtls_mpi exp;
|
|
++ mbedtls_mpi_init(&exp);
|
|
++ int ret = mbedtls_mpi_get_bit(&grp->P, 0) != 1 /*(p = 3 mod 4)*/
|
|
++ || mbedtls_mpi_get_bit(&grp->P, 1) != 1 /*(p = 3 mod 4)*/
|
|
++ || mbedtls_mpi_add_int(&exp, &grp->P, 1)
|
|
++ || mbedtls_mpi_shift_r(&exp, 2)
|
|
++ || mbedtls_mpi_exp_mod(bn, cy2, &exp, &grp->P, NULL)
|
|
++ || (mbedtls_mpi_get_bit(bn, 0) != parity_bit
|
|
++ && mbedtls_mpi_sub_mpi(bn, &grp->P, bn));
|
|
++ mbedtls_mpi_free(&exp);
|
|
++ mbedtls_mpi_free(cy2);
|
|
++ os_free(cy2);
|
|
++ return ret;
|
|
++}
|
|
++#endif
|
|
++
|
|
++struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
|
|
++ const u8 *key, size_t len)
|
|
++{
|
|
++ if (len == 0) /*(invalid peer key)*/
|
|
++ return NULL;
|
|
++
|
|
++ mbedtls_ecp_group *grp = &ecdh->grp;
|
|
++
|
|
++ #if defined(MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED)
|
|
++ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
|
|
++ /* add header for mbedtls_ecdh_read_public() */
|
|
++ u8 buf[256];
|
|
++ if (sizeof(buf)-1 < len)
|
|
++ return NULL;
|
|
++ buf[0] = (u8)(len);
|
|
++ os_memcpy(buf+1, key, len);
|
|
++
|
|
++ if (inc_y) {
|
|
++ if (!(len & 1)) { /*(dpp code/tests does not include tag?!?)*/
|
|
++ if (sizeof(buf)-2 < len)
|
|
++ return NULL;
|
|
++ buf[0] = (u8)(1+len);
|
|
++ buf[1] = 0x04;
|
|
++ os_memcpy(buf+2, key, len);
|
|
++ }
|
|
++ len >>= 1; /*(repurpose len to prime_len)*/
|
|
++ }
|
|
++ else if (key[0] == 0x02 || key[0] == 0x03) { /* (inc_y == 0) */
|
|
++ --len; /*(repurpose len to prime_len)*/
|
|
++
|
|
++ /* mbedtls_ecp_point_read_binary() does not currently support
|
|
++ * MBEDTLS_ECP_PF_COMPRESSED format (buf[1] = 0x02 or 0x03)
|
|
++ * (returns MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) */
|
|
++
|
|
++ /* derive y, amend buf[] with y for UNCOMPRESSED format */
|
|
++ if (sizeof(buf)-2 < len*2 || len == 0)
|
|
++ return NULL;
|
|
++ buf[0] = (u8)(1+len*2);
|
|
++ buf[1] = 0x04;
|
|
++ mbedtls_mpi bn;
|
|
++ mbedtls_mpi_init(&bn);
|
|
++ int ret = mbedtls_mpi_read_binary(&bn, key+1, len)
|
|
++ || crypto_mbedtls_short_weierstrass_derive_y(grp, &bn,
|
|
++ key[0] & 1)
|
|
++ || mbedtls_mpi_write_binary(&bn, buf+2+len, len);
|
|
++ mbedtls_mpi_free(&bn);
|
|
++ if (ret != 0)
|
|
++ return NULL;
|
|
++ }
|
|
++
|
|
++ if (key[0] == 0) /*(repurpose len to prime_len)*/
|
|
++ len = CRYPTO_EC_plen(grp);
|
|
++
|
|
++ if (mbedtls_ecdh_read_public(&ecdh->ctx, buf, buf[0]+1))
|
|
++ return NULL;
|
|
++ }
|
|
++ #endif
|
|
++ #if defined(MBEDTLS_ECP_MONTGOMERY_ENABLED)
|
|
++ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
|
++ if (mbedtls_ecdh_read_public(&ecdh->ctx, key, len))
|
|
++ return NULL;
|
|
++ }
|
|
++ #endif
|
|
++
|
|
++ struct wpabuf *buf = wpabuf_alloc(len);
|
|
++ if (buf == NULL)
|
|
++ return NULL;
|
|
++
|
|
++ if (mbedtls_ecdh_calc_secret(&ecdh->ctx, &len,
|
|
++ wpabuf_mhead(buf), len,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg()) == 0) {
|
|
++ wpabuf_put(buf, len);
|
|
++ return buf;
|
|
++ }
|
|
++
|
|
++ wpabuf_clear_free(buf);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++void crypto_ecdh_deinit(struct crypto_ecdh *ecdh)
|
|
++{
|
|
++ if (ecdh == NULL)
|
|
++ return;
|
|
++ mbedtls_ecp_point_free(&ecdh->Q);
|
|
++ mbedtls_ecp_group_free(&ecdh->grp);
|
|
++ mbedtls_ecdh_free(&ecdh->ctx);
|
|
++ os_free(ecdh);
|
|
++}
|
|
++
|
|
++size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh)
|
|
++{
|
|
++ return CRYPTO_EC_plen(&ecdh->grp);
|
|
++}
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_ECDH */
|
|
++
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC
|
|
++
|
|
++#include <mbedtls/ecp.h>
|
|
++
|
|
++struct crypto_ec *crypto_ec_init(int group)
|
|
++{
|
|
++ mbedtls_ecp_group_id grp_id =
|
|
++ crypto_mbedtls_ecp_group_id_from_ike_id(group);
|
|
++ if (grp_id == MBEDTLS_ECP_DP_NONE)
|
|
++ return NULL;
|
|
++ mbedtls_ecp_group *e = os_malloc(sizeof(*e));
|
|
++ if (e == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_ecp_group_init(e);
|
|
++ if (mbedtls_ecp_group_load(e, grp_id) == 0)
|
|
++ return (struct crypto_ec *)e;
|
|
++
|
|
++ mbedtls_ecp_group_free(e);
|
|
++ os_free(e);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++void crypto_ec_deinit(struct crypto_ec *e)
|
|
++{
|
|
++ mbedtls_ecp_group_free((mbedtls_ecp_group *)e);
|
|
++ os_free(e);
|
|
++}
|
|
++
|
|
++size_t crypto_ec_prime_len(struct crypto_ec *e)
|
|
++{
|
|
++ return CRYPTO_EC_plen(e);
|
|
++}
|
|
++
|
|
++size_t crypto_ec_prime_len_bits(struct crypto_ec *e)
|
|
++{
|
|
++ return CRYPTO_EC_pbits(e);
|
|
++}
|
|
++
|
|
++size_t crypto_ec_order_len(struct crypto_ec *e)
|
|
++{
|
|
++ return (mbedtls_mpi_bitlen(CRYPTO_EC_N(e)) + 7) / 8;
|
|
++}
|
|
++
|
|
++const struct crypto_bignum *crypto_ec_get_prime(struct crypto_ec *e)
|
|
++{
|
|
++ return (const struct crypto_bignum *)CRYPTO_EC_P(e);
|
|
++}
|
|
++
|
|
++const struct crypto_bignum *crypto_ec_get_order(struct crypto_ec *e)
|
|
++{
|
|
++ return (const struct crypto_bignum *)CRYPTO_EC_N(e);
|
|
++}
|
|
++
|
|
++const struct crypto_bignum *crypto_ec_get_a(struct crypto_ec *e)
|
|
++{
|
|
++ static const uint8_t secp256r1_a[] =
|
|
++ {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x01,
|
|
++ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
++ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc};
|
|
++ static const uint8_t secp384r1_a[] =
|
|
++ {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
|
|
++ 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
|
|
++ 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xfc};
|
|
++ static const uint8_t secp521r1_a[] =
|
|
++ {0x01,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xfc};
|
|
++ static const uint8_t secp192r1_a[] =
|
|
++ {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfc};
|
|
++ static const uint8_t secp224r1_a[] =
|
|
++ {0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,
|
|
++ 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
|
++ 0xff,0xff,0xff,0xfe};
|
|
++
|
|
++ const uint8_t *bin = NULL;
|
|
++ size_t len = 0;
|
|
++
|
|
++ /* (mbedtls groups matching supported sswu_curve_param() IKE groups) */
|
|
++ switch (((mbedtls_ecp_group *)e)->id) {
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_SECP256R1:
|
|
++ bin = secp256r1_a;
|
|
++ len = sizeof(secp256r1_a);
|
|
++ break;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP384R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_SECP384R1:
|
|
++ bin = secp384r1_a;
|
|
++ len = sizeof(secp384r1_a);
|
|
++ break;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP521R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_SECP521R1:
|
|
++ bin = secp521r1_a;
|
|
++ len = sizeof(secp521r1_a);
|
|
++ break;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP192R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_SECP192R1:
|
|
++ bin = secp192r1_a;
|
|
++ len = sizeof(secp192r1_a);
|
|
++ break;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_SECP224R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_SECP224R1:
|
|
++ bin = secp224r1_a;
|
|
++ len = sizeof(secp224r1_a);
|
|
++ break;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_BP256R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_BP256R1:
|
|
++ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_BP384R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_BP384R1:
|
|
++ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_BP512R1_ENABLED
|
|
++ case MBEDTLS_ECP_DP_BP512R1:
|
|
++ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
|
|
++ case MBEDTLS_ECP_DP_CURVE25519:
|
|
++ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
|
|
++ case MBEDTLS_ECP_DP_CURVE448:
|
|
++ return (const struct crypto_bignum *)CRYPTO_EC_A(e);
|
|
++ #endif
|
|
++ default:
|
|
++ return NULL;
|
|
++ }
|
|
++
|
|
++ /*(note: not thread-safe; returns file-scoped static storage)*/
|
|
++ if (mbedtls_mpi_read_binary(&mpi_sw_A, bin, len) == 0)
|
|
++ return (const struct crypto_bignum *)&mpi_sw_A;
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++const struct crypto_bignum *crypto_ec_get_b(struct crypto_ec *e)
|
|
++{
|
|
++ return (const struct crypto_bignum *)CRYPTO_EC_B(e);
|
|
++}
|
|
++
|
|
++const struct crypto_ec_point * crypto_ec_get_generator(struct crypto_ec *e)
|
|
++{
|
|
++ return (const struct crypto_ec_point *)CRYPTO_EC_G(e);
|
|
++}
|
|
++
|
|
++struct crypto_ec_point *crypto_ec_point_init(struct crypto_ec *e)
|
|
++{
|
|
++ mbedtls_ecp_point *p = os_malloc(sizeof(*p));
|
|
++ if (p != NULL)
|
|
++ mbedtls_ecp_point_init(p);
|
|
++ return (struct crypto_ec_point *)p;
|
|
++}
|
|
++
|
|
++void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear)
|
|
++{
|
|
++ mbedtls_ecp_point_free((mbedtls_ecp_point *)p);
|
|
++ os_free(p);
|
|
++}
|
|
++
|
|
++int crypto_ec_point_x(struct crypto_ec *e, const struct crypto_ec_point *p,
|
|
++ struct crypto_bignum *x)
|
|
++{
|
|
++ mbedtls_mpi *px = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X);
|
|
++ return mbedtls_mpi_copy((mbedtls_mpi *)x, px)
|
|
++ ? -1
|
|
++ : 0;
|
|
++}
|
|
++
|
|
++int crypto_ec_point_to_bin(struct crypto_ec *e,
|
|
++ const struct crypto_ec_point *point, u8 *x, u8 *y)
|
|
++{
|
|
++ /* crypto.h documents crypto_ec_point_to_bin() output is big-endian */
|
|
++ size_t len = CRYPTO_EC_plen(e);
|
|
++ if (x) {
|
|
++ mbedtls_mpi *px = &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(X);
|
|
++ if (mbedtls_mpi_write_binary(px, x, len))
|
|
++ return -1;
|
|
++ }
|
|
++ if (y) {
|
|
++ #if 0 /*(should not be necessary; py mpi should be in initial state)*/
|
|
++ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
|
|
++ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
|
|
++ == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
|
++ os_memset(y, 0, len);
|
|
++ return 0;
|
|
++ }
|
|
++ #endif
|
|
++ #endif
|
|
++ mbedtls_mpi *py = &((mbedtls_ecp_point *)point)->MBEDTLS_PRIVATE(Y);
|
|
++ if (mbedtls_mpi_write_binary(py, y, len))
|
|
++ return -1;
|
|
++ }
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
|
|
++ const u8 *val)
|
|
++{
|
|
++ size_t len = CRYPTO_EC_plen(e);
|
|
++ mbedtls_ecp_point *p = os_malloc(sizeof(*p));
|
|
++ u8 buf[1+MBEDTLS_MPI_MAX_SIZE*2];
|
|
++ if (p == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_ecp_point_init(p);
|
|
++
|
|
++ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
|
|
++ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
|
|
++ == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
|
|
++ #if 0 /* prefer alternative to MBEDTLS_PRIVATE() access */
|
|
++ mbedtls_mpi *px = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X);
|
|
++ mbedtls_mpi *py = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y);
|
|
++ mbedtls_mpi *pz = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Z);
|
|
++
|
|
++ if (mbedtls_mpi_read_binary(px, val, len) == 0
|
|
++ && mbedtls_mpi_read_binary(py, val + len, len) == 0
|
|
++ && mbedtls_mpi_lset(pz, 1) == 0)
|
|
++ return (struct crypto_ec_point *)p;
|
|
++ #else
|
|
++ buf[0] = 0x04;
|
|
++ os_memcpy(buf+1, val, len*2);
|
|
++ if (mbedtls_ecp_point_read_binary((mbedtls_ecp_group *)e, p,
|
|
++ buf, 1+len*2) == 0)
|
|
++ return (struct crypto_ec_point *)p;
|
|
++ #endif
|
|
++ }
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
|
|
++ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
|
|
++ == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
|
++ /* crypto.h interface documents crypto_ec_point_from_bin()
|
|
++ * val is length: prime_len * 2 and is big-endian
|
|
++ * (Short Weierstrass is assumed by hostap)
|
|
++ * Reverse to little-endian format for Montgomery */
|
|
++ for (unsigned int i = 0; i < len; ++i)
|
|
++ buf[i] = val[len-1-i];
|
|
++ if (mbedtls_ecp_point_read_binary((mbedtls_ecp_group *)e, p,
|
|
++ buf, len) == 0)
|
|
++ return (struct crypto_ec_point *)p;
|
|
++ }
|
|
++ #endif
|
|
++
|
|
++ mbedtls_ecp_point_free(p);
|
|
++ os_free(p);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a,
|
|
++ const struct crypto_ec_point *b,
|
|
++ struct crypto_ec_point *c)
|
|
++{
|
|
++ /* mbedtls does not provide an mbedtls_ecp_point add function */
|
|
++ mbedtls_mpi one;
|
|
++ mbedtls_mpi_init(&one);
|
|
++ int ret = mbedtls_mpi_lset(&one, 1)
|
|
++ || mbedtls_ecp_muladd(
|
|
++ (mbedtls_ecp_group *)e, (mbedtls_ecp_point *)c,
|
|
++ &one, (const mbedtls_ecp_point *)a,
|
|
++ &one, (const mbedtls_ecp_point *)b) ? -1 : 0;
|
|
++ mbedtls_mpi_free(&one);
|
|
++ return ret;
|
|
++}
|
|
++
|
|
++int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p,
|
|
++ const struct crypto_bignum *b,
|
|
++ struct crypto_ec_point *res)
|
|
++{
|
|
++ return mbedtls_ecp_mul(
|
|
++ (mbedtls_ecp_group *)e, (mbedtls_ecp_point *)res,
|
|
++ (const mbedtls_mpi *)b, (const mbedtls_ecp_point *)p,
|
|
++ mbedtls_ctr_drbg_random, crypto_mbedtls_ctr_drbg()) ? -1 : 0;
|
|
++}
|
|
++
|
|
++int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
|
|
++{
|
|
++ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
|
|
++ == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
|
++ /* e.g. MBEDTLS_ECP_DP_CURVE25519 and MBEDTLS_ECP_DP_CURVE448 */
|
|
++ wpa_printf(MSG_ERROR,
|
|
++ "%s not implemented for Montgomery curves",__func__);
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ /* mbedtls does not provide an mbedtls_ecp_point invert function */
|
|
++ /* below works for Short Weierstrass; incorrect for Montgomery curves */
|
|
++ mbedtls_mpi *py = &((mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y);
|
|
++ return mbedtls_ecp_is_zero((mbedtls_ecp_point *)p) /*point at infinity*/
|
|
++ || mbedtls_mpi_cmp_int(py, 0) == 0 /*point is its own inverse*/
|
|
++ || mbedtls_mpi_sub_abs(py, CRYPTO_EC_P(e), py) == 0 ? 0 : -1;
|
|
++}
|
|
++
|
|
++#ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
|
|
++static int
|
|
++crypto_ec_point_y_sqr_weierstrass(mbedtls_ecp_group *e, const mbedtls_mpi *x,
|
|
++ mbedtls_mpi *y2)
|
|
++{
|
|
++ /* MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS y^2 = x^3 + a x + b */
|
|
++
|
|
++ /* Short Weierstrass elliptic curve group w/o A set treated as A = -3 */
|
|
++ /* Attempt to match mbedtls/library/ecp.c:ecp_check_pubkey_sw() behavior
|
|
++ * and elsewhere in mbedtls/library/ecp.c where if A is not set, it is
|
|
++ * treated as if A = -3. */
|
|
++
|
|
++ #if 0
|
|
++ /* y^2 = x^3 + ax + b */
|
|
++ mbedtls_mpi *A = &e->A;
|
|
++ mbedtls_mpi t, A_neg3;
|
|
++ if (&e->A.p == NULL) {
|
|
++ mbedtls_mpi_init(&A_neg3);
|
|
++ if (mbedtls_mpi_lset(&A_neg3, -3) != 0) {
|
|
++ mbedtls_mpi_free(&A_neg3);
|
|
++ return -1;
|
|
++ }
|
|
++ A = &A_neg3;
|
|
++ }
|
|
++ mbedtls_mpi_init(&t);
|
|
++ int ret = /* x^3 */
|
|
++ mbedtls_mpi_lset(&t, 3)
|
|
++ || mbedtls_mpi_exp_mod(y2, x, &t, &e->P, NULL)
|
|
++ /* ax */
|
|
++ || mbedtls_mpi_mul_mpi(y2, y2, A)
|
|
++ || mbedtls_mpi_mod_mpi(&t, &t, &e->P)
|
|
++ /* ax + b */
|
|
++ || mbedtls_mpi_add_mpi(&t, &t, &e->B)
|
|
++ || mbedtls_mpi_mod_mpi(&t, &t, &e->P)
|
|
++ /* x^3 + ax + b */
|
|
++ || mbedtls_mpi_add_mpi(&t, &t, y2) /* ax + b + x^3 */
|
|
++ || mbedtls_mpi_mod_mpi(y2, &t, &e->P);
|
|
++ mbedtls_mpi_free(&t);
|
|
++ if (A == &A_neg3)
|
|
++ mbedtls_mpi_free(&A_neg3);
|
|
++ return ret; /* 0: success, non-zero: failure */
|
|
++ #else
|
|
++ /* y^2 = x^3 + ax + b = (x^2 + a)x + b */
|
|
++ return /* x^2 */
|
|
++ mbedtls_mpi_mul_mpi(y2, x, x)
|
|
++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
|
|
++ /* x^2 + a */
|
|
++ || (e->A.MBEDTLS_PRIVATE(p)
|
|
++ ? mbedtls_mpi_add_mpi(y2, y2, &e->A)
|
|
++ : mbedtls_mpi_sub_int(y2, y2, 3))
|
|
++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
|
|
++ /* (x^2 + a)x */
|
|
++ || mbedtls_mpi_mul_mpi(y2, y2, x)
|
|
++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
|
|
++ /* (x^2 + a)x + b */
|
|
++ || mbedtls_mpi_add_mpi(y2, y2, &e->B)
|
|
++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P);
|
|
++ #endif
|
|
++}
|
|
++#endif /* MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED */
|
|
++
|
|
++#if 0 /* not used by hostap */
|
|
++#ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
|
|
++static int
|
|
++crypto_ec_point_y_sqr_montgomery(mbedtls_ecp_group *e, const mbedtls_mpi *x,
|
|
++ mbedtls_mpi *y2)
|
|
++{
|
|
++ /* XXX: !!! must be reviewed and audited for correctness !!! */
|
|
++
|
|
++ /* MBEDTLS_ECP_TYPE_MONTGOMERY y^2 = x^3 + a x^2 + x */
|
|
++
|
|
++ /* y^2 = x^3 + a x^2 + x = (x + a)x^2 + x */
|
|
++ mbedtls_mpi x2;
|
|
++ mbedtls_mpi_init(&x2);
|
|
++ int ret = /* x^2 */
|
|
++ mbedtls_mpi_mul_mpi(&x2, x, x)
|
|
++ || mbedtls_mpi_mod_mpi(&x2, &x2, &e->P)
|
|
++ /* x + a */
|
|
++ || mbedtls_mpi_add_mpi(y2, x, &e->A)
|
|
++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
|
|
++ /* (x + a)x^2 */
|
|
++ || mbedtls_mpi_mul_mpi(y2, y2, &x2)
|
|
++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P)
|
|
++ /* (x + a)x^2 + x */
|
|
++ || mbedtls_mpi_add_mpi(y2, y2, x)
|
|
++ || mbedtls_mpi_mod_mpi(y2, y2, &e->P);
|
|
++ mbedtls_mpi_free(&x2);
|
|
++ return ret; /* 0: success, non-zero: failure */
|
|
++}
|
|
++#endif /* MBEDTLS_ECP_MONTGOMERY_ENABLED */
|
|
++#endif
|
|
++
|
|
++struct crypto_bignum *
|
|
++crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
|
|
++ const struct crypto_bignum *x)
|
|
++{
|
|
++ mbedtls_mpi *y2 = os_malloc(sizeof(*y2));
|
|
++ if (y2 == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_mpi_init(y2);
|
|
++
|
|
++ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
|
|
++ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
|
|
++ == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS
|
|
++ && crypto_ec_point_y_sqr_weierstrass((mbedtls_ecp_group *)e,
|
|
++ (const mbedtls_mpi *)x,
|
|
++ y2) == 0)
|
|
++ return (struct crypto_bignum *)y2;
|
|
++ #endif
|
|
++ #if 0 /* not used by hostap */
|
|
++ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
|
|
++ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
|
|
++ == MBEDTLS_ECP_TYPE_MONTGOMERY
|
|
++ && crypto_ec_point_y_sqr_montgomery((mbedtls_ecp_group *)e,
|
|
++ (const mbedtls_mpi *)x,
|
|
++ y2) == 0)
|
|
++ return (struct crypto_bignum *)y2;
|
|
++ #endif
|
|
++ #endif
|
|
++
|
|
++ mbedtls_mpi_free(y2);
|
|
++ os_free(y2);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++int crypto_ec_point_is_at_infinity(struct crypto_ec *e,
|
|
++ const struct crypto_ec_point *p)
|
|
++{
|
|
++ return mbedtls_ecp_is_zero((mbedtls_ecp_point *)p);
|
|
++}
|
|
++
|
|
++int crypto_ec_point_is_on_curve(struct crypto_ec *e,
|
|
++ const struct crypto_ec_point *p)
|
|
++{
|
|
++ #if 1
|
|
++ return mbedtls_ecp_check_pubkey((const mbedtls_ecp_group *)e,
|
|
++ (const mbedtls_ecp_point *)p) == 0;
|
|
++ #else
|
|
++ /* compute y^2 mod P and compare to y^2 mod P */
|
|
++ /*(ref: src/eap_common/eap_pwd_common.c:compute_password_element())*/
|
|
++ const mbedtls_mpi *px = &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(X);
|
|
++ mbedtls_mpi *cy2 = (mbedtls_mpi *)
|
|
++ crypto_ec_point_compute_y_sqr(e, (const struct crypto_bignum *)px);
|
|
++ if (cy2 == NULL)
|
|
++ return 0;
|
|
++
|
|
++ mbedtls_mpi y2;
|
|
++ mbedtls_mpi_init(&y2);
|
|
++ const mbedtls_mpi *py = &((const mbedtls_ecp_point *)p)->MBEDTLS_PRIVATE(Y);
|
|
++ int is_on_curve = mbedtls_mpi_mul_mpi(&y2, py, py) /* y^2 mod P */
|
|
++ || mbedtls_mpi_mod_mpi(&y2, &y2, CRYPTO_EC_P(e))
|
|
++ || mbedtls_mpi_cmp_mpi(&y2, cy2) != 0 ? 0 : 1;
|
|
++
|
|
++ mbedtls_mpi_free(&y2);
|
|
++ mbedtls_mpi_free(cy2);
|
|
++ os_free(cy2);
|
|
++ return is_on_curve;
|
|
++ #endif
|
|
++}
|
|
++
|
|
++int crypto_ec_point_cmp(const struct crypto_ec *e,
|
|
++ const struct crypto_ec_point *a,
|
|
++ const struct crypto_ec_point *b)
|
|
++{
|
|
++ return mbedtls_ecp_point_cmp((const mbedtls_ecp_point *)a,
|
|
++ (const mbedtls_ecp_point *)b);
|
|
++}
|
|
++
|
|
++#if !defined(CONFIG_NO_STDOUT_DEBUG)
|
|
++void crypto_ec_point_debug_print(const struct crypto_ec *e,
|
|
++ const struct crypto_ec_point *p,
|
|
++ const char *title)
|
|
++{
|
|
++ u8 x[MBEDTLS_MPI_MAX_SIZE];
|
|
++ u8 y[MBEDTLS_MPI_MAX_SIZE];
|
|
++ size_t len = CRYPTO_EC_plen(e);
|
|
++ /* crypto_ec_point_to_bin ought to take (const struct crypto_ec *e) */
|
|
++ struct crypto_ec *ee;
|
|
++ *(const struct crypto_ec **)&ee = e; /*(cast away const)*/
|
|
++ if (crypto_ec_point_to_bin(ee, p, x, y) == 0) {
|
|
++ if (title)
|
|
++ wpa_printf(MSG_DEBUG, "%s", title);
|
|
++ wpa_hexdump(MSG_DEBUG, "x:", x, len);
|
|
++ wpa_hexdump(MSG_DEBUG, "y:", y, len);
|
|
++ }
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len)
|
|
++{
|
|
++ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
|
|
++ if (ctx == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_pk_init(ctx);
|
|
++ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
|
|
++ if (mbedtls_pk_parse_key(ctx, der, der_len, NULL, 0) == 0)
|
|
++ #else
|
|
++ if (mbedtls_pk_parse_key(ctx, der, der_len, NULL, 0,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg()) == 0)
|
|
++ #endif
|
|
++ return (struct crypto_ec_key *)ctx;
|
|
++
|
|
++ mbedtls_pk_free(ctx);
|
|
++ os_free(ctx);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_HPKE
|
|
++#ifdef CONFIG_MODULE_TESTS
|
|
++/*(for crypto_module_tests.c)*/
|
|
++struct crypto_ec_key * crypto_ec_key_set_priv(int group,
|
|
++ const u8 *raw, size_t raw_len)
|
|
++{
|
|
++ mbedtls_ecp_group_id grp_id =
|
|
++ crypto_mbedtls_ecp_group_id_from_ike_id(group);
|
|
++ if (grp_id == MBEDTLS_ECP_DP_NONE)
|
|
++ return NULL;
|
|
++ const mbedtls_pk_info_t *pk_info =
|
|
++ mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
|
|
++ if (pk_info == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
|
|
++ if (ctx == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_pk_init(ctx);
|
|
++ if (mbedtls_pk_setup(ctx, pk_info) == 0
|
|
++ && mbedtls_ecp_read_key(grp_id,mbedtls_pk_ec(*ctx),raw,raw_len) == 0) {
|
|
++ return (struct crypto_ec_key *)ctx;
|
|
++ }
|
|
++
|
|
++ mbedtls_pk_free(ctx);
|
|
++ os_free(ctx);
|
|
++ return NULL;
|
|
++}
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++#include <mbedtls/error.h>
|
|
++#include <mbedtls/oid.h>
|
|
++static int crypto_mbedtls_pk_parse_subpubkey_compressed(mbedtls_pk_context *ctx, const u8 *der, size_t der_len)
|
|
++{
|
|
++ /* The following is modified from:
|
|
++ * mbedtls/library/pkparse.c:mbedtls_pk_parse_subpubkey()
|
|
++ * mbedtls/library/pkparse.c:pk_get_pk_alg()
|
|
++ * mbedtls/library/pkparse.c:pk_use_ecparams()
|
|
++ */
|
|
++ mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
|
|
++ const mbedtls_pk_info_t *pk_info;
|
|
++ int ret;
|
|
++ size_t len;
|
|
++ const unsigned char *end = der+der_len;
|
|
++ unsigned char *p;
|
|
++ *(const unsigned char **)&p = der;
|
|
++
|
|
++ if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
|
|
++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
|
|
++ {
|
|
++ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) );
|
|
++ }
|
|
++
|
|
++ end = p + len;
|
|
++
|
|
++ /*
|
|
++ if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, &alg_params ) ) != 0 )
|
|
++ return( ret );
|
|
++ */
|
|
++ mbedtls_asn1_buf alg_oid, params;
|
|
++ memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) );
|
|
++ if( ( ret = mbedtls_asn1_get_alg( &p, end, &alg_oid, ¶ms ) ) != 0 )
|
|
++ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_ALG, ret ) );
|
|
++ if( mbedtls_oid_get_pk_alg( &alg_oid, &pk_alg ) != 0 )
|
|
++ return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
|
|
++
|
|
++ if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end, &len ) ) != 0 )
|
|
++ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) );
|
|
++
|
|
++ if( p + len != end )
|
|
++ return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY,
|
|
++ MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) );
|
|
++
|
|
++ if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL )
|
|
++ return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG );
|
|
++
|
|
++ if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 )
|
|
++ return( ret );
|
|
++
|
|
++ /* assume mbedtls_pk_parse_subpubkey(&der, der+der_len, ctx)
|
|
++ * has already run with ctx initialized up to pk_get_ecpubkey(),
|
|
++ * and pk_get_ecpubkey() has returned MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE
|
|
++ *
|
|
++ * mbedtls mbedtls_ecp_point_read_binary()
|
|
++ * does not handle point in COMPRESSED format
|
|
++ *
|
|
++ * (validate assumption that algorithm is EC) */
|
|
++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*ctx);
|
|
++ if (ecp_kp == NULL)
|
|
++ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
|
|
++ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
|
|
++ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
|
|
++ mbedtls_ecp_group_id grp_id;
|
|
++
|
|
++
|
|
++ /* mbedtls/library/pkparse.c:pk_use_ecparams() */
|
|
++
|
|
++ if( params.tag == MBEDTLS_ASN1_OID )
|
|
++ {
|
|
++ if( mbedtls_oid_get_ec_grp( ¶ms, &grp_id ) != 0 )
|
|
++ return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE );
|
|
++ }
|
|
++ else
|
|
++ {
|
|
++#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED)
|
|
++ /*(large code block not copied from mbedtls; unsupported)*/
|
|
++ #if 0
|
|
++ if( ( ret = pk_group_id_from_specified( ¶ms, &grp_id ) ) != 0 )
|
|
++ return( ret );
|
|
++ #endif
|
|
++#endif
|
|
++ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
|
|
++ }
|
|
++
|
|
++ /*
|
|
++ * grp may already be initialized; if so, make sure IDs match
|
|
++ */
|
|
++ if( ecp_kp_grp->id != MBEDTLS_ECP_DP_NONE && ecp_kp_grp->id != grp_id )
|
|
++ return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT );
|
|
++
|
|
++ if( ( ret = mbedtls_ecp_group_load( ecp_kp_grp, grp_id ) ) != 0 )
|
|
++ return( ret );
|
|
++
|
|
++
|
|
++ /* (validate assumption that EC point is in COMPRESSED format) */
|
|
++ len = CRYPTO_EC_plen(ecp_kp_grp);
|
|
++ if( mbedtls_ecp_get_type(ecp_kp_grp) != MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS
|
|
++ || (end - p) != 1+len
|
|
++ || (*p != 0x02 && *p != 0x03) )
|
|
++ return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
|
|
++
|
|
++ /* Instead of calling mbedtls/library/pkparse.c:pk_get_ecpubkey() to call
|
|
++ * mbedtls_ecp_point_read_binary(), manually parse point into ecp_kp_Q */
|
|
++ mbedtls_mpi *X = &ecp_kp_Q->MBEDTLS_PRIVATE(X);
|
|
++ mbedtls_mpi *Y = &ecp_kp_Q->MBEDTLS_PRIVATE(Y);
|
|
++ mbedtls_mpi *Z = &ecp_kp_Q->MBEDTLS_PRIVATE(Z);
|
|
++ ret = mbedtls_mpi_lset(Z, 1);
|
|
++ if (ret != 0)
|
|
++ return( ret );
|
|
++ ret = mbedtls_mpi_read_binary(X, p+1, len);
|
|
++ if (ret != 0)
|
|
++ return( ret );
|
|
++ /* derive Y
|
|
++ * (similar derivation of Y in crypto_mbedtls.c:crypto_ecdh_set_peerkey())*/
|
|
++ ret = mbedtls_mpi_copy(Y, X) /*(Y is used as input and output obj below)*/
|
|
++ || crypto_mbedtls_short_weierstrass_derive_y(ecp_kp_grp, Y, (*p & 1));
|
|
++ if (ret != 0)
|
|
++ return( ret );
|
|
++
|
|
++ return mbedtls_ecp_check_pubkey( ecp_kp_grp, ecp_kp_Q );
|
|
++}
|
|
++
|
|
++struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len)
|
|
++{
|
|
++ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
|
|
++ if (ctx == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_pk_init(ctx);
|
|
++ /*int rc = mbedtls_pk_parse_subpubkey(&der, der+der_len, ctx);*/
|
|
++ int rc = mbedtls_pk_parse_public_key(ctx, der, der_len);
|
|
++ if (rc == 0)
|
|
++ return (struct crypto_ec_key *)ctx;
|
|
++ else if (rc == MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) {
|
|
++ /* mbedtls mbedtls_ecp_point_read_binary()
|
|
++ * does not handle point in COMPRESSED format; parse internally */
|
|
++ rc = crypto_mbedtls_pk_parse_subpubkey_compressed(ctx,der,der_len);
|
|
++ if (rc == 0)
|
|
++ return (struct crypto_ec_key *)ctx;
|
|
++ }
|
|
++
|
|
++ mbedtls_pk_free(ctx);
|
|
++ os_free(ctx);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
|
|
++
|
|
++static struct crypto_ec_key *
|
|
++crypto_ec_key_set_pub_point_for_group(mbedtls_ecp_group_id grp_id,
|
|
++ const mbedtls_ecp_point *pub,
|
|
++ const u8 *buf, size_t len)
|
|
++{
|
|
++ const mbedtls_pk_info_t *pk_info =
|
|
++ mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY);
|
|
++ if (pk_info == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
|
|
++ if (ctx == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_pk_init(ctx);
|
|
++ if (mbedtls_pk_setup(ctx, pk_info) == 0) {
|
|
++ /* (Is private key generation necessary for callers?)
|
|
++ * alt: gen key then overwrite Q
|
|
++ * mbedtls_ecp_gen_key(grp_id, ecp_kp,
|
|
++ * mbedtls_ctr_drbg_random,
|
|
++ * crypto_mbedtls_ctr_drbg()) == 0
|
|
++ */
|
|
++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*ctx);
|
|
++ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
|
|
++ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
|
|
++ mbedtls_mpi *ecp_kp_d = &ecp_kp->MBEDTLS_PRIVATE(d);
|
|
++ if (mbedtls_ecp_group_load(ecp_kp_grp, grp_id) == 0
|
|
++ && (pub
|
|
++ ? mbedtls_ecp_copy(ecp_kp_Q, pub) == 0
|
|
++ : mbedtls_ecp_point_read_binary(ecp_kp_grp, ecp_kp_Q,
|
|
++ buf, len) == 0)
|
|
++ && mbedtls_ecp_gen_privkey(ecp_kp_grp, ecp_kp_d,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg()) == 0){
|
|
++ return (struct crypto_ec_key *)ctx;
|
|
++ }
|
|
++ }
|
|
++
|
|
++ mbedtls_pk_free(ctx);
|
|
++ os_free(ctx);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *x,
|
|
++ const u8 *y, size_t len)
|
|
++{
|
|
++ mbedtls_ecp_group_id grp_id =
|
|
++ crypto_mbedtls_ecp_group_id_from_ike_id(group);
|
|
++ if (grp_id == MBEDTLS_ECP_DP_NONE)
|
|
++ return NULL;
|
|
++ if (len > MBEDTLS_MPI_MAX_SIZE)
|
|
++ return NULL;
|
|
++ u8 buf[1+MBEDTLS_MPI_MAX_SIZE*2];
|
|
++ buf[0] = 0x04; /* assume x,y for Short Weierstrass */
|
|
++ os_memcpy(buf+1, x, len);
|
|
++ os_memcpy(buf+1+len, y, len);
|
|
++
|
|
++ return crypto_ec_key_set_pub_point_for_group(grp_id,NULL,buf,1+len*2);
|
|
++}
|
|
++
|
|
++struct crypto_ec_key *
|
|
++crypto_ec_key_set_pub_point(struct crypto_ec *e,
|
|
++ const struct crypto_ec_point *pub)
|
|
++{
|
|
++ mbedtls_ecp_group_id grp_id = ((mbedtls_ecp_group *)e)->id;
|
|
++ mbedtls_ecp_point *p = (mbedtls_ecp_point *)pub;
|
|
++ return crypto_ec_key_set_pub_point_for_group(grp_id, p, NULL, 0);
|
|
++}
|
|
++
|
|
++
|
|
++struct crypto_ec_key * crypto_ec_key_gen(int group)
|
|
++{
|
|
++ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
|
|
++ if (ctx == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_pk_init(ctx);
|
|
++ if (crypto_mbedtls_keypair_gen(group, ctx) == 0)
|
|
++ return (struct crypto_ec_key *)ctx;
|
|
++ mbedtls_pk_free(ctx);
|
|
++ os_free(ctx);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
|
|
++
|
|
++void crypto_ec_key_deinit(struct crypto_ec_key *key)
|
|
++{
|
|
++ mbedtls_pk_free((mbedtls_pk_context *)key);
|
|
++ os_free(key);
|
|
++}
|
|
++
|
|
++struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
|
|
++{
|
|
++ /* (similar to crypto_ec_key_get_pubkey_point(),
|
|
++ * but compressed point format and ASN.1 DER wrapping)*/
|
|
++#ifndef MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES /*(mbedtls/library/pkwrite.h)*/
|
|
++#define MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES ( 30 + 2 * MBEDTLS_ECP_MAX_BYTES )
|
|
++#endif
|
|
++ unsigned char buf[MBEDTLS_PK_ECP_PUB_DER_MAX_BYTES];
|
|
++ int len = mbedtls_pk_write_pubkey_der((mbedtls_pk_context *)key,
|
|
++ buf, sizeof(buf));
|
|
++ if (len < 0)
|
|
++ return NULL;
|
|
++ /* Note: data is written at the end of the buffer! Use the
|
|
++ * return value to determine where you should start
|
|
++ * using the buffer */
|
|
++ unsigned char *p = buf+sizeof(buf)-len;
|
|
++
|
|
++ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
|
|
++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
|
|
++ if (ecp_kp == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_ecp_group *grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
|
|
++ /* Note: sae_pk.c expects pubkey point in compressed format,
|
|
++ * but mbedtls_pk_write_pubkey_der() writes uncompressed format.
|
|
++ * Manually translate format and update lengths in DER format */
|
|
++ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS) {
|
|
++ unsigned char *end = buf+sizeof(buf);
|
|
++ size_t n;
|
|
++ /* SubjectPublicKeyInfo SEQUENCE */
|
|
++ mbedtls_asn1_get_tag(&p, end, &n,
|
|
++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
|
++ /* algorithm AlgorithmIdentifier */
|
|
++ unsigned char *a = p;
|
|
++ size_t alen;
|
|
++ mbedtls_asn1_get_tag(&p, end, &alen,
|
|
++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
|
++ p += alen;
|
|
++ alen = (size_t)(p - a);
|
|
++ /* subjectPublicKey BIT STRING */
|
|
++ mbedtls_asn1_get_tag(&p, end, &n, MBEDTLS_ASN1_BIT_STRING);
|
|
++ /* rewrite into compressed point format and rebuild ASN.1 */
|
|
++ p[1] = (buf[sizeof(buf)-1] & 1) ? 0x03 : 0x02;
|
|
++ n = 1 + 1 + (n-2)/2;
|
|
++ len = mbedtls_asn1_write_len(&p, buf, n) + (int)n;
|
|
++ len += mbedtls_asn1_write_tag(&p, buf, MBEDTLS_ASN1_BIT_STRING);
|
|
++ os_memmove(p-alen, a, alen);
|
|
++ len += alen;
|
|
++ p -= alen;
|
|
++ len += mbedtls_asn1_write_len(&p, buf, (size_t)len);
|
|
++ len += mbedtls_asn1_write_tag(&p, buf,
|
|
++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
|
++ }
|
|
++ #endif
|
|
++ return wpabuf_alloc_copy(p, (size_t)len);
|
|
++}
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
|
|
++
|
|
++struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
|
|
++ bool include_pub)
|
|
++{
|
|
++#ifndef MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES /*(mbedtls/library/pkwrite.h)*/
|
|
++#define MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES ( 29 + 3 * MBEDTLS_ECP_MAX_BYTES )
|
|
++#endif
|
|
++ unsigned char priv[MBEDTLS_PK_ECP_PRV_DER_MAX_BYTES];
|
|
++ int privlen = mbedtls_pk_write_key_der((mbedtls_pk_context *)key,
|
|
++ priv, sizeof(priv));
|
|
++ if (privlen < 0)
|
|
++ return NULL;
|
|
++
|
|
++ struct wpabuf *wbuf;
|
|
++
|
|
++ /* Note: data is written at the end of the buffer! Use the
|
|
++ * return value to determine where you should start
|
|
++ * using the buffer */
|
|
++ /* mbedtls_pk_write_key_der() includes publicKey in DER */
|
|
++ if (include_pub)
|
|
++ wbuf = wpabuf_alloc_copy(priv+sizeof(priv)-privlen, privlen);
|
|
++ else {
|
|
++ /* calculate publicKey offset and skip from end of buffer */
|
|
++ unsigned char *p = priv+sizeof(priv)-privlen;
|
|
++ unsigned char *end = priv+sizeof(priv);
|
|
++ size_t len;
|
|
++ /* ECPrivateKey SEQUENCE */
|
|
++ mbedtls_asn1_get_tag(&p, end, &len,
|
|
++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
|
++ /* version INTEGER */
|
|
++ unsigned char *v = p;
|
|
++ mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
|
|
++ p += len;
|
|
++ /* privateKey OCTET STRING */
|
|
++ mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
|
|
++ p += len;
|
|
++ /* parameters ECParameters */
|
|
++ mbedtls_asn1_get_tag(&p, end, &len,
|
|
++ MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED);
|
|
++ p += len;
|
|
++
|
|
++ /* write new SEQUENCE header (we know that it fits in priv[]) */
|
|
++ len = (size_t)(p - v);
|
|
++ p = v;
|
|
++ len += mbedtls_asn1_write_len(&p, priv, len);
|
|
++ len += mbedtls_asn1_write_tag(&p, priv,
|
|
++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
|
++ wbuf = wpabuf_alloc_copy(p, len);
|
|
++ }
|
|
++
|
|
++ forced_memzero(priv, sizeof(priv));
|
|
++ return wbuf;
|
|
++}
|
|
++
|
|
++struct wpabuf * crypto_ec_key_get_pubkey_point(struct crypto_ec_key *key,
|
|
++ int prefix)
|
|
++{
|
|
++ /*(similarities to crypto_ecdh_get_pubkey(), but different struct)*/
|
|
++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
|
|
++ if (ecp_kp == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_ecp_group *grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
|
|
++ size_t len = CRYPTO_EC_plen(grp);
|
|
++ #ifdef MBEDTLS_ECP_MONTGOMERY_ENABLED
|
|
++ /* len */
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_ECP_SHORT_WEIERSTRASS_ENABLED
|
|
++ if (mbedtls_ecp_get_type(grp) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS)
|
|
++ len = len*2+1;
|
|
++ #endif
|
|
++ struct wpabuf *buf = wpabuf_alloc(len);
|
|
++ if (buf == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
|
|
++ if (mbedtls_ecp_point_write_binary(grp, ecp_kp_Q,
|
|
++ MBEDTLS_ECP_PF_UNCOMPRESSED, &len,
|
|
++ wpabuf_mhead_u8(buf), len) == 0) {
|
|
++ if (!prefix) /* Remove 0x04 prefix if requested */
|
|
++ os_memmove(wpabuf_mhead(buf),wpabuf_mhead(buf)+1,--len);
|
|
++ wpabuf_put(buf, len);
|
|
++ return buf;
|
|
++ }
|
|
++
|
|
++ wpabuf_free(buf);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++struct crypto_ec_point *
|
|
++crypto_ec_key_get_public_key(struct crypto_ec_key *key)
|
|
++{
|
|
++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
|
|
++ if (ecp_kp == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_ecp_point *p = os_malloc(sizeof(*p));
|
|
++ if (p != NULL) {
|
|
++ /*(mbedtls_ecp_export() uses &ecp_kp->MBEDTLS_PRIVATE(grp))*/
|
|
++ mbedtls_ecp_point_init(p);
|
|
++ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
|
|
++ if (mbedtls_ecp_copy(p, ecp_kp_Q)) {
|
|
++ mbedtls_ecp_point_free(p);
|
|
++ os_free(p);
|
|
++ p = NULL;
|
|
++ }
|
|
++ }
|
|
++ return (struct crypto_ec_point *)p;
|
|
++}
|
|
++
|
|
++struct crypto_bignum *
|
|
++crypto_ec_key_get_private_key(struct crypto_ec_key *key)
|
|
++{
|
|
++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
|
|
++ if (ecp_kp == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
|
|
++ if (bn) {
|
|
++ /*(mbedtls_ecp_export() uses &ecp_kp->MBEDTLS_PRIVATE(grp))*/
|
|
++ mbedtls_mpi_init(bn);
|
|
++ mbedtls_mpi *ecp_kp_d = &ecp_kp->MBEDTLS_PRIVATE(d);
|
|
++ if (mbedtls_mpi_copy(bn, ecp_kp_d)) {
|
|
++ mbedtls_mpi_free(bn);
|
|
++ os_free(bn);
|
|
++ bn = NULL;
|
|
++ }
|
|
++ }
|
|
++ return (struct crypto_bignum *)bn;
|
|
++}
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
|
|
++
|
|
++static mbedtls_md_type_t crypto_ec_key_sign_md(size_t len)
|
|
++{
|
|
++ /* get mbedtls_md_type_t from length of hash data to be signed */
|
|
++ switch (len) {
|
|
++ case 64: return MBEDTLS_MD_SHA512;
|
|
++ case 48: return MBEDTLS_MD_SHA384;
|
|
++ case 32: return MBEDTLS_MD_SHA256;
|
|
++ case 20: return MBEDTLS_MD_SHA1;
|
|
++ case 16: return MBEDTLS_MD_MD5;
|
|
++ default: return MBEDTLS_MD_NONE;
|
|
++ }
|
|
++}
|
|
++
|
|
++struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data,
|
|
++ size_t len)
|
|
++{
|
|
++ #ifndef MBEDTLS_PK_SIGNATURE_MAX_SIZE /*(defined since mbedtls 2.20.0)*/
|
|
++ #if MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_MPI_MAX_SIZE
|
|
++ #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN
|
|
++ #else
|
|
++ #define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE
|
|
++ #endif
|
|
++ #endif
|
|
++ size_t sig_len = MBEDTLS_PK_SIGNATURE_MAX_SIZE;
|
|
++ struct wpabuf *buf = wpabuf_alloc(sig_len);
|
|
++ if (buf == NULL)
|
|
++ return NULL;
|
|
++ if (mbedtls_pk_sign((mbedtls_pk_context *)key,
|
|
++ crypto_ec_key_sign_md(len), data, len,
|
|
++ wpabuf_mhead_u8(buf),
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++ sig_len,
|
|
++ #endif
|
|
++ &sig_len,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg()) == 0) {
|
|
++ wpabuf_put(buf, sig_len);
|
|
++ return buf;
|
|
++ }
|
|
++
|
|
++ wpabuf_free(buf);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
|
|
++struct wpabuf * crypto_ec_key_sign_r_s(struct crypto_ec_key *key,
|
|
++ const u8 *data, size_t len)
|
|
++{
|
|
++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
|
|
++ if (ecp_kp == NULL)
|
|
++ return NULL;
|
|
++
|
|
++ size_t sig_len = MBEDTLS_ECDSA_MAX_LEN;
|
|
++ u8 buf[MBEDTLS_ECDSA_MAX_LEN];
|
|
++ if (mbedtls_ecdsa_write_signature(ecp_kp, crypto_ec_key_sign_md(len),
|
|
++ data, len, buf,
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++ sig_len,
|
|
++ #endif
|
|
++ &sig_len,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg())) {
|
|
++ return NULL;
|
|
++ }
|
|
++
|
|
++ /*(mbedtls_ecdsa_write_signature() writes signature in ASN.1)*/
|
|
++ /* parse ASN.1 to get r and s and lengths */
|
|
++ u8 *p = buf, *r, *s;
|
|
++ u8 *end = p + sig_len;
|
|
++ size_t rlen, slen;
|
|
++ mbedtls_asn1_get_tag(&p, end, &rlen,
|
|
++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
|
++ mbedtls_asn1_get_tag(&p, end, &rlen, MBEDTLS_ASN1_INTEGER);
|
|
++ r = p;
|
|
++ p += rlen;
|
|
++ mbedtls_asn1_get_tag(&p, end, &slen, MBEDTLS_ASN1_INTEGER);
|
|
++ s = p;
|
|
++
|
|
++ /* write raw r and s into out
|
|
++ * (including removal of leading 0 if added for ASN.1 integer)
|
|
++ * note: DPP caller expects raw r, s each padded to prime len */
|
|
++ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
|
|
++ size_t plen = CRYPTO_EC_plen(ecp_kp_grp);
|
|
++ if (rlen > plen) {
|
|
++ r += (rlen - plen);
|
|
++ rlen = plen;
|
|
++ }
|
|
++ if (slen > plen) {
|
|
++ s += (slen - plen);
|
|
++ slen = plen;
|
|
++ }
|
|
++ struct wpabuf *out = wpabuf_alloc(plen*2);
|
|
++ if (out) {
|
|
++ wpabuf_put(out, plen*2);
|
|
++ p = wpabuf_mhead_u8(out);
|
|
++ os_memset(p, 0, plen*2);
|
|
++ os_memcpy(p+plen*1-rlen, r, rlen);
|
|
++ os_memcpy(p+plen*2-slen, s, slen);
|
|
++ }
|
|
++ return out;
|
|
++}
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
|
|
++
|
|
++int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data,
|
|
++ size_t len, const u8 *sig, size_t sig_len)
|
|
++{
|
|
++ switch (mbedtls_pk_verify((mbedtls_pk_context *)key,
|
|
++ crypto_ec_key_sign_md(len), data, len,
|
|
++ sig, sig_len)) {
|
|
++ case 0:
|
|
++ /*case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:*//* XXX: allow? */
|
|
++ return 1;
|
|
++ case MBEDTLS_ERR_ECP_VERIFY_FAILED:
|
|
++ return 0;
|
|
++ default:
|
|
++ return -1;
|
|
++ }
|
|
++}
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
|
|
++int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *key,
|
|
++ const u8 *data, size_t len,
|
|
++ const u8 *r, size_t r_len,
|
|
++ const u8 *s, size_t s_len)
|
|
++{
|
|
++ /* reimplement mbedtls_ecdsa_read_signature() without encoding r and s
|
|
++ * into ASN.1 just for mbedtls_ecdsa_read_signature() to decode ASN.1 */
|
|
++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
|
|
++ if (ecp_kp == NULL)
|
|
++ return -1;
|
|
++ mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp);
|
|
++ mbedtls_ecp_point *ecp_kp_Q = &ecp_kp->MBEDTLS_PRIVATE(Q);
|
|
++
|
|
++ mbedtls_mpi mpi_r;
|
|
++ mbedtls_mpi mpi_s;
|
|
++ mbedtls_mpi_init(&mpi_r);
|
|
++ mbedtls_mpi_init(&mpi_s);
|
|
++ int ret = mbedtls_mpi_read_binary(&mpi_r, r, r_len)
|
|
++ || mbedtls_mpi_read_binary(&mpi_s, s, s_len) ? -1 : 0;
|
|
++ if (ret == 0) {
|
|
++ ret = mbedtls_ecdsa_verify(ecp_kp_grp, data, len,
|
|
++ ecp_kp_Q, &mpi_r, &mpi_s);
|
|
++ ret = ret ? ret == MBEDTLS_ERR_ECP_BAD_INPUT_DATA ? 0 : -1 : 1;
|
|
++ }
|
|
++ mbedtls_mpi_free(&mpi_r);
|
|
++ mbedtls_mpi_free(&mpi_s);
|
|
++ return ret;
|
|
++}
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
|
|
++
|
|
++int crypto_ec_key_group(struct crypto_ec_key *key)
|
|
++{
|
|
++ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)key);
|
|
++ if (ecp_kp == NULL)
|
|
++ return -1;
|
|
++ mbedtls_ecp_group *ecp_group = &ecp_kp->MBEDTLS_PRIVATE(grp);
|
|
++ return crypto_mbedtls_ike_id_from_ecp_group_id(ecp_group->id);
|
|
++}
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_EC_DPP
|
|
++
|
|
++int crypto_ec_key_cmp(struct crypto_ec_key *key1, struct crypto_ec_key *key2)
|
|
++{
|
|
++#if 0 /*(DPP is passing two public keys; unable to use pk_check_pair())*/
|
|
++ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
|
|
++ return mbedtls_pk_check_pair((const mbedtls_pk_context *)key1,
|
|
++ (const mbedtls_pk_context *)key2) ? -1 : 0;
|
|
++ #else
|
|
++ return mbedtls_pk_check_pair((const mbedtls_pk_context *)key1,
|
|
++ (const mbedtls_pk_context *)key2,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg()) ? -1 : 0;
|
|
++ #endif
|
|
++#else
|
|
++ mbedtls_ecp_keypair *ecp_kp1=mbedtls_pk_ec(*(mbedtls_pk_context *)key1);
|
|
++ mbedtls_ecp_keypair *ecp_kp2=mbedtls_pk_ec(*(mbedtls_pk_context *)key2);
|
|
++ if (ecp_kp1 == NULL || ecp_kp2 == NULL)
|
|
++ return -1;
|
|
++ mbedtls_ecp_group *ecp_kp1_grp = &ecp_kp1->MBEDTLS_PRIVATE(grp);
|
|
++ mbedtls_ecp_group *ecp_kp2_grp = &ecp_kp2->MBEDTLS_PRIVATE(grp);
|
|
++ mbedtls_ecp_point *ecp_kp1_Q = &ecp_kp1->MBEDTLS_PRIVATE(Q);
|
|
++ mbedtls_ecp_point *ecp_kp2_Q = &ecp_kp2->MBEDTLS_PRIVATE(Q);
|
|
++ return ecp_kp1_grp->id != ecp_kp2_grp->id
|
|
++ || mbedtls_ecp_point_cmp(ecp_kp1_Q, ecp_kp2_Q) ? -1 : 0;
|
|
++#endif
|
|
++}
|
|
++
|
|
++void crypto_ec_key_debug_print(const struct crypto_ec_key *key,
|
|
++ const char *title)
|
|
++{
|
|
++ /* TBD: what info is desirable here and in what human readable format?*/
|
|
++ /*(crypto_openssl.c prints a human-readably public key and attributes)*/
|
|
++ #if 0
|
|
++ struct mbedtls_pk_debug_item debug_item;
|
|
++ if (mbedtls_pk_debug((const mbedtls_pk_context *)key, &debug_item))
|
|
++ return;
|
|
++ /* ... */
|
|
++ #endif
|
|
++ wpa_printf(MSG_DEBUG, "%s: %s not implemented", title, __func__);
|
|
++}
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_EC_DPP */
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_EC */
|
|
++
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_CSR
|
|
++
|
|
++#include <mbedtls/x509_csr.h>
|
|
++#include <mbedtls/oid.h>
|
|
++
|
|
++struct crypto_csr * crypto_csr_init(void)
|
|
++{
|
|
++ mbedtls_x509write_csr *csr = os_malloc(sizeof(*csr));
|
|
++ if (csr != NULL)
|
|
++ mbedtls_x509write_csr_init(csr);
|
|
++ return (struct crypto_csr *)csr;
|
|
++}
|
|
++
|
|
++struct crypto_csr * crypto_csr_verify(const struct wpabuf *req)
|
|
++{
|
|
++ /* future: look for alternatives to MBEDTLS_PRIVATE() access */
|
|
++
|
|
++ /* sole caller src/common/dpp_crypto.c:dpp_validate_csr()
|
|
++ * uses (mbedtls_x509_csr *) to obtain CSR_ATTR_CHALLENGE_PASSWORD
|
|
++ * so allocate different object (mbedtls_x509_csr *) and special-case
|
|
++ * object when used in crypto_csr_get_attribute() and when free()d in
|
|
++ * crypto_csr_deinit(). */
|
|
++
|
|
++ mbedtls_x509_csr *csr = os_malloc(sizeof(*csr));
|
|
++ if (csr == NULL)
|
|
++ return NULL;
|
|
++ mbedtls_x509_csr_init(csr);
|
|
++ const mbedtls_md_info_t *md_info;
|
|
++ unsigned char digest[MBEDTLS_MD_MAX_SIZE];
|
|
++ if (mbedtls_x509_csr_parse_der(csr,wpabuf_head(req),wpabuf_len(req))==0
|
|
++ && (md_info=mbedtls_md_info_from_type(csr->MBEDTLS_PRIVATE(sig_md)))
|
|
++ != NULL
|
|
++ && mbedtls_md(md_info, csr->cri.p, csr->cri.len, digest) == 0) {
|
|
++ switch (mbedtls_pk_verify(&csr->pk,csr->MBEDTLS_PRIVATE(sig_md),
|
|
++ digest, mbedtls_md_get_size(md_info),
|
|
++ csr->MBEDTLS_PRIVATE(sig).p,
|
|
++ csr->MBEDTLS_PRIVATE(sig).len)) {
|
|
++ case 0:
|
|
++ /*case MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH:*//* XXX: allow? */
|
|
++ return (struct crypto_csr *)((uintptr_t)csr | 1uL);
|
|
++ default:
|
|
++ break;
|
|
++ }
|
|
++ }
|
|
++
|
|
++ mbedtls_x509_csr_free(csr);
|
|
++ os_free(csr);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++void crypto_csr_deinit(struct crypto_csr *csr)
|
|
++{
|
|
++ if ((uintptr_t)csr & 1uL) {
|
|
++ csr = (struct crypto_csr *)((uintptr_t)csr & ~1uL);
|
|
++ mbedtls_x509_csr_free((mbedtls_x509_csr *)csr);
|
|
++ }
|
|
++ else
|
|
++ mbedtls_x509write_csr_free((mbedtls_x509write_csr *)csr);
|
|
++ os_free(csr);
|
|
++}
|
|
++
|
|
++int crypto_csr_set_ec_public_key(struct crypto_csr *csr,
|
|
++ struct crypto_ec_key *key)
|
|
++{
|
|
++ mbedtls_x509write_csr_set_key((mbedtls_x509write_csr *)csr,
|
|
++ (mbedtls_pk_context *)key);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++int crypto_csr_set_name(struct crypto_csr *csr, enum crypto_csr_name type,
|
|
++ const char *name)
|
|
++{
|
|
++ /* specialized for src/common/dpp_crypto.c */
|
|
++
|
|
++ /* sole caller src/common/dpp_crypto.c:dpp_build_csr()
|
|
++ * calls this function only once, using type == CSR_NAME_CN
|
|
++ * (If called more than once, this code would need to append
|
|
++ * components to the subject name, which we could do by
|
|
++ * appending to (mbedtls_x509write_csr *) private member
|
|
++ * mbedtls_asn1_named_data *MBEDTLS_PRIVATE(subject)) */
|
|
++
|
|
++ const char *label;
|
|
++ switch (type) {
|
|
++ case CSR_NAME_CN: label = "CN="; break;
|
|
++ case CSR_NAME_SN: label = "SN="; break;
|
|
++ case CSR_NAME_C: label = "C="; break;
|
|
++ case CSR_NAME_O: label = "O="; break;
|
|
++ case CSR_NAME_OU: label = "OU="; break;
|
|
++ default: return -1;
|
|
++ }
|
|
++
|
|
++ size_t len = strlen(name);
|
|
++ struct wpabuf *buf = wpabuf_alloc(3+len+1);
|
|
++ if (buf == NULL)
|
|
++ return -1;
|
|
++ wpabuf_put_data(buf, label, strlen(label));
|
|
++ wpabuf_put_data(buf, name, len+1); /*(include trailing '\0')*/
|
|
++ /* Note: 'name' provided is set as given and should be backslash-escaped
|
|
++ * by caller when necessary, e.g. literal ',' which are not separating
|
|
++ * components should be backslash-escaped */
|
|
++
|
|
++ int ret =
|
|
++ mbedtls_x509write_csr_set_subject_name((mbedtls_x509write_csr *)csr,
|
|
++ wpabuf_head(buf)) ? -1 : 0;
|
|
++ wpabuf_free(buf);
|
|
++ return ret;
|
|
++}
|
|
++
|
|
++/* OBJ_pkcs9_challengePassword 1 2 840 113549 1 9 7 */
|
|
++static const char OBJ_pkcs9_challengePassword[] = MBEDTLS_OID_PKCS9 "\x07";
|
|
++
|
|
++int crypto_csr_set_attribute(struct crypto_csr *csr, enum crypto_csr_attr attr,
|
|
++ int attr_type, const u8 *value, size_t len)
|
|
++{
|
|
++ /* specialized for src/common/dpp_crypto.c */
|
|
++ /* sole caller src/common/dpp_crypto.c:dpp_build_csr() passes
|
|
++ * attr == CSR_ATTR_CHALLENGE_PASSWORD
|
|
++ * attr_type == ASN1_TAG_UTF8STRING */
|
|
++
|
|
++ const char *oid;
|
|
++ size_t oid_len;
|
|
++ switch (attr) {
|
|
++ case CSR_ATTR_CHALLENGE_PASSWORD:
|
|
++ oid = OBJ_pkcs9_challengePassword;
|
|
++ oid_len = sizeof(OBJ_pkcs9_challengePassword)-1;
|
|
++ break;
|
|
++ default:
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ #if 0 /*(incorrect; sets an extension, not an attribute)*/
|
|
++ return mbedtls_x509write_csr_set_extension((mbedtls_x509write_csr *)csr,
|
|
++ oid, oid_len,
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++ 0, /*(critical flag)*/
|
|
++ #endif
|
|
++ value, len) ? -1 : 0;
|
|
++ #else
|
|
++ (void)oid;
|
|
++ (void)oid_len;
|
|
++ #endif
|
|
++
|
|
++ /* mbedtls does not currently provide way to set an attribute in a CSR:
|
|
++ * https://github.com/Mbed-TLS/mbedtls/issues/4886 */
|
|
++ wpa_printf(MSG_ERROR,
|
|
++ "mbedtls does not currently support setting challengePassword "
|
|
++ "attribute in CSR");
|
|
++ return -1;
|
|
++}
|
|
++
|
|
++const u8 * mbedtls_x509_csr_attr_oid_value(mbedtls_x509_csr *csr,
|
|
++ const char *oid, size_t oid_len,
|
|
++ size_t *vlen, int *vtype)
|
|
++{
|
|
++ /* Note: mbedtls_x509_csr_parse_der() has parsed and validated CSR,
|
|
++ * so validation checks are not repeated here
|
|
++ *
|
|
++ * It would be nicer if (mbedtls_x509_csr *) had an mbedtls_x509_buf of
|
|
++ * Attributes (or at least a pointer) since mbedtls_x509_csr_parse_der()
|
|
++ * already parsed the rest of CertificationRequestInfo, some of which is
|
|
++ * repeated here to step to Attributes. Since csr->subject_raw.p points
|
|
++ * into csr->cri.p, which points into csr->raw.p, step over version and
|
|
++ * subject of CertificationRequestInfo (SEQUENCE) */
|
|
++ unsigned char *p = csr->subject_raw.p + csr->subject_raw.len;
|
|
++ unsigned char *end = csr->cri.p + csr->cri.len, *ext;
|
|
++ size_t len;
|
|
++
|
|
++ /* step over SubjectPublicKeyInfo */
|
|
++ mbedtls_asn1_get_tag(&p, end, &len,
|
|
++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
|
|
++ p += len;
|
|
++
|
|
++ /* Attributes
|
|
++ * { ATTRIBUTE:IOSet } ::= SET OF { SEQUENCE { OID, value } }
|
|
++ */
|
|
++ if (mbedtls_asn1_get_tag(&p, end, &len,
|
|
++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC) != 0) {
|
|
++ return NULL;
|
|
++ }
|
|
++ while (p < end) {
|
|
++ if (mbedtls_asn1_get_tag(&p, end, &len,
|
|
++ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
|
|
++ return NULL;
|
|
++ }
|
|
++ ext = p;
|
|
++ p += len;
|
|
++
|
|
++ if (mbedtls_asn1_get_tag(&ext,end,&len,MBEDTLS_ASN1_OID) != 0)
|
|
++ return NULL;
|
|
++ if (oid_len != len || 0 != memcmp(ext, oid, oid_len))
|
|
++ continue;
|
|
++
|
|
++ /* found oid; return value */
|
|
++ *vtype = *ext++; /* tag */
|
|
++ return (mbedtls_asn1_get_len(&ext,end,vlen) == 0) ? ext : NULL;
|
|
++ }
|
|
++
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++const u8 * crypto_csr_get_attribute(struct crypto_csr *csr,
|
|
++ enum crypto_csr_attr attr,
|
|
++ size_t *len, int *type)
|
|
++{
|
|
++ /* specialized for src/common/dpp_crypto.c */
|
|
++ /* sole caller src/common/dpp_crypto.c:dpp_build_csr() passes
|
|
++ * attr == CSR_ATTR_CHALLENGE_PASSWORD */
|
|
++
|
|
++ const char *oid;
|
|
++ size_t oid_len;
|
|
++ switch (attr) {
|
|
++ case CSR_ATTR_CHALLENGE_PASSWORD:
|
|
++ oid = OBJ_pkcs9_challengePassword;
|
|
++ oid_len = sizeof(OBJ_pkcs9_challengePassword)-1;
|
|
++ break;
|
|
++ default:
|
|
++ return NULL;
|
|
++ }
|
|
++
|
|
++ /* see crypto_csr_verify(); expecting (mbedtls_x509_csr *) tagged |=1 */
|
|
++ if (!((uintptr_t)csr & 1uL))
|
|
++ return NULL;
|
|
++ csr = (struct crypto_csr *)((uintptr_t)csr & ~1uL);
|
|
++
|
|
++ return mbedtls_x509_csr_attr_oid_value((mbedtls_x509_csr *)csr,
|
|
++ oid, oid_len, len, type);
|
|
++}
|
|
++
|
|
++struct wpabuf * crypto_csr_sign(struct crypto_csr *csr,
|
|
++ struct crypto_ec_key *key,
|
|
++ enum crypto_hash_alg algo)
|
|
++{
|
|
++ mbedtls_md_type_t sig_md;
|
|
++ switch (algo) {
|
|
++ #ifdef MBEDTLS_SHA256_C
|
|
++ case CRYPTO_HASH_ALG_SHA256: sig_md = MBEDTLS_MD_SHA256; break;
|
|
++ #endif
|
|
++ #ifdef MBEDTLS_SHA512_C
|
|
++ case CRYPTO_HASH_ALG_SHA384: sig_md = MBEDTLS_MD_SHA384; break;
|
|
++ case CRYPTO_HASH_ALG_SHA512: sig_md = MBEDTLS_MD_SHA512; break;
|
|
++ #endif
|
|
++ default:
|
|
++ return NULL;
|
|
++ }
|
|
++ mbedtls_x509write_csr_set_md_alg((mbedtls_x509write_csr *)csr, sig_md);
|
|
++
|
|
++ #if 0
|
|
++ unsigned char key_usage = MBEDTLS_X509_KU_DIGITAL_SIGNATURE
|
|
++ | MBEDTLS_X509_KU_KEY_CERT_SIGN;
|
|
++ if (mbedtls_x509write_csr_set_key_usage((mbedtls_x509write_csr *)csr,
|
|
++ key_usage))
|
|
++ return NULL;
|
|
++ #endif
|
|
++
|
|
++ #if 0
|
|
++ unsigned char ns_cert_type = MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT
|
|
++ | MBEDTLS_X509_NS_CERT_TYPE_EMAIL;
|
|
++ if (mbedtls_x509write_csr_set_ns_cert_type((mbedtls_x509write_csr *)csr,
|
|
++ ns_cert_type))
|
|
++ return NULL;
|
|
++ #endif
|
|
++
|
|
++ #if 0
|
|
++ /* mbedtls does not currently provide way to set an attribute in a CSR:
|
|
++ * https://github.com/Mbed-TLS/mbedtls/issues/4886
|
|
++ * XXX: hwsim dpp_enterprise test fails due to this limitation.
|
|
++ *
|
|
++ * Current usage of this function is solely by dpp_build_csr(),
|
|
++ * so as a kludge, might consider custom (struct crypto_csr *)
|
|
++ * containing (mbedtls_x509write_csr *) and a list of attributes
|
|
++ * (i.e. challengePassword). Might have to totally reimplement
|
|
++ * mbedtls_x509write_csr_der(); underlying x509write_csr_der_internal()
|
|
++ * handles signing the CSR. (This is more work that appending an
|
|
++ * Attributes section to end of CSR and adjusting ASN.1 length of CSR.)
|
|
++ */
|
|
++ #endif
|
|
++
|
|
++ unsigned char buf[4096]; /* XXX: large enough? too large? */
|
|
++ int len = mbedtls_x509write_csr_der((mbedtls_x509write_csr *)csr,
|
|
++ buf, sizeof(buf),
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg());
|
|
++ if (len < 0)
|
|
++ return NULL;
|
|
++ /* Note: data is written at the end of the buffer! Use the
|
|
++ * return value to determine where you should start
|
|
++ * using the buffer */
|
|
++ return wpabuf_alloc_copy(buf+sizeof(buf)-len, (size_t)len);
|
|
++}
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_CSR */
|
|
++
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_PKCS7
|
|
++
|
|
++#if 0
|
|
++#include <mbedtls/pkcs7.h> /* PKCS7 is not currently supported in mbedtls */
|
|
++#include <mbedtls/pem.h>
|
|
++#endif
|
|
++
|
|
++struct wpabuf * crypto_pkcs7_get_certificates(const struct wpabuf *pkcs7)
|
|
++{
|
|
++ /* PKCS7 is not currently supported in mbedtls */
|
|
++ return NULL;
|
|
++
|
|
++#if 0
|
|
++ /* https://github.com/naynajain/mbedtls-1 branch: development-pkcs7
|
|
++ * (??? potential future contribution to mbedtls ???) */
|
|
++
|
|
++ /* Note: PKCS7 signature *is not* verified by this function.
|
|
++ * The function interface does not provide for passing a certificate */
|
|
++
|
|
++ mbedtls_pkcs7 mpkcs7;
|
|
++ mbedtls_pkcs7_init(&mpkcs7);
|
|
++ int pkcs7_type = mbedtls_pkcs7_parse_der(wpabuf_head(pkcs7),
|
|
++ wpabuf_len(pkcs7),
|
|
++ &mpkcs7);
|
|
++ wpabuf *buf = NULL;
|
|
++ do {
|
|
++ if (pkcs7_type < 0)
|
|
++ break;
|
|
++
|
|
++ /* src/common/dpp.c:dpp_parse_cred_dot1x() interested in certs
|
|
++ * for wpa_supplicant/dpp_supplicant.c:wpas_dpp_add_network()
|
|
++ * (? are adding certificate headers and footers desired ?) */
|
|
++
|
|
++ /* development-pkcs7 branch does not currently provide
|
|
++ * additional interfaces to retrieve the parsed data */
|
|
++
|
|
++ mbedtls_x509_crt *certs =
|
|
++ &mpkcs7.MBEDTLS_PRIVATE(signed_data).MBEDTLS_PRIVATE(certs);
|
|
++ int ncerts =
|
|
++ mpkcs7.MBEDTLS_PRIVATE(signed_data).MBEDTLS_PRIVATE(no_of_certs);
|
|
++
|
|
++ /* allocate buffer for PEM (base64-encoded DER)
|
|
++ * plus header, footer, newlines, and some extra */
|
|
++ buf = wpabuf_alloc((wpabuf_len(pkcs7)+2)/3*4 + ncerts*64);
|
|
++ if (buf == NULL)
|
|
++ break;
|
|
++
|
|
++ #define PEM_BEGIN_CRT "-----BEGIN CERTIFICATE-----\n"
|
|
++ #define PEM_END_CRT "-----END CERTIFICATE-----\n"
|
|
++ size_t olen;
|
|
++ for (int i = 0; i < ncerts; ++i) {
|
|
++ int ret = mbedtls_pem_write_buffer(
|
|
++ PEM_BEGIN_CRT, PEM_END_CRT,
|
|
++ certs[i].raw.p, certs[i].raw.len,
|
|
++ wpabuf_mhead(buf, 0), wpabuf_tailroom(buf),
|
|
++ &olen));
|
|
++ if (ret == 0)
|
|
++ wpabuf_put(buf, olen);
|
|
++ } else {
|
|
++ if (ret == MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL)
|
|
++ ret = wpabuf_resize(
|
|
++ &buf,olen-wpabuf_tailroom(buf));
|
|
++ if (ret == 0) {
|
|
++ --i;/*(adjust loop iterator for retry)*/
|
|
++ continue;
|
|
++ }
|
|
++ wpabuf_free(buf);
|
|
++ buf = NULL;
|
|
++ break;
|
|
++ }
|
|
++ }
|
|
++ } while (0);
|
|
++
|
|
++ mbedtls_pkcs7_free(&mpkcs7);
|
|
++ return buf;
|
|
++#endif
|
|
++}
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_PKCS7 */
|
|
++
|
|
++
|
|
++#ifdef MBEDTLS_ARC4_C
|
|
++#include <mbedtls/arc4.h>
|
|
++int rc4_skip(const u8 *key, size_t keylen, size_t skip,
|
|
++ u8 *data, size_t data_len)
|
|
++{
|
|
++ mbedtls_arc4_context ctx;
|
|
++ mbedtls_arc4_init(&ctx);
|
|
++ mbedtls_arc4_setup(&ctx, key, keylen);
|
|
++
|
|
++ if (skip) {
|
|
++ /*(prefer [16] on ancient hardware with smaller cache lines)*/
|
|
++ unsigned char skip_buf[64]; /*('skip' is generally small)*/
|
|
++ /*os_memset(skip_buf, 0, sizeof(skip_buf));*/ /*(necessary?)*/
|
|
++ size_t len;
|
|
++ do {
|
|
++ len = skip > sizeof(skip_buf) ? sizeof(skip_buf) : skip;
|
|
++ mbedtls_arc4_crypt(&ctx, len, skip_buf, skip_buf);
|
|
++ } while ((skip -= len));
|
|
++ }
|
|
++
|
|
++ int ret = mbedtls_arc4_crypt(&ctx, data_len, data, data);
|
|
++ mbedtls_arc4_free(&ctx);
|
|
++ return ret;
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++/* duplicated in tls_mbedtls.c:tls_mbedtls_readfile()*/
|
|
++__attribute_noinline__
|
|
++static int crypto_mbedtls_readfile(const char *path, u8 **buf, size_t *n)
|
|
++{
|
|
++ #if 0 /* #ifdef MBEDTLS_FS_IO */
|
|
++ /*(includes +1 for '\0' needed by mbedtls PEM parsing funcs)*/
|
|
++ if (mbedtls_pk_load_file(path, (unsigned char **)buf, n) != 0) {
|
|
++ wpa_printf(MSG_ERROR, "error: mbedtls_pk_load_file %s", path);
|
|
++ return -1;
|
|
++ }
|
|
++ #else
|
|
++ /*(use os_readfile() so that we can use os_free()
|
|
++ *(if we use mbedtls_pk_load_file() above, macros prevent calling free()
|
|
++ * directly #if defined(OS_REJECT_C_LIB_FUNCTIONS) and calling os_free()
|
|
++ * on buf aborts in tests if buf not allocated via os_malloc())*/
|
|
++ *buf = (u8 *)os_readfile(path, n);
|
|
++ if (!*buf) {
|
|
++ wpa_printf(MSG_ERROR, "error: os_readfile %s", path);
|
|
++ return -1;
|
|
++ }
|
|
++ u8 *buf0 = os_realloc(*buf, *n+1);
|
|
++ if (!buf0) {
|
|
++ bin_clear_free(*buf, *n);
|
|
++ *buf = NULL;
|
|
++ return -1;
|
|
++ }
|
|
++ buf0[(*n)++] = '\0';
|
|
++ *buf = buf0;
|
|
++ #endif
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_RSA
|
|
++#ifdef MBEDTLS_RSA_C
|
|
++
|
|
++#include <mbedtls/pk.h>
|
|
++#include <mbedtls/rsa.h>
|
|
++
|
|
++struct crypto_rsa_key * crypto_rsa_key_read(const char *file, bool private_key)
|
|
++{
|
|
++ /* mbedtls_pk_parse_keyfile() and mbedtls_pk_parse_public_keyfile()
|
|
++ * require #ifdef MBEDTLS_FS_IO in mbedtls library. Prefer to use
|
|
++ * crypto_mbedtls_readfile(), which wraps os_readfile() */
|
|
++ u8 *data;
|
|
++ size_t len;
|
|
++ if (crypto_mbedtls_readfile(file, &data, &len) != 0)
|
|
++ return NULL;
|
|
++
|
|
++ mbedtls_pk_context *ctx = os_malloc(sizeof(*ctx));
|
|
++ if (ctx == NULL) {
|
|
++ bin_clear_free(data, len);
|
|
++ return NULL;
|
|
++ }
|
|
++ mbedtls_pk_init(ctx);
|
|
++
|
|
++ int rc;
|
|
++ rc = (private_key
|
|
++ ? mbedtls_pk_parse_key(ctx, data, len, NULL, 0
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++ ,mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg()
|
|
++ #endif
|
|
++ )
|
|
++ : mbedtls_pk_parse_public_key(ctx, data, len)) == 0
|
|
++ && mbedtls_pk_can_do(ctx, MBEDTLS_PK_RSA);
|
|
++
|
|
++ bin_clear_free(data, len);
|
|
++
|
|
++ if (rc) {
|
|
++ /* use MBEDTLS_RSA_PKCS_V21 padding for RSAES-OAEP */
|
|
++ /* use MBEDTLS_MD_SHA256 for these hostap interfaces */
|
|
++ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
|
|
++ /*(no return value in mbedtls 2.x)*/
|
|
++ mbedtls_rsa_set_padding(mbedtls_pk_rsa(*ctx),
|
|
++ MBEDTLS_RSA_PKCS_V21,
|
|
++ MBEDTLS_MD_SHA256);
|
|
++ #else
|
|
++ if (mbedtls_rsa_set_padding(mbedtls_pk_rsa(*ctx),
|
|
++ MBEDTLS_RSA_PKCS_V21,
|
|
++ MBEDTLS_MD_SHA256) == 0)
|
|
++ #endif
|
|
++ return (struct crypto_rsa_key *)ctx;
|
|
++ }
|
|
++
|
|
++ mbedtls_pk_free(ctx);
|
|
++ os_free(ctx);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++struct wpabuf * crypto_rsa_oaep_sha256_encrypt(struct crypto_rsa_key *key,
|
|
++ const struct wpabuf *in)
|
|
++{
|
|
++ mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(*(mbedtls_pk_context*)key);
|
|
++ size_t olen = mbedtls_rsa_get_len(pk_rsa);
|
|
++ struct wpabuf *buf = wpabuf_alloc(olen);
|
|
++ if (buf == NULL)
|
|
++ return NULL;
|
|
++
|
|
++ /* mbedtls_pk_encrypt() takes a few more hops to get to same func */
|
|
++ if (mbedtls_rsa_rsaes_oaep_encrypt(pk_rsa,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg(),
|
|
++ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
|
|
++ MBEDTLS_RSA_PRIVATE,
|
|
++ #endif
|
|
++ NULL, 0,
|
|
++ wpabuf_len(in), wpabuf_head(in),
|
|
++ wpabuf_put(buf, olen)) == 0) {
|
|
++ return buf;
|
|
++ }
|
|
++
|
|
++ wpabuf_clear_free(buf);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++struct wpabuf * crypto_rsa_oaep_sha256_decrypt(struct crypto_rsa_key *key,
|
|
++ const struct wpabuf *in)
|
|
++{
|
|
++ mbedtls_rsa_context *pk_rsa = mbedtls_pk_rsa(*(mbedtls_pk_context*)key);
|
|
++ size_t olen = mbedtls_rsa_get_len(pk_rsa);
|
|
++ struct wpabuf *buf = wpabuf_alloc(olen);
|
|
++ if (buf == NULL)
|
|
++ return NULL;
|
|
++
|
|
++ /* mbedtls_pk_decrypt() takes a few more hops to get to same func */
|
|
++ if (mbedtls_rsa_rsaes_oaep_decrypt(pk_rsa,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ crypto_mbedtls_ctr_drbg(),
|
|
++ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
|
|
++ MBEDTLS_RSA_PUBLIC,
|
|
++ #endif
|
|
++ NULL, 0, &olen, wpabuf_head(in),
|
|
++ wpabuf_mhead(buf), olen) == 0) {
|
|
++ wpabuf_put(buf, olen);
|
|
++ return buf;
|
|
++ }
|
|
++
|
|
++ wpabuf_clear_free(buf);
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++void crypto_rsa_key_free(struct crypto_rsa_key *key)
|
|
++{
|
|
++ mbedtls_pk_free((mbedtls_pk_context *)key);
|
|
++ os_free(key);
|
|
++}
|
|
++
|
|
++#endif /* MBEDTLS_RSA_C */
|
|
++#endif /* CRYPTO_MBEDTLS_CRYPTO_RSA */
|
|
++
|
|
++#ifdef CRYPTO_MBEDTLS_CRYPTO_HPKE
|
|
++
|
|
++struct wpabuf * hpke_base_seal(enum hpke_kem_id kem_id,
|
|
++ enum hpke_kdf_id kdf_id,
|
|
++ enum hpke_aead_id aead_id,
|
|
++ struct crypto_ec_key *peer_pub,
|
|
++ const u8 *info, size_t info_len,
|
|
++ const u8 *aad, size_t aad_len,
|
|
++ const u8 *pt, size_t pt_len)
|
|
++{
|
|
++ /* not yet implemented */
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++struct wpabuf * hpke_base_open(enum hpke_kem_id kem_id,
|
|
++ enum hpke_kdf_id kdf_id,
|
|
++ enum hpke_aead_id aead_id,
|
|
++ struct crypto_ec_key *own_priv,
|
|
++ const u8 *info, size_t info_len,
|
|
++ const u8 *aad, size_t aad_len,
|
|
++ const u8 *enc_ct, size_t enc_ct_len)
|
|
++{
|
|
++ /* not yet implemented */
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++#endif
|
|
+--- /dev/null
|
|
++++ b/src/crypto/tls_mbedtls.c
|
|
+@@ -0,0 +1,3313 @@
|
|
++/*
|
|
++ * SSL/TLS interface functions for mbed TLS
|
|
++ *
|
|
++ * SPDX-FileCopyrightText: 2022 Glenn Strauss <gstrauss@gluelogic.com>
|
|
++ * SPDX-License-Identifier: BSD-3-Clause
|
|
++ *
|
|
++ * This software may be distributed under the terms of the BSD license.
|
|
++ * See README for more details.
|
|
++ *
|
|
++ * template: src/crypto/tls_none.c
|
|
++ * reference: src/crypto/tls_*.c
|
|
++ *
|
|
++ * Known Limitations:
|
|
++ * - no TLSv1.3 (not available in mbedtls 2.x; experimental in mbedtls 3.x)
|
|
++ * - no OCSP (not yet available in mbedtls)
|
|
++ * - mbedtls does not support all certificate encodings used by hwsim tests
|
|
++ * PCKS#5 v1.5
|
|
++ * PCKS#12
|
|
++ * DH DSA
|
|
++ * - EAP-FAST, EAP-TEAP session ticket support not implemented in tls_mbedtls.c
|
|
++ * - mbedtls does not currently provide way to set an attribute in a CSR
|
|
++ * https://github.com/Mbed-TLS/mbedtls/issues/4886
|
|
++ * so tests/hwsim dpp_enterprise tests fail
|
|
++ * - DPP2 not supported
|
|
++ * PKCS#7 parsing is not supported in mbedtls
|
|
++ * See crypto_mbedtls.c:crypto_pkcs7_get_certificates() comments
|
|
++ * - DPP3 not supported
|
|
++ * hpke_base_seal() and hpke_base_seal() not implemented in crypto_mbedtls.c
|
|
++ *
|
|
++ * Status:
|
|
++ * - code written to be compatible with mbedtls 2.x and mbedtls 3.x
|
|
++ * (currently requires mbedtls >= 2.27.0 for mbedtls_mpi_random())
|
|
++ * (currently requires mbedtls >= 2.18.0 for mbedtls_ssl_tls_prf())
|
|
++ * - builds with tests/build/build-wpa_supplicant-mbedtls.config
|
|
++ * - passes all tests/ crypto module tests (incomplete coverage)
|
|
++ * ($ cd tests; make clean; make -j 4 run-tests CONFIG_TLS=mbedtls)
|
|
++ * - passes almost all tests/hwsim tests
|
|
++ * (hwsim tests skipped for missing features)
|
|
++ *
|
|
++ * RFE:
|
|
++ * - EAP-FAST, EAP-TEAP session ticket support not implemented in tls_mbedtls.c
|
|
++ * - client/server session resumption, and/or save client session ticket
|
|
++ */
|
|
++
|
|
++#include "includes.h"
|
|
++#include "common.h"
|
|
++
|
|
++#include <mbedtls/version.h>
|
|
++#include <mbedtls/ctr_drbg.h>
|
|
++#include <mbedtls/error.h>
|
|
++#include <mbedtls/oid.h>
|
|
++#include <mbedtls/pem.h>
|
|
++#include <mbedtls/platform.h> /* mbedtls_calloc() mbedtls_free() */
|
|
++#include <mbedtls/platform_util.h> /* mbedtls_platform_zeroize() */
|
|
++#include <mbedtls/ssl.h>
|
|
++#include <mbedtls/ssl_ticket.h>
|
|
++#include <mbedtls/x509.h>
|
|
++#include <mbedtls/x509_crt.h>
|
|
++
|
|
++#if MBEDTLS_VERSION_NUMBER >= 0x02040000 /* mbedtls 2.4.0 */
|
|
++#include <mbedtls/net_sockets.h>
|
|
++#else
|
|
++#include <mbedtls/net.h>
|
|
++#endif
|
|
++
|
|
++#ifndef MBEDTLS_PRIVATE
|
|
++#define MBEDTLS_PRIVATE(x) x
|
|
++#endif
|
|
++
|
|
++#if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */
|
|
++#define mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl) \
|
|
++ ((ssl)->MBEDTLS_PRIVATE(session) \
|
|
++ ?(ssl)->MBEDTLS_PRIVATE(session)->MBEDTLS_PRIVATE(ciphersuite) \
|
|
++ : 0)
|
|
++#define mbedtls_ssl_ciphersuite_get_name(info) \
|
|
++ (info)->MBEDTLS_PRIVATE(name)
|
|
++#endif
|
|
++
|
|
++#include "crypto.h" /* sha256_vector() */
|
|
++#include "tls.h"
|
|
++
|
|
++#ifndef SHA256_DIGEST_LENGTH
|
|
++#define SHA256_DIGEST_LENGTH 32
|
|
++#endif
|
|
++
|
|
++#ifndef MBEDTLS_EXPKEY_FIXED_SECRET_LEN
|
|
++#define MBEDTLS_EXPKEY_FIXED_SECRET_LEN 48
|
|
++#endif
|
|
++
|
|
++#ifndef MBEDTLS_EXPKEY_RAND_LEN
|
|
++#define MBEDTLS_EXPKEY_RAND_LEN 32
|
|
++#endif
|
|
++
|
|
++#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++static mbedtls_ssl_export_keys_t tls_connection_export_keys_cb;
|
|
++#elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
|
|
++static mbedtls_ssl_export_keys_ext_t tls_connection_export_keys_cb;
|
|
++#else /*(not implemented; return error)*/
|
|
++#define mbedtls_ssl_tls_prf(a,b,c,d,e,f,g,h) (-1)
|
|
++typedef mbedtls_tls_prf_types int;
|
|
++#endif
|
|
++
|
|
++
|
|
++/* hostapd/wpa_supplicant provides forced_memzero(),
|
|
++ * but prefer mbedtls_platform_zeroize() */
|
|
++#define forced_memzero(ptr,sz) mbedtls_platform_zeroize(ptr,sz)
|
|
++
|
|
++
|
|
++#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) \
|
|
++ || defined(EAP_TEAP) || defined(EAP_SERVER_TEAP)
|
|
++#ifdef MBEDTLS_SSL_SESSION_TICKETS
|
|
++#ifdef MBEDTLS_SSL_TICKET_C
|
|
++#define TLS_MBEDTLS_SESSION_TICKETS
|
|
++#if defined(EAP_TEAP) || defined(EAP_SERVER_TEAP)
|
|
++#define TLS_MBEDTLS_EAP_TEAP
|
|
++#endif
|
|
++#if !defined(CONFIG_FIPS) /* EAP-FAST keys cannot be exported in FIPS mode */
|
|
++#if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST)
|
|
++#define TLS_MBEDTLS_EAP_FAST
|
|
++#endif
|
|
++#endif
|
|
++#endif
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++
|
|
++struct tls_conf {
|
|
++ mbedtls_ssl_config conf;
|
|
++
|
|
++ unsigned int verify_peer:1;
|
|
++ unsigned int verify_depth0_only:1;
|
|
++ unsigned int check_crl:2; /*(needs :2 bits for 0, 1, 2)*/
|
|
++ unsigned int check_crl_strict:1; /*(needs :1 bit for 0, 1)*/
|
|
++ unsigned int ca_cert_probe:1;
|
|
++ unsigned int has_ca_cert:1;
|
|
++ unsigned int has_client_cert:1;
|
|
++ unsigned int has_private_key:1;
|
|
++ unsigned int suiteb128:1;
|
|
++ unsigned int suiteb192:1;
|
|
++ mbedtls_x509_crl *crl;
|
|
++ mbedtls_x509_crt ca_cert;
|
|
++ mbedtls_x509_crt client_cert;
|
|
++ mbedtls_pk_context private_key;
|
|
++
|
|
++ uint32_t refcnt;
|
|
++
|
|
++ unsigned int flags;
|
|
++ char *subject_match;
|
|
++ char *altsubject_match;
|
|
++ char *suffix_match;
|
|
++ char *domain_match;
|
|
++ char *check_cert_subject;
|
|
++ u8 ca_cert_hash[SHA256_DIGEST_LENGTH];
|
|
++
|
|
++ int *ciphersuites; /* list of ciphersuite ids for mbedtls_ssl_config */
|
|
++#if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.1.0 */
|
|
++ mbedtls_ecp_group_id *curves;
|
|
++#else
|
|
++ uint16_t *curves; /* list of curve ids for mbedtls_ssl_config */
|
|
++#endif
|
|
++};
|
|
++
|
|
++
|
|
++struct tls_global {
|
|
++ struct tls_conf *tls_conf;
|
|
++ char *ocsp_stapling_response;
|
|
++ mbedtls_ctr_drbg_context *ctr_drbg; /*(see crypto_mbedtls.c)*/
|
|
++ #ifdef MBEDTLS_SSL_SESSION_TICKETS
|
|
++ mbedtls_ssl_ticket_context ticket_ctx;
|
|
++ #endif
|
|
++ char *ca_cert_file;
|
|
++ struct os_reltime crl_reload_previous;
|
|
++ unsigned int crl_reload_interval;
|
|
++ uint32_t refcnt;
|
|
++ struct tls_config init_conf;
|
|
++};
|
|
++
|
|
++static struct tls_global tls_ctx_global;
|
|
++
|
|
++
|
|
++struct tls_connection {
|
|
++ struct tls_conf *tls_conf;
|
|
++ struct wpabuf *push_buf;
|
|
++ struct wpabuf *pull_buf;
|
|
++ size_t pull_buf_offset;
|
|
++
|
|
++ unsigned int established:1;
|
|
++ unsigned int resumed:1;
|
|
++ unsigned int verify_peer:1;
|
|
++ unsigned int is_server:1;
|
|
++
|
|
++ mbedtls_ssl_context ssl;
|
|
++
|
|
++ mbedtls_tls_prf_types tls_prf_type;
|
|
++ size_t expkey_keyblock_size;
|
|
++ size_t expkey_secret_len;
|
|
++ #if MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
|
|
++ unsigned char expkey_secret[MBEDTLS_EXPKEY_FIXED_SECRET_LEN];
|
|
++ #else
|
|
++ unsigned char expkey_secret[MBEDTLS_MD_MAX_SIZE];
|
|
++ #endif
|
|
++ unsigned char expkey_randbytes[MBEDTLS_EXPKEY_RAND_LEN*2];
|
|
++
|
|
++ int read_alerts, write_alerts, failed;
|
|
++
|
|
++ #ifdef TLS_MBEDTLS_SESSION_TICKETS
|
|
++ tls_session_ticket_cb session_ticket_cb;
|
|
++ void *session_ticket_cb_ctx;
|
|
++ unsigned char *clienthello_session_ticket;
|
|
++ size_t clienthello_session_ticket_len;
|
|
++ #endif
|
|
++ char *peer_subject; /* peer subject info for authenticated peer */
|
|
++ struct wpabuf *success_data;
|
|
++};
|
|
++
|
|
++
|
|
++#ifndef __has_attribute
|
|
++#define __has_attribute(x) 0
|
|
++#endif
|
|
++
|
|
++#ifndef __GNUC_PREREQ
|
|
++#define __GNUC_PREREQ(maj,min) 0
|
|
++#endif
|
|
++
|
|
++#ifndef __attribute_cold__
|
|
++#if __has_attribute(cold) \
|
|
++ || __GNUC_PREREQ(4,3)
|
|
++#define __attribute_cold__ __attribute__((__cold__))
|
|
++#else
|
|
++#define __attribute_cold__
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++#ifndef __attribute_noinline__
|
|
++#if __has_attribute(noinline) \
|
|
++ || __GNUC_PREREQ(3,1)
|
|
++#define __attribute_noinline__ __attribute__((__noinline__))
|
|
++#else
|
|
++#define __attribute_noinline__
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++
|
|
++__attribute_cold__
|
|
++__attribute_noinline__
|
|
++static void emsg(int level, const char * const msg)
|
|
++{
|
|
++ wpa_printf(level, "MTLS: %s", msg);
|
|
++}
|
|
++
|
|
++
|
|
++__attribute_cold__
|
|
++__attribute_noinline__
|
|
++static void emsgrc(int level, const char * const msg, int rc)
|
|
++{
|
|
++ #ifdef MBEDTLS_ERROR_C
|
|
++ /* error logging convenience function that decodes mbedtls result codes */
|
|
++ char buf[256];
|
|
++ mbedtls_strerror(rc, buf, sizeof(buf));
|
|
++ wpa_printf(level, "MTLS: %s: %s (-0x%04x)", msg, buf, -rc);
|
|
++ #else
|
|
++ wpa_printf(level, "MTLS: %s: (-0x%04x)", msg, -rc);
|
|
++ #endif
|
|
++}
|
|
++
|
|
++
|
|
++#define elog(rc, msg) emsgrc(MSG_ERROR, (msg), (rc))
|
|
++#define ilog(rc, msg) emsgrc(MSG_INFO, (msg), (rc))
|
|
++
|
|
++
|
|
++struct tls_conf * tls_conf_init(void *tls_ctx)
|
|
++{
|
|
++ struct tls_conf *tls_conf = os_zalloc(sizeof(*tls_conf));
|
|
++ if (tls_conf == NULL)
|
|
++ return NULL;
|
|
++ tls_conf->refcnt = 1;
|
|
++
|
|
++ mbedtls_ssl_config_init(&tls_conf->conf);
|
|
++ mbedtls_ssl_conf_rng(&tls_conf->conf,
|
|
++ mbedtls_ctr_drbg_random, tls_ctx_global.ctr_drbg);
|
|
++ mbedtls_x509_crt_init(&tls_conf->ca_cert);
|
|
++ mbedtls_x509_crt_init(&tls_conf->client_cert);
|
|
++ mbedtls_pk_init(&tls_conf->private_key);
|
|
++
|
|
++ return tls_conf;
|
|
++}
|
|
++
|
|
++
|
|
++void tls_conf_deinit(struct tls_conf *tls_conf)
|
|
++{
|
|
++ if (tls_conf == NULL || --tls_conf->refcnt != 0)
|
|
++ return;
|
|
++
|
|
++ mbedtls_x509_crt_free(&tls_conf->ca_cert);
|
|
++ mbedtls_x509_crt_free(&tls_conf->client_cert);
|
|
++ if (tls_conf->crl) {
|
|
++ mbedtls_x509_crl_free(tls_conf->crl);
|
|
++ os_free(tls_conf->crl);
|
|
++ }
|
|
++ mbedtls_pk_free(&tls_conf->private_key);
|
|
++ mbedtls_ssl_config_free(&tls_conf->conf);
|
|
++ os_free(tls_conf->curves);
|
|
++ os_free(tls_conf->ciphersuites);
|
|
++ os_free(tls_conf->subject_match);
|
|
++ os_free(tls_conf->altsubject_match);
|
|
++ os_free(tls_conf->suffix_match);
|
|
++ os_free(tls_conf->domain_match);
|
|
++ os_free(tls_conf->check_cert_subject);
|
|
++ os_free(tls_conf);
|
|
++}
|
|
++
|
|
++
|
|
++mbedtls_ctr_drbg_context * crypto_mbedtls_ctr_drbg(void); /*(not in header)*/
|
|
++
|
|
++__attribute_cold__
|
|
++void * tls_init(const struct tls_config *conf)
|
|
++{
|
|
++ /* RFE: review struct tls_config *conf (different from tls_conf) */
|
|
++
|
|
++ if (++tls_ctx_global.refcnt > 1)
|
|
++ return &tls_ctx_global;
|
|
++
|
|
++ tls_ctx_global.ctr_drbg = crypto_mbedtls_ctr_drbg();
|
|
++ #ifdef MBEDTLS_SSL_SESSION_TICKETS
|
|
++ mbedtls_ssl_ticket_init(&tls_ctx_global.ticket_ctx);
|
|
++ mbedtls_ssl_ticket_setup(&tls_ctx_global.ticket_ctx,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ tls_ctx_global.ctr_drbg,
|
|
++ MBEDTLS_CIPHER_AES_256_GCM,
|
|
++ 43200); /* ticket timeout: 12 hours */
|
|
++ #endif
|
|
++ /* copy struct for future use */
|
|
++ tls_ctx_global.init_conf = *conf;
|
|
++ if (conf->openssl_ciphers)
|
|
++ tls_ctx_global.init_conf.openssl_ciphers =
|
|
++ os_strdup(conf->openssl_ciphers);
|
|
++
|
|
++ tls_ctx_global.crl_reload_interval = conf->crl_reload_interval;
|
|
++ os_get_reltime(&tls_ctx_global.crl_reload_previous);
|
|
++
|
|
++ return &tls_ctx_global;
|
|
++}
|
|
++
|
|
++
|
|
++__attribute_cold__
|
|
++void tls_deinit(void *tls_ctx)
|
|
++{
|
|
++ if (tls_ctx == NULL || --tls_ctx_global.refcnt != 0)
|
|
++ return;
|
|
++
|
|
++ tls_conf_deinit(tls_ctx_global.tls_conf);
|
|
++ os_free(tls_ctx_global.ca_cert_file);
|
|
++ os_free(tls_ctx_global.ocsp_stapling_response);
|
|
++ char *openssl_ciphers; /*(allocated in tls_init())*/
|
|
++ *(const char **)&openssl_ciphers =
|
|
++ tls_ctx_global.init_conf.openssl_ciphers;
|
|
++ os_free(openssl_ciphers);
|
|
++ #ifdef MBEDTLS_SSL_SESSION_TICKETS
|
|
++ mbedtls_ssl_ticket_free(&tls_ctx_global.ticket_ctx);
|
|
++ #endif
|
|
++ os_memset(&tls_ctx_global, 0, sizeof(tls_ctx_global));
|
|
++}
|
|
++
|
|
++
|
|
++int tls_get_errors(void *tls_ctx)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++static void tls_connection_deinit_expkey(struct tls_connection *conn)
|
|
++{
|
|
++ conn->tls_prf_type = 0; /* MBEDTLS_SSL_TLS_PRF_NONE; */
|
|
++ conn->expkey_keyblock_size = 0;
|
|
++ conn->expkey_secret_len = 0;
|
|
++ forced_memzero(conn->expkey_secret, sizeof(conn->expkey_secret));
|
|
++ forced_memzero(conn->expkey_randbytes, sizeof(conn->expkey_randbytes));
|
|
++}
|
|
++
|
|
++
|
|
++#ifdef TLS_MBEDTLS_SESSION_TICKETS
|
|
++void tls_connection_deinit_clienthello_session_ticket(struct tls_connection *conn)
|
|
++{
|
|
++ if (conn->clienthello_session_ticket) {
|
|
++ mbedtls_platform_zeroize(conn->clienthello_session_ticket,
|
|
++ conn->clienthello_session_ticket_len);
|
|
++ mbedtls_free(conn->clienthello_session_ticket);
|
|
++ conn->clienthello_session_ticket = NULL;
|
|
++ conn->clienthello_session_ticket_len = 0;
|
|
++ }
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn)
|
|
++{
|
|
++ if (conn == NULL)
|
|
++ return;
|
|
++
|
|
++ #if 0 /*(good intention, but never sent since we destroy self below)*/
|
|
++ if (conn->established)
|
|
++ mbedtls_ssl_close_notify(&conn->ssl);
|
|
++ #endif
|
|
++
|
|
++ if (conn->tls_prf_type)
|
|
++ tls_connection_deinit_expkey(conn);
|
|
++
|
|
++ #ifdef TLS_MBEDTLS_SESSION_TICKETS
|
|
++ if (conn->clienthello_session_ticket)
|
|
++ tls_connection_deinit_clienthello_session_ticket(conn);
|
|
++ #endif
|
|
++
|
|
++ os_free(conn->peer_subject);
|
|
++ wpabuf_free(conn->success_data);
|
|
++ wpabuf_free(conn->push_buf);
|
|
++ wpabuf_free(conn->pull_buf);
|
|
++ mbedtls_ssl_free(&conn->ssl);
|
|
++ tls_conf_deinit(conn->tls_conf);
|
|
++ os_free(conn);
|
|
++}
|
|
++
|
|
++
|
|
++static void tls_mbedtls_refresh_crl(void);
|
|
++static int tls_mbedtls_ssl_setup(struct tls_connection *conn);
|
|
++
|
|
++struct tls_connection * tls_connection_init(void *tls_ctx)
|
|
++{
|
|
++ struct tls_connection *conn = os_zalloc(sizeof(*conn));
|
|
++ if (conn == NULL)
|
|
++ return NULL;
|
|
++
|
|
++ mbedtls_ssl_init(&conn->ssl);
|
|
++
|
|
++ conn->tls_conf = tls_ctx_global.tls_conf; /*(inherit global conf, if set)*/
|
|
++ if (conn->tls_conf) {
|
|
++ ++conn->tls_conf->refcnt;
|
|
++ /* check for CRL refresh if inheriting from global config */
|
|
++ tls_mbedtls_refresh_crl();
|
|
++
|
|
++ conn->verify_peer = conn->tls_conf->verify_peer;
|
|
++ if (tls_mbedtls_ssl_setup(conn) != 0) {
|
|
++ tls_connection_deinit(&tls_ctx_global, conn);
|
|
++ return NULL;
|
|
++ }
|
|
++ }
|
|
++
|
|
++ return conn;
|
|
++}
|
|
++
|
|
++
|
|
++int tls_connection_established(void *tls_ctx, struct tls_connection *conn)
|
|
++{
|
|
++ return conn ? conn->established : 0;
|
|
++}
|
|
++
|
|
++
|
|
++__attribute_noinline__
|
|
++char * tls_mbedtls_peer_serial_num(const mbedtls_x509_crt *crt, char *serial_num, size_t len)
|
|
++{
|
|
++ /* mbedtls_x509_serial_gets() inefficiently formats to hex separated by
|
|
++ * colons, so generate the hex serial number here. The func
|
|
++ * wpa_snprintf_hex_uppercase() is similarly inefficient. */
|
|
++ size_t i = 0; /* skip leading 0's per Distinguished Encoding Rules (DER) */
|
|
++ while (i < crt->serial.len && crt->serial.p[i] == 0) ++i;
|
|
++ if (i == crt->serial.len) --i;
|
|
++
|
|
++ const unsigned char *s = crt->serial.p + i;
|
|
++ const size_t e = (crt->serial.len - i) * 2;
|
|
++ if (e >= len)
|
|
++ return NULL;
|
|
++ #if 0
|
|
++ wpa_snprintf_hex_uppercase(serial_num, len, s, crt->serial.len-i);
|
|
++ #else
|
|
++ for (i = 0; i < e; i+=2, ++s) {
|
|
++ serial_num[i+0] = "0123456789ABCDEF"[(*s >> 4)];
|
|
++ serial_num[i+1] = "0123456789ABCDEF"[(*s & 0xF)];
|
|
++ }
|
|
++ serial_num[e] = '\0';
|
|
++ #endif
|
|
++ return serial_num;
|
|
++}
|
|
++
|
|
++
|
|
++char * tls_connection_peer_serial_num(void *tls_ctx,
|
|
++ struct tls_connection *conn)
|
|
++{
|
|
++ const mbedtls_x509_crt *crt = mbedtls_ssl_get_peer_cert(&conn->ssl);
|
|
++ if (crt == NULL)
|
|
++ return NULL;
|
|
++ size_t len = crt->serial.len * 2 + 1;
|
|
++ char *serial_num = os_malloc(len);
|
|
++ if (!serial_num)
|
|
++ return NULL;
|
|
++ return tls_mbedtls_peer_serial_num(crt, serial_num, len);
|
|
++}
|
|
++
|
|
++
|
|
++static void tls_pull_buf_reset(struct tls_connection *conn);
|
|
++
|
|
++int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn)
|
|
++{
|
|
++ /* Note: this function called from eap_peer_tls_reauth_init()
|
|
++ * for session resumption, not for connection shutdown */
|
|
++
|
|
++ if (conn == NULL)
|
|
++ return -1;
|
|
++
|
|
++ tls_pull_buf_reset(conn);
|
|
++ wpabuf_free(conn->push_buf);
|
|
++ conn->push_buf = NULL;
|
|
++ conn->established = 0;
|
|
++ conn->resumed = 0;
|
|
++ if (conn->tls_prf_type)
|
|
++ tls_connection_deinit_expkey(conn);
|
|
++
|
|
++ /* RFE: prepare for session resumption? (see doc in crypto/tls.h) */
|
|
++
|
|
++ return mbedtls_ssl_session_reset(&conn->ssl);
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_wpabuf_resize_put_data(struct wpabuf **buf,
|
|
++ const unsigned char *data, size_t dlen)
|
|
++{
|
|
++ if (wpabuf_resize(buf, dlen) < 0)
|
|
++ return 0;
|
|
++ wpabuf_put_data(*buf, data, dlen);
|
|
++ return 1;
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_pull_buf_append(struct tls_connection *conn,
|
|
++ const struct wpabuf *in_data)
|
|
++{
|
|
++ /*(interface does not lend itself to move semantics)*/
|
|
++ return tls_wpabuf_resize_put_data(&conn->pull_buf,
|
|
++ wpabuf_head(in_data),
|
|
++ wpabuf_len(in_data));
|
|
++}
|
|
++
|
|
++
|
|
++static void tls_pull_buf_reset(struct tls_connection *conn)
|
|
++{
|
|
++ /*(future: might consider reusing conn->pull_buf)*/
|
|
++ wpabuf_free(conn->pull_buf);
|
|
++ conn->pull_buf = NULL;
|
|
++ conn->pull_buf_offset = 0;
|
|
++}
|
|
++
|
|
++
|
|
++__attribute_cold__
|
|
++static void tls_pull_buf_discard(struct tls_connection *conn, const char *func)
|
|
++{
|
|
++ size_t discard = wpabuf_len(conn->pull_buf) - conn->pull_buf_offset;
|
|
++ if (discard)
|
|
++ wpa_printf(MSG_DEBUG,
|
|
++ "%s - %zu bytes remaining in pull_buf; discarding",
|
|
++ func, discard);
|
|
++ tls_pull_buf_reset(conn);
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_pull_func(void *ptr, unsigned char *buf, size_t len)
|
|
++{
|
|
++ struct tls_connection *conn = (struct tls_connection *) ptr;
|
|
++ if (conn->pull_buf == NULL)
|
|
++ return MBEDTLS_ERR_SSL_WANT_READ;
|
|
++ const size_t dlen = wpabuf_len(conn->pull_buf) - conn->pull_buf_offset;
|
|
++ if (dlen == 0)
|
|
++ return MBEDTLS_ERR_SSL_WANT_READ;
|
|
++
|
|
++ if (len > dlen)
|
|
++ len = dlen;
|
|
++ os_memcpy(buf, wpabuf_head(conn->pull_buf)+conn->pull_buf_offset, len);
|
|
++
|
|
++ if (len == dlen) {
|
|
++ tls_pull_buf_reset(conn);
|
|
++ /*wpa_printf(MSG_DEBUG, "%s - emptied pull_buf", __func__);*/
|
|
++ }
|
|
++ else {
|
|
++ conn->pull_buf_offset += len;
|
|
++ /*wpa_printf(MSG_DEBUG, "%s - %zu bytes remaining in pull_buf",
|
|
++ __func__, dlen - len);*/
|
|
++ }
|
|
++ return (int)len;
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_push_func(void *ptr, const unsigned char *buf, size_t len)
|
|
++{
|
|
++ struct tls_connection *conn = (struct tls_connection *) ptr;
|
|
++ return tls_wpabuf_resize_put_data(&conn->push_buf, buf, len)
|
|
++ ? (int)len
|
|
++ : MBEDTLS_ERR_SSL_ALLOC_FAILED;
|
|
++}
|
|
++
|
|
++
|
|
++static int
|
|
++tls_mbedtls_verify_cb (void *arg, mbedtls_x509_crt *crt, int depth, uint32_t *flags);
|
|
++
|
|
++
|
|
++static int tls_mbedtls_ssl_setup(struct tls_connection *conn)
|
|
++{
|
|
++ #if 0
|
|
++ /* mbedtls_ssl_setup() must be called only once */
|
|
++ /* If this func might be called multiple times (e.g. via set_params),
|
|
++ * then we should set a flag in conn that ssl was initialized */
|
|
++ if (conn->ssl_is_init) {
|
|
++ mbedtls_ssl_free(&conn->ssl);
|
|
++ mbedtls_ssl_init(&conn->ssl);
|
|
++ }
|
|
++ #endif
|
|
++
|
|
++ int ret = mbedtls_ssl_setup(&conn->ssl, &conn->tls_conf->conf);
|
|
++ if (ret != 0) {
|
|
++ elog(ret, "mbedtls_ssl_setup");
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ mbedtls_ssl_set_bio(&conn->ssl, conn, tls_push_func, tls_pull_func, NULL);
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++ mbedtls_ssl_set_export_keys_cb(
|
|
++ &conn->ssl, tls_connection_export_keys_cb, conn);
|
|
++ #elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
|
|
++ mbedtls_ssl_conf_export_keys_ext_cb(
|
|
++ &conn->tls_conf->conf, tls_connection_export_keys_cb, conn);
|
|
++ #endif
|
|
++ if (conn->verify_peer)
|
|
++ mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn);
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_mbedtls_data_is_pem(const u8 *data)
|
|
++{
|
|
++ return (NULL != os_strstr((char *)data, "-----"));
|
|
++}
|
|
++
|
|
++
|
|
++static void tls_mbedtls_set_allowed_tls_vers(struct tls_conf *tls_conf,
|
|
++ mbedtls_ssl_config *conf)
|
|
++{
|
|
++ #if !defined(MBEDTLS_SSL_PROTO_TLS1_3)
|
|
++ tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_3;
|
|
++ #endif
|
|
++
|
|
++ /* unconditionally require TLSv1.2+ for TLS_CONN_SUITEB */
|
|
++ if (tls_conf->flags & TLS_CONN_SUITEB) {
|
|
++ tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_0;
|
|
++ tls_conf->flags |= TLS_CONN_DISABLE_TLSv1_1;
|
|
++ }
|
|
++
|
|
++ const unsigned int flags = tls_conf->flags;
|
|
++
|
|
++ /* attempt to map flags to min and max TLS protocol version */
|
|
++
|
|
++ int min = (flags & TLS_CONN_DISABLE_TLSv1_0)
|
|
++ ? (flags & TLS_CONN_DISABLE_TLSv1_1)
|
|
++ ? (flags & TLS_CONN_DISABLE_TLSv1_2)
|
|
++ ? (flags & TLS_CONN_DISABLE_TLSv1_3)
|
|
++ ? 4
|
|
++ : 3
|
|
++ : 2
|
|
++ : 1
|
|
++ : 0;
|
|
++
|
|
++ int max = (flags & TLS_CONN_DISABLE_TLSv1_3)
|
|
++ ? (flags & TLS_CONN_DISABLE_TLSv1_2)
|
|
++ ? (flags & TLS_CONN_DISABLE_TLSv1_1)
|
|
++ ? (flags & TLS_CONN_DISABLE_TLSv1_0)
|
|
++ ? -1
|
|
++ : 0
|
|
++ : 1
|
|
++ : 2
|
|
++ : 3;
|
|
++
|
|
++ if ((flags & TLS_CONN_ENABLE_TLSv1_2) && min > 2) min = 2;
|
|
++ if ((flags & TLS_CONN_ENABLE_TLSv1_1) && min > 1) min = 1;
|
|
++ if ((flags & TLS_CONN_ENABLE_TLSv1_0) && min > 0) min = 0;
|
|
++ if (max < min) {
|
|
++ emsg(MSG_ERROR, "invalid tls_disable_tlsv* params; ignoring");
|
|
++ return;
|
|
++ }
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++ /* mbed TLS 3.0.0 removes support for protocols < TLSv1.2 */
|
|
++ if (min < 2 || max < 2) {
|
|
++ emsg(MSG_ERROR, "invalid tls_disable_tlsv* params; ignoring");
|
|
++ if (min < 2) min = 2;
|
|
++ if (max < 2) max = 2;
|
|
++ }
|
|
++ #endif
|
|
++
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */
|
|
++ /* MBEDTLS_SSL_VERSION_TLS1_2 = 0x0303 *//*!< (D)TLS 1.2 */
|
|
++ /* MBEDTLS_SSL_VERSION_TLS1_3 = 0x0304 *//*!< (D)TLS 1.3 */
|
|
++ min = (min == 2) ? MBEDTLS_SSL_VERSION_TLS1_2 : MBEDTLS_SSL_VERSION_TLS1_3;
|
|
++ max = (max == 2) ? MBEDTLS_SSL_VERSION_TLS1_2 : MBEDTLS_SSL_VERSION_TLS1_3;
|
|
++ mbedtls_ssl_conf_min_tls_version(conf, min);
|
|
++ mbedtls_ssl_conf_max_tls_version(conf, max);
|
|
++ #else
|
|
++ #ifndef MBEDTLS_SSL_MINOR_VERSION_4
|
|
++ if (min == 3) min = 2;
|
|
++ if (max == 3) max = 2;
|
|
++ #endif
|
|
++ /* MBEDTLS_SSL_MINOR_VERSION_0 0 *//*!< SSL v3.0 */
|
|
++ /* MBEDTLS_SSL_MINOR_VERSION_1 1 *//*!< TLS v1.0 */
|
|
++ /* MBEDTLS_SSL_MINOR_VERSION_2 2 *//*!< TLS v1.1 */
|
|
++ /* MBEDTLS_SSL_MINOR_VERSION_3 3 *//*!< TLS v1.2 */
|
|
++ /* MBEDTLS_SSL_MINOR_VERSION_4 4 *//*!< TLS v1.3 */
|
|
++ mbedtls_ssl_conf_min_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, min+1);
|
|
++ mbedtls_ssl_conf_max_version(conf, MBEDTLS_SSL_MAJOR_VERSION_3, max+1);
|
|
++ #endif
|
|
++}
|
|
++
|
|
++
|
|
++__attribute_noinline__
|
|
++static int tls_mbedtls_readfile(const char *path, u8 **buf, size_t *n);
|
|
++
|
|
++
|
|
++static int
|
|
++tls_mbedtls_set_dhparams(struct tls_conf *tls_conf, const char *dh_file)
|
|
++{
|
|
++ size_t len;
|
|
++ u8 *data;
|
|
++ if (tls_mbedtls_readfile(dh_file, &data, &len))
|
|
++ return 0;
|
|
++
|
|
++ /* parse only if DH parameters if in PEM format */
|
|
++ if (tls_mbedtls_data_is_pem(data)
|
|
++ && NULL == os_strstr((char *)data, "-----BEGIN DH PARAMETERS-----")) {
|
|
++ if (os_strstr((char *)data, "-----BEGIN DSA PARAMETERS-----"))
|
|
++ wpa_printf(MSG_WARNING, "DSA parameters not handled (%s)", dh_file);
|
|
++ else
|
|
++ wpa_printf(MSG_WARNING, "unexpected DH param content (%s)",dh_file);
|
|
++ forced_memzero(data, len);
|
|
++ os_free(data);
|
|
++ return 0;
|
|
++ }
|
|
++
|
|
++ /* mbedtls_dhm_parse_dhm() expects "-----BEGIN DH PARAMETERS-----" if PEM */
|
|
++ mbedtls_dhm_context dhm;
|
|
++ mbedtls_dhm_init(&dhm);
|
|
++ int rc = mbedtls_dhm_parse_dhm(&dhm, data, len);
|
|
++ if (0 == rc)
|
|
++ rc = mbedtls_ssl_conf_dh_param_ctx(&tls_conf->conf, &dhm);
|
|
++ if (0 != rc)
|
|
++ elog(rc, dh_file);
|
|
++ mbedtls_dhm_free(&dhm);
|
|
++
|
|
++ forced_memzero(data, len);
|
|
++ os_free(data);
|
|
++ return (0 == rc);
|
|
++}
|
|
++
|
|
++
|
|
++/* reference: lighttpd src/mod_mbedtls.c:mod_mbedtls_ssl_append_curve()
|
|
++ * (same author: gstrauss@gluelogic.com; same license: BSD-3-Clause) */
|
|
++#if MBEDTLS_VERSION_NUMBER < 0x03010000 /* mbedtls 3.1.0 */
|
|
++static int
|
|
++tls_mbedtls_append_curve (mbedtls_ecp_group_id *ids, int nids, int idsz, const mbedtls_ecp_group_id id)
|
|
++{
|
|
++ if (1 >= idsz - (nids + 1)) {
|
|
++ emsg(MSG_ERROR, "error: too many curves during list expand");
|
|
++ return -1;
|
|
++ }
|
|
++ ids[++nids] = id;
|
|
++ return nids;
|
|
++}
|
|
++
|
|
++
|
|
++static int
|
|
++tls_mbedtls_set_curves(struct tls_conf *tls_conf, const char *curvelist)
|
|
++{
|
|
++ mbedtls_ecp_group_id ids[512];
|
|
++ int nids = -1;
|
|
++ const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1);
|
|
++ const mbedtls_ecp_curve_info * const curve_info = mbedtls_ecp_curve_list();
|
|
++
|
|
++ for (const char *e = curvelist-1; e; ) {
|
|
++ const char * const n = e+1;
|
|
++ e = os_strchr(n, ':');
|
|
++ size_t len = e ? (size_t)(e - n) : os_strlen(n);
|
|
++ mbedtls_ecp_group_id grp_id = MBEDTLS_ECP_DP_NONE;
|
|
++ switch (len) {
|
|
++ case 5:
|
|
++ if (0 == os_memcmp("P-521", n, 5))
|
|
++ grp_id = MBEDTLS_ECP_DP_SECP521R1;
|
|
++ else if (0 == os_memcmp("P-384", n, 5))
|
|
++ grp_id = MBEDTLS_ECP_DP_SECP384R1;
|
|
++ else if (0 == os_memcmp("P-256", n, 5))
|
|
++ grp_id = MBEDTLS_ECP_DP_SECP256R1;
|
|
++ break;
|
|
++ case 6:
|
|
++ if (0 == os_memcmp("BP-521", n, 6))
|
|
++ grp_id = MBEDTLS_ECP_DP_BP512R1;
|
|
++ else if (0 == os_memcmp("BP-384", n, 6))
|
|
++ grp_id = MBEDTLS_ECP_DP_BP384R1;
|
|
++ else if (0 == os_memcmp("BP-256", n, 6))
|
|
++ grp_id = MBEDTLS_ECP_DP_BP256R1;
|
|
++ break;
|
|
++ default:
|
|
++ break;
|
|
++ }
|
|
++ if (grp_id != MBEDTLS_ECP_DP_NONE) {
|
|
++ nids = tls_mbedtls_append_curve(ids, nids, idsz, grp_id);
|
|
++ if (-1 == nids) return 0;
|
|
++ continue;
|
|
++ }
|
|
++ /* similar to mbedtls_ecp_curve_info_from_name() */
|
|
++ const mbedtls_ecp_curve_info *info;
|
|
++ for (info = curve_info; info->grp_id != MBEDTLS_ECP_DP_NONE; ++info) {
|
|
++ if (0 == os_strncmp(info->name, n, len) && info->name[len] == '\0')
|
|
++ break;
|
|
++ }
|
|
++ if (info->grp_id == MBEDTLS_ECP_DP_NONE) {
|
|
++ wpa_printf(MSG_ERROR, "MTLS: unrecognized curve: %.*s",(int)len,n);
|
|
++ return 0;
|
|
++ }
|
|
++
|
|
++ nids = tls_mbedtls_append_curve(ids, nids, idsz, info->grp_id);
|
|
++ if (-1 == nids) return 0;
|
|
++ }
|
|
++
|
|
++ /* mod_openssl configures "prime256v1" if curve list not specified,
|
|
++ * but mbedtls provides a list of supported curves if not explicitly set */
|
|
++ if (-1 == nids) return 1; /* empty list; no-op */
|
|
++
|
|
++ ids[++nids] = MBEDTLS_ECP_DP_NONE; /* terminate list */
|
|
++ ++nids;
|
|
++
|
|
++ /* curves list must be persistent for lifetime of mbedtls_ssl_config */
|
|
++ tls_conf->curves = os_malloc(nids * sizeof(mbedtls_ecp_group_id));
|
|
++ if (tls_conf->curves == NULL)
|
|
++ return 0;
|
|
++ os_memcpy(tls_conf->curves, ids, nids * sizeof(mbedtls_ecp_group_id));
|
|
++
|
|
++ mbedtls_ssl_conf_curves(&tls_conf->conf, tls_conf->curves);
|
|
++ return 1;
|
|
++}
|
|
++#else
|
|
++static int
|
|
++tls_mbedtls_append_curve (uint16_t *ids, int nids, int idsz, const uint16_t id)
|
|
++{
|
|
++ if (1 >= idsz - (nids + 1)) {
|
|
++ emsg(MSG_ERROR, "error: too many curves during list expand");
|
|
++ return -1;
|
|
++ }
|
|
++ ids[++nids] = id;
|
|
++ return nids;
|
|
++}
|
|
++
|
|
++
|
|
++static int
|
|
++tls_mbedtls_set_curves(struct tls_conf *tls_conf, const char *curvelist)
|
|
++{
|
|
++ /* TLS Supported Groups (renamed from "EC Named Curve Registry")
|
|
++ * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
|
|
++ */
|
|
++ uint16_t ids[512];
|
|
++ int nids = -1;
|
|
++ const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1);
|
|
++ const mbedtls_ecp_curve_info * const curve_info = mbedtls_ecp_curve_list();
|
|
++
|
|
++ for (const char *e = curvelist-1; e; ) {
|
|
++ const char * const n = e+1;
|
|
++ e = os_strchr(n, ':');
|
|
++ size_t len = e ? (size_t)(e - n) : os_strlen(n);
|
|
++ uint16_t tls_id = 0;
|
|
++ switch (len) {
|
|
++ case 5:
|
|
++ if (0 == os_memcmp("P-521", n, 5))
|
|
++ tls_id = 25; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP521R1 */
|
|
++ else if (0 == os_memcmp("P-384", n, 5))
|
|
++ tls_id = 24; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP384R1 */
|
|
++ else if (0 == os_memcmp("P-256", n, 5))
|
|
++ tls_id = 23; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_SECP256R1 */
|
|
++ break;
|
|
++ case 6:
|
|
++ if (0 == os_memcmp("BP-521", n, 6))
|
|
++ tls_id = 28; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP512R1 */
|
|
++ else if (0 == os_memcmp("BP-384", n, 6))
|
|
++ tls_id = 27; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP384R1 */
|
|
++ else if (0 == os_memcmp("BP-256", n, 6))
|
|
++ tls_id = 26; /* mbedtls_ecp_group_id MBEDTLS_ECP_DP_BP256R1 */
|
|
++ break;
|
|
++ default:
|
|
++ break;
|
|
++ }
|
|
++ if (tls_id != 0) {
|
|
++ nids = tls_mbedtls_append_curve(ids, nids, idsz, tls_id);
|
|
++ if (-1 == nids) return 0;
|
|
++ continue;
|
|
++ }
|
|
++ /* similar to mbedtls_ecp_curve_info_from_name() */
|
|
++ const mbedtls_ecp_curve_info *info;
|
|
++ for (info = curve_info; info->tls_id != 0; ++info) {
|
|
++ if (0 == os_strncmp(info->name, n, len) && info->name[len] == '\0')
|
|
++ break;
|
|
++ }
|
|
++ if (info->tls_id == 0) {
|
|
++ wpa_printf(MSG_ERROR, "MTLS: unrecognized curve: %.*s",(int)len,n);
|
|
++ return 0;
|
|
++ }
|
|
++
|
|
++ nids = tls_mbedtls_append_curve(ids, nids, idsz, info->tls_id);
|
|
++ if (-1 == nids) return 0;
|
|
++ }
|
|
++
|
|
++ /* mod_openssl configures "prime256v1" if curve list not specified,
|
|
++ * but mbedtls provides a list of supported curves if not explicitly set */
|
|
++ if (-1 == nids) return 1; /* empty list; no-op */
|
|
++
|
|
++ ids[++nids] = 0; /* terminate list */
|
|
++ ++nids;
|
|
++
|
|
++ /* curves list must be persistent for lifetime of mbedtls_ssl_config */
|
|
++ tls_conf->curves = os_malloc(nids * sizeof(uint16_t));
|
|
++ if (tls_conf->curves == NULL)
|
|
++ return 0;
|
|
++ os_memcpy(tls_conf->curves, ids, nids * sizeof(uint16_t));
|
|
++
|
|
++ mbedtls_ssl_conf_groups(&tls_conf->conf, tls_conf->curves);
|
|
++ return 1;
|
|
++}
|
|
++#endif /* MBEDTLS_VERSION_NUMBER >= 0x03010000 */ /* mbedtls 3.1.0 */
|
|
++
|
|
++
|
|
++/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */
|
|
++static const int suite_AES_256_ephemeral[] = {
|
|
++ /* All AES-256 ephemeral suites */
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8
|
|
++};
|
|
++
|
|
++/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */
|
|
++static const int suite_AES_128_ephemeral[] = {
|
|
++ /* All AES-128 ephemeral suites */
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8
|
|
++};
|
|
++
|
|
++/* data copied from lighttpd src/mod_mbedtls.c (BSD-3-Clause) */
|
|
++/* HIGH cipher list (mapped from openssl list to mbedtls) */
|
|
++static const int suite_HIGH[] = {
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CCM_8,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CCM_8,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM,
|
|
++ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CCM_8,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM,
|
|
++ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CCM_8,
|
|
++ MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_RSA_WITH_AES_256_CCM,
|
|
++ MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256,
|
|
++ MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_RSA_WITH_AES_256_CCM_8,
|
|
++ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256,
|
|
++ MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_RSA_WITH_AES_128_CCM,
|
|
++ MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_RSA_WITH_AES_128_CCM_8,
|
|
++ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_RSA_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
|
++ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256,
|
|
++ MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_PSK_WITH_AES_256_CCM,
|
|
++ MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA,
|
|
++ MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384,
|
|
++ MBEDTLS_TLS_PSK_WITH_AES_256_CCM_8,
|
|
++ MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384,
|
|
++ MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256,
|
|
++ MBEDTLS_TLS_PSK_WITH_AES_128_CCM,
|
|
++ MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA,
|
|
++ MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256,
|
|
++ MBEDTLS_TLS_PSK_WITH_AES_128_CCM_8,
|
|
++ MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256
|
|
++};
|
|
++
|
|
++
|
|
++__attribute_noinline__
|
|
++static int
|
|
++tls_mbedtls_append_ciphersuite (int *ids, int nids, int idsz, const int *x, int xsz)
|
|
++{
|
|
++ if (xsz >= idsz - (nids + 1)) {
|
|
++ emsg(MSG_ERROR, "error: too many ciphers during list expand");
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ for (int i = 0; i < xsz; ++i)
|
|
++ ids[++nids] = x[i];
|
|
++
|
|
++ return nids;
|
|
++}
|
|
++
|
|
++
|
|
++static int
|
|
++tls_mbedtls_translate_ciphername(int id, char *buf, size_t buflen)
|
|
++{
|
|
++ const mbedtls_ssl_ciphersuite_t *info =
|
|
++ mbedtls_ssl_ciphersuite_from_id(id);
|
|
++ if (info == NULL)
|
|
++ return 0;
|
|
++ const char *name = mbedtls_ssl_ciphersuite_get_name(info);
|
|
++ const size_t len = os_strlen(name);
|
|
++ if (len == 7 && 0 == os_memcmp(name, "unknown", 7))
|
|
++ return 0;
|
|
++ if (len >= buflen)
|
|
++ return 0;
|
|
++ os_strlcpy(buf, name, buflen);
|
|
++
|
|
++ /* attempt to translate mbedtls string to openssl string
|
|
++ * (some heuristics; incomplete) */
|
|
++ size_t i = 0, j = 0;
|
|
++ if (buf[0] == 'T') {
|
|
++ if (os_strncmp(buf, "TLS1-3-", 7) == 0) {
|
|
++ buf[3] = '-';
|
|
++ j = 4; /* remove "1-3" from "TLS1-3-" prefix */
|
|
++ i = 7;
|
|
++ }
|
|
++ else if (os_strncmp(buf, "TLS-", 4) == 0)
|
|
++ i = 4; /* remove "TLS-" prefix */
|
|
++ }
|
|
++ for (; buf[i]; ++i) {
|
|
++ if (buf[i] == '-') {
|
|
++ if (i >= 3) {
|
|
++ if (0 == os_memcmp(buf+i-3, "AES", 3))
|
|
++ continue; /* "AES-" -> "AES" */
|
|
++ }
|
|
++ if (i >= 4) {
|
|
++ if (0 == os_memcmp(buf+i-4, "WITH", 4)) {
|
|
++ j -= 4; /* remove "WITH-" */
|
|
++ continue;
|
|
++ }
|
|
++ }
|
|
++ }
|
|
++ buf[j++] = buf[i];
|
|
++ }
|
|
++ buf[j] = '\0';
|
|
++
|
|
++ return j;
|
|
++}
|
|
++
|
|
++
|
|
++__attribute_noinline__
|
|
++static int
|
|
++tls_mbedtls_set_ciphersuites(struct tls_conf *tls_conf, int *ids, int nids)
|
|
++{
|
|
++ /* ciphersuites list must be persistent for lifetime of mbedtls_ssl_config*/
|
|
++ os_free(tls_conf->ciphersuites);
|
|
++ tls_conf->ciphersuites = os_malloc(nids * sizeof(int));
|
|
++ if (tls_conf->ciphersuites == NULL)
|
|
++ return 0;
|
|
++ os_memcpy(tls_conf->ciphersuites, ids, nids * sizeof(int));
|
|
++ mbedtls_ssl_conf_ciphersuites(&tls_conf->conf, tls_conf->ciphersuites);
|
|
++ return 1;
|
|
++}
|
|
++
|
|
++
|
|
++static int
|
|
++tls_mbedtls_set_ciphers(struct tls_conf *tls_conf, const char *ciphers)
|
|
++{
|
|
++ char buf[64];
|
|
++ int ids[512];
|
|
++ int nids = -1;
|
|
++ const int idsz = (int)(sizeof(ids)/sizeof(*ids)-1);
|
|
++ const char *next;
|
|
++ size_t blen, clen;
|
|
++ do {
|
|
++ next = os_strchr(ciphers, ':');
|
|
++ clen = next ? (size_t)(next - ciphers) : os_strlen(ciphers);
|
|
++ if (!clen)
|
|
++ continue;
|
|
++
|
|
++ /* special-case a select set of openssl group names for hwsim tests */
|
|
++ /* (review; remove excess code if tests are not run for non-OpenSSL?) */
|
|
++ if (clen == 9 && os_memcmp(ciphers, "SUITEB192", 9) == 0) {
|
|
++ static int ssl_preset_suiteb192_ciphersuites[] = {
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
|
|
++ 0
|
|
++ };
|
|
++ return tls_mbedtls_set_ciphersuites(tls_conf,
|
|
++ ssl_preset_suiteb192_ciphersuites,
|
|
++ 2);
|
|
++ }
|
|
++ if (clen == 9 && os_memcmp(ciphers, "SUITEB128", 9) == 0) {
|
|
++ static int ssl_preset_suiteb128_ciphersuites[] = {
|
|
++ MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
|
|
++ 0
|
|
++ };
|
|
++ return tls_mbedtls_set_ciphersuites(tls_conf,
|
|
++ ssl_preset_suiteb128_ciphersuites,
|
|
++ 2);
|
|
++ }
|
|
++ if (clen == 7 && os_memcmp(ciphers, "DEFAULT", 7) == 0)
|
|
++ continue;
|
|
++ if (clen == 6 && os_memcmp(ciphers, "AES128", 6) == 0) {
|
|
++ nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz,
|
|
++ suite_AES_128_ephemeral,
|
|
++ (int)ARRAY_SIZE(suite_AES_128_ephemeral));
|
|
++ if (nids == -1)
|
|
++ return 0;
|
|
++ continue;
|
|
++ }
|
|
++ if (clen == 6 && os_memcmp(ciphers, "AES256", 6) == 0) {
|
|
++ nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz,
|
|
++ suite_AES_256_ephemeral,
|
|
++ (int)ARRAY_SIZE(suite_AES_256_ephemeral));
|
|
++ if (nids == -1)
|
|
++ return 0;
|
|
++ continue;
|
|
++ }
|
|
++ if (clen == 4 && os_memcmp(ciphers, "HIGH", 4) == 0) {
|
|
++ nids = tls_mbedtls_append_ciphersuite(ids, nids, idsz, suite_HIGH,
|
|
++ (int)ARRAY_SIZE(suite_HIGH));
|
|
++ if (nids == -1)
|
|
++ return 0;
|
|
++ continue;
|
|
++ }
|
|
++ /* ignore anonymous cipher group names (?not supported by mbedtls?) */
|
|
++ if (clen == 4 && os_memcmp(ciphers, "!ADH", 4) == 0)
|
|
++ continue;
|
|
++ if (clen == 6 && os_memcmp(ciphers, "-aECDH", 6) == 0)
|
|
++ continue;
|
|
++ if (clen == 7 && os_memcmp(ciphers, "-aECDSA", 7) == 0)
|
|
++ continue;
|
|
++
|
|
++ /* attempt to match mbedtls cipher names
|
|
++ * nb: does not support openssl group names or list manipulation syntax
|
|
++ * (alt: could copy almost 1200 lines (!!!) of lighttpd mod_mbedtls.c
|
|
++ * mod_mbedtls_ssl_conf_ciphersuites() to translate strings)
|
|
++ * note: not efficient to rewrite list for each ciphers entry,
|
|
++ * but this code is expected to run only at startup
|
|
++ */
|
|
++ const int *list = mbedtls_ssl_list_ciphersuites();
|
|
++ for (; *list; ++list) {
|
|
++ blen = tls_mbedtls_translate_ciphername(*list,buf,sizeof(buf));
|
|
++ if (!blen)
|
|
++ continue;
|
|
++
|
|
++ /* matching heuristics additional to translate_ciphername above */
|
|
++ if (blen == clen+4) {
|
|
++ char *cbc = os_strstr(buf, "CBC-");
|
|
++ if (cbc) {
|
|
++ os_memmove(cbc, cbc+4, blen-(cbc+4-buf)+1); /*(w/ '\0')*/
|
|
++ blen -= 4;
|
|
++ }
|
|
++ }
|
|
++ if (blen >= clen && os_memcmp(ciphers, buf, clen) == 0
|
|
++ && (blen == clen
|
|
++ || (blen == clen+7 && os_memcmp(buf+clen, "-SHA256", 7)))) {
|
|
++ if (1 >= idsz - (nids + 1)) {
|
|
++ emsg(MSG_ERROR,
|
|
++ "error: too many ciphers during list expand");
|
|
++ return 0;
|
|
++ }
|
|
++ ids[++nids] = *list;
|
|
++ break;
|
|
++ }
|
|
++ }
|
|
++ if (*list == 0) {
|
|
++ wpa_printf(MSG_ERROR,
|
|
++ "MTLS: unrecognized cipher: %.*s", (int)clen, ciphers);
|
|
++ return 0;
|
|
++ }
|
|
++ } while ((ciphers = next ? next+1 : NULL));
|
|
++
|
|
++ if (-1 == nids) return 1; /* empty list; no-op */
|
|
++
|
|
++ ids[++nids] = 0; /* terminate list */
|
|
++ ++nids;
|
|
++
|
|
++ return tls_mbedtls_set_ciphersuites(tls_conf, ids, nids);
|
|
++}
|
|
++
|
|
++
|
|
++__attribute_noinline__
|
|
++static int tls_mbedtls_set_item(char **config_item, const char *item)
|
|
++{
|
|
++ os_free(*config_item);
|
|
++ *config_item = NULL;
|
|
++ return item ? (*config_item = os_strdup(item)) != NULL : 1;
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_connection_set_subject_match(struct tls_conf *tls_conf,
|
|
++ const struct tls_connection_params *params)
|
|
++{
|
|
++ int rc = 1;
|
|
++ rc &= tls_mbedtls_set_item(&tls_conf->subject_match,
|
|
++ params->subject_match);
|
|
++ rc &= tls_mbedtls_set_item(&tls_conf->altsubject_match,
|
|
++ params->altsubject_match);
|
|
++ rc &= tls_mbedtls_set_item(&tls_conf->suffix_match,
|
|
++ params->suffix_match);
|
|
++ rc &= tls_mbedtls_set_item(&tls_conf->domain_match,
|
|
++ params->domain_match);
|
|
++ rc &= tls_mbedtls_set_item(&tls_conf->check_cert_subject,
|
|
++ params->check_cert_subject);
|
|
++ return rc;
|
|
++}
|
|
++
|
|
++
|
|
++/* duplicated in crypto_mbedtls.c:crypto_mbedtls_readfile()*/
|
|
++__attribute_noinline__
|
|
++static int tls_mbedtls_readfile(const char *path, u8 **buf, size_t *n)
|
|
++{
|
|
++ #if 0 /* #ifdef MBEDTLS_FS_IO */
|
|
++ /*(includes +1 for '\0' needed by mbedtls PEM parsing funcs)*/
|
|
++ if (mbedtls_pk_load_file(path, (unsigned char **)buf, n) != 0) {
|
|
++ wpa_printf(MSG_ERROR, "error: mbedtls_pk_load_file %s", path);
|
|
++ return -1;
|
|
++ }
|
|
++ #else
|
|
++ /*(use os_readfile() so that we can use os_free()
|
|
++ *(if we use mbedtls_pk_load_file() above, macros prevent calling free()
|
|
++ * directly #if defined(OS_REJECT_C_LIB_FUNCTIONS) and calling os_free()
|
|
++ * on buf aborts in tests if buf not allocated via os_malloc())*/
|
|
++ *buf = (u8 *)os_readfile(path, n);
|
|
++ if (!*buf) {
|
|
++ wpa_printf(MSG_ERROR, "error: os_readfile %s", path);
|
|
++ return -1;
|
|
++ }
|
|
++ u8 *buf0 = os_realloc(*buf, *n+1);
|
|
++ if (!buf0) {
|
|
++ bin_clear_free(*buf, *n);
|
|
++ *buf = NULL;
|
|
++ return -1;
|
|
++ }
|
|
++ buf0[(*n)++] = '\0';
|
|
++ *buf = buf0;
|
|
++ #endif
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_mbedtls_set_crl(struct tls_conf *tls_conf, const u8 *data, size_t len)
|
|
++{
|
|
++ /* do not use mbedtls_x509_crl_parse() on PEM unless it contains CRL */
|
|
++ if (len && data[len-1] == '\0'
|
|
++ && NULL == os_strstr((const char *)data,"-----BEGIN X509 CRL-----")
|
|
++ && tls_mbedtls_data_is_pem(data))
|
|
++ return 0;
|
|
++
|
|
++ mbedtls_x509_crl crl;
|
|
++ mbedtls_x509_crl_init(&crl);
|
|
++ int rc = mbedtls_x509_crl_parse(&crl, data, len);
|
|
++ if (rc < 0) {
|
|
++ mbedtls_x509_crl_free(&crl);
|
|
++ return rc == MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ? 0 : rc;
|
|
++ }
|
|
++
|
|
++ mbedtls_x509_crl *crl_new = os_malloc(sizeof(crl));
|
|
++ if (crl_new == NULL) {
|
|
++ mbedtls_x509_crl_free(&crl);
|
|
++ return MBEDTLS_ERR_X509_ALLOC_FAILED;
|
|
++ }
|
|
++ os_memcpy(crl_new, &crl, sizeof(crl));
|
|
++
|
|
++ mbedtls_x509_crl *crl_old = tls_conf->crl;
|
|
++ tls_conf->crl = crl_new;
|
|
++ if (crl_old) {
|
|
++ mbedtls_x509_crl_free(crl_old);
|
|
++ os_free(crl_old);
|
|
++ }
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_mbedtls_set_ca(struct tls_conf *tls_conf, u8 *data, size_t len)
|
|
++{
|
|
++ /* load crt struct onto stack and then copy into tls_conf in
|
|
++ * order to preserve existing tls_conf value if error occurs
|
|
++ *
|
|
++ * hostapd is not threaded, or else should allocate memory and swap in
|
|
++ * pointer reduce race condition. (If threaded, would also need to
|
|
++ * keep reference count of use to avoid freeing while still in use.) */
|
|
++
|
|
++ mbedtls_x509_crt crt;
|
|
++ mbedtls_x509_crt_init(&crt);
|
|
++ int rc = mbedtls_x509_crt_parse(&crt, data, len);
|
|
++ if (rc < 0) {
|
|
++ mbedtls_x509_crt_free(&crt);
|
|
++ return rc;
|
|
++ }
|
|
++
|
|
++ mbedtls_x509_crt_free(&tls_conf->ca_cert);
|
|
++ os_memcpy(&tls_conf->ca_cert, &crt, sizeof(crt));
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_mbedtls_set_ca_and_crl(struct tls_conf *tls_conf, const char *ca_cert_file)
|
|
++{
|
|
++ size_t len;
|
|
++ u8 *data;
|
|
++ if (tls_mbedtls_readfile(ca_cert_file, &data, &len))
|
|
++ return -1;
|
|
++
|
|
++ int rc;
|
|
++ if (0 == (rc = tls_mbedtls_set_ca(tls_conf, data, len))
|
|
++ && (!tls_mbedtls_data_is_pem(data) /*skip parse for CRL if not PEM*/
|
|
++ || 0 == (rc = tls_mbedtls_set_crl(tls_conf, data, len)))) {
|
|
++ mbedtls_ssl_conf_ca_chain(&tls_conf->conf,
|
|
++ &tls_conf->ca_cert,
|
|
++ tls_conf->crl);
|
|
++ }
|
|
++ else {
|
|
++ elog(rc, __func__);
|
|
++ emsg(MSG_ERROR, ca_cert_file);
|
|
++ }
|
|
++
|
|
++ forced_memzero(data, len);
|
|
++ os_free(data);
|
|
++ return rc;
|
|
++}
|
|
++
|
|
++
|
|
++static void tls_mbedtls_refresh_crl(void)
|
|
++{
|
|
++ /* check for CRL refresh
|
|
++ * continue even if error occurs; continue with previous cert, CRL */
|
|
++ unsigned int crl_reload_interval = tls_ctx_global.crl_reload_interval;
|
|
++ const char *ca_cert_file = tls_ctx_global.ca_cert_file;
|
|
++ if (!crl_reload_interval || !ca_cert_file)
|
|
++ return;
|
|
++
|
|
++ struct os_reltime *previous = &tls_ctx_global.crl_reload_previous;
|
|
++ struct os_reltime now;
|
|
++ if (os_get_reltime(&now) != 0
|
|
++ || !os_reltime_expired(&now, previous, crl_reload_interval))
|
|
++ return;
|
|
++
|
|
++ /* Note: modifying global state is not thread-safe
|
|
++ * if in use by existing connections
|
|
++ *
|
|
++ * src/utils/os.h does not provide a portable stat()
|
|
++ * or else it would be a good idea to check mtime and size,
|
|
++ * and avoid reloading if file has not changed */
|
|
++
|
|
++ if (tls_mbedtls_set_ca_and_crl(tls_ctx_global.tls_conf, ca_cert_file) == 0)
|
|
++ *previous = now;
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_mbedtls_set_ca_cert(struct tls_conf *tls_conf,
|
|
++ const struct tls_connection_params *params)
|
|
++{
|
|
++ if (params->ca_cert) {
|
|
++ if (os_strncmp(params->ca_cert, "probe://", 8) == 0) {
|
|
++ tls_conf->ca_cert_probe = 1;
|
|
++ tls_conf->has_ca_cert = 1;
|
|
++ return 0;
|
|
++ }
|
|
++
|
|
++ if (os_strncmp(params->ca_cert, "hash://", 7) == 0) {
|
|
++ const char *pos = params->ca_cert + 7;
|
|
++ if (os_strncmp(pos, "server/sha256/", 14) != 0) {
|
|
++ emsg(MSG_ERROR, "unsupported ca_cert hash value");
|
|
++ return -1;
|
|
++ }
|
|
++ pos += 14;
|
|
++ if (os_strlen(pos) != SHA256_DIGEST_LENGTH*2) {
|
|
++ emsg(MSG_ERROR, "unexpected ca_cert hash length");
|
|
++ return -1;
|
|
++ }
|
|
++ if (hexstr2bin(pos, tls_conf->ca_cert_hash,
|
|
++ SHA256_DIGEST_LENGTH) < 0) {
|
|
++ emsg(MSG_ERROR, "invalid ca_cert hash value");
|
|
++ return -1;
|
|
++ }
|
|
++ emsg(MSG_DEBUG, "checking only server certificate match");
|
|
++ tls_conf->verify_depth0_only = 1;
|
|
++ tls_conf->has_ca_cert = 1;
|
|
++ return 0;
|
|
++ }
|
|
++
|
|
++ if (tls_mbedtls_set_ca_and_crl(tls_conf, params->ca_cert) != 0)
|
|
++ return -1;
|
|
++ }
|
|
++ if (params->ca_cert_blob) {
|
|
++ size_t len = params->ca_cert_blob_len;
|
|
++ int is_pem = tls_mbedtls_data_is_pem(params->ca_cert_blob);
|
|
++ if (len && params->ca_cert_blob[len-1] != '\0' && is_pem)
|
|
++ ++len; /*(include '\0' in len for PEM)*/
|
|
++ int ret = mbedtls_x509_crt_parse(&tls_conf->ca_cert,
|
|
++ params->ca_cert_blob, len);
|
|
++ if (ret != 0) {
|
|
++ elog(ret, "mbedtls_x509_crt_parse");
|
|
++ return -1;
|
|
++ }
|
|
++ if (is_pem) { /*(ca_cert_blob in DER format contains ca cert only)*/
|
|
++ ret = tls_mbedtls_set_crl(tls_conf, params->ca_cert_blob, len);
|
|
++ if (ret != 0) {
|
|
++ elog(ret, "mbedtls_x509_crl_parse");
|
|
++ return -1;
|
|
++ }
|
|
++ }
|
|
++ }
|
|
++
|
|
++ if (mbedtls_x509_time_is_future(&tls_conf->ca_cert.valid_from)
|
|
++ || mbedtls_x509_time_is_past(&tls_conf->ca_cert.valid_to)) {
|
|
++ emsg(MSG_WARNING, "ca_cert expired or not yet valid");
|
|
++ if (params->ca_cert)
|
|
++ emsg(MSG_WARNING, params->ca_cert);
|
|
++ }
|
|
++
|
|
++ tls_conf->has_ca_cert = 1;
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_mbedtls_set_certs(struct tls_conf *tls_conf,
|
|
++ const struct tls_connection_params *params)
|
|
++{
|
|
++ int ret;
|
|
++
|
|
++ if (params->ca_cert || params->ca_cert_blob) {
|
|
++ if (tls_mbedtls_set_ca_cert(tls_conf, params) != 0)
|
|
++ return -1;
|
|
++ }
|
|
++ else if (params->ca_path) {
|
|
++ emsg(MSG_INFO, "ca_path support not implemented");
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ if (!tls_conf->has_ca_cert)
|
|
++ mbedtls_ssl_conf_authmode(&tls_conf->conf, MBEDTLS_SSL_VERIFY_NONE);
|
|
++ else {
|
|
++ /* Initial setting: REQUIRED for client, OPTIONAL for server
|
|
++ * (see also tls_connection_set_verify()) */
|
|
++ tls_conf->verify_peer = (tls_ctx_global.tls_conf == NULL);
|
|
++ int authmode = tls_conf->verify_peer
|
|
++ ? MBEDTLS_SSL_VERIFY_REQUIRED
|
|
++ : MBEDTLS_SSL_VERIFY_OPTIONAL;
|
|
++ mbedtls_ssl_conf_authmode(&tls_conf->conf, authmode);
|
|
++ mbedtls_ssl_conf_ca_chain(&tls_conf->conf,
|
|
++ &tls_conf->ca_cert,
|
|
++ tls_conf->crl);
|
|
++
|
|
++ if (!tls_connection_set_subject_match(tls_conf, params))
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ if (params->client_cert2) /*(yes, server_cert2 in msg below)*/
|
|
++ emsg(MSG_INFO, "server_cert2 support not implemented");
|
|
++
|
|
++ if (params->client_cert) {
|
|
++ size_t len;
|
|
++ u8 *data;
|
|
++ if (tls_mbedtls_readfile(params->client_cert, &data, &len))
|
|
++ return -1;
|
|
++ ret = mbedtls_x509_crt_parse(&tls_conf->client_cert, data, len);
|
|
++ forced_memzero(data, len);
|
|
++ os_free(data);
|
|
++ }
|
|
++ if (params->client_cert_blob) {
|
|
++ size_t len = params->client_cert_blob_len;
|
|
++ if (len && params->client_cert_blob[len-1] != '\0'
|
|
++ && tls_mbedtls_data_is_pem(params->client_cert_blob))
|
|
++ ++len; /*(include '\0' in len for PEM)*/
|
|
++ ret = mbedtls_x509_crt_parse(&tls_conf->client_cert,
|
|
++ params->client_cert_blob, len);
|
|
++ }
|
|
++ if (params->client_cert || params->client_cert_blob) {
|
|
++ if (ret < 0) {
|
|
++ elog(ret, "mbedtls_x509_crt_parse");
|
|
++ if (params->client_cert)
|
|
++ emsg(MSG_ERROR, params->client_cert);
|
|
++ return -1;
|
|
++ }
|
|
++ if (mbedtls_x509_time_is_future(&tls_conf->client_cert.valid_from)
|
|
++ || mbedtls_x509_time_is_past(&tls_conf->client_cert.valid_to)) {
|
|
++ emsg(MSG_WARNING, "cert expired or not yet valid");
|
|
++ if (params->client_cert)
|
|
++ emsg(MSG_WARNING, params->client_cert);
|
|
++ }
|
|
++ tls_conf->has_client_cert = 1;
|
|
++ }
|
|
++
|
|
++ if (params->private_key || params->private_key_blob) {
|
|
++ size_t len = params->private_key_blob_len;
|
|
++ u8 *data;
|
|
++ *(const u8 **)&data = params->private_key_blob;
|
|
++ if (len && data[len-1] != '\0' && tls_mbedtls_data_is_pem(data))
|
|
++ ++len; /*(include '\0' in len for PEM)*/
|
|
++ if (params->private_key
|
|
++ && tls_mbedtls_readfile(params->private_key, &data, &len)) {
|
|
++ return -1;
|
|
++ }
|
|
++ const char *pwd = params->private_key_passwd;
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++ ret = mbedtls_pk_parse_key(&tls_conf->private_key,
|
|
++ data, len,
|
|
++ (const unsigned char *)pwd,
|
|
++ pwd ? os_strlen(pwd) : 0,
|
|
++ mbedtls_ctr_drbg_random,
|
|
++ tls_ctx_global.ctr_drbg);
|
|
++ #else
|
|
++ ret = mbedtls_pk_parse_key(&tls_conf->private_key,
|
|
++ data, len,
|
|
++ (const unsigned char *)pwd,
|
|
++ pwd ? os_strlen(pwd) : 0);
|
|
++ #endif
|
|
++ if (params->private_key) {
|
|
++ forced_memzero(data, len);
|
|
++ os_free(data);
|
|
++ }
|
|
++ if (ret < 0) {
|
|
++ elog(ret, "mbedtls_pk_parse_key");
|
|
++ return -1;
|
|
++ }
|
|
++ tls_conf->has_private_key = 1;
|
|
++ }
|
|
++
|
|
++ if (tls_conf->has_client_cert && tls_conf->has_private_key) {
|
|
++ ret = mbedtls_ssl_conf_own_cert(
|
|
++ &tls_conf->conf, &tls_conf->client_cert, &tls_conf->private_key);
|
|
++ if (ret < 0) {
|
|
++ elog(ret, "mbedtls_ssl_conf_own_cert");
|
|
++ return -1;
|
|
++ }
|
|
++ }
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++/* mbedtls_x509_crt_profile_suiteb plus rsa_min_bitlen 2048 */
|
|
++/* (reference: see also mbedtls_x509_crt_profile_next) */
|
|
++/* ??? should permit SHA-512, too, and additional curves ??? */
|
|
++static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb128 =
|
|
++{
|
|
++ /* Only SHA-256 and 384 */
|
|
++ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) |
|
|
++ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
|
|
++ /* Only ECDSA */
|
|
++ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
|
|
++ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
|
|
++#if defined(MBEDTLS_ECP_C)
|
|
++ /* Only NIST P-256 and P-384 */
|
|
++ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) |
|
|
++ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
|
|
++#else
|
|
++ 0,
|
|
++#endif
|
|
++ 2048,
|
|
++};
|
|
++
|
|
++
|
|
++/* stricter than mbedtls_x509_crt_profile_suiteb */
|
|
++/* (reference: see also mbedtls_x509_crt_profile_next) */
|
|
++/* ??? should permit SHA-512, too, and additional curves ??? */
|
|
++static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb192 =
|
|
++{
|
|
++ /* Only SHA-384 */
|
|
++ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
|
|
++ /* Only ECDSA */
|
|
++ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) |
|
|
++ MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ),
|
|
++#if defined(MBEDTLS_ECP_C)
|
|
++ /* Only NIST P-384 */
|
|
++ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
|
|
++#else
|
|
++ 0,
|
|
++#endif
|
|
++ 3072,
|
|
++};
|
|
++
|
|
++
|
|
++/* stricter than mbedtls_x509_crt_profile_suiteb except allow any PK alg */
|
|
++/* (reference: see also mbedtls_x509_crt_profile_next) */
|
|
++/* ??? should permit SHA-512, too, and additional curves ??? */
|
|
++static const mbedtls_x509_crt_profile tls_mbedtls_crt_profile_suiteb192_anypk =
|
|
++{
|
|
++ /* Only SHA-384 */
|
|
++ MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ),
|
|
++ 0xFFFFFFF, /* Any PK alg */
|
|
++#if defined(MBEDTLS_ECP_C)
|
|
++ /* Only NIST P-384 */
|
|
++ MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ),
|
|
++#else
|
|
++ 0,
|
|
++#endif
|
|
++ 3072,
|
|
++};
|
|
++
|
|
++
|
|
++static int tls_mbedtls_set_params(struct tls_conf *tls_conf,
|
|
++ const struct tls_connection_params *params)
|
|
++{
|
|
++ tls_conf->flags = params->flags;
|
|
++
|
|
++ if (tls_conf->flags & TLS_CONN_REQUIRE_OCSP_ALL) {
|
|
++ emsg(MSG_INFO, "ocsp=3 not supported");
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ if (tls_conf->flags & TLS_CONN_REQUIRE_OCSP) {
|
|
++ emsg(MSG_INFO, "ocsp not supported");
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ int suiteb128 = 0;
|
|
++ int suiteb192 = 0;
|
|
++ if (params->openssl_ciphers) {
|
|
++ if (os_strcmp(params->openssl_ciphers, "SUITEB192") == 0) {
|
|
++ suiteb192 = 1;
|
|
++ tls_conf->flags |= TLS_CONN_SUITEB;
|
|
++ }
|
|
++ if (os_strcmp(params->openssl_ciphers, "SUITEB128") == 0) {
|
|
++ suiteb128 = 1;
|
|
++ tls_conf->flags |= TLS_CONN_SUITEB;
|
|
++ }
|
|
++ }
|
|
++
|
|
++ int ret = mbedtls_ssl_config_defaults(
|
|
++ &tls_conf->conf, tls_ctx_global.tls_conf ? MBEDTLS_SSL_IS_SERVER
|
|
++ : MBEDTLS_SSL_IS_CLIENT,
|
|
++ MBEDTLS_SSL_TRANSPORT_STREAM,
|
|
++ (tls_conf->flags & TLS_CONN_SUITEB) ? MBEDTLS_SSL_PRESET_SUITEB
|
|
++ : MBEDTLS_SSL_PRESET_DEFAULT);
|
|
++ if (ret != 0) {
|
|
++ elog(ret, "mbedtls_ssl_config_defaults");
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ if (suiteb128) {
|
|
++ mbedtls_ssl_conf_cert_profile(&tls_conf->conf,
|
|
++ &tls_mbedtls_crt_profile_suiteb128);
|
|
++ mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 2048);
|
|
++ }
|
|
++ else if (suiteb192) {
|
|
++ mbedtls_ssl_conf_cert_profile(&tls_conf->conf,
|
|
++ &tls_mbedtls_crt_profile_suiteb192);
|
|
++ mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 3072);
|
|
++ }
|
|
++ else if (tls_conf->flags & TLS_CONN_SUITEB) {
|
|
++ /* treat as suiteb192 while allowing any PK algorithm */
|
|
++ mbedtls_ssl_conf_cert_profile(&tls_conf->conf,
|
|
++ &tls_mbedtls_crt_profile_suiteb192_anypk);
|
|
++ mbedtls_ssl_conf_dhm_min_bitlen(&tls_conf->conf, 3072);
|
|
++ }
|
|
++
|
|
++ tls_mbedtls_set_allowed_tls_vers(tls_conf, &tls_conf->conf);
|
|
++ ret = tls_mbedtls_set_certs(tls_conf, params);
|
|
++ if (ret != 0)
|
|
++ return -1;
|
|
++
|
|
++ if (params->dh_file
|
|
++ && !tls_mbedtls_set_dhparams(tls_conf, params->dh_file)) {
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ if (params->openssl_ecdh_curves
|
|
++ && !tls_mbedtls_set_curves(tls_conf, params->openssl_ecdh_curves)) {
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ if (params->openssl_ciphers) {
|
|
++ if (!tls_mbedtls_set_ciphers(tls_conf, params->openssl_ciphers))
|
|
++ return -1;
|
|
++ }
|
|
++ else if (tls_conf->flags & TLS_CONN_SUITEB) {
|
|
++ /* special-case a select set of ciphers for hwsim tests */
|
|
++ if (!tls_mbedtls_set_ciphers(tls_conf,
|
|
++ (tls_conf->flags & TLS_CONN_SUITEB_NO_ECDH)
|
|
++ ? "DHE-RSA-AES256-GCM-SHA384"
|
|
++ : "ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384"))
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn,
|
|
++ const struct tls_connection_params *params)
|
|
++{
|
|
++ if (conn == NULL || params == NULL)
|
|
++ return -1;
|
|
++
|
|
++ tls_conf_deinit(conn->tls_conf);
|
|
++ struct tls_conf *tls_conf = conn->tls_conf = tls_conf_init(tls_ctx);
|
|
++ if (tls_conf == NULL)
|
|
++ return -1;
|
|
++
|
|
++ if (tls_ctx_global.tls_conf) {
|
|
++ tls_conf->check_crl = tls_ctx_global.tls_conf->check_crl;
|
|
++ tls_conf->check_crl_strict = tls_ctx_global.tls_conf->check_crl_strict;
|
|
++ /*(tls_openssl.c inherits check_cert_subject from global conf)*/
|
|
++ if (tls_ctx_global.tls_conf->check_cert_subject) {
|
|
++ tls_conf->check_cert_subject =
|
|
++ os_strdup(tls_ctx_global.tls_conf->check_cert_subject);
|
|
++ if (tls_conf->check_cert_subject == NULL)
|
|
++ return -1;
|
|
++ }
|
|
++ }
|
|
++
|
|
++ if (tls_mbedtls_set_params(tls_conf, params) != 0)
|
|
++ return -1;
|
|
++ conn->verify_peer = tls_conf->verify_peer;
|
|
++
|
|
++ return tls_mbedtls_ssl_setup(conn);
|
|
++}
|
|
++
|
|
++
|
|
++#ifdef TLS_MBEDTLS_SESSION_TICKETS
|
|
++
|
|
++static int tls_mbedtls_clienthello_session_ticket_prep (struct tls_connection *conn,
|
|
++ const u8 *data, size_t len)
|
|
++{
|
|
++ if (conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET)
|
|
++ return -1;
|
|
++ if (conn->clienthello_session_ticket)
|
|
++ tls_connection_deinit_clienthello_session_ticket(conn);
|
|
++ if (len) {
|
|
++ conn->clienthello_session_ticket = mbedtls_calloc(1, len);
|
|
++ if (conn->clienthello_session_ticket == NULL)
|
|
++ return -1;
|
|
++ conn->clienthello_session_ticket_len = len;
|
|
++ os_memcpy(conn->clienthello_session_ticket, data, len);
|
|
++ }
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++static void tls_mbedtls_clienthello_session_ticket_set (struct tls_connection *conn)
|
|
++{
|
|
++ mbedtls_ssl_session *sess = conn->ssl.MBEDTLS_PRIVATE(session_negotiate);
|
|
++ if (sess->MBEDTLS_PRIVATE(ticket)) {
|
|
++ mbedtls_platform_zeroize(sess->MBEDTLS_PRIVATE(ticket),
|
|
++ sess->MBEDTLS_PRIVATE(ticket_len));
|
|
++ mbedtls_free(sess->MBEDTLS_PRIVATE(ticket));
|
|
++ }
|
|
++ sess->MBEDTLS_PRIVATE(ticket) = conn->clienthello_session_ticket;
|
|
++ sess->MBEDTLS_PRIVATE(ticket_len) = conn->clienthello_session_ticket_len;
|
|
++ sess->MBEDTLS_PRIVATE(ticket_lifetime) = 86400;/* XXX: can hint be 0? */
|
|
++
|
|
++ conn->clienthello_session_ticket = NULL;
|
|
++ conn->clienthello_session_ticket_len = 0;
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_mbedtls_ssl_ticket_write(void *p_ticket,
|
|
++ const mbedtls_ssl_session *session,
|
|
++ unsigned char *start,
|
|
++ const unsigned char *end,
|
|
++ size_t *tlen,
|
|
++ uint32_t *lifetime)
|
|
++{
|
|
++ struct tls_connection *conn = p_ticket;
|
|
++ if (conn && conn->session_ticket_cb) {
|
|
++ /* see tls_mbedtls_clienthello_session_ticket_prep() */
|
|
++ /* see tls_mbedtls_clienthello_session_ticket_set() */
|
|
++ return 0;
|
|
++ }
|
|
++
|
|
++ return mbedtls_ssl_ticket_write(&tls_ctx_global.ticket_ctx,
|
|
++ session, start, end, tlen, lifetime);
|
|
++}
|
|
++
|
|
++
|
|
++static int tls_mbedtls_ssl_ticket_parse(void *p_ticket,
|
|
++ mbedtls_ssl_session *session,
|
|
++ unsigned char *buf,
|
|
++ size_t len)
|
|
++{
|
|
++ /* XXX: TODO: not implemented in client;
|
|
++ * mbedtls_ssl_conf_session_tickets_cb() callbacks only for TLS server*/
|
|
++
|
|
++ if (len == 0)
|
|
++ return MBEDTLS_ERR_SSL_BAD_INPUT_DATA;
|
|
++
|
|
++ struct tls_connection *conn = p_ticket;
|
|
++ if (conn && conn->session_ticket_cb) {
|
|
++ /* XXX: have random and secret been initialized yet?
|
|
++ * or must keys first be exported?
|
|
++ * EAP-FAST uses all args, EAP-TEAP only uses secret */
|
|
++ struct tls_random data;
|
|
++ if (tls_connection_get_random(NULL, conn, &data) != 0)
|
|
++ return MBEDTLS_ERR_SSL_INTERNAL_ERROR;
|
|
++ int ret =
|
|
++ conn->session_ticket_cb(conn->session_ticket_cb_ctx,
|
|
++ buf, len,
|
|
++ data.client_random,
|
|
++ data.server_random,
|
|
++ conn->expkey_secret);
|
|
++ if (ret == 1) {
|
|
++ conn->resumed = 1;
|
|
++ return 0;
|
|
++ }
|
|
++ emsg(MSG_ERROR, "EAP session ticket ext not implemented");
|
|
++ return MBEDTLS_ERR_SSL_INVALID_MAC;
|
|
++ /*(non-zero return used for mbedtls debug logging)*/
|
|
++ }
|
|
++
|
|
++ /* XXX: TODO always use tls_mbedtls_ssl_ticket_parse() for callback? */
|
|
++ int rc = mbedtls_ssl_ticket_parse(&tls_ctx_global.ticket_ctx,
|
|
++ session, buf, len);
|
|
++ if (conn)
|
|
++ conn->resumed = (rc == 0);
|
|
++ return rc;
|
|
++}
|
|
++
|
|
++#endif /* TLS_MBEDTLS_SESSION_TICKETS */
|
|
++
|
|
++
|
|
++__attribute_cold__
|
|
++int tls_global_set_params(void *tls_ctx,
|
|
++ const struct tls_connection_params *params)
|
|
++{
|
|
++ /* XXX: why might global_set_params be called more than once? */
|
|
++ if (tls_ctx_global.tls_conf)
|
|
++ tls_conf_deinit(tls_ctx_global.tls_conf);
|
|
++ tls_ctx_global.tls_conf = tls_conf_init(tls_ctx);
|
|
++ if (tls_ctx_global.tls_conf == NULL)
|
|
++ return -1;
|
|
++
|
|
++ #ifdef MBEDTLS_SSL_SESSION_TICKETS
|
|
++ #ifdef MBEDTLS_SSL_TICKET_C
|
|
++ if (!(params->flags & TLS_CONN_DISABLE_SESSION_TICKET))
|
|
++ #ifdef TLS_MBEDTLS_SESSION_TICKETS
|
|
++ mbedtls_ssl_conf_session_tickets_cb(&tls_ctx_global.tls_conf->conf,
|
|
++ tls_mbedtls_ssl_ticket_write,
|
|
++ tls_mbedtls_ssl_ticket_parse,
|
|
++ NULL);
|
|
++ #else
|
|
++ mbedtls_ssl_conf_session_tickets_cb(&tls_ctx_global.tls_conf->conf,
|
|
++ mbedtls_ssl_ticket_write,
|
|
++ mbedtls_ssl_ticket_parse,
|
|
++ &tls_ctx_global.ticket_ctx);
|
|
++ #endif
|
|
++ #endif
|
|
++ #endif
|
|
++
|
|
++ os_free(tls_ctx_global.ocsp_stapling_response);
|
|
++ tls_ctx_global.ocsp_stapling_response = NULL;
|
|
++ if (params->ocsp_stapling_response)
|
|
++ tls_ctx_global.ocsp_stapling_response =
|
|
++ os_strdup(params->ocsp_stapling_response);
|
|
++
|
|
++ os_free(tls_ctx_global.ca_cert_file);
|
|
++ tls_ctx_global.ca_cert_file = NULL;
|
|
++ if (params->ca_cert)
|
|
++ tls_ctx_global.ca_cert_file = os_strdup(params->ca_cert);
|
|
++ return tls_mbedtls_set_params(tls_ctx_global.tls_conf, params);
|
|
++}
|
|
++
|
|
++
|
|
++int tls_global_set_verify(void *tls_ctx, int check_crl, int strict)
|
|
++{
|
|
++ tls_ctx_global.tls_conf->check_crl = check_crl;
|
|
++ tls_ctx_global.tls_conf->check_crl_strict = strict; /*(time checks)*/
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn,
|
|
++ int verify_peer, unsigned int flags,
|
|
++ const u8 *session_ctx, size_t session_ctx_len)
|
|
++{
|
|
++ /*(EAP server-side calls this from eap_server_tls_ssl_init())*/
|
|
++ if (conn == NULL)
|
|
++ return -1;
|
|
++
|
|
++ conn->tls_conf->flags |= flags;/* TODO: reprocess flags, if necessary */
|
|
++
|
|
++ int authmode;
|
|
++ switch (verify_peer) {
|
|
++ case 2: authmode = MBEDTLS_SSL_VERIFY_OPTIONAL; break;/*(eap_teap_init())*/
|
|
++ case 1: authmode = MBEDTLS_SSL_VERIFY_REQUIRED; break;
|
|
++ default: authmode = MBEDTLS_SSL_VERIFY_NONE; break;
|
|
++ }
|
|
++ mbedtls_ssl_set_hs_authmode(&conn->ssl, authmode);
|
|
++
|
|
++ if ((conn->verify_peer = (authmode != MBEDTLS_SSL_VERIFY_NONE)))
|
|
++ mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn);
|
|
++ else
|
|
++ mbedtls_ssl_set_verify(&conn->ssl, NULL, NULL);
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++static void tls_connection_export_keys_cb(
|
|
++ void *p_expkey, mbedtls_ssl_key_export_type secret_type,
|
|
++ const unsigned char *secret, size_t secret_len,
|
|
++ const unsigned char client_random[MBEDTLS_EXPKEY_RAND_LEN],
|
|
++ const unsigned char server_random[MBEDTLS_EXPKEY_RAND_LEN],
|
|
++ mbedtls_tls_prf_types tls_prf_type)
|
|
++{
|
|
++ struct tls_connection *conn = p_expkey;
|
|
++ conn->tls_prf_type = tls_prf_type;
|
|
++ if (!tls_prf_type)
|
|
++ return;
|
|
++ if (secret_len > sizeof(conn->expkey_secret)) {
|
|
++ emsg(MSG_ERROR, "tls_connection_export_keys_cb secret too long");
|
|
++ conn->tls_prf_type = MBEDTLS_SSL_TLS_PRF_NONE; /* 0 */
|
|
++ return;
|
|
++ }
|
|
++ conn->expkey_secret_len = secret_len;
|
|
++ os_memcpy(conn->expkey_secret, secret, secret_len);
|
|
++ os_memcpy(conn->expkey_randbytes,
|
|
++ client_random, MBEDTLS_EXPKEY_RAND_LEN);
|
|
++ os_memcpy(conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN,
|
|
++ server_random, MBEDTLS_EXPKEY_RAND_LEN);
|
|
++}
|
|
++#elif MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
|
|
++static int tls_connection_export_keys_cb(
|
|
++ void *p_expkey,
|
|
++ const unsigned char *ms,
|
|
++ const unsigned char *kb,
|
|
++ size_t maclen,
|
|
++ size_t keylen,
|
|
++ size_t ivlen,
|
|
++ const unsigned char client_random[MBEDTLS_EXPKEY_RAND_LEN],
|
|
++ const unsigned char server_random[MBEDTLS_EXPKEY_RAND_LEN],
|
|
++ mbedtls_tls_prf_types tls_prf_type )
|
|
++{
|
|
++ struct tls_connection *conn = p_expkey;
|
|
++ conn->tls_prf_type = tls_prf_type;
|
|
++ if (!tls_prf_type)
|
|
++ return -1; /*(return value ignored by mbedtls)*/
|
|
++ conn->expkey_keyblock_size = maclen + keylen + ivlen;
|
|
++ conn->expkey_secret_len = MBEDTLS_EXPKEY_FIXED_SECRET_LEN;
|
|
++ os_memcpy(conn->expkey_secret, ms, MBEDTLS_EXPKEY_FIXED_SECRET_LEN);
|
|
++ os_memcpy(conn->expkey_randbytes,
|
|
++ client_random, MBEDTLS_EXPKEY_RAND_LEN);
|
|
++ os_memcpy(conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN,
|
|
++ server_random, MBEDTLS_EXPKEY_RAND_LEN);
|
|
++ return 0;
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++int tls_connection_get_random(void *tls_ctx, struct tls_connection *conn,
|
|
++ struct tls_random *data)
|
|
++{
|
|
++ if (!conn || !conn->tls_prf_type)
|
|
++ return -1;
|
|
++ data->client_random = conn->expkey_randbytes;
|
|
++ data->client_random_len = MBEDTLS_EXPKEY_RAND_LEN;
|
|
++ data->server_random = conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN;
|
|
++ data->server_random_len = MBEDTLS_EXPKEY_RAND_LEN;
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++int tls_connection_export_key(void *tls_ctx, struct tls_connection *conn,
|
|
++ const char *label, const u8 *context,
|
|
++ size_t context_len, u8 *out, size_t out_len)
|
|
++{
|
|
++ /* (EAP-PEAP EAP-TLS EAP-TTLS) */
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
|
|
++ return (conn && conn->established && conn->tls_prf_type)
|
|
++ ? mbedtls_ssl_tls_prf(conn->tls_prf_type,
|
|
++ conn->expkey_secret, conn->expkey_secret_len, label,
|
|
++ conn->expkey_randbytes,
|
|
++ sizeof(conn->expkey_randbytes), out, out_len)
|
|
++ : -1;
|
|
++ #else
|
|
++ /* not implemented here for mbedtls < 2.18.0 */
|
|
++ return -1;
|
|
++ #endif
|
|
++}
|
|
++
|
|
++
|
|
++#ifdef TLS_MBEDTLS_EAP_FAST
|
|
++
|
|
++#if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++/* keyblock size info is not exposed in mbed TLS 3.0.0 */
|
|
++/* extracted from mbedtls library/ssl_tls.c:ssl_tls12_populate_transform() */
|
|
++#include <mbedtls/ssl_ciphersuites.h>
|
|
++#include <mbedtls/cipher.h>
|
|
++static size_t tls_mbedtls_ssl_keyblock_size (mbedtls_ssl_context *ssl)
|
|
++{
|
|
++ #if !defined(MBEDTLS_USE_PSA_CRYPTO) /* XXX: (not extracted for PSA crypto) */
|
|
++ #if defined(MBEDTLS_SSL_PROTO_TLS1_3)
|
|
++ if (tls_version == MBEDTLS_SSL_VERSION_TLS1_3)
|
|
++ return 0; /* (calculation not extracted) */
|
|
++ #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
|
|
++
|
|
++ int ciphersuite = mbedtls_ssl_get_ciphersuite_id_from_ssl(ssl);
|
|
++ const mbedtls_ssl_ciphersuite_t *ciphersuite_info =
|
|
++ mbedtls_ssl_ciphersuite_from_id(ciphersuite);
|
|
++ if (ciphersuite_info == NULL)
|
|
++ return 0;
|
|
++
|
|
++ const mbedtls_cipher_info_t *cipher_info =
|
|
++ mbedtls_cipher_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(cipher));
|
|
++ if (cipher_info == NULL)
|
|
++ return 0;
|
|
++
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03010000 /* mbedtls 3.1.0 */
|
|
++ size_t keylen = mbedtls_cipher_info_get_key_bitlen(cipher_info) / 8;
|
|
++ mbedtls_cipher_mode_t mode = mbedtls_cipher_info_get_mode(cipher_info);
|
|
++ #else
|
|
++ size_t keylen = cipher_info->MBEDTLS_PRIVATE(key_bitlen) / 8;
|
|
++ mbedtls_cipher_mode_t mode = cipher_info->MBEDTLS_PRIVATE(mode);
|
|
++ #endif
|
|
++ #if defined(MBEDTLS_GCM_C) || \
|
|
++ defined(MBEDTLS_CCM_C) || \
|
|
++ defined(MBEDTLS_CHACHAPOLY_C)
|
|
++ if (mode == MBEDTLS_MODE_GCM || mode == MBEDTLS_MODE_CCM)
|
|
++ return keylen + 4;
|
|
++ else if (mode == MBEDTLS_MODE_CHACHAPOLY)
|
|
++ return keylen + 12;
|
|
++ else
|
|
++ #endif /* MBEDTLS_GCM_C || MBEDTLS_CCM_C || MBEDTLS_CHACHAPOLY_C */
|
|
++ #if defined(MBEDTLS_SSL_SOME_SUITES_USE_MAC)
|
|
++ {
|
|
++ const mbedtls_md_info_t *md_info =
|
|
++ mbedtls_md_info_from_type(ciphersuite_info->MBEDTLS_PRIVATE(mac));
|
|
++ if (md_info == NULL)
|
|
++ return 0;
|
|
++ size_t mac_key_len = mbedtls_md_get_size(md_info);
|
|
++ size_t ivlen = mbedtls_cipher_info_get_iv_size(cipher_info);
|
|
++ return keylen + mac_key_len + ivlen;
|
|
++ }
|
|
++ #endif /* MBEDTLS_SSL_SOME_SUITES_USE_MAC */
|
|
++ #endif /* !MBEDTLS_USE_PSA_CRYPTO *//* (not extracted for PSA crypto) */
|
|
++ return 0;
|
|
++}
|
|
++#endif /* MBEDTLS_VERSION_NUMBER >= 0x03000000 *//* mbedtls 3.0.0 */
|
|
++
|
|
++
|
|
++int tls_connection_get_eap_fast_key(void *tls_ctx, struct tls_connection *conn,
|
|
++ u8 *out, size_t out_len)
|
|
++{
|
|
++ /* XXX: has export keys callback been run? */
|
|
++ if (!conn || !conn->tls_prf_type)
|
|
++ return -1;
|
|
++
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++ conn->expkey_keyblock_size = tls_mbedtls_ssl_keyblock_size(&conn->ssl);
|
|
++ if (conn->expkey_keyblock_size == 0)
|
|
++ return -1;
|
|
++ #endif
|
|
++ size_t skip = conn->expkey_keyblock_size * 2;
|
|
++ unsigned char *tmp_out = os_malloc(skip + out_len);
|
|
++ if (!tmp_out)
|
|
++ return -1;
|
|
++
|
|
++ /* server_random and then client_random */
|
|
++ unsigned char seed[MBEDTLS_EXPKEY_RAND_LEN*2];
|
|
++ os_memcpy(seed, conn->expkey_randbytes + MBEDTLS_EXPKEY_RAND_LEN,
|
|
++ MBEDTLS_EXPKEY_RAND_LEN);
|
|
++ os_memcpy(seed + MBEDTLS_EXPKEY_RAND_LEN, conn->expkey_randbytes,
|
|
++ MBEDTLS_EXPKEY_RAND_LEN);
|
|
++
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
|
|
++ int ret = mbedtls_ssl_tls_prf(conn->tls_prf_type,
|
|
++ conn->expkey_secret, conn->expkey_secret_len,
|
|
++ "key expansion", seed, sizeof(seed),
|
|
++ tmp_out, skip + out_len);
|
|
++ if (ret == 0)
|
|
++ os_memcpy(out, tmp_out + skip, out_len);
|
|
++ #else
|
|
++ int ret = -1; /*(not reached if not impl; return -1 at top of func)*/
|
|
++ #endif
|
|
++
|
|
++ bin_clear_free(tmp_out, skip + out_len);
|
|
++ forced_memzero(seed, sizeof(seed));
|
|
++ return ret;
|
|
++}
|
|
++
|
|
++#endif /* TLS_MBEDTLS_EAP_FAST */
|
|
++
|
|
++
|
|
++__attribute_cold__
|
|
++static void tls_mbedtls_suiteb_handshake_alert (struct tls_connection *conn)
|
|
++{
|
|
++ /* tests/hwsim/test_suite_b.py test_suite_b_192_rsa_insufficient_dh */
|
|
++ if (!(conn->tls_conf->flags & TLS_CONN_SUITEB))
|
|
++ return;
|
|
++ if (tls_ctx_global.tls_conf) /*(is server; want issue event on client)*/
|
|
++ return;
|
|
++ #if 0
|
|
++ /*(info not available on client;
|
|
++ * mbed TLS library enforces dhm min bitlen in ServerKeyExchange)*/
|
|
++ if (MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ==
|
|
++ #if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */
|
|
++ mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl)
|
|
++ #else
|
|
++ mbedtls_ssl_get_ciphersuite_id(
|
|
++ mbedtls_ssl_get_ciphersuite(&conn->ssl))
|
|
++ #endif
|
|
++ && mbedtls_mpi_size(&conn->tls_conf->conf.MBEDTLS_PRIVATE(dhm_P))
|
|
++ < 384 /*(3072/8)*/)
|
|
++ #endif
|
|
++ {
|
|
++ struct tls_config *init_conf = &tls_ctx_global.init_conf;
|
|
++ if (init_conf->event_cb) {
|
|
++ union tls_event_data ev;
|
|
++ os_memset(&ev, 0, sizeof(ev));
|
|
++ ev.alert.is_local = 1;
|
|
++ ev.alert.type = "fatal";
|
|
++ /*"internal error" string for tests/hwsim/test_suiteb.py */
|
|
++ ev.alert.description = "internal error: handshake failure";
|
|
++ /*ev.alert.description = "insufficient security";*/
|
|
++ init_conf->event_cb(init_conf->cb_ctx, TLS_ALERT, &ev);
|
|
++ }
|
|
++ }
|
|
++}
|
|
++
|
|
++
|
|
++struct wpabuf * tls_connection_handshake(void *tls_ctx,
|
|
++ struct tls_connection *conn,
|
|
++ const struct wpabuf *in_data,
|
|
++ struct wpabuf **appl_data)
|
|
++{
|
|
++ if (appl_data)
|
|
++ *appl_data = NULL;
|
|
++
|
|
++ if (in_data && wpabuf_len(in_data)) {
|
|
++ /*(unsure why tls_gnutls.c discards buffer contents; skip here)*/
|
|
++ if (conn->pull_buf && 0) /* disable; appears unwise */
|
|
++ tls_pull_buf_discard(conn, __func__);
|
|
++ if (!tls_pull_buf_append(conn, in_data))
|
|
++ return NULL;
|
|
++ }
|
|
++
|
|
++ if (conn->tls_conf == NULL) {
|
|
++ struct tls_connection_params params;
|
|
++ os_memset(¶ms, 0, sizeof(params));
|
|
++ params.openssl_ciphers =
|
|
++ tls_ctx_global.init_conf.openssl_ciphers;
|
|
++ params.flags = tls_ctx_global.tls_conf->flags;
|
|
++ if (tls_connection_set_params(tls_ctx, conn, ¶ms) != 0)
|
|
++ return NULL;
|
|
++ }
|
|
++
|
|
++ if (conn->verify_peer) /*(call here might be redundant; nbd)*/
|
|
++ mbedtls_ssl_set_verify(&conn->ssl, tls_mbedtls_verify_cb, conn);
|
|
++
|
|
++ #ifdef TLS_MBEDTLS_SESSION_TICKETS
|
|
++ if (conn->clienthello_session_ticket)
|
|
++ /*(starting handshake for EAP-FAST and EAP-TEAP)*/
|
|
++ tls_mbedtls_clienthello_session_ticket_set(conn);
|
|
++
|
|
++ /* (not thread-safe due to need to set userdata 'conn' for callback) */
|
|
++ /* (unable to use mbedtls_ssl_set_user_data_p() with mbedtls 3.2.0+
|
|
++ * since ticket write and parse callbacks take (mbedtls_ssl_session *)
|
|
++ * param instead of (mbedtls_ssl_context *) param) */
|
|
++ if (conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET)
|
|
++ mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf,
|
|
++ NULL, NULL, NULL);
|
|
++ else
|
|
++ mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf,
|
|
++ tls_mbedtls_ssl_ticket_write,
|
|
++ tls_mbedtls_ssl_ticket_parse,
|
|
++ conn);
|
|
++ #endif
|
|
++
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03020000 /* mbedtls 3.2.0 */
|
|
++ int ret = mbedtls_ssl_handshake(&conn->ssl);
|
|
++ #else
|
|
++ int ret = 0;
|
|
++ while (conn->ssl.MBEDTLS_PRIVATE(state) != MBEDTLS_SSL_HANDSHAKE_OVER) {
|
|
++ ret = mbedtls_ssl_handshake_step(&conn->ssl);
|
|
++ if (ret != 0)
|
|
++ break;
|
|
++ }
|
|
++ #endif
|
|
++
|
|
++ #ifdef TLS_MBEDTLS_SESSION_TICKETS
|
|
++ mbedtls_ssl_conf_session_tickets_cb(&conn->tls_conf->conf,
|
|
++ tls_mbedtls_ssl_ticket_write,
|
|
++ tls_mbedtls_ssl_ticket_parse,
|
|
++ NULL);
|
|
++ #endif
|
|
++
|
|
++ switch (ret) {
|
|
++ case 0:
|
|
++ conn->established = 1;
|
|
++ if (conn->push_buf == NULL)
|
|
++ /* Need to return something to get final TLS ACK. */
|
|
++ conn->push_buf = wpabuf_alloc(0);
|
|
++
|
|
++ if (appl_data /*&& conn->pull_buf && wpabuf_len(conn->pull_buf)*/)
|
|
++ *appl_data = NULL; /* RFE: check for application data */
|
|
++ break;
|
|
++ case MBEDTLS_ERR_SSL_WANT_WRITE:
|
|
++ case MBEDTLS_ERR_SSL_WANT_READ:
|
|
++ case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
|
|
++ case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
|
|
++ if (tls_ctx_global.tls_conf /*(is server)*/
|
|
++ && conn->established && conn->push_buf == NULL)
|
|
++ /* Need to return something to trigger completion of EAP-TLS. */
|
|
++ conn->push_buf = wpabuf_alloc(0);
|
|
++ break;
|
|
++ default:
|
|
++ ++conn->failed;
|
|
++ switch (ret) {
|
|
++ case MBEDTLS_ERR_SSL_CLIENT_RECONNECT:
|
|
++ case MBEDTLS_ERR_NET_CONN_RESET:
|
|
++ case MBEDTLS_ERR_NET_SEND_FAILED:
|
|
++ ++conn->write_alerts;
|
|
++ break;
|
|
++ #if MBEDTLS_VERSION_NUMBER >= 0x03000000 /* mbedtls 3.0.0 */
|
|
++ case MBEDTLS_ERR_SSL_HANDSHAKE_FAILURE:
|
|
++ #else
|
|
++ case MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE:
|
|
++ #endif
|
|
++ tls_mbedtls_suiteb_handshake_alert(conn);
|
|
++ /* fall through */
|
|
++ case MBEDTLS_ERR_NET_RECV_FAILED:
|
|
++ case MBEDTLS_ERR_SSL_CONN_EOF:
|
|
++ case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
|
|
++ case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
|
|
++ ++conn->read_alerts;
|
|
++ break;
|
|
++ default:
|
|
++ break;
|
|
++ }
|
|
++
|
|
++ ilog(ret, "mbedtls_ssl_handshake");
|
|
++ break;
|
|
++ }
|
|
++
|
|
++ struct wpabuf *out_data = conn->push_buf;
|
|
++ conn->push_buf = NULL;
|
|
++ return out_data;
|
|
++}
|
|
++
|
|
++
|
|
++struct wpabuf * tls_connection_server_handshake(void *tls_ctx,
|
|
++ struct tls_connection *conn,
|
|
++ const struct wpabuf *in_data,
|
|
++ struct wpabuf **appl_data)
|
|
++{
|
|
++ conn->is_server = 1;
|
|
++ return tls_connection_handshake(tls_ctx, conn, in_data, appl_data);
|
|
++}
|
|
++
|
|
++
|
|
++struct wpabuf * tls_connection_encrypt(void *tls_ctx,
|
|
++ struct tls_connection *conn,
|
|
++ const struct wpabuf *in_data)
|
|
++{
|
|
++ int res = mbedtls_ssl_write(&conn->ssl,
|
|
++ wpabuf_head_u8(in_data), wpabuf_len(in_data));
|
|
++ if (res < 0) {
|
|
++ elog(res, "mbedtls_ssl_write");
|
|
++ return NULL;
|
|
++ }
|
|
++
|
|
++ struct wpabuf *buf = conn->push_buf;
|
|
++ conn->push_buf = NULL;
|
|
++ return buf;
|
|
++}
|
|
++
|
|
++
|
|
++struct wpabuf * tls_connection_decrypt(void *tls_ctx,
|
|
++ struct tls_connection *conn,
|
|
++ const struct wpabuf *in_data)
|
|
++{
|
|
++ int res;
|
|
++ struct wpabuf *out;
|
|
++
|
|
++ /*assert(in_data != NULL);*/
|
|
++ if (!tls_pull_buf_append(conn, in_data))
|
|
++ return NULL;
|
|
++
|
|
++ #if defined(MBEDTLS_ZLIB_SUPPORT) /* removed in mbedtls 3.x */
|
|
++ /* Add extra buffer space to handle the possibility of decrypted
|
|
++ * data being longer than input data due to TLS compression. */
|
|
++ out = wpabuf_alloc((wpabuf_len(in_data) + 500) * 3);
|
|
++ #else /* TLS compression is disabled in mbedtls 3.x */
|
|
++ out = wpabuf_alloc(wpabuf_len(in_data));
|
|
++ #endif
|
|
++ if (out == NULL)
|
|
++ return NULL;
|
|
++
|
|
++ res = mbedtls_ssl_read(&conn->ssl, wpabuf_mhead(out), wpabuf_size(out));
|
|
++ if (res < 0) {
|
|
++ #if 1 /*(seems like a different error if wpabuf_len(in_data) == 0)*/
|
|
++ if (res == MBEDTLS_ERR_SSL_WANT_READ)
|
|
++ return out;
|
|
++ #endif
|
|
++ elog(res, "mbedtls_ssl_read");
|
|
++ wpabuf_free(out);
|
|
++ return NULL;
|
|
++ }
|
|
++ wpabuf_put(out, res);
|
|
++
|
|
++ return out;
|
|
++}
|
|
++
|
|
++
|
|
++int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn)
|
|
++{
|
|
++ /* XXX: might need to detect if session resumed from TLS session ticket
|
|
++ * even if not special session ticket handling for EAP-FAST, EAP-TEAP */
|
|
++ /* (?ssl->handshake->resume during session ticket validation?) */
|
|
++ return conn && conn->resumed;
|
|
++}
|
|
++
|
|
++
|
|
++#ifdef TLS_MBEDTLS_EAP_FAST
|
|
++int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn,
|
|
++ u8 *ciphers)
|
|
++{
|
|
++ /* ciphers is list of TLS_CIPHER_* from hostap/src/crypto/tls.h */
|
|
++ int ids[7];
|
|
++ const int idsz = (int)sizeof(ids);
|
|
++ int nids = -1, id;
|
|
++ for ( ; *ciphers != TLS_CIPHER_NONE; ++ciphers) {
|
|
++ switch (*ciphers) {
|
|
++ case TLS_CIPHER_RC4_SHA:
|
|
++ #ifdef MBEDTLS_TLS_RSA_WITH_RC4_128_SHA
|
|
++ id = MBEDTLS_TLS_RSA_WITH_RC4_128_SHA;
|
|
++ break;
|
|
++ #else
|
|
++ continue; /*(not supported in mbedtls 3.x; ignore)*/
|
|
++ #endif
|
|
++ case TLS_CIPHER_AES128_SHA:
|
|
++ id = MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA;
|
|
++ break;
|
|
++ case TLS_CIPHER_RSA_DHE_AES128_SHA:
|
|
++ id = MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA;
|
|
++ break;
|
|
++ case TLS_CIPHER_ANON_DH_AES128_SHA:
|
|
++ continue; /*(not supported in mbedtls; ignore)*/
|
|
++ case TLS_CIPHER_RSA_DHE_AES256_SHA:
|
|
++ id = MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA;
|
|
++ break;
|
|
++ case TLS_CIPHER_AES256_SHA:
|
|
++ id = MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA;
|
|
++ break;
|
|
++ default:
|
|
++ return -1; /* should not happen */
|
|
++ }
|
|
++ if (++nids == idsz)
|
|
++ return -1; /* should not happen */
|
|
++ ids[nids] = id;
|
|
++ }
|
|
++ if (nids < 0)
|
|
++ return 0; /* nothing to do */
|
|
++ if (++nids == idsz)
|
|
++ return -1; /* should not happen */
|
|
++ ids[nids] = 0; /* terminate list */
|
|
++ ++nids;
|
|
++
|
|
++ return tls_mbedtls_set_ciphersuites(conn->tls_conf, ids, nids) ? 0 : -1;
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++int tls_get_version(void *ssl_ctx, struct tls_connection *conn,
|
|
++ char *buf, size_t buflen)
|
|
++{
|
|
++ if (conn == NULL)
|
|
++ return -1;
|
|
++ os_strlcpy(buf, mbedtls_ssl_get_version(&conn->ssl), buflen);
|
|
++ return buf[0] != 'u' ? 0 : -1; /*(-1 if "unknown")*/
|
|
++}
|
|
++
|
|
++
|
|
++#ifdef TLS_MBEDTLS_EAP_TEAP
|
|
++u16 tls_connection_get_cipher_suite(struct tls_connection *conn)
|
|
++{
|
|
++ if (conn == NULL)
|
|
++ return 0;
|
|
++ return (u16)mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl);
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++int tls_get_cipher(void *tls_ctx, struct tls_connection *conn,
|
|
++ char *buf, size_t buflen)
|
|
++{
|
|
++ if (conn == NULL)
|
|
++ return -1;
|
|
++ const int id = mbedtls_ssl_get_ciphersuite_id_from_ssl(&conn->ssl);
|
|
++ return tls_mbedtls_translate_ciphername(id, buf, buflen) ? 0 : -1;
|
|
++}
|
|
++
|
|
++
|
|
++#ifdef TLS_MBEDTLS_SESSION_TICKETS
|
|
++
|
|
++int tls_connection_enable_workaround(void *tls_ctx,
|
|
++ struct tls_connection *conn)
|
|
++{
|
|
++ /* (see comment in src/eap_peer/eap_fast.c:eap_fast_init()) */
|
|
++ /* XXX: is there a relevant setting for this in mbed TLS? */
|
|
++ /* (do we even care that much about older CBC ciphers?) */
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
++int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn,
|
|
++ int ext_type, const u8 *data,
|
|
++ size_t data_len)
|
|
++{
|
|
++ /* (EAP-FAST and EAP-TEAP) */
|
|
++ if (ext_type == MBEDTLS_TLS_EXT_SESSION_TICKET) /*(ext_type == 35)*/
|
|
++ return tls_mbedtls_clienthello_session_ticket_prep(conn, data,
|
|
++ data_len);
|
|
++
|
|
++ return -1;
|
|
++}
|
|
++
|
|
++#endif /* TLS_MBEDTLS_SESSION_TICKETS */
|
|
++
|
|
++
|
|
++int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn)
|
|
++{
|
|
++ return conn ? conn->failed : -1;
|
|
++}
|
|
++
|
|
++
|
|
++int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn)
|
|
++{
|
|
++ return conn ? conn->read_alerts : -1;
|
|
++}
|
|
++
|
|
++
|
|
++int tls_connection_get_write_alerts(void *tls_ctx,
|
|
++ struct tls_connection *conn)
|
|
++{
|
|
++ return conn ? conn->write_alerts : -1;
|
|
++}
|
|
++
|
|
++
|
|
++#ifdef TLS_MBEDTLS_SESSION_TICKETS
|
|
++int tls_connection_set_session_ticket_cb(
|
|
++ void *tls_ctx, struct tls_connection *conn,
|
|
++ tls_session_ticket_cb cb, void *ctx)
|
|
++{
|
|
++ if (!(conn->tls_conf->flags & TLS_CONN_DISABLE_SESSION_TICKET)) {
|
|
++ /* (EAP-FAST and EAP-TEAP) */
|
|
++ conn->session_ticket_cb = cb;
|
|
++ conn->session_ticket_cb_ctx = ctx;
|
|
++ return 0;
|
|
++ }
|
|
++ return -1;
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++int tls_get_library_version(char *buf, size_t buf_len)
|
|
++{
|
|
++ #ifndef MBEDTLS_VERSION_C
|
|
++ const char * const ver = "n/a";
|
|
++ #else
|
|
++ char ver[9];
|
|
++ mbedtls_version_get_string(ver);
|
|
++ #endif
|
|
++ return os_snprintf(buf, buf_len,
|
|
++ "mbed TLS build=" MBEDTLS_VERSION_STRING " run=%s", ver);
|
|
++}
|
|
++
|
|
++
|
|
++void tls_connection_set_success_data(struct tls_connection *conn,
|
|
++ struct wpabuf *data)
|
|
++{
|
|
++ wpabuf_free(conn->success_data);
|
|
++ conn->success_data = data;
|
|
++}
|
|
++
|
|
++
|
|
++void tls_connection_set_success_data_resumed(struct tls_connection *conn)
|
|
++{
|
|
++}
|
|
++
|
|
++
|
|
++const struct wpabuf *
|
|
++tls_connection_get_success_data(struct tls_connection *conn)
|
|
++{
|
|
++ return conn->success_data;
|
|
++}
|
|
++
|
|
++
|
|
++void tls_connection_remove_session(struct tls_connection *conn)
|
|
++{
|
|
++}
|
|
++
|
|
++
|
|
++#ifdef TLS_MBEDTLS_EAP_TEAP
|
|
++int tls_get_tls_unique(struct tls_connection *conn, u8 *buf, size_t max_len)
|
|
++{
|
|
++ #if defined(MBEDTLS_SSL_RENEGOTIATION) /* XXX: renegotiation or resumption? */
|
|
++ /* data from TLS handshake Finished message */
|
|
++ size_t verify_len = conn->ssl.MBEDTLS_PRIVATE(verify_data_len);
|
|
++ char *verify_data = (conn->is_server ^ conn->resumed)
|
|
++ ? conn->ssl.MBEDTLS_PRIVATE(peer_verify_data)
|
|
++ : conn->ssl.MBEDTLS_PRIVATE(own_verify_data);
|
|
++ if (verify_len && verify_len <= max_len) {
|
|
++ os_memcpy(buf, verify_data, verify_len);
|
|
++ return (int)verify_len;
|
|
++ }
|
|
++ #endif
|
|
++ return -1;
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++__attribute_noinline__
|
|
++static void tls_mbedtls_set_peer_subject(struct tls_connection *conn, const mbedtls_x509_crt *crt)
|
|
++{
|
|
++ if (conn->peer_subject)
|
|
++ return;
|
|
++ char buf[MBEDTLS_X509_MAX_DN_NAME_SIZE*2];
|
|
++ int buflen = mbedtls_x509_dn_gets(buf, sizeof(buf), &crt->subject);
|
|
++ if (buflen >= 0 && (conn->peer_subject = os_malloc((size_t)buflen+1)))
|
|
++ os_memcpy(conn->peer_subject, buf, (size_t)buflen+1);
|
|
++}
|
|
++
|
|
++
|
|
++#ifdef TLS_MBEDTLS_EAP_TEAP
|
|
++const char * tls_connection_get_peer_subject(struct tls_connection *conn)
|
|
++{
|
|
++ if (!conn)
|
|
++ return NULL;
|
|
++ if (!conn->peer_subject) { /*(if not set during cert verify)*/
|
|
++ const mbedtls_x509_crt *peer_cert =
|
|
++ mbedtls_ssl_get_peer_cert(&conn->ssl);
|
|
++ if (peer_cert)
|
|
++ tls_mbedtls_set_peer_subject(conn, peer_cert);
|
|
++ }
|
|
++ return conn->peer_subject;
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++#ifdef TLS_MBEDTLS_EAP_TEAP
|
|
++bool tls_connection_get_own_cert_used(struct tls_connection *conn)
|
|
++{
|
|
++ /* XXX: availability of cert does not necessary mean that client
|
|
++ * received certificate request from server and then sent cert.
|
|
++ * ? step handshake in tls_connection_handshake() looking for
|
|
++ * MBEDTLS_SSL_CERTIFICATE_REQUEST ? */
|
|
++ const struct tls_conf * const tls_conf = conn->tls_conf;
|
|
++ return (tls_conf->has_client_cert && tls_conf->has_private_key);
|
|
++}
|
|
++#endif
|
|
++
|
|
++
|
|
++#if defined(CONFIG_FIPS)
|
|
++#define TLS_MBEDTLS_CONFIG_FIPS
|
|
++#endif
|
|
++
|
|
++#if defined(CONFIG_SHA256)
|
|
++#define TLS_MBEDTLS_TLS_PRF_SHA256
|
|
++#endif
|
|
++
|
|
++#if defined(CONFIG_SHA384)
|
|
++#define TLS_MBEDTLS_TLS_PRF_SHA384
|
|
++#endif
|
|
++
|
|
++
|
|
++#ifndef TLS_MBEDTLS_CONFIG_FIPS
|
|
++#if defined(CONFIG_MODULE_TESTS)
|
|
++/* unused with CONFIG_TLS=mbedtls except in crypto_module_tests.c */
|
|
++#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */ \
|
|
++ && MBEDTLS_VERSION_NUMBER < 0x03000000 /* mbedtls 3.0.0 */
|
|
++/* sha1-tlsprf.c */
|
|
++#include "sha1.h"
|
|
++int tls_prf_sha1_md5(const u8 *secret, size_t secret_len, const char *label,
|
|
++ const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
|
|
++{
|
|
++ return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_TLS1,
|
|
++ secret, secret_len, label,
|
|
++ seed, seed_len, out, outlen) ? -1 : 0;
|
|
++}
|
|
++#else
|
|
++#include "sha1-tlsprf.c" /* pull in hostap local implementation */
|
|
++#endif
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++#ifdef TLS_MBEDTLS_TLS_PRF_SHA256
|
|
++/* sha256-tlsprf.c */
|
|
++#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
|
|
++#include "sha256.h"
|
|
++int tls_prf_sha256(const u8 *secret, size_t secret_len, const char *label,
|
|
++ const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
|
|
++{
|
|
++ return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_SHA256,
|
|
++ secret, secret_len, label,
|
|
++ seed, seed_len, out, outlen) ? -1 : 0;
|
|
++}
|
|
++#else
|
|
++#include "sha256-tlsprf.c" /* pull in hostap local implementation */
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++#ifdef TLS_MBEDTLS_TLS_PRF_SHA384
|
|
++/* sha384-tlsprf.c */
|
|
++#if MBEDTLS_VERSION_NUMBER >= 0x02120000 /* mbedtls 2.18.0 */
|
|
++#include "sha384.h"
|
|
++int tls_prf_sha384(const u8 *secret, size_t secret_len, const char *label,
|
|
++ const u8 *seed, size_t seed_len, u8 *out, size_t outlen)
|
|
++{
|
|
++ return mbedtls_ssl_tls_prf(MBEDTLS_SSL_TLS_PRF_SHA384,
|
|
++ secret, secret_len, label,
|
|
++ seed, seed_len, out, outlen) ? -1 : 0;
|
|
++}
|
|
++#else
|
|
++#include "sha384-tlsprf.c" /* pull in hostap local implementation */
|
|
++#endif
|
|
++#endif
|
|
++
|
|
++
|
|
++#if MBEDTLS_VERSION_NUMBER < 0x03020000 /* mbedtls 3.2.0 */
|
|
++#define mbedtls_x509_crt_has_ext_type(crt, ext_type) \
|
|
++ ((crt)->MBEDTLS_PRIVATE(ext_types) & (ext_type))
|
|
++#endif
|
|
++
|
|
++struct mlist { const char *p; size_t n; };
|
|
++
|
|
++
|
|
++static int
|
|
++tls_mbedtls_match_altsubject(mbedtls_x509_crt *crt, const char *match)
|
|
++{
|
|
++ /* RFE: this could be pre-parsed into structured data at config time */
|
|
++ struct mlist list[256]; /*(much larger than expected)*/
|
|
++ int nlist = 0;
|
|
++ if ( os_strncmp(match, "EMAIL:", 6) != 0
|
|
++ && os_strncmp(match, "DNS:", 4) != 0
|
|
++ && os_strncmp(match, "URI:", 4) != 0 ) {
|
|
++ wpa_printf(MSG_INFO, "MTLS: Invalid altSubjectName match '%s'", match);
|
|
++ return 0;
|
|
++ }
|
|
++ for (const char *s = match, *tok; *s; s = tok ? tok+1 : "") {
|
|
++ do { } while ((tok = os_strchr(s, ';'))
|
|
++ && os_strncmp(tok+1, "EMAIL:", 6) != 0
|
|
++ && os_strncmp(tok+1, "DNS:", 4) != 0
|
|
++ && os_strncmp(tok+1, "URI:", 4) != 0);
|
|
++ list[nlist].p = s;
|
|
++ list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s);
|
|
++ if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) {
|
|
++ wpa_printf(MSG_INFO, "MTLS: excessive altSubjectName match '%s'",
|
|
++ match);
|
|
++ break; /* truncate huge list and continue */
|
|
++ }
|
|
++ }
|
|
++
|
|
++ if (!mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME))
|
|
++ return 0;
|
|
++
|
|
++ const mbedtls_x509_sequence *cur = &crt->subject_alt_names;
|
|
++ for (; cur != NULL; cur = cur->next) {
|
|
++ const unsigned char san_type = (unsigned char)cur->buf.tag
|
|
++ & MBEDTLS_ASN1_TAG_VALUE_MASK;
|
|
++ char t;
|
|
++ size_t step = 4;
|
|
++ switch (san_type) { /* "EMAIL:" or "DNS:" or "URI:" */
|
|
++ case MBEDTLS_X509_SAN_RFC822_NAME: step = 6; t = 'E'; break;
|
|
++ case MBEDTLS_X509_SAN_DNS_NAME: t = 'D'; break;
|
|
++ case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: t = 'U'; break;
|
|
++ default: continue;
|
|
++ }
|
|
++
|
|
++ for (int i = 0; i < nlist; ++i) {
|
|
++ /* step over "EMAIL:" or "DNS:" or "URI:" in list[i].p */
|
|
++ /* Note: v is not '\0'-terminated, but is a known length vlen,
|
|
++ * so okay to pass to os_strncasecmp() even though not z-string */
|
|
++ if (cur->buf.len == list[i].n - step && t == *list[i].p
|
|
++ && 0 == os_strncasecmp((char *)cur->buf.p,
|
|
++ list[i].p+step, cur->buf.len)) {
|
|
++ return 1; /* match */
|
|
++ }
|
|
++ }
|
|
++ }
|
|
++ return 0; /* no match */
|
|
++}
|
|
++
|
|
++
|
|
++static int
|
|
++tls_mbedtls_match_suffix(const char *v, size_t vlen,
|
|
++ const struct mlist *list, int nlist, int full)
|
|
++{
|
|
++ /* Note: v is not '\0'-terminated, but is a known length vlen,
|
|
++ * so okay to pass to os_strncasecmp() even though not z-string */
|
|
++ for (int i = 0; i < nlist; ++i) {
|
|
++ size_t n = list[i].n;
|
|
++ if ((n == vlen || (n < vlen && v[vlen-n-1] == '.' && !full))
|
|
++ && 0 == os_strncasecmp(v+vlen-n, list[i].p, n))
|
|
++ return 1; /* match */
|
|
++ }
|
|
++ return 0; /* no match */
|
|
++}
|
|
++
|
|
++
|
|
++static int
|
|
++tls_mbedtls_match_suffixes(mbedtls_x509_crt *crt, const char *match, int full)
|
|
++{
|
|
++ /* RFE: this could be pre-parsed into structured data at config time */
|
|
++ struct mlist list[256]; /*(much larger than expected)*/
|
|
++ int nlist = 0;
|
|
++ for (const char *s = match, *tok; *s; s = tok ? tok+1 : "") {
|
|
++ tok = os_strchr(s, ';');
|
|
++ list[nlist].p = s;
|
|
++ list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s);
|
|
++ if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) {
|
|
++ wpa_printf(MSG_INFO, "MTLS: excessive suffix match '%s'", match);
|
|
++ break; /* truncate huge list and continue */
|
|
++ }
|
|
++ }
|
|
++
|
|
++ /* check subjectAltNames */
|
|
++ if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME)) {
|
|
++ const mbedtls_x509_sequence *cur = &crt->subject_alt_names;
|
|
++ for (; cur != NULL; cur = cur->next) {
|
|
++ const unsigned char san_type = (unsigned char)cur->buf.tag
|
|
++ & MBEDTLS_ASN1_TAG_VALUE_MASK;
|
|
++ if (san_type == MBEDTLS_X509_SAN_DNS_NAME
|
|
++ && tls_mbedtls_match_suffix((char *)cur->buf.p,
|
|
++ cur->buf.len,
|
|
++ list, nlist, full)) {
|
|
++ return 1; /* match */
|
|
++ }
|
|
++ }
|
|
++ }
|
|
++
|
|
++ /* check subject CN */
|
|
++ const mbedtls_x509_name *name = &crt->subject;
|
|
++ for (; name != NULL; name = name->next) {
|
|
++ if (name->oid.p && MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid) == 0)
|
|
++ break;
|
|
++ }
|
|
++ if (name && tls_mbedtls_match_suffix((char *)name->val.p, name->val.len,
|
|
++ list, nlist, full)) {
|
|
++ return 1; /* match */
|
|
++ }
|
|
++
|
|
++ return 0; /* no match */
|
|
++}
|
|
++
|
|
++
|
|
++static int
|
|
++tls_mbedtls_match_dn_field(mbedtls_x509_crt *crt, const char *match)
|
|
++{
|
|
++ /* RFE: this could be pre-parsed into structured data at config time */
|
|
++ struct mlistoid { const char *p; size_t n;
|
|
++ const char *oid; size_t olen;
|
|
++ int prefix; };
|
|
++ struct mlistoid list[32]; /*(much larger than expected)*/
|
|
++ int nlist = 0;
|
|
++ for (const char *s = match, *tok, *e; *s; s = tok ? tok+1 : "") {
|
|
++ tok = os_strchr(s, '/');
|
|
++ list[nlist].oid = NULL;
|
|
++ list[nlist].olen = 0;
|
|
++ list[nlist].n = tok ? (size_t)(tok - s) : os_strlen(s);
|
|
++ e = memchr(s, '=', list[nlist].n);
|
|
++ if (e == NULL) {
|
|
++ if (list[nlist].n == 0)
|
|
++ continue; /* skip consecutive, repeated '/' */
|
|
++ if (list[nlist].n == 1 && *s == '*') {
|
|
++ /* special-case "*" to match any OID and value */
|
|
++ s = e = "=*";
|
|
++ list[nlist].n = 2;
|
|
++ list[nlist].oid = "";
|
|
++ }
|
|
++ else {
|
|
++ wpa_printf(MSG_INFO,
|
|
++ "MTLS: invalid check_cert_subject '%s' missing '='",
|
|
++ match);
|
|
++ return 0;
|
|
++ }
|
|
++ }
|
|
++ switch (e - s) {
|
|
++ case 1:
|
|
++ if (*s == 'C') {
|
|
++ list[nlist].oid = MBEDTLS_OID_AT_COUNTRY;
|
|
++ list[nlist].olen = sizeof(MBEDTLS_OID_AT_COUNTRY)-1;
|
|
++ }
|
|
++ else if (*s == 'L') {
|
|
++ list[nlist].oid = MBEDTLS_OID_AT_LOCALITY;
|
|
++ list[nlist].olen = sizeof(MBEDTLS_OID_AT_LOCALITY)-1;
|
|
++ }
|
|
++ else if (*s == 'O') {
|
|
++ list[nlist].oid = MBEDTLS_OID_AT_ORGANIZATION;
|
|
++ list[nlist].olen = sizeof(MBEDTLS_OID_AT_ORGANIZATION)-1;
|
|
++ }
|
|
++ break;
|
|
++ case 2:
|
|
++ if (s[0] == 'C' && s[1] == 'N') {
|
|
++ list[nlist].oid = MBEDTLS_OID_AT_CN;
|
|
++ list[nlist].olen = sizeof(MBEDTLS_OID_AT_CN)-1;
|
|
++ }
|
|
++ else if (s[0] == 'S' && s[1] == 'T') {
|
|
++ list[nlist].oid = MBEDTLS_OID_AT_STATE;
|
|
++ list[nlist].olen = sizeof(MBEDTLS_OID_AT_STATE)-1;
|
|
++ }
|
|
++ else if (s[0] == 'O' && s[1] == 'U') {
|
|
++ list[nlist].oid = MBEDTLS_OID_AT_ORG_UNIT;
|
|
++ list[nlist].olen = sizeof(MBEDTLS_OID_AT_ORG_UNIT)-1;
|
|
++ }
|
|
++ break;
|
|
++ case 12:
|
|
++ if (os_memcmp(s, "emailAddress", 12) == 0) {
|
|
++ list[nlist].oid = MBEDTLS_OID_PKCS9_EMAIL;
|
|
++ list[nlist].olen = sizeof(MBEDTLS_OID_PKCS9_EMAIL)-1;
|
|
++ }
|
|
++ break;
|
|
++ default:
|
|
++ break;
|
|
++ }
|
|
++ if (list[nlist].oid == NULL) {
|
|
++ wpa_printf(MSG_INFO,
|
|
++ "MTLS: Unknown field in check_cert_subject '%s'",
|
|
++ match);
|
|
++ return 0;
|
|
++ }
|
|
++ list[nlist].n -= (size_t)(++e - s);
|
|
++ list[nlist].p = e;
|
|
++ if (list[nlist].n && e[list[nlist].n-1] == '*') {
|
|
++ --list[nlist].n;
|
|
++ list[nlist].prefix = 1;
|
|
++ }
|
|
++ /*(could easily add support for suffix matches if value begins with '*',
|
|
++ * but suffix match is not currently supported by other TLS modules)*/
|
|
++
|
|
++ if (list[nlist].n && ++nlist == sizeof(list)/sizeof(*list)) {
|
|
++ wpa_printf(MSG_INFO,
|
|
++ "MTLS: excessive check_cert_subject match '%s'",
|
|
++ match);
|
|
++ break; /* truncate huge list and continue */
|
|
++ }
|
|
++ }
|
|
++
|
|
++ /* each component in match string must match cert Subject in order listed
|
|
++ * The behavior below preserves ordering but is slightly different than
|
|
++ * the grossly inefficient contortions implemented in tls_openssl.c */
|
|
++ const mbedtls_x509_name *name = &crt->subject;
|
|
++ for (int i = 0; i < nlist; ++i) {
|
|
++ int found = 0;
|
|
++ for (; name != NULL && !found; name = name->next) {
|
|
++ if (!name->oid.p)
|
|
++ continue;
|
|
++ /* special-case "*" to match any OID and value */
|
|
++ if (list[i].olen == 0) {
|
|
++ found = 1;
|
|
++ continue;
|
|
++ }
|
|
++ /* perform equalent of !MBEDTLS_OID_CMP() with oid ptr and len */
|
|
++ if (list[i].olen != name->oid.len
|
|
++ || os_memcmp(list[i].oid, name->oid.p, name->oid.len) != 0)
|
|
++ continue;
|
|
++ /* Note: v is not '\0'-terminated, but is a known length vlen,
|
|
++ * so okay to pass to os_strncasecmp() even though not z-string */
|
|
++ if ((list[i].prefix
|
|
++ ? list[i].n <= name->val.len /* prefix match */
|
|
++ : list[i].n == name->val.len) /* full match */
|
|
++ && 0 == os_strncasecmp((char *)name->val.p,
|
|
++ list[i].p, list[i].n)) {
|
|
++ found = 1;
|
|
++ continue;
|
|
++ }
|
|
++ }
|
|
++ if (!found)
|
|
++ return 0; /* no match */
|
|
++ }
|
|
++ return 1; /* match */
|
|
++}
|
|
++
|
|
++
|
|
++__attribute_cold__
|
|
++static void
|
|
++tls_mbedtls_verify_fail_event (mbedtls_x509_crt *crt, int depth,
|
|
++ const char *errmsg, enum tls_fail_reason reason)
|
|
++{
|
|
++ struct tls_config *init_conf = &tls_ctx_global.init_conf;
|
|
++ if (init_conf->event_cb == NULL)
|
|
++ return;
|
|
++
|
|
++ struct wpabuf *certbuf = wpabuf_alloc_copy(crt->raw.p, crt->raw.len);
|
|
++ char subject[MBEDTLS_X509_MAX_DN_NAME_SIZE*2];
|
|
++ if (mbedtls_x509_dn_gets(subject, sizeof(subject), &crt->subject) < 0)
|
|
++ subject[0] = '\0';
|
|
++ union tls_event_data ev;
|
|
++ os_memset(&ev, 0, sizeof(ev));
|
|
++ ev.cert_fail.reason = reason;
|
|
++ ev.cert_fail.depth = depth;
|
|
++ ev.cert_fail.subject = subject;
|
|
++ ev.cert_fail.reason_txt = errmsg;
|
|
++ ev.cert_fail.cert = certbuf;
|
|
++
|
|
++ init_conf->event_cb(init_conf->cb_ctx, TLS_CERT_CHAIN_FAILURE, &ev);
|
|
++
|
|
++ wpabuf_free(certbuf);
|
|
++}
|
|
++
|
|
++
|
|
++__attribute_noinline__
|
|
++static void
|
|
++tls_mbedtls_verify_cert_event (struct tls_connection *conn,
|
|
++ mbedtls_x509_crt *crt, int depth)
|
|
++{
|
|
++ struct tls_config *init_conf = &tls_ctx_global.init_conf;
|
|
++ if (init_conf->event_cb == NULL)
|
|
++ return;
|
|
++
|
|
++ struct wpabuf *certbuf = NULL;
|
|
++ union tls_event_data ev;
|
|
++ os_memset(&ev, 0, sizeof(ev));
|
|
++
|
|
++ #ifdef MBEDTLS_SHA256_C
|
|
++ u8 hash[SHA256_DIGEST_LENGTH];
|
|
++ const u8 *addr[] = { (u8 *)crt->raw.p };
|
|
++ if (sha256_vector(1, addr, &crt->raw.len, hash) == 0) {
|
|
++ ev.peer_cert.hash = hash;
|
|
++ ev.peer_cert.hash_len = sizeof(hash);
|
|
++ }
|
|
++ #endif
|
|
++ ev.peer_cert.depth = depth;
|
|
++ char subject[MBEDTLS_X509_MAX_DN_NAME_SIZE*2];
|
|
++ if (depth == 0)
|
|
++ ev.peer_cert.subject = conn->peer_subject;
|
|
++ if (ev.peer_cert.subject == NULL) {
|
|
++ ev.peer_cert.subject = subject;
|
|
++ if (mbedtls_x509_dn_gets(subject, sizeof(subject), &crt->subject) < 0)
|
|
++ subject[0] = '\0';
|
|
++ }
|
|
++
|
|
++ char serial_num[128+1];
|
|
++ ev.peer_cert.serial_num =
|
|
++ tls_mbedtls_peer_serial_num(crt, serial_num, sizeof(serial_num));
|
|
++
|
|
++ const mbedtls_x509_sequence *cur;
|
|
++
|
|
++ cur = NULL;
|
|
++ if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_SUBJECT_ALT_NAME))
|
|
++ cur = &crt->subject_alt_names;
|
|
++ for (; cur != NULL; cur = cur->next) {
|
|
++ const unsigned char san_type = (unsigned char)cur->buf.tag
|
|
++ & MBEDTLS_ASN1_TAG_VALUE_MASK;
|
|
++ size_t prelen = 4;
|
|
++ const char *pre;
|
|
++ switch (san_type) {
|
|
++ case MBEDTLS_X509_SAN_RFC822_NAME: prelen = 6; pre = "EMAIL:";break;
|
|
++ case MBEDTLS_X509_SAN_DNS_NAME: pre = "DNS:"; break;
|
|
++ case MBEDTLS_X509_SAN_UNIFORM_RESOURCE_IDENTIFIER: pre = "URI:"; break;
|
|
++ default: continue;
|
|
++ }
|
|
++
|
|
++ char *pos = os_malloc(prelen + cur->buf.len + 1);
|
|
++ if (pos == NULL)
|
|
++ break;
|
|
++ ev.peer_cert.altsubject[ev.peer_cert.num_altsubject] = pos;
|
|
++ os_memcpy(pos, pre, prelen);
|
|
++ /* data should be properly backslash-escaped if needed,
|
|
++ * so code below does not re-escape, but does replace CTLs */
|
|
++ /*os_memcpy(pos+prelen, cur->buf.p, cur->buf.len);*/
|
|
++ /*pos[prelen+cur->buf.len] = '\0';*/
|
|
++ pos += prelen;
|
|
++ for (size_t i = 0; i < cur->buf.len; ++i) {
|
|
++ unsigned char c = cur->buf.p[i];
|
|
++ *pos++ = (c >= 32 && c != 127) ? c : '?';
|
|
++ }
|
|
++ *pos = '\0';
|
|
++
|
|
++ if (++ev.peer_cert.num_altsubject == TLS_MAX_ALT_SUBJECT)
|
|
++ break;
|
|
++ }
|
|
++
|
|
++ cur = NULL;
|
|
++ if (mbedtls_x509_crt_has_ext_type(crt, MBEDTLS_X509_EXT_CERTIFICATE_POLICIES))
|
|
++ cur = &crt->certificate_policies;
|
|
++ for (; cur != NULL; cur = cur->next) {
|
|
++ if (cur->buf.len != 11) /* len of OID_TOD_STRICT or OID_TOD_TOFU */
|
|
++ continue;
|
|
++ /* TOD-STRICT "1.3.6.1.4.1.40808.1.3.1" */
|
|
++ /* TOD-TOFU "1.3.6.1.4.1.40808.1.3.2" */
|
|
++ #define OID_TOD_STRICT "\x2b\x06\x01\x04\x01\x82\xbe\x68\x01\x03\x01"
|
|
++ #define OID_TOD_TOFU "\x2b\x06\x01\x04\x01\x82\xbe\x68\x01\x03\x02"
|
|
++ if (os_memcmp(cur->buf.p,
|
|
++ OID_TOD_STRICT, sizeof(OID_TOD_STRICT)-1) == 0) {
|
|
++ ev.peer_cert.tod = 1; /* TOD-STRICT */
|
|
++ break;
|
|
++ }
|
|
++ if (os_memcmp(cur->buf.p,
|
|
++ OID_TOD_TOFU, sizeof(OID_TOD_TOFU)-1) == 0) {
|
|
++ ev.peer_cert.tod = 2; /* TOD-TOFU */
|
|
++ break;
|
|
++ }
|
|
++ }
|
|
++
|
|
++ struct tls_conf *tls_conf = conn->tls_conf;
|
|
++ if (tls_conf->ca_cert_probe || (tls_conf->flags & TLS_CONN_EXT_CERT_CHECK)
|
|
++ || init_conf->cert_in_cb) {
|
|
++ certbuf = wpabuf_alloc_copy(crt->raw.p, crt->raw.len);
|
|
++ ev.peer_cert.cert = certbuf;
|
|
++ }
|
|
++
|
|
++ init_conf->event_cb(init_conf->cb_ctx, TLS_PEER_CERTIFICATE, &ev);
|
|
++
|
|
++ wpabuf_free(certbuf);
|
|
++ char **altsubject;
|
|
++ *(const char ***)&altsubject = ev.peer_cert.altsubject;
|
|
++ for (size_t i = 0; i < ev.peer_cert.num_altsubject; ++i)
|
|
++ os_free(altsubject[i]);
|
|
++}
|
|
++
|
|
++
|
|
++static int
|
|
++tls_mbedtls_verify_cb (void *arg, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
|
|
++{
|
|
++ /* XXX: N.B. verify code not carefully tested besides hwsim tests
|
|
++ *
|
|
++ * RFE: mbedtls_x509_crt_verify_info() and enhance log trace messages
|
|
++ * RFE: review and add support for additional TLS_CONN_* flags
|
|
++ * not handling OCSP (not available in mbedtls)
|
|
++ * ... */
|
|
++
|
|
++ struct tls_connection *conn = (struct tls_connection *)arg;
|
|
++ struct tls_conf *tls_conf = conn->tls_conf;
|
|
++ uint32_t flags_in = *flags;
|
|
++
|
|
++ if (depth > 8) { /*(depth 8 picked as arbitrary limit)*/
|
|
++ emsg(MSG_WARNING, "client cert chain too long");
|
|
++ *flags |= MBEDTLS_X509_BADCERT_OTHER; /* cert chain too long */
|
|
++ tls_mbedtls_verify_fail_event(crt, depth,
|
|
++ "client cert chain too long",
|
|
++ TLS_FAIL_BAD_CERTIFICATE);
|
|
++ }
|
|
++ else if (tls_conf->verify_depth0_only) {
|
|
++ if (depth > 0)
|
|
++ *flags = 0;
|
|
++ else {
|
|
++ #ifdef MBEDTLS_SHA256_C
|
|
++ u8 hash[SHA256_DIGEST_LENGTH];
|
|
++ const u8 *addr[] = { (u8 *)crt->raw.p };
|
|
++ if (sha256_vector(1, addr, &crt->raw.len, hash) < 0
|
|
++ || os_memcmp(tls_conf->ca_cert_hash, hash, sizeof(hash)) != 0) {
|
|
++ *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED;
|
|
++ tls_mbedtls_verify_fail_event(crt, depth,
|
|
++ "cert hash mismatch",
|
|
++ TLS_FAIL_UNTRUSTED);
|
|
++ }
|
|
++ else /* hash matches; ignore other issues *except* if revoked)*/
|
|
++ *flags &= MBEDTLS_X509_BADCERT_REVOKED;
|
|
++ #endif
|
|
++ }
|
|
++ }
|
|
++ else if (depth == 0) {
|
|
++ if (!conn->peer_subject)
|
|
++ tls_mbedtls_set_peer_subject(conn, crt);
|
|
++ /*(use same labels to tls_mbedtls_verify_fail_event() as used in
|
|
++ * other TLS modules so that hwsim tests find exact string match)*/
|
|
++ if (!conn->peer_subject) { /* error copying subject string */
|
|
++ *flags |= MBEDTLS_X509_BADCERT_OTHER;
|
|
++ tls_mbedtls_verify_fail_event(crt, depth,
|
|
++ "internal error",
|
|
++ TLS_FAIL_UNSPECIFIED);
|
|
++ }
|
|
++ /*(use os_strstr() for subject match as is done in tls_mbedtls.c
|
|
++ * to follow the same behavior, even though a suffix match would
|
|
++ * make more sense. Also, note that strstr match does not
|
|
++ * normalize whitespace (between components) for comparison)*/
|
|
++ else if (tls_conf->subject_match
|
|
++ && os_strstr(conn->peer_subject,
|
|
++ tls_conf->subject_match) == NULL) {
|
|
++ wpa_printf(MSG_WARNING,
|
|
++ "MTLS: Subject '%s' did not match with '%s'",
|
|
++ conn->peer_subject, tls_conf->subject_match);
|
|
++ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
|
|
++ tls_mbedtls_verify_fail_event(crt, depth,
|
|
++ "Subject mismatch",
|
|
++ TLS_FAIL_SUBJECT_MISMATCH);
|
|
++ }
|
|
++ if (tls_conf->altsubject_match
|
|
++ && !tls_mbedtls_match_altsubject(crt, tls_conf->altsubject_match)) {
|
|
++ wpa_printf(MSG_WARNING,
|
|
++ "MTLS: altSubjectName match '%s' not found",
|
|
++ tls_conf->altsubject_match);
|
|
++ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
|
|
++ tls_mbedtls_verify_fail_event(crt, depth,
|
|
++ "AltSubject mismatch",
|
|
++ TLS_FAIL_ALTSUBJECT_MISMATCH);
|
|
++ }
|
|
++ if (tls_conf->suffix_match
|
|
++ && !tls_mbedtls_match_suffixes(crt, tls_conf->suffix_match, 0)) {
|
|
++ wpa_printf(MSG_WARNING,
|
|
++ "MTLS: Domain suffix match '%s' not found",
|
|
++ tls_conf->suffix_match);
|
|
++ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
|
|
++ tls_mbedtls_verify_fail_event(crt, depth,
|
|
++ "Domain suffix mismatch",
|
|
++ TLS_FAIL_DOMAIN_SUFFIX_MISMATCH);
|
|
++ }
|
|
++ if (tls_conf->domain_match
|
|
++ && !tls_mbedtls_match_suffixes(crt, tls_conf->domain_match, 1)) {
|
|
++ wpa_printf(MSG_WARNING,
|
|
++ "MTLS: Domain match '%s' not found",
|
|
++ tls_conf->domain_match);
|
|
++ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
|
|
++ tls_mbedtls_verify_fail_event(crt, depth,
|
|
++ "Domain mismatch",
|
|
++ TLS_FAIL_DOMAIN_MISMATCH);
|
|
++ }
|
|
++ if (tls_conf->check_cert_subject
|
|
++ && !tls_mbedtls_match_dn_field(crt, tls_conf->check_cert_subject)) {
|
|
++ *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
|
|
++ tls_mbedtls_verify_fail_event(crt, depth,
|
|
++ "Distinguished Name",
|
|
++ TLS_FAIL_DN_MISMATCH);
|
|
++ }
|
|
++ if (tls_conf->flags & TLS_CONN_SUITEB) {
|
|
++ /* check RSA modulus size (public key bitlen) */
|
|
++ const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type(&crt->pk);
|
|
++ if ((pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS)
|
|
++ && mbedtls_pk_get_bitlen(&crt->pk) < 3072) {
|
|
++ /* hwsim suite_b RSA tests expect 3072
|
|
++ * suite_b_192_rsa_ecdhe_radius_rsa2048_client
|
|
++ * suite_b_192_rsa_dhe_radius_rsa2048_client */
|
|
++ *flags |= MBEDTLS_X509_BADCERT_BAD_KEY;
|
|
++ tls_mbedtls_verify_fail_event(crt, depth,
|
|
++ "Insufficient RSA modulus size",
|
|
++ TLS_FAIL_INSUFFICIENT_KEY_LEN);
|
|
++ }
|
|
++ }
|
|
++ if (tls_conf->check_crl && tls_conf->crl == NULL) {
|
|
++ /* see tests/hwsim test_ap_eap.py ap_wpa2_eap_tls_check_crl */
|
|
++ emsg(MSG_WARNING, "check_crl set but no CRL loaded; reject all?");
|
|
++ *flags |= MBEDTLS_X509_BADCERT_OTHER;
|
|
++ tls_mbedtls_verify_fail_event(crt, depth,
|
|
++ "check_crl set but no CRL loaded; "
|
|
++ "reject all?",
|
|
++ TLS_FAIL_BAD_CERTIFICATE);
|
|
++ }
|
|
++ }
|
|
++ else {
|
|
++ if (tls_conf->check_crl != 2) /* 2 == verify CRLs for all certs */
|
|
++ *flags &= ~MBEDTLS_X509_BADCERT_REVOKED;
|
|
++ }
|
|
++
|
|
++ if (!tls_conf->check_crl_strict) {
|
|
++ *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED;
|
|
++ *flags &= ~MBEDTLS_X509_BADCRL_FUTURE;
|
|
++ }
|
|
++
|
|
++ if (tls_conf->flags & TLS_CONN_DISABLE_TIME_CHECKS) {
|
|
++ *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED;
|
|
++ *flags &= ~MBEDTLS_X509_BADCERT_FUTURE;
|
|
++ }
|
|
++
|
|
++ tls_mbedtls_verify_cert_event(conn, crt, depth);
|
|
++
|
|
++ if (*flags) {
|
|
++ if (*flags & (MBEDTLS_X509_BADCERT_NOT_TRUSTED
|
|
++ |MBEDTLS_X509_BADCERT_CN_MISMATCH
|
|
++ |MBEDTLS_X509_BADCERT_REVOKED)) {
|
|
++ emsg(MSG_WARNING, "client cert not trusted");
|
|
++ }
|
|
++ /* report event if flags set but no additional flags set above */
|
|
++ /* (could translate flags to more detailed TLS_FAIL_* if needed) */
|
|
++ if (!(*flags & ~flags_in)) {
|
|
++ enum tls_fail_reason reason = TLS_FAIL_UNSPECIFIED;
|
|
++ const char *errmsg = "cert verify fail unspecified";
|
|
++ if (*flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
|
|
++ reason = TLS_FAIL_UNTRUSTED;
|
|
++ errmsg = "certificate not trusted";
|
|
++ }
|
|
++ if (*flags & MBEDTLS_X509_BADCERT_REVOKED) {
|
|
++ reason = TLS_FAIL_REVOKED;
|
|
++ errmsg = "certificate has been revoked";
|
|
++ }
|
|
++ if (*flags & MBEDTLS_X509_BADCERT_FUTURE) {
|
|
++ reason = TLS_FAIL_NOT_YET_VALID;
|
|
++ errmsg = "certificate not yet valid";
|
|
++ }
|
|
++ if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) {
|
|
++ reason = TLS_FAIL_EXPIRED;
|
|
++ errmsg = "certificate has expired";
|
|
++ }
|
|
++ if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) {
|
|
++ reason = TLS_FAIL_BAD_CERTIFICATE;
|
|
++ errmsg = "certificate uses insecure algorithm";
|
|
++ }
|
|
++ tls_mbedtls_verify_fail_event(crt, depth, errmsg, reason);
|
|
++ }
|
|
++ #if 0
|
|
++ /* ??? send (again) cert events for all certs in chain ???
|
|
++ * (should already have been called for greater depths) */
|
|
++ /* tls_openssl.c:tls_verify_cb() sends cert events for all certs
|
|
++ * in chain if certificate validation fails, but sends all events
|
|
++ * with depth set to 0 (might be a bug) */
|
|
++ if (depth > 0) {
|
|
++ int pdepth = depth + 1;
|
|
++ for (mbedtls_x509_crt *pcrt; (pcrt = crt->next); ++pdepth) {
|
|
++ tls_mbedtls_verify_cert_event(conn, pcrt, pdepth);
|
|
++ }
|
|
++ }
|
|
++ #endif
|
|
++ /*(do not preserve subject if verification failed but was optional)*/
|
|
++ if (depth == 0 && conn->peer_subject) {
|
|
++ os_free(conn->peer_subject);
|
|
++ conn->peer_subject = NULL;
|
|
++ }
|
|
++ }
|
|
++ else if (depth == 0) {
|
|
++ struct tls_config *init_conf = &tls_ctx_global.init_conf;
|
|
++ if (tls_conf->ca_cert_probe) {
|
|
++ /* reject server certificate on probe-only run */
|
|
++ *flags |= MBEDTLS_X509_BADCERT_OTHER;
|
|
++ tls_mbedtls_verify_fail_event(crt, depth,
|
|
++ "server chain probe",
|
|
++ TLS_FAIL_SERVER_CHAIN_PROBE);
|
|
++ }
|
|
++ else if (init_conf->event_cb) {
|
|
++ /* ??? send event as soon as depth == 0 is verified ???
|
|
++ * What about rest of chain?
|
|
++ * Follows tls_mbedtls.c behavior: */
|
|
++ init_conf->event_cb(init_conf->cb_ctx,
|
|
++ TLS_CERT_CHAIN_SUCCESS, NULL);
|
|
++ }
|
|
++ }
|
|
++
|
|
++ return 0;
|
|
++}
|
|
+--- /dev/null
|
|
++++ b/tests/build/build-wpa_supplicant-mbedtls.config
|
|
+@@ -0,0 +1,24 @@
|
|
++CONFIG_TLS=mbedtls
|
|
++
|
|
++CONFIG_WPS=y
|
|
++CONFIG_EAP_TLS=y
|
|
++CONFIG_EAP_MSCHAPV2=y
|
|
++
|
|
++CONFIG_EAP_PSK=y
|
|
++CONFIG_EAP_GPSK=y
|
|
++CONFIG_EAP_AKA=y
|
|
++CONFIG_EAP_SIM=y
|
|
++CONFIG_EAP_SAKE=y
|
|
++CONFIG_EAP_PAX=y
|
|
++CONFIG_EAP_FAST=y
|
|
++CONFIG_EAP_IKEV2=y
|
|
++
|
|
++CONFIG_SAE=y
|
|
++CONFIG_FILS=y
|
|
++CONFIG_FILS_SK_PFS=y
|
|
++CONFIG_OWE=y
|
|
++CONFIG_DPP=y
|
|
++CONFIG_SUITEB=y
|
|
++CONFIG_SUITEB192=y
|
|
++
|
|
++CFLAGS += -Werror
|
|
+--- a/tests/hwsim/example-hostapd.config
|
|
++++ b/tests/hwsim/example-hostapd.config
|
|
+@@ -4,6 +4,7 @@ CONFIG_DRIVER_NONE=y
|
|
+ CONFIG_DRIVER_NL80211=y
|
|
+ CONFIG_RSN_PREAUTH=y
|
|
+
|
|
++#CONFIG_TLS=mbedtls
|
|
+ #CONFIG_TLS=internal
|
|
+ #CONFIG_INTERNAL_LIBTOMMATH=y
|
|
+ #CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
|
+@@ -39,6 +40,9 @@ endif
|
|
+ ifeq ($(CONFIG_TLS), wolfssl)
|
|
+ CONFIG_EAP_PWD=y
|
|
+ endif
|
|
++ifeq ($(CONFIG_TLS), mbedtls)
|
|
++CONFIG_EAP_PWD=y
|
|
++endif
|
|
+ CONFIG_EAP_EKE=y
|
|
+ CONFIG_PKCS12=y
|
|
+ CONFIG_RADIUS_SERVER=y
|
|
+--- a/tests/hwsim/example-wpa_supplicant.config
|
|
++++ b/tests/hwsim/example-wpa_supplicant.config
|
|
+@@ -2,6 +2,7 @@
|
|
+
|
|
+ CONFIG_TLS=openssl
|
|
+ #CONFIG_TLS=wolfssl
|
|
++#CONFIG_TLS=mbedtls
|
|
+ #CONFIG_TLS=internal
|
|
+ #CONFIG_INTERNAL_LIBTOMMATH=y
|
|
+ #CONFIG_INTERNAL_LIBTOMMATH_FAST=y
|
|
+@@ -41,6 +42,9 @@ endif
|
|
+ ifeq ($(CONFIG_TLS), wolfssl)
|
|
+ CONFIG_EAP_PWD=y
|
|
+ endif
|
|
++ifeq ($(CONFIG_TLS), mbedtls)
|
|
++CONFIG_EAP_PWD=y
|
|
++endif
|
|
+
|
|
+ CONFIG_USIM_SIMULATOR=y
|
|
+ CONFIG_SIM_SIMULATOR=y
|
|
+--- a/wpa_supplicant/Makefile
|
|
++++ b/wpa_supplicant/Makefile
|
|
+@@ -1163,6 +1163,29 @@ endif
|
|
+ CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\"
|
|
+ endif
|
|
+
|
|
++ifeq ($(CONFIG_TLS), mbedtls)
|
|
++ifndef CONFIG_CRYPTO
|
|
++CONFIG_CRYPTO=mbedtls
|
|
++endif
|
|
++ifdef TLS_FUNCS
|
|
++OBJS += ../src/crypto/tls_mbedtls.o
|
|
++LIBS += -lmbedtls -lmbedx509
|
|
++endif
|
|
++OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
|
|
++OBJS_p += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
|
|
++OBJS_priv += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
|
|
++ifdef NEED_FIPS186_2_PRF
|
|
++OBJS += ../src/crypto/fips_prf_internal.o
|
|
++SHA1OBJS += ../src/crypto/sha1-internal.o
|
|
++endif
|
|
++ifeq ($(CONFIG_CRYPTO), mbedtls)
|
|
++LIBS += -lmbedcrypto
|
|
++LIBS_p += -lmbedcrypto
|
|
++# XXX: create a config option?
|
|
++CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
|
|
++endif
|
|
++endif
|
|
++
|
|
+ ifeq ($(CONFIG_TLS), gnutls)
|
|
+ ifndef CONFIG_CRYPTO
|
|
+ # default to libgcrypt
|
|
+@@ -1355,9 +1378,11 @@ endif
|
|
+
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ NEED_INTERNAL_AES_WRAP=y
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ ifdef CONFIG_OPENSSL_INTERNAL_AES_WRAP
|
|
+ # Seems to be needed at least with BoringSSL
|
|
+ NEED_INTERNAL_AES_WRAP=y
|
|
+@@ -1371,9 +1396,11 @@ endif
|
|
+
|
|
+ ifdef NEED_INTERNAL_AES_WRAP
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ AESOBJS += ../src/crypto/aes-unwrap.o
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_AES_EAX
|
|
+ AESOBJS += ../src/crypto/aes-eax.o
|
|
+ NEED_AES_CTR=y
|
|
+@@ -1383,35 +1410,45 @@ AESOBJS += ../src/crypto/aes-siv.o
|
|
+ NEED_AES_CTR=y
|
|
+ endif
|
|
+ ifdef NEED_AES_CTR
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ AESOBJS += ../src/crypto/aes-ctr.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_AES_ENCBLOCK
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ AESOBJS += ../src/crypto/aes-encblock.o
|
|
+ endif
|
|
++endif
|
|
+ NEED_AES_ENC=y
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ AESOBJS += ../src/crypto/aes-omac1.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_AES_WRAP
|
|
+ NEED_AES_ENC=y
|
|
+ ifdef NEED_INTERNAL_AES_WRAP
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ AESOBJS += ../src/crypto/aes-wrap.o
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_AES_CBC
|
|
+ NEED_AES_ENC=y
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ AESOBJS += ../src/crypto/aes-cbc.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_AES_ENC
|
|
+ ifdef CONFIG_INTERNAL_AES
|
|
+ AESOBJS += ../src/crypto/aes-internal-enc.o
|
|
+@@ -1426,12 +1463,16 @@ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), gnutls)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA1OBJS += ../src/crypto/sha1.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA1OBJS += ../src/crypto/sha1-prf.o
|
|
++endif
|
|
+ ifdef CONFIG_INTERNAL_SHA1
|
|
+ SHA1OBJS += ../src/crypto/sha1-internal.o
|
|
+ ifdef NEED_FIPS186_2_PRF
|
|
+@@ -1443,29 +1484,37 @@ CFLAGS += -DCONFIG_NO_PBKDF2
|
|
+ else
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA1OBJS += ../src/crypto/sha1-pbkdf2.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_T_PRF
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA1OBJS += ../src/crypto/sha1-tprf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_TLS_PRF
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA1OBJS += ../src/crypto/sha1-tlsprf.o
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+
|
|
+ ifndef CONFIG_FIPS
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), gnutls)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ MD5OBJS += ../src/crypto/md5.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_MD5
|
|
+ ifdef CONFIG_INTERNAL_MD5
|
|
+ MD5OBJS += ../src/crypto/md5-internal.o
|
|
+@@ -1520,12 +1569,17 @@ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), gnutls)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA256OBJS += ../src/crypto/sha256.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
++
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA256OBJS += ../src/crypto/sha256-prf.o
|
|
++endif
|
|
+ ifdef CONFIG_INTERNAL_SHA256
|
|
+ SHA256OBJS += ../src/crypto/sha256-internal.o
|
|
+ endif
|
|
+@@ -1538,50 +1592,68 @@ CFLAGS += -DCONFIG_INTERNAL_SHA512
|
|
+ SHA256OBJS += ../src/crypto/sha512-internal.o
|
|
+ endif
|
|
+ ifdef NEED_TLS_PRF_SHA256
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA256OBJS += ../src/crypto/sha256-tlsprf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_TLS_PRF_SHA384
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ SHA256OBJS += ../src/crypto/sha384-tlsprf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_HMAC_SHA256_KDF
|
|
+ CFLAGS += -DCONFIG_HMAC_SHA256_KDF
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha256-kdf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_HMAC_SHA384_KDF
|
|
+ CFLAGS += -DCONFIG_HMAC_SHA384_KDF
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha384-kdf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_HMAC_SHA512_KDF
|
|
+ CFLAGS += -DCONFIG_HMAC_SHA512_KDF
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha512-kdf.o
|
|
+ endif
|
|
++endif
|
|
+ OBJS += $(SHA256OBJS)
|
|
+ ifdef NEED_SHA384
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), gnutls)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha384.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ CFLAGS += -DCONFIG_SHA384
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha384-prf.o
|
|
+ endif
|
|
++endif
|
|
+ ifdef NEED_SHA512
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), linux)
|
|
+ ifneq ($(CONFIG_TLS), gnutls)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha512.o
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+ CFLAGS += -DCONFIG_SHA512
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ OBJS += ../src/crypto/sha512-prf.o
|
|
+ endif
|
|
++endif
|
|
+
|
|
+ ifdef NEED_ASN1
|
|
+ OBJS += ../src/tls/asn1.o
|
|
+@@ -1756,10 +1828,12 @@ ifdef CONFIG_FIPS
|
|
+ CFLAGS += -DCONFIG_FIPS
|
|
+ ifneq ($(CONFIG_TLS), openssl)
|
|
+ ifneq ($(CONFIG_TLS), wolfssl)
|
|
++ifneq ($(CONFIG_TLS), mbedtls)
|
|
+ $(error CONFIG_FIPS=y requires CONFIG_TLS=openssl)
|
|
+ endif
|
|
+ endif
|
|
+ endif
|
|
++endif
|
|
+
|
|
+ OBJS += $(SHA1OBJS) $(DESOBJS)
|
|
+
|
|
+--- a/wpa_supplicant/defconfig
|
|
++++ b/wpa_supplicant/defconfig
|
|
+@@ -10,8 +10,8 @@
|
|
+ # to override previous values of the variables.
|
|
+
|
|
+
|
|
+-# Uncomment following two lines and fix the paths if you have installed OpenSSL
|
|
+-# or GnuTLS in non-default location
|
|
++# Uncomment following two lines and fix the paths if you have installed TLS
|
|
++# libraries in a non-default location
|
|
+ #CFLAGS += -I/usr/local/openssl/include
|
|
+ #LIBS += -L/usr/local/openssl/lib
|
|
+
|
|
+@@ -20,6 +20,7 @@
|
|
+ # used to fix build issues on such systems (krb5.h not found).
|
|
+ #CFLAGS += -I/usr/include/kerberos
|
|
+
|
|
++
|
|
+ # Driver interface for generic Linux wireless extensions
|
|
+ # Note: WEXT is deprecated in the current Linux kernel version and no new
|
|
+ # functionality is added to it. nl80211-based interface is the new
|
|
+@@ -326,6 +327,7 @@ CONFIG_BACKEND=file
|
|
+ # openssl = OpenSSL (default)
|
|
+ # gnutls = GnuTLS
|
|
+ # internal = Internal TLSv1 implementation (experimental)
|
|
++# mbedtls = mbed TLS
|
|
+ # linux = Linux kernel AF_ALG and internal TLSv1 implementation (experimental)
|
|
+ # none = Empty template
|
|
+ #CONFIG_TLS=openssl
|
|
diff --git a/package/network/services/hostapd/patches/120-mbedtls-fips186_2_prf.patch b/package/network/services/hostapd/patches/120-mbedtls-fips186_2_prf.patch
|
|
new file mode 100644
|
|
index 0000000000..a48725264f
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/120-mbedtls-fips186_2_prf.patch
|
|
@@ -0,0 +1,114 @@
|
|
+From c8dba4bd750269bcc80fed3d546e2077cb4cdf0e Mon Sep 17 00:00:00 2001
|
|
+From: Glenn Strauss <gstrauss@gluelogic.com>
|
|
+Date: Tue, 19 Jul 2022 20:02:21 -0400
|
|
+Subject: [PATCH 2/7] mbedtls: fips186_2_prf()
|
|
+
|
|
+Signed-off-by: Glenn Strauss <gstrauss@gluelogic.com>
|
|
+---
|
|
+ hostapd/Makefile | 4 ---
|
|
+ src/crypto/crypto_mbedtls.c | 60 +++++++++++++++++++++++++++++++++++++
|
|
+ wpa_supplicant/Makefile | 4 ---
|
|
+ 3 files changed, 60 insertions(+), 8 deletions(-)
|
|
+
|
|
+--- a/hostapd/Makefile
|
|
++++ b/hostapd/Makefile
|
|
+@@ -759,10 +759,6 @@ endif
|
|
+ OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
|
|
+ HOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
|
|
+ SOBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
|
|
+-ifdef NEED_FIPS186_2_PRF
|
|
+-OBJS += ../src/crypto/fips_prf_internal.o
|
|
+-SHA1OBJS += ../src/crypto/sha1-internal.o
|
|
+-endif
|
|
+ ifeq ($(CONFIG_CRYPTO), mbedtls)
|
|
+ ifdef CONFIG_DPP
|
|
+ LIBS += -lmbedx509
|
|
+--- a/src/crypto/crypto_mbedtls.c
|
|
++++ b/src/crypto/crypto_mbedtls.c
|
|
+@@ -132,6 +132,12 @@
|
|
+ #define CRYPTO_MBEDTLS_HMAC_KDF_SHA512
|
|
+ #endif
|
|
+
|
|
++#if defined(EAP_SIM) || defined(EAP_SIM_DYNAMIC) || defined(EAP_SERVER_SIM) \
|
|
++ || defined(EAP_AKA) || defined(EAP_AKA_DYNAMIC) || defined(EAP_SERVER_AKA)
|
|
++/* EAP_SIM=y EAP_AKA=y */
|
|
++#define CRYPTO_MBEDTLS_FIPS186_2_PRF
|
|
++#endif
|
|
++
|
|
+ #if defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || defined(EAP_SERVER_FAST) \
|
|
+ || defined(EAP_TEAP) || defined(EAP_TEAP_DYNAMIC) || defined(EAP_SERVER_FAST)
|
|
+ #define CRYPTO_MBEDTLS_SHA1_T_PRF
|
|
+@@ -813,6 +819,60 @@ int sha1_t_prf(const u8 *key, size_t key
|
|
+
|
|
+ #endif /* CRYPTO_MBEDTLS_SHA1_T_PRF */
|
|
+
|
|
++#ifdef CRYPTO_MBEDTLS_FIPS186_2_PRF
|
|
++
|
|
++/* fips_prf_internal.c sha1-internal.c */
|
|
++
|
|
++/* used only by src/eap_common/eap_sim_common.c:eap_sim_prf()
|
|
++ * for eap_sim_derive_keys() and eap_sim_derive_keys_reauth()
|
|
++ * where xlen is 160 */
|
|
++
|
|
++int fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, size_t xlen)
|
|
++{
|
|
++ /* FIPS 186-2 + change notice 1 */
|
|
++
|
|
++ mbedtls_sha1_context ctx;
|
|
++ u8 * const xkey = ctx.MBEDTLS_PRIVATE(buffer);
|
|
++ u32 * const xstate = ctx.MBEDTLS_PRIVATE(state);
|
|
++ const u32 xstate_init[] =
|
|
++ { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };
|
|
++
|
|
++ mbedtls_sha1_init(&ctx);
|
|
++ os_memcpy(xkey, seed, seed_len < 64 ? seed_len : 64);
|
|
++
|
|
++ /* note: does not fill extra bytes if (xlen % 20) (SHA1_MAC_LEN) */
|
|
++ for (; xlen >= 20; xlen -= 20) {
|
|
++ /* XSEED_j = 0 */
|
|
++ /* XVAL = (XKEY + XSEED_j) mod 2^b */
|
|
++
|
|
++ /* w_i = G(t, XVAL) */
|
|
++ os_memcpy(xstate, xstate_init, sizeof(xstate_init));
|
|
++ mbedtls_internal_sha1_process(&ctx, xkey);
|
|
++
|
|
++ #if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
++ xstate[0] = host_to_be32(xstate[0]);
|
|
++ xstate[1] = host_to_be32(xstate[1]);
|
|
++ xstate[2] = host_to_be32(xstate[2]);
|
|
++ xstate[3] = host_to_be32(xstate[3]);
|
|
++ xstate[4] = host_to_be32(xstate[4]);
|
|
++ #endif
|
|
++ os_memcpy(x, xstate, 20);
|
|
++ if (xlen == 20) /*(done; skip prep for next loop)*/
|
|
++ break;
|
|
++
|
|
++ /* XKEY = (1 + XKEY + w_i) mod 2^b */
|
|
++ for (u32 carry = 1, k = 20; k-- > 0; carry >>= 8)
|
|
++ xkey[k] = (carry += xkey[k] + x[k]) & 0xff;
|
|
++ x += 20;
|
|
++ /* x_j = w_0|w_1 (each pair of iterations through loop)*/
|
|
++ }
|
|
++
|
|
++ mbedtls_sha1_free(&ctx);
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++#endif /* CRYPTO_MBEDTLS_FIPS186_2_PRF */
|
|
++
|
|
+ #endif /* MBEDTLS_SHA1_C */
|
|
+
|
|
+
|
|
+--- a/wpa_supplicant/Makefile
|
|
++++ b/wpa_supplicant/Makefile
|
|
+@@ -1174,10 +1174,6 @@ endif
|
|
+ OBJS += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
|
|
+ OBJS_p += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
|
|
+ OBJS_priv += ../src/crypto/crypto_$(CONFIG_CRYPTO).o
|
|
+-ifdef NEED_FIPS186_2_PRF
|
|
+-OBJS += ../src/crypto/fips_prf_internal.o
|
|
+-SHA1OBJS += ../src/crypto/sha1-internal.o
|
|
+-endif
|
|
+ ifeq ($(CONFIG_CRYPTO), mbedtls)
|
|
+ LIBS += -lmbedcrypto
|
|
+ LIBS_p += -lmbedcrypto
|
|
diff --git a/package/network/services/hostapd/patches/130-mbedtls-annotate-with-TEST_FAIL-for-hwsim-tests.patch b/package/network/services/hostapd/patches/130-mbedtls-annotate-with-TEST_FAIL-for-hwsim-tests.patch
|
|
new file mode 100644
|
|
index 0000000000..ae7620b90c
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/130-mbedtls-annotate-with-TEST_FAIL-for-hwsim-tests.patch
|
|
@@ -0,0 +1,421 @@
|
|
+From 31bd19e0e0254b910cccfd3ddc6a6a9222bbcfc0 Mon Sep 17 00:00:00 2001
|
|
+From: Glenn Strauss <gstrauss@gluelogic.com>
|
|
+Date: Sun, 9 Oct 2022 05:12:17 -0400
|
|
+Subject: [PATCH 3/7] mbedtls: annotate with TEST_FAIL() for hwsim tests
|
|
+
|
|
+Signed-off-by: Glenn Strauss <gstrauss@gluelogic.com>
|
|
+---
|
|
+ src/crypto/crypto_mbedtls.c | 124 ++++++++++++++++++++++++++++++++++++
|
|
+ 1 file changed, 124 insertions(+)
|
|
+
|
|
+--- a/src/crypto/crypto_mbedtls.c
|
|
++++ b/src/crypto/crypto_mbedtls.c
|
|
+@@ -280,6 +280,9 @@ __attribute_noinline__
|
|
+ static int md_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
|
+ u8 *mac, mbedtls_md_type_t md_type)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ mbedtls_md_context_t ctx;
|
|
+ mbedtls_md_init(&ctx);
|
|
+ if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0) != 0){
|
|
+@@ -343,6 +346,9 @@ __attribute_noinline__
|
|
+ static int sha384_512_vector(size_t num_elem, const u8 *addr[],
|
|
+ const size_t *len, u8 *mac, int is384)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ struct mbedtls_sha512_context ctx;
|
|
+ mbedtls_sha512_init(&ctx);
|
|
+ #if MBEDTLS_VERSION_MAJOR >= 3
|
|
+@@ -375,6 +381,9 @@ int sha384_vector(size_t num_elem, const
|
|
+ #include <mbedtls/sha256.h>
|
|
+ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ struct mbedtls_sha256_context ctx;
|
|
+ mbedtls_sha256_init(&ctx);
|
|
+ #if MBEDTLS_VERSION_MAJOR >= 3
|
|
+@@ -397,6 +406,9 @@ int sha256_vector(size_t num_elem, const
|
|
+ #include <mbedtls/sha1.h>
|
|
+ int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ struct mbedtls_sha1_context ctx;
|
|
+ mbedtls_sha1_init(&ctx);
|
|
+ #if MBEDTLS_VERSION_MAJOR >= 3
|
|
+@@ -419,6 +431,9 @@ int sha1_vector(size_t num_elem, const u
|
|
+ #include <mbedtls/md5.h>
|
|
+ int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ struct mbedtls_md5_context ctx;
|
|
+ mbedtls_md5_init(&ctx);
|
|
+ #if MBEDTLS_VERSION_MAJOR >= 3
|
|
+@@ -441,6 +456,9 @@ int md5_vector(size_t num_elem, const u8
|
|
+ #include <mbedtls/md4.h>
|
|
+ int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ struct mbedtls_md4_context ctx;
|
|
+ mbedtls_md4_init(&ctx);
|
|
+ mbedtls_md4_starts_ret(&ctx);
|
|
+@@ -460,6 +478,9 @@ static int hmac_vector(const u8 *key, si
|
|
+ const u8 *addr[], const size_t *len, u8 *mac,
|
|
+ mbedtls_md_type_t md_type)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ mbedtls_md_context_t ctx;
|
|
+ mbedtls_md_init(&ctx);
|
|
+ if (mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 1) != 0){
|
|
+@@ -571,6 +592,9 @@ static int hmac_kdf_expand(const u8 *prk
|
|
+ const char *label, const u8 *info, size_t info_len,
|
|
+ u8 *okm, size_t okm_len, mbedtls_md_type_t md_type)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
|
|
+ #ifdef MBEDTLS_HKDF_C
|
|
+ if (label == NULL) /* RFC 5869 HKDF-Expand when (label == NULL) */
|
|
+@@ -663,6 +687,9 @@ static int hmac_prf_bits(const u8 *key,
|
|
+ const u8 *data, size_t data_len, u8 *buf,
|
|
+ size_t buf_len_bits, mbedtls_md_type_t md_type)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ mbedtls_md_context_t ctx;
|
|
+ mbedtls_md_init(&ctx);
|
|
+ const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_type);
|
|
+@@ -938,6 +965,9 @@ int pbkdf2_sha1(const char *passphrase,
|
|
+
|
|
+ static void *aes_crypt_init_mode(const u8 *key, size_t len, int mode)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return NULL;
|
|
++
|
|
+ mbedtls_aes_context *aes = os_malloc(sizeof(*aes));
|
|
+ if (!aes)
|
|
+ return NULL;
|
|
+@@ -996,6 +1026,9 @@ void aes_decrypt_deinit(void *ctx)
|
|
+ /* aes-wrap.c */
|
|
+ int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ mbedtls_nist_kw_context ctx;
|
|
+ mbedtls_nist_kw_init(&ctx);
|
|
+ size_t olen;
|
|
+@@ -1010,6 +1043,9 @@ int aes_wrap(const u8 *kek, size_t kek_l
|
|
+ /* aes-unwrap.c */
|
|
+ int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, u8 *plain)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ mbedtls_nist_kw_context ctx;
|
|
+ mbedtls_nist_kw_init(&ctx);
|
|
+ size_t olen;
|
|
+@@ -1041,6 +1077,9 @@ int omac1_aes_vector(
|
|
+ const u8 *key, size_t key_len, size_t num_elem, const u8 *addr[],
|
|
+ const size_t *len, u8 *mac)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ mbedtls_cipher_type_t cipher_type;
|
|
+ switch (key_len) {
|
|
+ case 16: cipher_type = MBEDTLS_CIPHER_AES_128_ECB; break;
|
|
+@@ -1103,6 +1142,9 @@ int omac1_aes_256(const u8 *key, const u
|
|
+ /* aes-encblock.c */
|
|
+ int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ mbedtls_aes_context aes;
|
|
+ mbedtls_aes_init(&aes);
|
|
+ int ret = mbedtls_aes_setkey_enc(&aes, key, 128)
|
|
+@@ -1118,6 +1160,9 @@ int aes_128_encrypt_block(const u8 *key,
|
|
+ int aes_ctr_encrypt(const u8 *key, size_t key_len, const u8 *nonce,
|
|
+ u8 *data, size_t data_len)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ unsigned char counter[MBEDTLS_AES_BLOCK_SIZE];
|
|
+ unsigned char stream_block[MBEDTLS_AES_BLOCK_SIZE];
|
|
+ os_memcpy(counter, nonce, MBEDTLS_AES_BLOCK_SIZE);/*(must be writable)*/
|
|
+@@ -1160,11 +1205,17 @@ static int aes_128_cbc_oper(const u8 *ke
|
|
+
|
|
+ int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_ENCRYPT);
|
|
+ }
|
|
+
|
|
+ int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ return aes_128_cbc_oper(key, iv, data, data_len, MBEDTLS_AES_DECRYPT);
|
|
+ }
|
|
+
|
|
+@@ -1407,6 +1458,10 @@ int crypto_hash_finish(struct crypto_has
|
|
+ }
|
|
+ mbedtls_md_free(mctx);
|
|
+ os_free(mctx);
|
|
++
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+@@ -1421,6 +1476,9 @@ int crypto_hash_finish(struct crypto_has
|
|
+
|
|
+ struct crypto_bignum *crypto_bignum_init(void)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return NULL;
|
|
++
|
|
+ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
|
|
+ if (bn)
|
|
+ mbedtls_mpi_init(bn);
|
|
+@@ -1429,6 +1487,9 @@ struct crypto_bignum *crypto_bignum_init
|
|
+
|
|
+ struct crypto_bignum *crypto_bignum_init_set(const u8 *buf, size_t len)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return NULL;
|
|
++
|
|
+ mbedtls_mpi *bn = os_malloc(sizeof(*bn));
|
|
+ if (bn) {
|
|
+ mbedtls_mpi_init(bn);
|
|
+@@ -1442,6 +1503,9 @@ struct crypto_bignum *crypto_bignum_init
|
|
+
|
|
+ struct crypto_bignum *crypto_bignum_init_uint(unsigned int val)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return NULL;
|
|
++
|
|
+ #if 0 /*(hostap use of this interface passes int, not uint)*/
|
|
+ val = host_to_be32(val);
|
|
+ return crypto_bignum_init_set((const u8 *)&val, sizeof(val));
|
|
+@@ -1467,6 +1531,9 @@ void crypto_bignum_deinit(struct crypto_
|
|
+ int crypto_bignum_to_bin(const struct crypto_bignum *a,
|
|
+ u8 *buf, size_t buflen, size_t padlen)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ size_t n = mbedtls_mpi_size((mbedtls_mpi *)a);
|
|
+ if (n < padlen)
|
|
+ n = padlen;
|
|
+@@ -1477,6 +1544,9 @@ int crypto_bignum_to_bin(const struct cr
|
|
+
|
|
+ int crypto_bignum_rand(struct crypto_bignum *r, const struct crypto_bignum *m)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ /*assert(r != m);*//* r must not be same as m for mbedtls_mpi_random()*/
|
|
+ #if MBEDTLS_VERSION_NUMBER >= 0x021B0000 /* mbedtls 2.27.0 */
|
|
+ return mbedtls_mpi_random((mbedtls_mpi *)r, 0, (mbedtls_mpi *)m,
|
|
+@@ -1513,6 +1583,9 @@ int crypto_bignum_exptmod(const struct c
|
|
+ const struct crypto_bignum *c,
|
|
+ struct crypto_bignum *d)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ /* (check if input params match d; d is the result) */
|
|
+ /* (a == d) is ok in current mbedtls implementation */
|
|
+ if (b == d || c == d) { /*(not ok; store result in intermediate)*/
|
|
+@@ -1540,6 +1613,9 @@ int crypto_bignum_inverse(const struct c
|
|
+ const struct crypto_bignum *b,
|
|
+ struct crypto_bignum *c)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ return mbedtls_mpi_inv_mod((mbedtls_mpi *)c,
|
|
+ (const mbedtls_mpi *)a,
|
|
+ (const mbedtls_mpi *)b) ? -1 : 0;
|
|
+@@ -1549,6 +1625,9 @@ int crypto_bignum_sub(const struct crypt
|
|
+ const struct crypto_bignum *b,
|
|
+ struct crypto_bignum *c)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ return mbedtls_mpi_sub_mpi((mbedtls_mpi *)c,
|
|
+ (const mbedtls_mpi *)a,
|
|
+ (const mbedtls_mpi *)b) ? -1 : 0;
|
|
+@@ -1558,6 +1637,9 @@ int crypto_bignum_div(const struct crypt
|
|
+ const struct crypto_bignum *b,
|
|
+ struct crypto_bignum *c)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ /*(most current use of this crypto.h interface has a == c (result),
|
|
+ * so store result in an intermediate to avoid overwritten input)*/
|
|
+ mbedtls_mpi R;
|
|
+@@ -1575,6 +1657,9 @@ int crypto_bignum_addmod(const struct cr
|
|
+ const struct crypto_bignum *c,
|
|
+ struct crypto_bignum *d)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ return mbedtls_mpi_add_mpi((mbedtls_mpi *)d,
|
|
+ (const mbedtls_mpi *)a,
|
|
+ (const mbedtls_mpi *)b)
|
|
+@@ -1588,6 +1673,9 @@ int crypto_bignum_mulmod(const struct cr
|
|
+ const struct crypto_bignum *c,
|
|
+ struct crypto_bignum *d)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ return mbedtls_mpi_mul_mpi((mbedtls_mpi *)d,
|
|
+ (const mbedtls_mpi *)a,
|
|
+ (const mbedtls_mpi *)b)
|
|
+@@ -1600,6 +1688,9 @@ int crypto_bignum_sqrmod(const struct cr
|
|
+ const struct crypto_bignum *b,
|
|
+ struct crypto_bignum *c)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ #if 1
|
|
+ return crypto_bignum_mulmod(a, a, b, c);
|
|
+ #else
|
|
+@@ -1650,6 +1741,9 @@ int crypto_bignum_is_odd(const struct cr
|
|
+ int crypto_bignum_legendre(const struct crypto_bignum *a,
|
|
+ const struct crypto_bignum *p)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -2;
|
|
++
|
|
+ /* Security Note:
|
|
+ * mbedtls_mpi_exp_mod() is not documented to run in constant time,
|
|
+ * though mbedtls/library/bignum.c uses constant_time_internal.h funcs.
|
|
+@@ -1702,6 +1796,9 @@ int crypto_mod_exp(const u8 *base, size_
|
|
+ const u8 *modulus, size_t modulus_len,
|
|
+ u8 *result, size_t *result_len)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ mbedtls_mpi bn_base, bn_exp, bn_modulus, bn_result;
|
|
+ mbedtls_mpi_init(&bn_base);
|
|
+ mbedtls_mpi_init(&bn_exp);
|
|
+@@ -1769,6 +1866,9 @@ static int crypto_mbedtls_dh_init_public
|
|
+ int crypto_dh_init(u8 generator, const u8 *prime, size_t prime_len, u8 *privkey,
|
|
+ u8 *pubkey)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ #if 0 /*(crypto_dh_init() duplicated (and identical) in crypto_*.c modules)*/
|
|
+ size_t pubkey_len, pad;
|
|
+
|
|
+@@ -1810,6 +1910,9 @@ int crypto_dh_derive_secret(u8 generator
|
|
+ const u8 *pubkey, size_t pubkey_len,
|
|
+ u8 *secret, size_t *len)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ #if 0
|
|
+ if (pubkey_len > prime_len ||
|
|
+ (pubkey_len == prime_len &&
|
|
+@@ -2512,6 +2615,9 @@ const struct crypto_ec_point * crypto_ec
|
|
+
|
|
+ struct crypto_ec_point *crypto_ec_point_init(struct crypto_ec *e)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return NULL;
|
|
++
|
|
+ mbedtls_ecp_point *p = os_malloc(sizeof(*p));
|
|
+ if (p != NULL)
|
|
+ mbedtls_ecp_point_init(p);
|
|
+@@ -2536,6 +2642,9 @@ int crypto_ec_point_x(struct crypto_ec *
|
|
+ int crypto_ec_point_to_bin(struct crypto_ec *e,
|
|
+ const struct crypto_ec_point *point, u8 *x, u8 *y)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ /* crypto.h documents crypto_ec_point_to_bin() output is big-endian */
|
|
+ size_t len = CRYPTO_EC_plen(e);
|
|
+ if (x) {
|
|
+@@ -2563,6 +2672,9 @@ int crypto_ec_point_to_bin(struct crypto
|
|
+ struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e,
|
|
+ const u8 *val)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return NULL;
|
|
++
|
|
+ size_t len = CRYPTO_EC_plen(e);
|
|
+ mbedtls_ecp_point *p = os_malloc(sizeof(*p));
|
|
+ u8 buf[1+MBEDTLS_MPI_MAX_SIZE*2];
|
|
+@@ -2615,6 +2727,9 @@ int crypto_ec_point_add(struct crypto_ec
|
|
+ const struct crypto_ec_point *b,
|
|
+ struct crypto_ec_point *c)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ /* mbedtls does not provide an mbedtls_ecp_point add function */
|
|
+ mbedtls_mpi one;
|
|
+ mbedtls_mpi_init(&one);
|
|
+@@ -2631,6 +2746,9 @@ int crypto_ec_point_mul(struct crypto_ec
|
|
+ const struct crypto_bignum *b,
|
|
+ struct crypto_ec_point *res)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ return mbedtls_ecp_mul(
|
|
+ (mbedtls_ecp_group *)e, (mbedtls_ecp_point *)res,
|
|
+ (const mbedtls_mpi *)b, (const mbedtls_ecp_point *)p,
|
|
+@@ -2639,6 +2757,9 @@ int crypto_ec_point_mul(struct crypto_ec
|
|
+
|
|
+ int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return -1;
|
|
++
|
|
+ if (mbedtls_ecp_get_type((mbedtls_ecp_group *)e)
|
|
+ == MBEDTLS_ECP_TYPE_MONTGOMERY) {
|
|
+ /* e.g. MBEDTLS_ECP_DP_CURVE25519 and MBEDTLS_ECP_DP_CURVE448 */
|
|
+@@ -2751,6 +2872,9 @@ struct crypto_bignum *
|
|
+ crypto_ec_point_compute_y_sqr(struct crypto_ec *e,
|
|
+ const struct crypto_bignum *x)
|
|
+ {
|
|
++ if (TEST_FAIL())
|
|
++ return NULL;
|
|
++
|
|
+ mbedtls_mpi *y2 = os_malloc(sizeof(*y2));
|
|
+ if (y2 == NULL)
|
|
+ return NULL;
|
|
diff --git a/package/network/services/hostapd/patches/140-tests-Makefile-make-run-tests-with-CONFIG_TLS.patch b/package/network/services/hostapd/patches/140-tests-Makefile-make-run-tests-with-CONFIG_TLS.patch
|
|
new file mode 100644
|
|
index 0000000000..148c268f9c
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/140-tests-Makefile-make-run-tests-with-CONFIG_TLS.patch
|
|
@@ -0,0 +1,1358 @@
|
|
+From f24933dc175e0faf44a3cce3330c256a59649ca6 Mon Sep 17 00:00:00 2001
|
|
+From: Glenn Strauss <gstrauss@gluelogic.com>
|
|
+Date: Tue, 19 Jul 2022 23:01:17 -0400
|
|
+Subject: [PATCH 4/7] tests/Makefile make run-tests with CONFIG_TLS=...
|
|
+
|
|
+add test-crypto_module.c to run crypto_module_tests()
|
|
+
|
|
+adjust some tests/hwsim/*.py for mbed TLS (work in progress)
|
|
+
|
|
+option to build and run-tests with CONFIG_TLS=internal # (default)
|
|
+$ cd tests; make clean
|
|
+$ make run-tests
|
|
+
|
|
+option to build and run-tests with CONFIG_TLS=gnutls
|
|
+$ cd tests; make clean CONFIG_TLS=gnutls
|
|
+$ make run-tests CONFIG_TLS=gnutls
|
|
+
|
|
+option to build and run-tests with CONFIG_TLS=mbedtls
|
|
+$ cd tests; make clean CONFIG_TLS=mbedtls
|
|
+$ make run-tests CONFIG_TLS=mbedtls
|
|
+
|
|
+option to build and run-tests with CONFIG_TLS=openssl
|
|
+$ cd tests; make clean CONFIG_TLS=openssl
|
|
+$ make run-tests CONFIG_TLS=openssl
|
|
+
|
|
+option to build and run-tests with CONFIG_TLS=wolfssl
|
|
+$ cd tests; make clean CONFIG_TLS=wolfssl
|
|
+$ make run-tests CONFIG_TLS=wolfssl
|
|
+
|
|
+RFE: Makefile logic for crypto objects should be centralized
|
|
+ instead of being duplicated in hostapd/Makefile,
|
|
+ wpa_supplicant/Makefile, src/crypto/Makefile,
|
|
+ tests/Makefile, ...
|
|
+
|
|
+Signed-off-by: Glenn Strauss <gstrauss@gluelogic.com>
|
|
+---
|
|
+ hostapd/Makefile | 6 +
|
|
+ src/crypto/Makefile | 129 ++++++++++++++++++++-
|
|
+ src/crypto/crypto_module_tests.c | 134 ++++++++++++++++++++++
|
|
+ src/tls/Makefile | 11 ++
|
|
+ tests/Makefile | 75 +++++++++---
|
|
+ tests/hwsim/example-hostapd.config | 11 +-
|
|
+ tests/hwsim/example-wpa_supplicant.config | 12 +-
|
|
+ tests/hwsim/test_ap_eap.py | 114 +++++++++++++-----
|
|
+ tests/hwsim/test_ap_ft.py | 4 +-
|
|
+ tests/hwsim/test_authsrv.py | 9 +-
|
|
+ tests/hwsim/test_dpp.py | 19 ++-
|
|
+ tests/hwsim/test_erp.py | 16 +--
|
|
+ tests/hwsim/test_fils.py | 5 +-
|
|
+ tests/hwsim/test_pmksa_cache.py | 4 +-
|
|
+ tests/hwsim/test_sae.py | 7 ++
|
|
+ tests/hwsim/test_suite_b.py | 3 +
|
|
+ tests/hwsim/test_wpas_ctrl.py | 2 +-
|
|
+ tests/hwsim/utils.py | 8 +-
|
|
+ tests/test-crypto_module.c | 16 +++
|
|
+ tests/test-https.c | 12 +-
|
|
+ tests/test-https_server.c | 12 +-
|
|
+ wpa_supplicant/Makefile | 6 +
|
|
+ 22 files changed, 524 insertions(+), 91 deletions(-)
|
|
+ create mode 100644 tests/test-crypto_module.c
|
|
+
|
|
+--- a/hostapd/Makefile
|
|
++++ b/hostapd/Makefile
|
|
+@@ -696,6 +696,7 @@ CFLAGS += -DCONFIG_TLSV12
|
|
+ endif
|
|
+
|
|
+ ifeq ($(CONFIG_TLS), wolfssl)
|
|
++CFLAGS += -DCONFIG_TLS_WOLFSSL
|
|
+ CONFIG_CRYPTO=wolfssl
|
|
+ ifdef TLS_FUNCS
|
|
+ OBJS += ../src/crypto/tls_wolfssl.o
|
|
+@@ -716,6 +717,7 @@ endif
|
|
+ endif
|
|
+
|
|
+ ifeq ($(CONFIG_TLS), openssl)
|
|
++CFLAGS += -DCONFIG_TLS_OPENSSL
|
|
+ CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
|
|
+ CONFIG_CRYPTO=openssl
|
|
+ ifdef TLS_FUNCS
|
|
+@@ -746,6 +748,7 @@ CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONF
|
|
+ endif
|
|
+
|
|
+ ifeq ($(CONFIG_TLS), mbedtls)
|
|
++CFLAGS += -DCONFIG_TLS_MBEDTLS
|
|
+ ifndef CONFIG_CRYPTO
|
|
+ CONFIG_CRYPTO=mbedtls
|
|
+ endif
|
|
+@@ -776,6 +779,7 @@ endif
|
|
+ endif
|
|
+
|
|
+ ifeq ($(CONFIG_TLS), gnutls)
|
|
++CFLAGS += -DCONFIG_TLS_GNUTLS
|
|
+ ifndef CONFIG_CRYPTO
|
|
+ # default to libgcrypt
|
|
+ CONFIG_CRYPTO=gnutls
|
|
+@@ -806,6 +810,7 @@ endif
|
|
+ endif
|
|
+
|
|
+ ifeq ($(CONFIG_TLS), internal)
|
|
++CFLAGS += -DCONFIG_TLS_INTERNAL
|
|
+ ifndef CONFIG_CRYPTO
|
|
+ CONFIG_CRYPTO=internal
|
|
+ endif
|
|
+@@ -884,6 +889,7 @@ endif
|
|
+ endif
|
|
+
|
|
+ ifeq ($(CONFIG_TLS), linux)
|
|
++CFLAGS += -DCONFIG_TLS_INTERNAL
|
|
+ OBJS += ../src/crypto/crypto_linux.o
|
|
+ ifdef TLS_FUNCS
|
|
+ OBJS += ../src/crypto/crypto_internal-rsa.o
|
|
+--- a/src/crypto/Makefile
|
|
++++ b/src/crypto/Makefile
|
|
+@@ -1,10 +1,121 @@
|
|
+-CFLAGS += -DCONFIG_CRYPTO_INTERNAL
|
|
+-CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
|
|
+-CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
|
|
+ #CFLAGS += -DALL_DH_GROUPS
|
|
+ CFLAGS += -DCONFIG_SHA256
|
|
+ CFLAGS += -DCONFIG_SHA384
|
|
++CFLAGS += -DCONFIG_HMAC_SHA256_KDF
|
|
+ CFLAGS += -DCONFIG_HMAC_SHA384_KDF
|
|
++
|
|
++# crypto_module_tests.c
|
|
++CFLAGS += -DCONFIG_MODULE_TESTS
|
|
++CFLAGS += -DCONFIG_DPP
|
|
++#CFLAGS += -DCONFIG_DPP2
|
|
++#CFLAGS += -DCONFIG_DPP3
|
|
++CFLAGS += -DCONFIG_ECC
|
|
++CFLAGS += -DCONFIG_MESH
|
|
++CFLAGS += -DEAP_PSK
|
|
++CFLAGS += -DEAP_FAST
|
|
++
|
|
++ifeq ($(CONFIG_TLS),mbedtls)
|
|
++
|
|
++# (enable features for 'cd tests; make run-tests CONFIG_TLS=mbedtls')
|
|
++CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
|
|
++CFLAGS += -DCONFIG_DES
|
|
++CFLAGS += -DEAP_IKEV2
|
|
++CFLAGS += -DEAP_MSCHAPv2
|
|
++CFLAGS += -DEAP_SIM
|
|
++
|
|
++LIB_OBJS = tls_mbedtls.o crypto_mbedtls.o
|
|
++LIB_OBJS+= \
|
|
++ aes-eax.o \
|
|
++ aes-siv.o \
|
|
++ dh_groups.o \
|
|
++ milenage.o \
|
|
++ ms_funcs.o
|
|
++
|
|
++else
|
|
++ifeq ($(CONFIG_TLS),openssl)
|
|
++
|
|
++# (enable features for 'cd tests; make run-tests CONFIG_TLS=openssl')
|
|
++ifndef CONFIG_TLS_DEFAULT_CIPHERS
|
|
++CONFIG_TLS_DEFAULT_CIPHERS = "DEFAULT:!EXP:!LOW"
|
|
++endif
|
|
++CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONFIG_TLS_DEFAULT_CIPHERS)\"
|
|
++CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
|
|
++CFLAGS += -DEAP_TLS_OPENSSL
|
|
++
|
|
++LIB_OBJS = tls_openssl.o fips_prf_openssl.o crypto_openssl.o
|
|
++LIB_OBJS+= \
|
|
++ aes-ctr.o \
|
|
++ aes-eax.o \
|
|
++ aes-encblock.o \
|
|
++ aes-siv.o \
|
|
++ dh_groups.o \
|
|
++ milenage.o \
|
|
++ ms_funcs.o \
|
|
++ sha1-prf.o \
|
|
++ sha1-tlsprf.o \
|
|
++ sha1-tprf.o \
|
|
++ sha256-kdf.o \
|
|
++ sha256-prf.o \
|
|
++ sha256-tlsprf.o
|
|
++
|
|
++else
|
|
++ifeq ($(CONFIG_TLS),wolfssl)
|
|
++
|
|
++# (wolfssl libraries must be built with ./configure --enable-wpas)
|
|
++# (enable features for 'cd tests; make run-tests CONFIG_TLS=wolfssl')
|
|
++CFLAGS += -DWOLFSSL_DER_LOAD
|
|
++CFLAGS += -DCONFIG_DES
|
|
++
|
|
++LIB_OBJS = tls_wolfssl.o fips_prf_wolfssl.o crypto_wolfssl.o
|
|
++LIB_OBJS+= \
|
|
++ aes-ctr.o \
|
|
++ aes-eax.o \
|
|
++ aes-encblock.o \
|
|
++ aes-siv.o \
|
|
++ dh_groups.o \
|
|
++ milenage.o \
|
|
++ ms_funcs.o \
|
|
++ sha1-prf.o \
|
|
++ sha1-tlsprf.o \
|
|
++ sha1-tprf.o \
|
|
++ sha256-kdf.o \
|
|
++ sha256-prf.o \
|
|
++ sha256-tlsprf.o
|
|
++
|
|
++else
|
|
++ifeq ($(CONFIG_TLS),gnutls)
|
|
++
|
|
++# (enable features for 'cd tests; make run-tests CONFIG_TLS=gnutls')
|
|
++LIB_OBJS = tls_gnutls.o crypto_gnutls.o
|
|
++LIB_OBJS+= \
|
|
++ aes-cbc.o \
|
|
++ aes-ctr.o \
|
|
++ aes-eax.o \
|
|
++ aes-encblock.o \
|
|
++ aes-omac1.o \
|
|
++ aes-siv.o \
|
|
++ aes-unwrap.o \
|
|
++ aes-wrap.o \
|
|
++ dh_group5.o \
|
|
++ dh_groups.o \
|
|
++ milenage.o \
|
|
++ ms_funcs.o \
|
|
++ rc4.o \
|
|
++ sha1-pbkdf2.o \
|
|
++ sha1-prf.o \
|
|
++ fips_prf_internal.o \
|
|
++ sha1-internal.o \
|
|
++ sha1-tlsprf.o \
|
|
++ sha1-tprf.o \
|
|
++ sha256-kdf.o \
|
|
++ sha256-prf.o \
|
|
++ sha256-tlsprf.o
|
|
++
|
|
++else
|
|
++
|
|
++CFLAGS += -DCONFIG_CRYPTO_INTERNAL
|
|
++CFLAGS += -DCONFIG_TLS_INTERNAL_CLIENT
|
|
++CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
|
|
+ CFLAGS += -DCONFIG_INTERNAL_SHA384
|
|
+
|
|
+ LIB_OBJS= \
|
|
+@@ -13,7 +124,6 @@ LIB_OBJS= \
|
|
+ aes-ctr.o \
|
|
+ aes-eax.o \
|
|
+ aes-encblock.o \
|
|
+- aes-gcm.o \
|
|
+ aes-internal.o \
|
|
+ aes-internal-dec.o \
|
|
+ aes-internal-enc.o \
|
|
+@@ -37,6 +147,7 @@ LIB_OBJS= \
|
|
+ sha1-tlsprf.o \
|
|
+ sha1-tprf.o \
|
|
+ sha256.o \
|
|
++ sha256-kdf.o \
|
|
+ sha256-prf.o \
|
|
+ sha256-tlsprf.o \
|
|
+ sha256-internal.o \
|
|
+@@ -53,6 +164,16 @@ LIB_OBJS += crypto_internal-modexp.o
|
|
+ LIB_OBJS += crypto_internal-rsa.o
|
|
+ LIB_OBJS += tls_internal.o
|
|
+ LIB_OBJS += fips_prf_internal.o
|
|
++
|
|
++endif
|
|
++endif
|
|
++endif
|
|
++endif
|
|
++
|
|
++
|
|
++# (used by wlantest/{bip,gcmp,rx_mgmt}.c and tests/test-aes.c)
|
|
++LIB_OBJS += aes-gcm.o
|
|
++
|
|
+ ifndef TEST_FUZZ
|
|
+ LIB_OBJS += random.o
|
|
+ endif
|
|
+--- a/src/crypto/crypto_module_tests.c
|
|
++++ b/src/crypto/crypto_module_tests.c
|
|
+@@ -2469,6 +2469,139 @@ static int test_hpke(void)
|
|
+ }
|
|
+
|
|
+
|
|
++static int test_ecc(void)
|
|
++{
|
|
++#ifdef CONFIG_ECC
|
|
++#ifndef CONFIG_TLS_INTERNAL
|
|
++#ifndef CONFIG_TLS_GNUTLS
|
|
++#if defined(CONFIG_TLS_MBEDTLS) \
|
|
++ || defined(CONFIG_TLS_OPENSSL) \
|
|
++ || defined(CONFIG_TLS_WOLFSSL)
|
|
++ wpa_printf(MSG_INFO, "Testing ECC");
|
|
++ /* Note: some tests below are valid on supported Short Weierstrass
|
|
++ * curves, but not on Montgomery curves (e.g. IKE groups 31 and 32)
|
|
++ * (e.g. deriving and comparing y^2 test below not valid on Montgomery)
|
|
++ */
|
|
++#ifdef CONFIG_TLS_MBEDTLS
|
|
++ const int grps[] = {19, 20, 21, 25, 26, 28};
|
|
++#endif
|
|
++#ifdef CONFIG_TLS_OPENSSL
|
|
++ const int grps[] = {19, 20, 21, 26};
|
|
++#endif
|
|
++#ifdef CONFIG_TLS_WOLFSSL
|
|
++ const int grps[] = {19, 20, 21, 26};
|
|
++#endif
|
|
++ uint32_t i;
|
|
++ struct crypto_ec *e = NULL;
|
|
++ struct crypto_ec_point *p = NULL, *q = NULL;
|
|
++ struct crypto_bignum *x = NULL, *y = NULL;
|
|
++#ifdef CONFIG_DPP
|
|
++ u8 bin[4096];
|
|
++#endif
|
|
++ for (i = 0; i < ARRAY_SIZE(grps); ++i) {
|
|
++ e = crypto_ec_init(grps[i]);
|
|
++ if (e == NULL
|
|
++ || crypto_ec_prime_len(e) == 0
|
|
++ || crypto_ec_prime_len_bits(e) == 0
|
|
++ || crypto_ec_order_len(e) == 0
|
|
++ || crypto_ec_get_prime(e) == NULL
|
|
++ || crypto_ec_get_order(e) == NULL
|
|
++ || crypto_ec_get_a(e) == NULL
|
|
++ || crypto_ec_get_b(e) == NULL
|
|
++ || crypto_ec_get_generator(e) == NULL) {
|
|
++ break;
|
|
++ }
|
|
++#ifdef CONFIG_DPP
|
|
++ struct crypto_ec_key *key = crypto_ec_key_gen(grps[i]);
|
|
++ if (key == NULL)
|
|
++ break;
|
|
++ p = crypto_ec_key_get_public_key(key);
|
|
++ q = crypto_ec_key_get_public_key(key);
|
|
++ crypto_ec_key_deinit(key);
|
|
++ if (p == NULL || q == NULL)
|
|
++ break;
|
|
++ if (!crypto_ec_point_is_on_curve(e, p))
|
|
++ break;
|
|
++
|
|
++ /* inverted point should not match original;
|
|
++ * double-invert should match */
|
|
++ if (crypto_ec_point_invert(e, q) != 0
|
|
++ || crypto_ec_point_cmp(e, p, q) == 0
|
|
++ || crypto_ec_point_invert(e, q) != 0
|
|
++ || crypto_ec_point_cmp(e, p, q) != 0) {
|
|
++ break;
|
|
++ }
|
|
++
|
|
++ /* crypto_ec_point_to_bin() and crypto_ec_point_from_bin()
|
|
++ * imbalanced interfaces? */
|
|
++ size_t prime_len = crypto_ec_prime_len(e);
|
|
++ if (prime_len * 2 > sizeof(bin))
|
|
++ break;
|
|
++ if (crypto_ec_point_to_bin(e, p, bin, bin+prime_len) != 0)
|
|
++ break;
|
|
++ struct crypto_ec_point *tmp = crypto_ec_point_from_bin(e, bin);
|
|
++ if (tmp == NULL)
|
|
++ break;
|
|
++ if (crypto_ec_point_cmp(e, p, tmp) != 0) {
|
|
++ crypto_ec_point_deinit(tmp, 0);
|
|
++ break;
|
|
++ }
|
|
++ crypto_ec_point_deinit(tmp, 0);
|
|
++
|
|
++ x = crypto_bignum_init();
|
|
++ y = crypto_bignum_init_set(bin+prime_len, prime_len);
|
|
++ if (x == NULL || y == NULL || crypto_ec_point_x(e, p, x) != 0)
|
|
++ break;
|
|
++ struct crypto_bignum *y2 = crypto_ec_point_compute_y_sqr(e, x);
|
|
++ if (y2 == NULL)
|
|
++ break;
|
|
++ if (crypto_bignum_sqrmod(y, crypto_ec_get_prime(e), y) != 0
|
|
++ || crypto_bignum_cmp(y, y2) != 0) {
|
|
++ crypto_bignum_deinit(y2, 0);
|
|
++ break;
|
|
++ }
|
|
++ crypto_bignum_deinit(y2, 0);
|
|
++ crypto_bignum_deinit(x, 0);
|
|
++ crypto_bignum_deinit(y, 0);
|
|
++ x = NULL;
|
|
++ y = NULL;
|
|
++
|
|
++ x = crypto_bignum_init();
|
|
++ if (x == NULL)
|
|
++ break;
|
|
++ if (crypto_bignum_rand(x, crypto_ec_get_prime(e)) != 0)
|
|
++ break;
|
|
++ crypto_bignum_deinit(x, 0);
|
|
++ x = NULL;
|
|
++
|
|
++ crypto_ec_point_deinit(p, 0);
|
|
++ p = NULL;
|
|
++ crypto_ec_point_deinit(q, 0);
|
|
++ q = NULL;
|
|
++#endif /* CONFIG_DPP */
|
|
++ crypto_ec_deinit(e);
|
|
++ e = NULL;
|
|
++ }
|
|
++ if (i != ARRAY_SIZE(grps)) {
|
|
++ crypto_bignum_deinit(x, 0);
|
|
++ crypto_bignum_deinit(y, 0);
|
|
++ crypto_ec_point_deinit(p, 0);
|
|
++ crypto_ec_point_deinit(q, 0);
|
|
++ crypto_ec_deinit(e);
|
|
++ wpa_printf(MSG_INFO,
|
|
++ "ECC test case failed tls_id:%d", grps[i]);
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
++ wpa_printf(MSG_INFO, "ECC test cases passed");
|
|
++#endif
|
|
++#endif /* !CONFIG_TLS_GNUTLS */
|
|
++#endif /* !CONFIG_TLS_INTERNAL */
|
|
++#endif /* CONFIG_ECC */
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
+ static int test_ms_funcs(void)
|
|
+ {
|
|
+ #ifndef CONFIG_FIPS
|
|
+@@ -2590,6 +2723,7 @@ int crypto_module_tests(void)
|
|
+ test_fips186_2_prf() ||
|
|
+ test_extract_expand_hkdf() ||
|
|
+ test_hpke() ||
|
|
++ test_ecc() ||
|
|
+ test_ms_funcs())
|
|
+ ret = -1;
|
|
+
|
|
+--- a/src/tls/Makefile
|
|
++++ b/src/tls/Makefile
|
|
+@@ -1,3 +1,10 @@
|
|
++LIB_OBJS= asn1.o
|
|
++
|
|
++ifneq ($(CONFIG_TLS),gnutls)
|
|
++ifneq ($(CONFIG_TLS),mbedtls)
|
|
++ifneq ($(CONFIG_TLS),openssl)
|
|
++ifneq ($(CONFIG_TLS),wolfssl)
|
|
++
|
|
+ CFLAGS += -DCONFIG_INTERNAL_LIBTOMMATH
|
|
+ CFLAGS += -DCONFIG_CRYPTO_INTERNAL
|
|
+ CFLAGS += -DCONFIG_TLSV11
|
|
+@@ -21,5 +28,9 @@ LIB_OBJS= \
|
|
+ tlsv1_server_read.o \
|
|
+ tlsv1_server_write.o \
|
|
+ x509v3.o
|
|
++endif
|
|
++endif
|
|
++endif
|
|
++endif
|
|
+
|
|
+ include ../lib.rules
|
|
+--- a/tests/Makefile
|
|
++++ b/tests/Makefile
|
|
+@@ -1,8 +1,10 @@
|
|
+-ALL=test-base64 test-md4 test-milenage \
|
|
+- test-rsa-sig-ver \
|
|
+- test-sha1 \
|
|
+- test-https test-https_server \
|
|
+- test-sha256 test-aes test-x509v3 test-list test-rc4
|
|
++RUN_TESTS= \
|
|
++ test-list \
|
|
++ test-md4 test-rc4 test-sha1 test-sha256 \
|
|
++ test-milenage test-aes \
|
|
++ test-crypto_module
|
|
++
|
|
++ALL=$(RUN_TESTS) test-base64 test-https test-https_server
|
|
+
|
|
+ include ../src/build.rules
|
|
+
|
|
+@@ -24,13 +26,27 @@ CFLAGS += -DCONFIG_IEEE80211R_AP
|
|
+ CFLAGS += -DCONFIG_IEEE80211R
|
|
+ CFLAGS += -DCONFIG_TDLS
|
|
+
|
|
++# test-crypto_module
|
|
++CFLAGS += -DCONFIG_MODULE_TESTS
|
|
++CFLAGS += -DCONFIG_DPP
|
|
++#CFLAGS += -DCONFIG_DPP2
|
|
++#CFLAGS += -DCONFIG_DPP3
|
|
++CFLAGS += -DCONFIG_ECC
|
|
++CFLAGS += -DCONFIG_HMAC_SHA256_KDF
|
|
++CFLAGS += -DCONFIG_HMAC_SHA384_KDF
|
|
++CFLAGS += -DCONFIG_MESH
|
|
++CFLAGS += -DCONFIG_SHA256
|
|
++CFLAGS += -DCONFIG_SHA384
|
|
++CFLAGS += -DEAP_PSK
|
|
++CFLAGS += -DEAP_FAST
|
|
++
|
|
+ CFLAGS += -I../src
|
|
+ CFLAGS += -I../src/utils
|
|
+
|
|
+ SLIBS = ../src/utils/libutils.a
|
|
+
|
|
+-DLIBS = ../src/crypto/libcrypto.a \
|
|
+- ../src/tls/libtls.a
|
|
++DLIBS = ../src/tls/libtls.a \
|
|
++ ../src/crypto/libcrypto.a
|
|
+
|
|
+ _OBJS_VAR := LLIBS
|
|
+ include ../src/objs.mk
|
|
+@@ -42,12 +58,43 @@ include ../src/objs.mk
|
|
+ LIBS = $(SLIBS) $(DLIBS)
|
|
+ LLIBS = -Wl,--start-group $(DLIBS) -Wl,--end-group $(SLIBS)
|
|
+
|
|
++ifeq ($(CONFIG_TLS),mbedtls)
|
|
++CFLAGS += -DCONFIG_TLS_MBEDTLS
|
|
++LLIBS += -lmbedtls -lmbedx509 -lmbedcrypto
|
|
++else
|
|
++ifeq ($(CONFIG_TLS),openssl)
|
|
++CFLAGS += -DCONFIG_TLS_OPENSSL
|
|
++LLIBS += -lssl -lcrypto
|
|
++else
|
|
++ifeq ($(CONFIG_TLS),gnutls)
|
|
++CFLAGS += -DCONFIG_TLS_GNUTLS
|
|
++LLIBS += -lgnutls -lgpg-error -lgcrypt
|
|
++else
|
|
++ifeq ($(CONFIG_TLS),wolfssl)
|
|
++CFLAGS += -DCONFIG_TLS_WOLFSSL
|
|
++LLIBS += -lwolfssl -lm
|
|
++else
|
|
++CFLAGS += -DCONFIG_TLS_INTERNAL
|
|
++CFLAGS += -DCONFIG_TLS_INTERNAL_SERVER
|
|
++ALL += test-rsa-sig-ver
|
|
++ALL += test-x509v3
|
|
++clean-config_tls_internal:
|
|
++ rm -f test_x509v3_nist.out.*
|
|
++ rm -f test_x509v3_nist2.out.*
|
|
++endif
|
|
++endif
|
|
++endif
|
|
++endif
|
|
++
|
|
+ # glibc < 2.17 needs -lrt for clock_gettime()
|
|
+ LLIBS += -lrt
|
|
+
|
|
+ test-aes: $(call BUILDOBJ,test-aes.o) $(LIBS)
|
|
+ $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS)
|
|
+
|
|
++test-crypto_module: $(call BUILDOBJ,test-crypto_module.o) $(LIBS)
|
|
++ $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS)
|
|
++
|
|
+ test-base64: $(call BUILDOBJ,test-base64.o) $(LIBS)
|
|
+ $(LDO) $(LDFLAGS) -o $@ $^ $(LLIBS)
|
|
+
|
|
+@@ -83,17 +130,11 @@ test-x509v3: $(call BUILDOBJ,test-x509v3
|
|
+
|
|
+
|
|
+ run-tests: $(ALL)
|
|
+- ./test-aes
|
|
+- ./test-list
|
|
+- ./test-md4
|
|
+- ./test-milenage
|
|
+- ./test-rsa-sig-ver
|
|
+- ./test-sha1
|
|
+- ./test-sha256
|
|
++ @set -ex; for i in $(RUN_TESTS); do ./$$i; done
|
|
+ @echo
|
|
+ @echo All tests completed successfully.
|
|
+
|
|
+-clean: common-clean
|
|
++clean: common-clean clean-config_tls_internal
|
|
+ rm -f *~
|
|
+- rm -f test_x509v3_nist.out.*
|
|
+- rm -f test_x509v3_nist2.out.*
|
|
++
|
|
++.PHONY: run-tests clean-config_tls_internal
|
|
+--- a/tests/hwsim/example-hostapd.config
|
|
++++ b/tests/hwsim/example-hostapd.config
|
|
+@@ -34,15 +34,7 @@ CONFIG_EAP_TNC=y
|
|
+ CFLAGS += -DTNC_CONFIG_FILE=\"tnc/tnc_config\"
|
|
+ LIBS += -rdynamic
|
|
+ CONFIG_EAP_UNAUTH_TLS=y
|
|
+-ifeq ($(CONFIG_TLS), openssl)
|
|
+-CONFIG_EAP_PWD=y
|
|
+-endif
|
|
+-ifeq ($(CONFIG_TLS), wolfssl)
|
|
+-CONFIG_EAP_PWD=y
|
|
+-endif
|
|
+-ifeq ($(CONFIG_TLS), mbedtls)
|
|
+-CONFIG_EAP_PWD=y
|
|
+-endif
|
|
++CONFIG_EAP_PWD=$(if $(filter openssl wolfssl mbedtls,$(CONFIG_TLS)),y,)
|
|
+ CONFIG_EAP_EKE=y
|
|
+ CONFIG_PKCS12=y
|
|
+ CONFIG_RADIUS_SERVER=y
|
|
+@@ -89,6 +81,7 @@ CFLAGS += -DCONFIG_RADIUS_TEST
|
|
+ CONFIG_MODULE_TESTS=y
|
|
+
|
|
+ CONFIG_SUITEB=y
|
|
++CONFIG_SUITEB192=$(if $(filter openssl mbedtls,$(CONFIG_TLS)),y,)
|
|
+
|
|
+ # AddressSanitizer (ASan) can be enabled by uncommenting the following lines.
|
|
+ # This can be used as a more efficient memory error detector than valgrind
|
|
+--- a/tests/hwsim/example-wpa_supplicant.config
|
|
++++ b/tests/hwsim/example-wpa_supplicant.config
|
|
+@@ -35,16 +35,7 @@ LIBS += -rdynamic
|
|
+ CONFIG_EAP_FAST=y
|
|
+ CONFIG_EAP_TEAP=y
|
|
+ CONFIG_EAP_IKEV2=y
|
|
+-
|
|
+-ifeq ($(CONFIG_TLS), openssl)
|
|
+-CONFIG_EAP_PWD=y
|
|
+-endif
|
|
+-ifeq ($(CONFIG_TLS), wolfssl)
|
|
+-CONFIG_EAP_PWD=y
|
|
+-endif
|
|
+-ifeq ($(CONFIG_TLS), mbedtls)
|
|
+-CONFIG_EAP_PWD=y
|
|
+-endif
|
|
++CONFIG_EAP_PWD=$(if $(filter openssl wolfssl mbedtls,$(CONFIG_TLS)),y,)
|
|
+
|
|
+ CONFIG_USIM_SIMULATOR=y
|
|
+ CONFIG_SIM_SIMULATOR=y
|
|
+@@ -137,6 +128,7 @@ CONFIG_TESTING_OPTIONS=y
|
|
+ CONFIG_MODULE_TESTS=y
|
|
+
|
|
+ CONFIG_SUITEB=y
|
|
++CONFIG_SUITEB192=$(if $(filter openssl mbedtls,$(CONFIG_TLS)),y,)
|
|
+
|
|
+ # AddressSanitizer (ASan) can be enabled by uncommenting the following lines.
|
|
+ # This can be used as a more efficient memory error detector than valgrind
|
|
+--- a/tests/hwsim/test_ap_eap.py
|
|
++++ b/tests/hwsim/test_ap_eap.py
|
|
+@@ -42,20 +42,42 @@ def check_eap_capa(dev, method):
|
|
+ res = dev.get_capability("eap")
|
|
+ if method not in res:
|
|
+ raise HwsimSkip("EAP method %s not supported in the build" % method)
|
|
++ if method == "FAST" or method == "TEAP":
|
|
++ tls = dev.request("GET tls_library")
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ raise HwsimSkip("EAP-%s not supported with this TLS library: " % method + tls)
|
|
+
|
|
+ def check_subject_match_support(dev):
|
|
+ tls = dev.request("GET tls_library")
|
|
+- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"):
|
|
++ if tls.startswith("OpenSSL"):
|
|
++ return
|
|
++ elif tls.startswith("wolfSSL"):
|
|
++ return
|
|
++ elif tls.startswith("mbed TLS"):
|
|
++ return
|
|
++ else:
|
|
+ raise HwsimSkip("subject_match not supported with this TLS library: " + tls)
|
|
+
|
|
+ def check_check_cert_subject_support(dev):
|
|
+ tls = dev.request("GET tls_library")
|
|
+- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"):
|
|
++ if tls.startswith("OpenSSL"):
|
|
++ return
|
|
++ elif tls.startswith("wolfSSL"):
|
|
++ return
|
|
++ elif tls.startswith("mbed TLS"):
|
|
++ return
|
|
++ else:
|
|
+ raise HwsimSkip("check_cert_subject not supported with this TLS library: " + tls)
|
|
+
|
|
+ def check_altsubject_match_support(dev):
|
|
+ tls = dev.request("GET tls_library")
|
|
+- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"):
|
|
++ if tls.startswith("OpenSSL"):
|
|
++ return
|
|
++ elif tls.startswith("wolfSSL"):
|
|
++ return
|
|
++ elif tls.startswith("mbed TLS"):
|
|
++ return
|
|
++ else:
|
|
+ raise HwsimSkip("altsubject_match not supported with this TLS library: " + tls)
|
|
+
|
|
+ def check_domain_match(dev):
|
|
+@@ -70,7 +92,13 @@ def check_domain_suffix_match(dev):
|
|
+
|
|
+ def check_domain_match_full(dev):
|
|
+ tls = dev.request("GET tls_library")
|
|
+- if not tls.startswith("OpenSSL") and not tls.startswith("wolfSSL"):
|
|
++ if tls.startswith("OpenSSL"):
|
|
++ return
|
|
++ elif tls.startswith("wolfSSL"):
|
|
++ return
|
|
++ elif tls.startswith("mbed TLS"):
|
|
++ return
|
|
++ else:
|
|
+ raise HwsimSkip("domain_suffix_match requires full match with this TLS library: " + tls)
|
|
+
|
|
+ def check_cert_probe_support(dev):
|
|
+@@ -79,8 +107,15 @@ def check_cert_probe_support(dev):
|
|
+ raise HwsimSkip("Certificate probing not supported with this TLS library: " + tls)
|
|
+
|
|
+ def check_ext_cert_check_support(dev):
|
|
++ if not openssl_imported:
|
|
++ raise HwsimSkip("OpenSSL python method not available")
|
|
++
|
|
+ tls = dev.request("GET tls_library")
|
|
+- if not tls.startswith("OpenSSL"):
|
|
++ if tls.startswith("OpenSSL"):
|
|
++ return
|
|
++ elif tls.startswith("mbed TLS"):
|
|
++ return
|
|
++ else:
|
|
+ raise HwsimSkip("ext_cert_check not supported with this TLS library: " + tls)
|
|
+
|
|
+ def check_ocsp_support(dev):
|
|
+@@ -91,14 +126,18 @@ def check_ocsp_support(dev):
|
|
+ # raise HwsimSkip("OCSP not supported with this TLS library: " + tls)
|
|
+ #if tls.startswith("wolfSSL"):
|
|
+ # raise HwsimSkip("OCSP not supported with this TLS library: " + tls)
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ raise HwsimSkip("OCSP not supported with this TLS library: " + tls)
|
|
+
|
|
+ def check_pkcs5_v15_support(dev):
|
|
+ tls = dev.request("GET tls_library")
|
|
+- if "BoringSSL" in tls or "GnuTLS" in tls:
|
|
++ if "BoringSSL" in tls or "GnuTLS" in tls or "mbed TLS" in tls:
|
|
+ raise HwsimSkip("PKCS#5 v1.5 not supported with this TLS library: " + tls)
|
|
+
|
|
+ def check_tls13_support(dev):
|
|
+ tls = dev.request("GET tls_library")
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ raise HwsimSkip("TLS v1.3 not supported")
|
|
+ if "run=OpenSSL 1.1.1" not in tls and "run=OpenSSL 3.0" not in tls and "wolfSSL" not in tls:
|
|
+ raise HwsimSkip("TLS v1.3 not supported")
|
|
+
|
|
+@@ -118,11 +157,15 @@ def check_pkcs12_support(dev):
|
|
+ # raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls)
|
|
+ if tls.startswith("wolfSSL"):
|
|
+ raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls)
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ raise HwsimSkip("PKCS#12 not supported with this TLS library: " + tls)
|
|
+
|
|
+ def check_dh_dsa_support(dev):
|
|
+ tls = dev.request("GET tls_library")
|
|
+ if tls.startswith("internal"):
|
|
+ raise HwsimSkip("DH DSA not supported with this TLS library: " + tls)
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ raise HwsimSkip("DH DSA not supported with this TLS library: " + tls)
|
|
+
|
|
+ def check_ec_support(dev):
|
|
+ tls = dev.request("GET tls_library")
|
|
+@@ -1595,7 +1638,7 @@ def test_ap_wpa2_eap_ttls_pap_subject_ma
|
|
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
|
|
+ anonymous_identity="ttls", password="password",
|
|
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
|
|
+- subject_match="/C=FI/O=w1.fi/CN=server.w1.fi",
|
|
++ check_cert_subject="/C=FI/O=w1.fi/CN=server.w1.fi",
|
|
+ altsubject_match="EMAIL:noone@example.com;DNS:server.w1.fi;URI:http://example.com/")
|
|
+ eap_reauth(dev[0], "TTLS")
|
|
+
|
|
+@@ -2830,6 +2873,7 @@ def test_ap_wpa2_eap_tls_neg_domain_matc
|
|
+
|
|
+ def test_ap_wpa2_eap_tls_neg_subject_match(dev, apdev):
|
|
+ """WPA2-Enterprise negative test - subject mismatch"""
|
|
++ check_subject_match_support(dev[0])
|
|
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
|
|
+ hostapd.add_ap(apdev[0], params)
|
|
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
|
|
+@@ -2890,6 +2934,7 @@ def test_ap_wpa2_eap_tls_neg_subject_mat
|
|
+
|
|
+ def test_ap_wpa2_eap_tls_neg_altsubject_match(dev, apdev):
|
|
+ """WPA2-Enterprise negative test - altsubject mismatch"""
|
|
++ check_altsubject_match_support(dev[0])
|
|
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
|
|
+ hostapd.add_ap(apdev[0], params)
|
|
+
|
|
+@@ -3430,7 +3475,7 @@ def test_ap_wpa2_eap_ikev2_oom(dev, apde
|
|
+ dev[0].request("REMOVE_NETWORK all")
|
|
+
|
|
+ tls = dev[0].request("GET tls_library")
|
|
+- if not tls.startswith("wolfSSL"):
|
|
++ if not tls.startswith("wolfSSL") and not tls.startswith("mbed TLS"):
|
|
+ tests = [(1, "os_get_random;dh_init")]
|
|
+ else:
|
|
+ tests = [(1, "crypto_dh_init;dh_init")]
|
|
+@@ -4744,7 +4789,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca
|
|
+ params["private_key"] = "auth_serv/iCA-server/server.key"
|
|
+ hostapd.add_ap(apdev[0], params)
|
|
+ tls = dev[0].request("GET tls_library")
|
|
+- if "GnuTLS" in tls or "wolfSSL" in tls:
|
|
++ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
|
|
+ ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
|
|
+ client_cert = "auth_serv/iCA-user/user_and_ica.pem"
|
|
+ else:
|
|
+@@ -4810,6 +4855,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca
|
|
+ run_ap_wpa2_eap_tls_intermediate_ca_ocsp(dev, apdev, params, "-sha1")
|
|
+
|
|
+ def run_ap_wpa2_eap_tls_intermediate_ca_ocsp(dev, apdev, params, md):
|
|
++ check_ocsp_support(dev[0])
|
|
+ params = int_eap_server_params()
|
|
+ params["ca_cert"] = "auth_serv/iCA-server/ca-and-root.pem"
|
|
+ params["server_cert"] = "auth_serv/iCA-server/server.pem"
|
|
+@@ -4819,7 +4865,7 @@ def run_ap_wpa2_eap_tls_intermediate_ca_
|
|
+ try:
|
|
+ hostapd.add_ap(apdev[0], params)
|
|
+ tls = dev[0].request("GET tls_library")
|
|
+- if "GnuTLS" in tls or "wolfSSL" in tls:
|
|
++ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
|
|
+ ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
|
|
+ client_cert = "auth_serv/iCA-user/user_and_ica.pem"
|
|
+ else:
|
|
+@@ -4855,7 +4901,7 @@ def run_ap_wpa2_eap_tls_intermediate_ca_
|
|
+ try:
|
|
+ hostapd.add_ap(apdev[0], params)
|
|
+ tls = dev[0].request("GET tls_library")
|
|
+- if "GnuTLS" in tls or "wolfSSL" in tls:
|
|
++ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
|
|
+ ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
|
|
+ client_cert = "auth_serv/iCA-user/user_and_ica.pem"
|
|
+ else:
|
|
+@@ -4905,7 +4951,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca
|
|
+ try:
|
|
+ hostapd.add_ap(apdev[0], params)
|
|
+ tls = dev[0].request("GET tls_library")
|
|
+- if "GnuTLS" in tls or "wolfSSL" in tls:
|
|
++ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
|
|
+ ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
|
|
+ client_cert = "auth_serv/iCA-user/user_and_ica.pem"
|
|
+ else:
|
|
+@@ -4972,7 +5018,7 @@ def test_ap_wpa2_eap_tls_intermediate_ca
|
|
+
|
|
+ hostapd.add_ap(apdev[0], params)
|
|
+ tls = dev[0].request("GET tls_library")
|
|
+- if "GnuTLS" in tls or "wolfSSL" in tls:
|
|
++ if "GnuTLS" in tls or "wolfSSL" in tls or "mbed TLS" in tls:
|
|
+ ca_cert = "auth_serv/iCA-user/ca-and-root.pem"
|
|
+ client_cert = "auth_serv/iCA-user/user_and_ica.pem"
|
|
+ else:
|
|
+@@ -5230,6 +5276,7 @@ def test_ap_wpa2_eap_ttls_server_cert_ek
|
|
+
|
|
+ def test_ap_wpa2_eap_ttls_server_pkcs12(dev, apdev):
|
|
+ """WPA2-Enterprise using EAP-TTLS and server PKCS#12 file"""
|
|
++ check_pkcs12_support(dev[0])
|
|
+ skip_with_fips(dev[0])
|
|
+ params = int_eap_server_params()
|
|
+ del params["server_cert"]
|
|
+@@ -5242,6 +5289,7 @@ def test_ap_wpa2_eap_ttls_server_pkcs12(
|
|
+
|
|
+ def test_ap_wpa2_eap_ttls_server_pkcs12_extra(dev, apdev):
|
|
+ """EAP-TTLS and server PKCS#12 file with extra certs"""
|
|
++ check_pkcs12_support(dev[0])
|
|
+ skip_with_fips(dev[0])
|
|
+ params = int_eap_server_params()
|
|
+ del params["server_cert"]
|
|
+@@ -5264,6 +5312,7 @@ def test_ap_wpa2_eap_ttls_dh_params_serv
|
|
+
|
|
+ def test_ap_wpa2_eap_ttls_dh_params_dsa_server(dev, apdev):
|
|
+ """WPA2-Enterprise using EAP-TTLS and alternative server dhparams (DSA)"""
|
|
++ check_dh_dsa_support(dev[0])
|
|
+ params = int_eap_server_params()
|
|
+ params["dh_file"] = "auth_serv/dsaparam.pem"
|
|
+ hapd = hostapd.add_ap(apdev[0], params)
|
|
+@@ -5575,8 +5624,8 @@ def test_ap_wpa2_eap_non_ascii_identity2
|
|
+ def test_openssl_cipher_suite_config_wpas(dev, apdev):
|
|
+ """OpenSSL cipher suite configuration on wpa_supplicant"""
|
|
+ tls = dev[0].request("GET tls_library")
|
|
+- if not tls.startswith("OpenSSL"):
|
|
+- raise HwsimSkip("TLS library is not OpenSSL: " + tls)
|
|
++ if not tls.startswith("OpenSSL") and not tls.startswith("mbed TLS"):
|
|
++ raise HwsimSkip("TLS library is not OpenSSL or mbed TLS: " + tls)
|
|
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
|
|
+ hapd = hostapd.add_ap(apdev[0], params)
|
|
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
|
|
+@@ -5602,14 +5651,14 @@ def test_openssl_cipher_suite_config_wpa
|
|
+ def test_openssl_cipher_suite_config_hapd(dev, apdev):
|
|
+ """OpenSSL cipher suite configuration on hostapd"""
|
|
+ tls = dev[0].request("GET tls_library")
|
|
+- if not tls.startswith("OpenSSL"):
|
|
+- raise HwsimSkip("wpa_supplicant TLS library is not OpenSSL: " + tls)
|
|
++ if not tls.startswith("OpenSSL") and not tls.startswith("mbed TLS"):
|
|
++ raise HwsimSkip("wpa_supplicant TLS library is not OpenSSL or mbed TLS: " + tls)
|
|
+ params = int_eap_server_params()
|
|
+ params['openssl_ciphers'] = "AES256"
|
|
+ hapd = hostapd.add_ap(apdev[0], params)
|
|
+ tls = hapd.request("GET tls_library")
|
|
+- if not tls.startswith("OpenSSL"):
|
|
+- raise HwsimSkip("hostapd TLS library is not OpenSSL: " + tls)
|
|
++ if not tls.startswith("OpenSSL") and not tls.startswith("mbed TLS"):
|
|
++ raise HwsimSkip("hostapd TLS library is not OpenSSL or mbed TLS: " + tls)
|
|
+ eap_connect(dev[0], hapd, "TTLS", "pap user",
|
|
+ anonymous_identity="ttls", password="password",
|
|
+ ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
|
|
+@@ -6051,13 +6100,17 @@ def test_ap_wpa2_eap_tls_versions(dev, a
|
|
+ check_tls_ver(dev[0], hapd,
|
|
+ "tls_disable_tlsv1_0=1 tls_disable_tlsv1_1=1",
|
|
+ "TLSv1.2")
|
|
+- elif tls.startswith("internal"):
|
|
++ elif tls.startswith("internal") or tls.startswith("mbed TLS"):
|
|
+ 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_1=0 tls_disable_tlsv1_2=1", "TLSv1.1")
|
|
+- check_tls_ver(dev[2], hapd,
|
|
+- "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1")
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ check_tls_ver(dev[2], hapd,
|
|
++ "tls_disable_tlsv1_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1.0")
|
|
++ else:
|
|
++ check_tls_ver(dev[1], hapd,
|
|
++ "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_0=0 tls_disable_tlsv1_1=1 tls_disable_tlsv1_2=1", "TLSv1")
|
|
+ if "run=OpenSSL 1.1.1" in tls or "run=OpenSSL 3.0" 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")
|
|
+@@ -6079,6 +6132,11 @@ def test_ap_wpa2_eap_tls_versions_server
|
|
+ tests = [("TLSv1", "[ENABLE-TLSv1.0][DISABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"),
|
|
+ ("TLSv1.1", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"),
|
|
+ ("TLSv1.2", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][ENABLE-TLSv1.2][DISABLE-TLSv1.3]")]
|
|
++ tls = dev[0].request("GET tls_library")
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ tests = [#("TLSv1.0", "[ENABLE-TLSv1.0][DISABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"),
|
|
++ #("TLSv1.1", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][DISABLE-TLSv1.2][DISABLE-TLSv1.3]"),
|
|
++ ("TLSv1.2", "[ENABLE-TLSv1.0][ENABLE-TLSv1.1][ENABLE-TLSv1.2][DISABLE-TLSv1.3]")]
|
|
+ for exp, flags in tests:
|
|
+ hapd.disable()
|
|
+ hapd.set("tls_flags", flags)
|
|
+@@ -7115,6 +7173,7 @@ def test_ap_wpa2_eap_assoc_rsn(dev, apde
|
|
+ def test_eap_tls_ext_cert_check(dev, apdev):
|
|
+ """EAP-TLS and external server certification validation"""
|
|
+ # With internal server certificate chain validation
|
|
++ check_ext_cert_check_support(dev[0])
|
|
+ id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TLS",
|
|
+ identity="tls user",
|
|
+ ca_cert="auth_serv/ca.pem",
|
|
+@@ -7127,6 +7186,7 @@ def test_eap_tls_ext_cert_check(dev, apd
|
|
+ def test_eap_ttls_ext_cert_check(dev, apdev):
|
|
+ """EAP-TTLS and external server certification validation"""
|
|
+ # Without internal server certificate chain validation
|
|
++ check_ext_cert_check_support(dev[0])
|
|
+ id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
|
|
+ identity="pap user", anonymous_identity="ttls",
|
|
+ password="password", phase2="auth=PAP",
|
|
+@@ -7137,6 +7197,7 @@ def test_eap_ttls_ext_cert_check(dev, ap
|
|
+ def test_eap_peap_ext_cert_check(dev, apdev):
|
|
+ """EAP-PEAP and external server certification validation"""
|
|
+ # With internal server certificate chain validation
|
|
++ check_ext_cert_check_support(dev[0])
|
|
+ id = dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="PEAP",
|
|
+ identity="user", anonymous_identity="peap",
|
|
+ ca_cert="auth_serv/ca.pem",
|
|
+@@ -7147,6 +7208,7 @@ def test_eap_peap_ext_cert_check(dev, ap
|
|
+
|
|
+ def test_eap_fast_ext_cert_check(dev, apdev):
|
|
+ """EAP-FAST and external server certification validation"""
|
|
++ check_ext_cert_check_support(dev[0])
|
|
+ check_eap_capa(dev[0], "FAST")
|
|
+ # With internal server certificate chain validation
|
|
+ dev[0].request("SET blob fast_pac_auth_ext ")
|
|
+@@ -7161,10 +7223,6 @@ def test_eap_fast_ext_cert_check(dev, ap
|
|
+ run_ext_cert_check(dev, apdev, id)
|
|
+
|
|
+ def run_ext_cert_check(dev, apdev, net_id):
|
|
+- check_ext_cert_check_support(dev[0])
|
|
+- if not openssl_imported:
|
|
+- raise HwsimSkip("OpenSSL python method not available")
|
|
+-
|
|
+ params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
|
|
+ hapd = hostapd.add_ap(apdev[0], params)
|
|
+
|
|
+--- a/tests/hwsim/test_ap_ft.py
|
|
++++ b/tests/hwsim/test_ap_ft.py
|
|
+@@ -2471,11 +2471,11 @@ def test_ap_ft_ap_oom5(dev, apdev):
|
|
+ # This will fail to roam
|
|
+ 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"):
|
|
++ with fail_test(hapd1, 1, "sha256_prf;wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
|
|
+ # This will fail to roam
|
|
+ dev[0].roam(bssid1, check_bssid=False)
|
|
+
|
|
+- with fail_test(hapd1, 3, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
|
|
++ with fail_test(hapd1, 2, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
|
|
+ # This will fail to roam
|
|
+ dev[0].roam(bssid1, check_bssid=False)
|
|
+
|
|
+--- a/tests/hwsim/test_authsrv.py
|
|
++++ b/tests/hwsim/test_authsrv.py
|
|
+@@ -156,9 +156,12 @@ def test_authsrv_oom(dev, apdev):
|
|
+ if "FAIL" not in authsrv.request("ENABLE"):
|
|
+ raise Exception("ENABLE succeeded during OOM")
|
|
+
|
|
+- with alloc_fail(authsrv, 1, "tls_init;authsrv_init"):
|
|
+- if "FAIL" not in authsrv.request("ENABLE"):
|
|
+- raise Exception("ENABLE succeeded during OOM")
|
|
++ # tls_mbedtls.c:tls_init() does not alloc memory (no alloc fail trigger)
|
|
++ tls = dev[0].request("GET tls_library")
|
|
++ if not tls.startswith("mbed TLS"):
|
|
++ with alloc_fail(authsrv, 1, "tls_init;authsrv_init"):
|
|
++ if "FAIL" not in authsrv.request("ENABLE"):
|
|
++ raise Exception("ENABLE succeeded during OOM")
|
|
+
|
|
+ for count in range(1, 3):
|
|
+ with alloc_fail(authsrv, count, "eap_sim_db_init;authsrv_init"):
|
|
+--- a/tests/hwsim/test_dpp.py
|
|
++++ b/tests/hwsim/test_dpp.py
|
|
+@@ -39,7 +39,8 @@ def check_dpp_capab(dev, brainpool=False
|
|
+ raise HwsimSkip("DPP not supported")
|
|
+ if brainpool:
|
|
+ tls = dev.request("GET tls_library")
|
|
+- if (not tls.startswith("OpenSSL") or "run=BoringSSL" in tls) and not tls.startswith("wolfSSL"):
|
|
++ if (not tls.startswith("OpenSSL") or "run=BoringSSL" in tls) and not tls.startswith("wolfSSL") \
|
|
++ and not tls.startswith("mbed TLS"):
|
|
+ raise HwsimSkip("Crypto library does not support Brainpool curves: " + tls)
|
|
+ capa = dev.request("GET_CAPABILITY dpp")
|
|
+ ver = 1
|
|
+@@ -3892,6 +3893,9 @@ def test_dpp_proto_auth_req_no_i_proto_k
|
|
+
|
|
+ def test_dpp_proto_auth_req_invalid_i_proto_key(dev, apdev):
|
|
+ """DPP protocol testing - invalid I-proto key in Auth Req"""
|
|
++ tls = dev[0].request("GET tls_library")
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ raise HwsimSkip("mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key; no response")
|
|
+ run_dpp_proto_auth_req_missing(dev, 66, "Invalid Initiator Protocol Key")
|
|
+
|
|
+ def test_dpp_proto_auth_req_no_i_nonce(dev, apdev):
|
|
+@@ -3987,7 +3991,12 @@ def test_dpp_proto_auth_resp_no_r_proto_
|
|
+
|
|
+ def test_dpp_proto_auth_resp_invalid_r_proto_key(dev, apdev):
|
|
+ """DPP protocol testing - invalid R-Proto Key in Auth Resp"""
|
|
+- run_dpp_proto_auth_resp_missing(dev, 67, "Invalid Responder Protocol Key")
|
|
++ tls = dev[0].request("GET tls_library")
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ # mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key
|
|
++ run_dpp_proto_auth_resp_missing(dev, 67, "Failed to derive ECDH shared secret")
|
|
++ else:
|
|
++ run_dpp_proto_auth_resp_missing(dev, 67, "Invalid Responder Protocol Key")
|
|
+
|
|
+ def test_dpp_proto_auth_resp_no_r_nonce(dev, apdev):
|
|
+ """DPP protocol testing - no R-nonce in Auth Resp"""
|
|
+@@ -4349,11 +4358,17 @@ def test_dpp_proto_pkex_exchange_resp_in
|
|
+
|
|
+ def test_dpp_proto_pkex_cr_req_invalid_bootstrap_key(dev, apdev):
|
|
+ """DPP protocol testing - invalid Bootstrap Key in PKEX Commit-Reveal Request"""
|
|
++ tls = dev[0].request("GET tls_library")
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ raise HwsimSkip("mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key; no response")
|
|
+ run_dpp_proto_pkex_req_missing(dev, 47,
|
|
+ "Peer bootstrapping key is invalid")
|
|
+
|
|
+ def test_dpp_proto_pkex_cr_resp_invalid_bootstrap_key(dev, apdev):
|
|
+ """DPP protocol testing - invalid Bootstrap Key in PKEX Commit-Reveal Response"""
|
|
++ tls = dev[0].request("GET tls_library")
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ raise HwsimSkip("mbed TLS crypto_ecdh_set_peerkey() properly detects invalid key; no response")
|
|
+ run_dpp_proto_pkex_resp_missing(dev, 48,
|
|
+ "Peer bootstrapping key is invalid")
|
|
+
|
|
+--- a/tests/hwsim/test_erp.py
|
|
++++ b/tests/hwsim/test_erp.py
|
|
+@@ -12,7 +12,7 @@ import time
|
|
+
|
|
+ import hostapd
|
|
+ from utils import *
|
|
+-from test_ap_eap import int_eap_server_params, check_tls13_support
|
|
++from test_ap_eap import int_eap_server_params, check_tls13_support, check_eap_capa
|
|
+ from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
|
|
+
|
|
+ def test_erp_initiate_reauth_start(dev, apdev):
|
|
+@@ -276,6 +276,7 @@ def test_erp_radius_eap_methods(dev, apd
|
|
+ params['erp_domain'] = 'example.com'
|
|
+ params['disable_pmksa_caching'] = '1'
|
|
+ hapd = hostapd.add_ap(apdev[0], params)
|
|
++ tls = dev[0].request("GET tls_library")
|
|
+
|
|
+ erp_test(dev[0], hapd, eap="AKA", identity="0232010000000000@example.com",
|
|
+ password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581:000000000123")
|
|
+@@ -289,7 +290,7 @@ def test_erp_radius_eap_methods(dev, apd
|
|
+ password="5122250214c33e723a5dd523fc145fc0:981d464c7c52eb6e5036234984ad0bcf:000000000123")
|
|
+ erp_test(dev[0], hapd, eap="EKE", identity="erp-eke@example.com",
|
|
+ password="hello")
|
|
+- if "FAST" in eap_methods:
|
|
++ if "FAST" in eap_methods and check_eap_capa(dev[0], "FAST"):
|
|
+ erp_test(dev[0], hapd, eap="FAST", identity="erp-fast@example.com",
|
|
+ password="password", ca_cert="auth_serv/ca.pem",
|
|
+ phase2="auth=GTC",
|
|
+@@ -301,13 +302,14 @@ def test_erp_radius_eap_methods(dev, apd
|
|
+ password="password")
|
|
+ erp_test(dev[0], hapd, eap="PAX", identity="erp-pax@example.com",
|
|
+ password_hex="0123456789abcdef0123456789abcdef")
|
|
+- if "MSCHAPV2" in eap_methods:
|
|
++ if "MSCHAPV2" in eap_methods and check_eap_capa(dev[0], "MSCHAPV2"):
|
|
+ erp_test(dev[0], hapd, eap="PEAP", identity="erp-peap@example.com",
|
|
+ password="password", ca_cert="auth_serv/ca.pem",
|
|
+ phase2="auth=MSCHAPV2")
|
|
+- erp_test(dev[0], hapd, eap="TEAP", identity="erp-teap@example.com",
|
|
+- password="password", ca_cert="auth_serv/ca.pem",
|
|
+- phase2="auth=MSCHAPV2", pac_file="blob://teap_pac")
|
|
++ if check_eap_capa(dev[0], "TEAP"):
|
|
++ erp_test(dev[0], hapd, eap="TEAP", identity="erp-teap@example.com",
|
|
++ password="password", ca_cert="auth_serv/ca.pem",
|
|
++ phase2="auth=MSCHAPV2", pac_file="blob://teap_pac")
|
|
+ erp_test(dev[0], hapd, eap="PSK", identity="erp-psk@example.com",
|
|
+ password_hex="0123456789abcdef0123456789abcdef")
|
|
+ if "PWD" in eap_methods:
|
|
+@@ -640,7 +642,7 @@ def test_erp_local_errors(dev, apdev):
|
|
+ dev[0].request("REMOVE_NETWORK all")
|
|
+ dev[0].wait_disconnected()
|
|
+
|
|
+- for count in range(1, 6):
|
|
++ for count in range(1, 4):
|
|
+ dev[0].request("ERP_FLUSH")
|
|
+ with fail_test(dev[0], count, "hmac_sha256_kdf;eap_peer_erp_init"):
|
|
+ dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
|
|
+--- a/tests/hwsim/test_fils.py
|
|
++++ b/tests/hwsim/test_fils.py
|
|
+@@ -1422,7 +1422,10 @@ def run_fils_sk_pfs(dev, apdev, group, p
|
|
+ check_erp_capa(dev[0])
|
|
+
|
|
+ tls = dev[0].request("GET tls_library")
|
|
+- if not tls.startswith("wolfSSL"):
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ if int(group) == 27:
|
|
++ raise HwsimSkip("Brainpool EC group 27 not supported by mbed TLS")
|
|
++ elif not tls.startswith("wolfSSL"):
|
|
+ if int(group) in [25]:
|
|
+ if not (tls.startswith("OpenSSL") and ("build=OpenSSL 1.0.2" in tls or "build=OpenSSL 1.1" in tls or "build=OpenSSL 3.0" in tls) and ("run=OpenSSL 1.0.2" in tls or "run=OpenSSL 1.1" in tls or "run=OpenSSL 3.0" in tls)):
|
|
+ raise HwsimSkip("EC group not supported")
|
|
+--- a/tests/hwsim/test_pmksa_cache.py
|
|
++++ b/tests/hwsim/test_pmksa_cache.py
|
|
+@@ -955,7 +955,7 @@ def test_pmksa_cache_preauth_wpas_oom(de
|
|
+ eap_connect(dev[0], hapd, "PAX", "pax.user@example.com",
|
|
+ password_hex="0123456789abcdef0123456789abcdef",
|
|
+ bssid=apdev[0]['bssid'])
|
|
+- for i in range(1, 11):
|
|
++ for i in range(1, 10):
|
|
+ with alloc_fail(dev[0], i, "rsn_preauth_init"):
|
|
+ res = dev[0].request("PREAUTH f2:11:22:33:44:55").strip()
|
|
+ logger.info("Iteration %d - PREAUTH command results: %s" % (i, res))
|
|
+@@ -963,7 +963,7 @@ def test_pmksa_cache_preauth_wpas_oom(de
|
|
+ state = dev[0].request('GET_ALLOC_FAIL')
|
|
+ if state.startswith('0:'):
|
|
+ break
|
|
+- time.sleep(0.05)
|
|
++ time.sleep(0.10)
|
|
+
|
|
+ def test_pmksa_cache_ctrl(dev, apdev):
|
|
+ """PMKSA cache control interface operations"""
|
|
+--- a/tests/hwsim/test_sae.py
|
|
++++ b/tests/hwsim/test_sae.py
|
|
+@@ -177,6 +177,11 @@ def test_sae_groups(dev, apdev):
|
|
+ if tls.startswith("OpenSSL") and "run=OpenSSL 1." in tls:
|
|
+ logger.info("Add Brainpool EC groups since OpenSSL is new enough")
|
|
+ sae_groups += [27, 28, 29, 30]
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ # secp224k1 and secp224r1 (26) have prime p = 1 mod 4, and mbedtls
|
|
++ # does not have code to derive y from compressed format for those curves
|
|
++ sae_groups = [19, 25, 20, 21, 1, 2, 5, 14, 15, 16, 22, 23, 24]
|
|
++ sae_groups += [27, 28, 29, 30]
|
|
+ heavy_groups = [14, 15, 16]
|
|
+ suitable_groups = [15, 16, 17, 18, 19, 20, 21]
|
|
+ groups = [str(g) for g in sae_groups]
|
|
+@@ -2188,6 +2193,8 @@ def run_sae_pwe_group(dev, apdev, group)
|
|
+ logger.info("Add Brainpool EC groups since OpenSSL is new enough")
|
|
+ elif tls.startswith("wolfSSL"):
|
|
+ logger.info("Make sure Brainpool EC groups were enabled when compiling wolfSSL")
|
|
++ elif tls.startswith("mbed TLS"):
|
|
++ logger.info("Make sure Brainpool EC groups were enabled when compiling mbed TLS")
|
|
+ else:
|
|
+ raise HwsimSkip("Brainpool curve not supported")
|
|
+ start_sae_pwe_ap(apdev[0], group, 2)
|
|
+--- a/tests/hwsim/test_suite_b.py
|
|
++++ b/tests/hwsim/test_suite_b.py
|
|
+@@ -27,6 +27,8 @@ def check_suite_b_tls_lib(dev, dhe=False
|
|
+ return
|
|
+ if tls.startswith("wolfSSL"):
|
|
+ return
|
|
++ if tls.startswith("mbed TLS"):
|
|
++ return
|
|
+ if not tls.startswith("OpenSSL"):
|
|
+ raise HwsimSkip("TLS library not supported for Suite B: " + tls)
|
|
+ supported = False
|
|
+@@ -520,6 +522,7 @@ def test_suite_b_192_rsa_insufficient_dh
|
|
+
|
|
+ dev[0].connect("test-suite-b", key_mgmt="WPA-EAP-SUITE-B-192",
|
|
+ ieee80211w="2",
|
|
++ openssl_ciphers="DHE-RSA-AES256-GCM-SHA384",
|
|
+ phase1="tls_suiteb=1",
|
|
+ eap="TLS", identity="tls user",
|
|
+ ca_cert="auth_serv/rsa3072-ca.pem",
|
|
+--- a/tests/hwsim/test_wpas_ctrl.py
|
|
++++ b/tests/hwsim/test_wpas_ctrl.py
|
|
+@@ -1842,7 +1842,7 @@ def _test_wpas_ctrl_oom(dev):
|
|
+ tls = dev[0].request("GET tls_library")
|
|
+ if not tls.startswith("internal"):
|
|
+ tests.append(('NFC_GET_HANDOVER_SEL NDEF P2P-CR-TAG', 'FAIL',
|
|
+- 4, 'wpas_ctrl_nfc_get_handover_sel_p2p'))
|
|
++ 3, 'wpas_ctrl_nfc_get_handover_sel_p2p'))
|
|
+ for cmd, exp, count, func in tests:
|
|
+ with alloc_fail(dev[0], count, func):
|
|
+ res = dev[0].request(cmd)
|
|
+--- a/tests/hwsim/utils.py
|
|
++++ b/tests/hwsim/utils.py
|
|
+@@ -141,7 +141,13 @@ def check_imsi_privacy_support(dev):
|
|
+
|
|
+ def check_tls_tod(dev):
|
|
+ tls = dev.request("GET tls_library")
|
|
+- if not tls.startswith("OpenSSL") and not tls.startswith("internal"):
|
|
++ if tls.startswith("OpenSSL"):
|
|
++ return
|
|
++ elif tls.startswith("internal"):
|
|
++ return
|
|
++ elif tls.startswith("mbed TLS"):
|
|
++ return
|
|
++ else:
|
|
+ raise HwsimSkip("TLS TOD-TOFU/STRICT not supported with this TLS library: " + tls)
|
|
+
|
|
+ def vht_supported():
|
|
+--- /dev/null
|
|
++++ b/tests/test-crypto_module.c
|
|
+@@ -0,0 +1,16 @@
|
|
++/*
|
|
++ * crypto module tests - test program
|
|
++ * Copyright (c) 2022, Glenn Strauss <gstrauss@gluelogic.com>
|
|
++ *
|
|
++ * This software may be distributed under the terms of the BSD license.
|
|
++ * See README for more details.
|
|
++ */
|
|
++
|
|
++#include "utils/includes.h"
|
|
++#include "utils/module_tests.h"
|
|
++#include "crypto/crypto_module_tests.c"
|
|
++
|
|
++int main(int argc, char *argv[])
|
|
++{
|
|
++ return crypto_module_tests();
|
|
++}
|
|
+--- a/tests/test-https.c
|
|
++++ b/tests/test-https.c
|
|
+@@ -75,7 +75,7 @@ static int https_client(int s, const cha
|
|
+ struct tls_connection *conn;
|
|
+ struct wpabuf *in, *out, *appl;
|
|
+ int res = -1;
|
|
+- int need_more_data;
|
|
++ int need_more_data = 0;
|
|
+
|
|
+ os_memset(&conf, 0, sizeof(conf));
|
|
+ conf.event_cb = https_tls_event_cb;
|
|
+@@ -93,8 +93,12 @@ static int https_client(int s, const cha
|
|
+
|
|
+ for (;;) {
|
|
+ appl = NULL;
|
|
++#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
+ out = tls_connection_handshake2(tls, conn, in, &appl,
|
|
+ &need_more_data);
|
|
++#else
|
|
++ out = tls_connection_handshake(tls, conn, in, &appl);
|
|
++#endif
|
|
+ wpabuf_free(in);
|
|
+ in = NULL;
|
|
+ if (out == NULL) {
|
|
+@@ -152,11 +156,15 @@ static int https_client(int s, const cha
|
|
+
|
|
+ wpa_printf(MSG_INFO, "Reading HTTP response");
|
|
+ for (;;) {
|
|
+- int need_more_data;
|
|
++ int need_more_data = 0;
|
|
+ in = https_recv(s);
|
|
+ if (in == NULL)
|
|
+ goto done;
|
|
++#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
+ out = tls_connection_decrypt2(tls, conn, in, &need_more_data);
|
|
++#else
|
|
++ out = tls_connection_decrypt(tls, conn, in);
|
|
++#endif
|
|
+ if (need_more_data)
|
|
+ wpa_printf(MSG_DEBUG, "HTTP: Need more data");
|
|
+ wpabuf_free(in);
|
|
+--- a/tests/test-https_server.c
|
|
++++ b/tests/test-https_server.c
|
|
+@@ -67,10 +67,12 @@ static struct wpabuf * https_recv(int s,
|
|
+ }
|
|
+
|
|
+
|
|
++#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
+ static void https_tls_log_cb(void *ctx, const char *msg)
|
|
+ {
|
|
+ wpa_printf(MSG_DEBUG, "TLS: %s", msg);
|
|
+ }
|
|
++#endif
|
|
+
|
|
+
|
|
+ static int https_server(int s)
|
|
+@@ -79,7 +81,7 @@ static int https_server(int s)
|
|
+ void *tls;
|
|
+ struct tls_connection_params params;
|
|
+ struct tls_connection *conn;
|
|
+- struct wpabuf *in, *out, *appl;
|
|
++ struct wpabuf *in = NULL, *out = NULL, *appl = NULL;
|
|
+ int res = -1;
|
|
+
|
|
+ os_memset(&conf, 0, sizeof(conf));
|
|
+@@ -106,7 +108,9 @@ static int https_server(int s)
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
++#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
+ tls_connection_set_log_cb(conn, https_tls_log_cb, NULL);
|
|
++#endif
|
|
+
|
|
+ for (;;) {
|
|
+ in = https_recv(s, 5000);
|
|
+@@ -147,12 +151,16 @@ static int https_server(int s)
|
|
+
|
|
+ wpa_printf(MSG_INFO, "Reading HTTP request");
|
|
+ for (;;) {
|
|
+- int need_more_data;
|
|
++ int need_more_data = 0;
|
|
+
|
|
+ in = https_recv(s, 5000);
|
|
+ if (!in)
|
|
+ goto done;
|
|
++#ifdef CONFIG_TLS_INTERNAL_SERVER
|
|
+ out = tls_connection_decrypt2(tls, conn, in, &need_more_data);
|
|
++#else
|
|
++ out = tls_connection_decrypt(tls, conn, in);
|
|
++#endif
|
|
+ wpabuf_free(in);
|
|
+ in = NULL;
|
|
+ if (need_more_data) {
|
|
+--- a/wpa_supplicant/Makefile
|
|
++++ b/wpa_supplicant/Makefile
|
|
+@@ -1122,6 +1122,7 @@ CFLAGS += -DCONFIG_TLSV12
|
|
+ endif
|
|
+
|
|
+ ifeq ($(CONFIG_TLS), wolfssl)
|
|
++CFLAGS += -DCONFIG_TLS_WOLFSSL
|
|
+ ifdef TLS_FUNCS
|
|
+ CFLAGS += -DWOLFSSL_DER_LOAD
|
|
+ OBJS += ../src/crypto/tls_wolfssl.o
|
|
+@@ -1137,6 +1138,7 @@ LIBS_p += -lwolfssl -lm
|
|
+ endif
|
|
+
|
|
+ ifeq ($(CONFIG_TLS), openssl)
|
|
++CFLAGS += -DCONFIG_TLS_OPENSSL
|
|
+ CFLAGS += -DCRYPTO_RSA_OAEP_SHA256
|
|
+ ifdef TLS_FUNCS
|
|
+ CFLAGS += -DEAP_TLS_OPENSSL
|
|
+@@ -1164,6 +1166,7 @@ CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONF
|
|
+ endif
|
|
+
|
|
+ ifeq ($(CONFIG_TLS), mbedtls)
|
|
++CFLAGS += -DCONFIG_TLS_MBEDTLS
|
|
+ ifndef CONFIG_CRYPTO
|
|
+ CONFIG_CRYPTO=mbedtls
|
|
+ endif
|
|
+@@ -1183,6 +1186,7 @@ endif
|
|
+ endif
|
|
+
|
|
+ ifeq ($(CONFIG_TLS), gnutls)
|
|
++CFLAGS += -DCONFIG_TLS_GNUTLS
|
|
+ ifndef CONFIG_CRYPTO
|
|
+ # default to libgcrypt
|
|
+ CONFIG_CRYPTO=gnutls
|
|
+@@ -1213,6 +1217,7 @@ endif
|
|
+ endif
|
|
+
|
|
+ ifeq ($(CONFIG_TLS), internal)
|
|
++CFLAGS += -DCONFIG_TLS_INTERNAL
|
|
+ ifndef CONFIG_CRYPTO
|
|
+ CONFIG_CRYPTO=internal
|
|
+ endif
|
|
+@@ -1293,6 +1298,7 @@ endif
|
|
+ endif
|
|
+
|
|
+ ifeq ($(CONFIG_TLS), linux)
|
|
++CFLAGS += -DCONFIG_TLS_INTERNAL
|
|
+ OBJS += ../src/crypto/crypto_linux.o
|
|
+ OBJS_p += ../src/crypto/crypto_linux.o
|
|
+ ifdef TLS_FUNCS
|
|
diff --git a/package/network/services/hostapd/patches/150-add-NULL-checks-encountered-during-tests-hwsim.patch b/package/network/services/hostapd/patches/150-add-NULL-checks-encountered-during-tests-hwsim.patch
|
|
new file mode 100644
|
|
index 0000000000..c8c3ff33f4
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/150-add-NULL-checks-encountered-during-tests-hwsim.patch
|
|
@@ -0,0 +1,45 @@
|
|
+From 33afce36c54b0cad38643629ded10ff5d727f077 Mon Sep 17 00:00:00 2001
|
|
+From: Glenn Strauss <gstrauss@gluelogic.com>
|
|
+Date: Fri, 12 Aug 2022 05:34:47 -0400
|
|
+Subject: [PATCH 5/7] add NULL checks (encountered during tests/hwsim)
|
|
+
|
|
+sae_derive_commit_element_ecc NULL pwe_ecc check
|
|
+dpp_gen_keypair() NULL curve check
|
|
+
|
|
+Signed-off-by: Glenn Strauss <gstrauss@gluelogic.com>
|
|
+---
|
|
+ src/common/dpp_crypto.c | 6 ++++++
|
|
+ src/common/sae.c | 7 +++++++
|
|
+ 2 files changed, 13 insertions(+)
|
|
+
|
|
+--- a/src/common/dpp_crypto.c
|
|
++++ b/src/common/dpp_crypto.c
|
|
+@@ -269,6 +269,12 @@ int dpp_get_pubkey_hash(struct crypto_ec
|
|
+
|
|
+ struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve)
|
|
+ {
|
|
++ if (curve == NULL) {
|
|
++ wpa_printf(MSG_DEBUG,
|
|
++ "DPP: %s curve must be initialized", __func__);
|
|
++ return NULL;
|
|
++ }
|
|
++
|
|
+ struct crypto_ec_key *key;
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "DPP: Generating a keypair");
|
|
+--- a/src/common/sae.c
|
|
++++ b/src/common/sae.c
|
|
+@@ -1278,6 +1278,13 @@ void sae_deinit_pt(struct sae_pt *pt)
|
|
+ static int sae_derive_commit_element_ecc(struct sae_data *sae,
|
|
+ struct crypto_bignum *mask)
|
|
+ {
|
|
++ if (sae->tmp->pwe_ecc == NULL) {
|
|
++ wpa_printf(MSG_DEBUG,
|
|
++ "SAE: %s sae->tmp->pwe_ecc must be initialized",
|
|
++ __func__);
|
|
++ return -1;
|
|
++ }
|
|
++
|
|
+ /* COMMIT-ELEMENT = inverse(scalar-op(mask, PWE)) */
|
|
+ if (!sae->tmp->own_commit_element_ecc) {
|
|
+ sae->tmp->own_commit_element_ecc =
|
|
diff --git a/package/network/services/hostapd/patches/160-dpp_pkex-EC-point-mul-w-value-prime.patch b/package/network/services/hostapd/patches/160-dpp_pkex-EC-point-mul-w-value-prime.patch
|
|
new file mode 100644
|
|
index 0000000000..db4fcfe235
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/160-dpp_pkex-EC-point-mul-w-value-prime.patch
|
|
@@ -0,0 +1,26 @@
|
|
+From 54211caa2e0e5163aefef390daf88a971367a702 Mon Sep 17 00:00:00 2001
|
|
+From: Glenn Strauss <gstrauss@gluelogic.com>
|
|
+Date: Tue, 4 Oct 2022 17:09:24 -0400
|
|
+Subject: [PATCH 6/7] dpp_pkex: EC point mul w/ value < prime
|
|
+
|
|
+crypto_ec_point_mul() with mbedtls requires point
|
|
+be multiplied by a multiplicand with value < prime
|
|
+
|
|
+Signed-off-by: Glenn Strauss <gstrauss@gluelogic.com>
|
|
+---
|
|
+ src/common/dpp_crypto.c | 4 +++-
|
|
+ 1 file changed, 3 insertions(+), 1 deletion(-)
|
|
+
|
|
+--- a/src/common/dpp_crypto.c
|
|
++++ b/src/common/dpp_crypto.c
|
|
+@@ -1588,7 +1588,9 @@ dpp_pkex_derive_Qr(const struct dpp_curv
|
|
+ Pr = crypto_ec_key_get_public_key(Pr_key);
|
|
+ Qr = crypto_ec_point_init(ec);
|
|
+ hash_bn = crypto_bignum_init_set(hash, curve->hash_len);
|
|
+- if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
|
|
++ if (!Pr || !Qr || !hash_bn ||
|
|
++ crypto_bignum_mod(hash_bn, crypto_ec_get_prime(ec), hash_bn) ||
|
|
++ crypto_ec_point_mul(ec, Pr, hash_bn, Qr))
|
|
+ goto fail;
|
|
+
|
|
+ if (crypto_ec_point_is_at_infinity(ec, Qr)) {
|
|
diff --git a/package/network/services/hostapd/patches/170-hostapd-update-cfs0-and-cfs1-for-160MHz.patch b/package/network/services/hostapd/patches/170-hostapd-update-cfs0-and-cfs1-for-160MHz.patch
|
|
new file mode 100644
|
|
index 0000000000..710a3c851e
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/170-hostapd-update-cfs0-and-cfs1-for-160MHz.patch
|
|
@@ -0,0 +1,141 @@
|
|
+From d4c4ef302f98fd6bce173b8636e7e350d8b44981 Mon Sep 17 00:00:00 2001
|
|
+From: P Praneesh <ppranees@codeaurora.org>
|
|
+Date: Fri, 19 Mar 2021 12:17:27 +0530
|
|
+Subject: [PATCH] hostapd: update cfs0 and cfs1 for 160MHz
|
|
+
|
|
+As per standard Draft P802.11ax_D8.0,( Table 26-9—Setting
|
|
+of the VHT Channel Width and VHT NSS at an HE STA
|
|
+transmitting the OM Control subfield ), center frequency of
|
|
+160MHz should be published in HT information subset 2 of
|
|
+HT information when EXT NSS BW field is enabled.
|
|
+
|
|
+If the supported number of NSS in 160MHz is at least max NSS
|
|
+support, then center_freq_seg0 indicates the center frequency of 80MHz and
|
|
+center_freq_seg1 indicates the center frequency of 160MHz.
|
|
+
|
|
+If the supported number of NSS in 160MHz is less than max NSS
|
|
+support, then center_freq_seg0 indicates the center frequency of 80MHz and
|
|
+center_freq_seg1 is 0. The center frequency of 160MHz is published in HT
|
|
+operation information element instead.
|
|
+
|
|
+Signed-off-by: P Praneesh <ppranees@codeaurora.org>
|
|
+---
|
|
+ hostapd/config_file.c | 2 ++
|
|
+ src/ap/ieee802_11_ht.c | 7 +++++++
|
|
+ src/ap/ieee802_11_vht.c | 16 ++++++++++++++++
|
|
+ src/common/hw_features_common.c | 1 +
|
|
+ src/common/ieee802_11_defs.h | 1 +
|
|
+ 5 files changed, 27 insertions(+)
|
|
+
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -1153,6 +1153,8 @@ static int hostapd_config_vht_capab(stru
|
|
+ conf->vht_capab |= VHT_CAP_RX_ANTENNA_PATTERN;
|
|
+ if (os_strstr(capab, "[TX-ANTENNA-PATTERN]"))
|
|
+ conf->vht_capab |= VHT_CAP_TX_ANTENNA_PATTERN;
|
|
++ if (os_strstr(capab, "[EXT-NSS-BW-SUPP]"))
|
|
++ conf->vht_capab |= VHT_CAP_EXTENDED_NSS_BW_SUPPORT;
|
|
+ return 0;
|
|
+ }
|
|
+ #endif /* CONFIG_IEEE80211AC */
|
|
+--- a/src/ap/ieee802_11_ht.c
|
|
++++ b/src/ap/ieee802_11_ht.c
|
|
+@@ -82,7 +82,9 @@ u8 * hostapd_eid_ht_capabilities(struct
|
|
+ u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid)
|
|
+ {
|
|
+ struct ieee80211_ht_operation *oper;
|
|
++ le32 vht_capabilities_info;
|
|
+ u8 *pos = eid;
|
|
++ u8 chwidth;
|
|
+
|
|
+ if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n ||
|
|
+ is_6ghz_op_class(hapd->iconf->op_class))
|
|
+@@ -103,6 +105,13 @@ u8 * hostapd_eid_ht_operation(struct hos
|
|
+ oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW |
|
|
+ HT_INFO_HT_PARAM_STA_CHNL_WIDTH;
|
|
+
|
|
++ vht_capabilities_info = host_to_le32(hapd->iface->current_mode->vht_capab);
|
|
++ chwidth = hostapd_get_oper_chwidth(hapd->iconf);
|
|
++ if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT
|
|
++ && ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) {
|
|
++ oper->operation_mode = host_to_le16(hapd->iconf->vht_oper_centr_freq_seg0_idx << 5);
|
|
++ }
|
|
++
|
|
+ pos += sizeof(*oper);
|
|
+
|
|
+ return pos;
|
|
+--- a/src/ap/ieee802_11_vht.c
|
|
++++ b/src/ap/ieee802_11_vht.c
|
|
+@@ -25,6 +25,7 @@ u8 * hostapd_eid_vht_capabilities(struct
|
|
+ struct ieee80211_vht_capabilities *cap;
|
|
+ struct hostapd_hw_modes *mode = hapd->iface->current_mode;
|
|
+ u8 *pos = eid;
|
|
++ u8 chwidth;
|
|
+
|
|
+ if (!mode || is_6ghz_op_class(hapd->iconf->op_class))
|
|
+ return eid;
|
|
+@@ -62,6 +63,17 @@ u8 * hostapd_eid_vht_capabilities(struct
|
|
+ host_to_le32(nsts << VHT_CAP_BEAMFORMEE_STS_OFFSET);
|
|
+ }
|
|
+
|
|
++ chwidth = hostapd_get_oper_chwidth(hapd->iconf);
|
|
++ if (((host_to_le32(mode->vht_capab)) & VHT_CAP_EXTENDED_NSS_BW_SUPPORT)
|
|
++ && ((chwidth == CHANWIDTH_160MHZ) || (chwidth == CHANWIDTH_80P80MHZ))) {
|
|
++ cap->vht_capabilities_info |= VHT_CAP_EXTENDED_NSS_BW_SUPPORT;
|
|
++ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ));
|
|
++ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_160MHZ));
|
|
++ cap->vht_capabilities_info &= ~(host_to_le32(VHT_CAP_SUPP_CHAN_WIDTH_MASK));
|
|
++ } else {
|
|
++ cap->vht_capabilities_info &= ~VHT_CAP_EXTENDED_NSS_BW_SUPPORT_MASK;
|
|
++ }
|
|
++
|
|
+ /* Supported MCS set comes from hw */
|
|
+ os_memcpy(&cap->vht_supported_mcs_set, mode->vht_mcs_set, 8);
|
|
+
|
|
+@@ -74,6 +86,7 @@ u8 * hostapd_eid_vht_capabilities(struct
|
|
+ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
|
|
+ {
|
|
+ struct ieee80211_vht_operation *oper;
|
|
++ le32 vht_capabilities_info;
|
|
+ u8 *pos = eid;
|
|
+ enum oper_chan_width oper_chwidth =
|
|
+ hostapd_get_oper_chwidth(hapd->iconf);
|
|
+@@ -106,6 +119,7 @@ u8 * hostapd_eid_vht_operation(struct ho
|
|
+ oper->vht_op_info_chan_center_freq_seg1_idx = seg1;
|
|
+
|
|
+ oper->vht_op_info_chwidth = oper_chwidth;
|
|
++ vht_capabilities_info = host_to_le32(hapd->iface->current_mode->vht_capab);
|
|
+ if (oper_chwidth == CONF_OPER_CHWIDTH_160MHZ) {
|
|
+ /*
|
|
+ * Convert 160 MHz channel width to new style as interop
|
|
+@@ -119,6 +133,9 @@ u8 * hostapd_eid_vht_operation(struct ho
|
|
+ oper->vht_op_info_chan_center_freq_seg0_idx -= 8;
|
|
+ else
|
|
+ oper->vht_op_info_chan_center_freq_seg0_idx += 8;
|
|
++
|
|
++ if (vht_capabilities_info & VHT_CAP_EXTENDED_NSS_BW_SUPPORT)
|
|
++ oper->vht_op_info_chan_center_freq_seg1_idx = 0;
|
|
+ } else if (oper_chwidth == CONF_OPER_CHWIDTH_80P80MHZ) {
|
|
+ /*
|
|
+ * Convert 80+80 MHz channel width to new style as interop
|
|
+--- a/src/common/hw_features_common.c
|
|
++++ b/src/common/hw_features_common.c
|
|
+@@ -808,6 +808,7 @@ int ieee80211ac_cap_check(u32 hw, u32 co
|
|
+ VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB);
|
|
+ VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN);
|
|
+ VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN);
|
|
++ VHT_CAP_CHECK(VHT_CAP_EXTENDED_NSS_BW_SUPPORT);
|
|
+
|
|
+ #undef VHT_CAP_CHECK
|
|
+ #undef VHT_CAP_CHECK_MAX
|
|
+--- a/src/common/ieee802_11_defs.h
|
|
++++ b/src/common/ieee802_11_defs.h
|
|
+@@ -1348,6 +1348,8 @@ struct ieee80211_ampe_ie {
|
|
+ #define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB ((u32) BIT(26) | BIT(27))
|
|
+ #define VHT_CAP_RX_ANTENNA_PATTERN ((u32) BIT(28))
|
|
+ #define VHT_CAP_TX_ANTENNA_PATTERN ((u32) BIT(29))
|
|
++#define VHT_CAP_EXTENDED_NSS_BW_SUPPORT ((u32) BIT(30))
|
|
++#define VHT_CAP_EXTENDED_NSS_BW_SUPPORT_MASK ((u32) BIT(30) | BIT(31))
|
|
+
|
|
+ #define VHT_OPMODE_CHANNEL_WIDTH_MASK ((u8) BIT(0) | BIT(1))
|
|
+ #define VHT_OPMODE_CHANNEL_RxNSS_MASK ((u8) BIT(4) | BIT(5) | \
|
|
diff --git a/package/network/services/hostapd/patches/180-BSS-coloring-fix-CCA-with-multiple-BSS.patch b/package/network/services/hostapd/patches/180-BSS-coloring-fix-CCA-with-multiple-BSS.patch
|
|
new file mode 100644
|
|
index 0000000000..7b0435a453
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/180-BSS-coloring-fix-CCA-with-multiple-BSS.patch
|
|
@@ -0,0 +1,103 @@
|
|
+From: Felix Fietkau <nbd@nbd.name>
|
|
+Date: Mon, 7 Aug 2023 21:55:57 +0200
|
|
+Subject: [PATCH] BSS coloring: fix CCA with multiple BSS
|
|
+
|
|
+Pass bss->ctx instead of drv->ctx in order to avoid multiple reports for
|
|
+the first bss. The first report would otherwise clear hapd->cca_color and
|
|
+subsequent reports would cause the iface bss color to be set to 0.
|
|
+In order to avoid any issues with cancellations, only overwrite the color
|
|
+based on hapd->cca_color if it was actually set.
|
|
+
|
|
+Fixes: 33c4dd26cd11 ("BSS coloring: Handle the collision and CCA events coming from the kernel")
|
|
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
+---
|
|
+
|
|
+--- a/src/ap/drv_callbacks.c
|
|
++++ b/src/ap/drv_callbacks.c
|
|
+@@ -2260,7 +2260,8 @@ void wpa_supplicant_event(void *ctx, enu
|
|
+ case EVENT_CCA_NOTIFY:
|
|
+ wpa_printf(MSG_DEBUG, "CCA finished on on %s",
|
|
+ hapd->conf->iface);
|
|
+- hapd->iface->conf->he_op.he_bss_color = hapd->cca_color;
|
|
++ if (hapd->cca_color)
|
|
++ hapd->iface->conf->he_op.he_bss_color = hapd->cca_color;
|
|
+ hostapd_cleanup_cca_params(hapd);
|
|
+ break;
|
|
+ #endif /* CONFIG_IEEE80211AX */
|
|
+--- a/src/drivers/driver_nl80211_event.c
|
|
++++ b/src/drivers/driver_nl80211_event.c
|
|
+@@ -3653,7 +3653,7 @@ static void nl80211_assoc_comeback(struc
|
|
+
|
|
+ #ifdef CONFIG_IEEE80211AX
|
|
+
|
|
+-static void nl80211_obss_color_collision(struct wpa_driver_nl80211_data *drv,
|
|
++static void nl80211_obss_color_collision(struct i802_bss *bss,
|
|
+ struct nlattr *tb[])
|
|
+ {
|
|
+ union wpa_event_data data;
|
|
+@@ -3667,37 +3667,37 @@ static void nl80211_obss_color_collision
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: BSS color collision - bitmap %08llx",
|
|
+ (long long unsigned int) data.bss_color_collision.bitmap);
|
|
+- wpa_supplicant_event(drv->ctx, EVENT_BSS_COLOR_COLLISION, &data);
|
|
++ wpa_supplicant_event(bss->ctx, EVENT_BSS_COLOR_COLLISION, &data);
|
|
+ }
|
|
+
|
|
+
|
|
+ static void
|
|
+-nl80211_color_change_announcement_started(struct wpa_driver_nl80211_data *drv)
|
|
++nl80211_color_change_announcement_started(struct i802_bss *bss)
|
|
+ {
|
|
+ union wpa_event_data data = {};
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: CCA started");
|
|
+- wpa_supplicant_event(drv->ctx, EVENT_CCA_STARTED_NOTIFY, &data);
|
|
++ wpa_supplicant_event(bss->ctx, EVENT_CCA_STARTED_NOTIFY, &data);
|
|
+ }
|
|
+
|
|
+
|
|
+ static void
|
|
+-nl80211_color_change_announcement_aborted(struct wpa_driver_nl80211_data *drv)
|
|
++nl80211_color_change_announcement_aborted(struct i802_bss *bss)
|
|
+ {
|
|
+ union wpa_event_data data = {};
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: CCA aborted");
|
|
+- wpa_supplicant_event(drv->ctx, EVENT_CCA_ABORTED_NOTIFY, &data);
|
|
++ wpa_supplicant_event(bss->ctx, EVENT_CCA_ABORTED_NOTIFY, &data);
|
|
+ }
|
|
+
|
|
+
|
|
+ static void
|
|
+-nl80211_color_change_announcement_completed(struct wpa_driver_nl80211_data *drv)
|
|
++nl80211_color_change_announcement_completed(struct i802_bss *bss)
|
|
+ {
|
|
+ union wpa_event_data data = {};
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: CCA completed");
|
|
+- wpa_supplicant_event(drv->ctx, EVENT_CCA_NOTIFY, &data);
|
|
++ wpa_supplicant_event(bss->ctx, EVENT_CCA_NOTIFY, &data);
|
|
+ }
|
|
+
|
|
+ #endif /* CONFIG_IEEE80211AX */
|
|
+@@ -3957,16 +3957,16 @@ static void do_process_drv_event(struct
|
|
+ break;
|
|
+ #ifdef CONFIG_IEEE80211AX
|
|
+ case NL80211_CMD_OBSS_COLOR_COLLISION:
|
|
+- nl80211_obss_color_collision(drv, tb);
|
|
++ nl80211_obss_color_collision(bss, tb);
|
|
+ break;
|
|
+ case NL80211_CMD_COLOR_CHANGE_STARTED:
|
|
+- nl80211_color_change_announcement_started(drv);
|
|
++ nl80211_color_change_announcement_started(bss);
|
|
+ break;
|
|
+ case NL80211_CMD_COLOR_CHANGE_ABORTED:
|
|
+- nl80211_color_change_announcement_aborted(drv);
|
|
++ nl80211_color_change_announcement_aborted(bss);
|
|
+ break;
|
|
+ case NL80211_CMD_COLOR_CHANGE_COMPLETED:
|
|
+- nl80211_color_change_announcement_completed(drv);
|
|
++ nl80211_color_change_announcement_completed(bss);
|
|
+ break;
|
|
+ #endif /* CONFIG_IEEE80211AX */
|
|
+ default:
|
|
diff --git a/package/network/services/hostapd/patches/200-multicall.patch b/package/network/services/hostapd/patches/200-multicall.patch
|
|
new file mode 100644
|
|
index 0000000000..8ebbed0c32
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/200-multicall.patch
|
|
@@ -0,0 +1,355 @@
|
|
+--- a/hostapd/Makefile
|
|
++++ b/hostapd/Makefile
|
|
+@@ -1,6 +1,7 @@
|
|
+ ALL=hostapd hostapd_cli
|
|
+ CONFIG_FILE = .config
|
|
+
|
|
++-include $(if $(MULTICALL), ../wpa_supplicant/.config)
|
|
+ include ../src/build.rules
|
|
+
|
|
+ ifdef LIBS
|
|
+@@ -199,7 +200,8 @@ endif
|
|
+
|
|
+ ifdef CONFIG_NO_VLAN
|
|
+ CFLAGS += -DCONFIG_NO_VLAN
|
|
+-else
|
|
++endif
|
|
++ifneq ($(findstring CONFIG_NO_VLAN,$(CFLAGS)), CONFIG_NO_VLAN)
|
|
+ OBJS += ../src/ap/vlan_init.o
|
|
+ OBJS += ../src/ap/vlan_ifconfig.o
|
|
+ OBJS += ../src/ap/vlan.o
|
|
+@@ -357,10 +359,14 @@ CFLAGS += -DCONFIG_MBO
|
|
+ OBJS += ../src/ap/mbo_ap.o
|
|
+ endif
|
|
+
|
|
++ifndef MULTICALL
|
|
++CFLAGS += -DNO_SUPPLICANT
|
|
++endif
|
|
++
|
|
+ include ../src/drivers/drivers.mak
|
|
+-OBJS += $(DRV_AP_OBJS)
|
|
+-CFLAGS += $(DRV_AP_CFLAGS)
|
|
+-LDFLAGS += $(DRV_AP_LDFLAGS)
|
|
++OBJS += $(sort $(DRV_AP_OBJS) $(if $(MULTICALL),$(DRV_WPA_OBJS)))
|
|
++CFLAGS += $(DRV_AP_CFLAGS) $(if $(MULTICALL),$(DRV_WPA_CFLAGS))
|
|
++LDFLAGS += $(DRV_AP_LDFLAGS) $(if $(MULTICALL),$(DRV_WPA_LDFLAGS))
|
|
+ LIBS += $(DRV_AP_LIBS)
|
|
+
|
|
+ ifdef CONFIG_L2_PACKET
|
|
+@@ -1380,6 +1386,12 @@ install: $(addprefix $(DESTDIR)$(BINDIR)
|
|
+ _OBJS_VAR := OBJS
|
|
+ include ../src/objs.mk
|
|
+
|
|
++hostapd_multi.a: $(BCHECK) $(OBJS)
|
|
++ $(Q)$(CC) -c -o hostapd_multi.o -Dmain=hostapd_main $(CFLAGS) main.c
|
|
++ @$(E) " CC " $<
|
|
++ @rm -f $@
|
|
++ @$(AR) cr $@ hostapd_multi.o $(OBJS)
|
|
++
|
|
+ hostapd: $(OBJS)
|
|
+ $(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
|
|
+ @$(E) " LD " $@
|
|
+@@ -1460,6 +1472,12 @@ include ../src/objs.mk
|
|
+ _OBJS_VAR := SOBJS
|
|
+ include ../src/objs.mk
|
|
+
|
|
++dump_cflags:
|
|
++ @printf "%s " "$(CFLAGS)"
|
|
++
|
|
++dump_ldflags:
|
|
++ @printf "%s " "$(LDFLAGS) $(LIBS) $(EXTRALIBS)"
|
|
++
|
|
+ nt_password_hash: $(NOBJS)
|
|
+ $(Q)$(CC) $(LDFLAGS) -o nt_password_hash $(NOBJS) $(LIBS_n)
|
|
+ @$(E) " LD " $@
|
|
+--- a/wpa_supplicant/Makefile
|
|
++++ b/wpa_supplicant/Makefile
|
|
+@@ -10,6 +10,7 @@ ALL += dbus/fi.w1.wpa_supplicant1.servic
|
|
+ EXTRA_TARGETS=dynamic_eap_methods
|
|
+
|
|
+ CONFIG_FILE=.config
|
|
++-include $(if $(MULTICALL),../hostapd/.config)
|
|
+ include ../src/build.rules
|
|
+
|
|
+ ifdef CONFIG_BUILD_PASN_SO
|
|
+@@ -382,7 +383,9 @@ endif
|
|
+ ifdef CONFIG_IBSS_RSN
|
|
+ NEED_RSN_AUTHENTICATOR=y
|
|
+ CFLAGS += -DCONFIG_IBSS_RSN
|
|
++ifndef MULTICALL
|
|
+ CFLAGS += -DCONFIG_NO_VLAN
|
|
++endif
|
|
+ OBJS += ibss_rsn.o
|
|
+ endif
|
|
+
|
|
+@@ -924,6 +927,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS
|
|
+ CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS
|
|
+ LIBS += -ldl -rdynamic
|
|
+ endif
|
|
++else
|
|
++ ifdef MULTICALL
|
|
++ OBJS += ../src/eap_common/eap_common.o
|
|
++ endif
|
|
+ endif
|
|
+
|
|
+ ifdef CONFIG_AP
|
|
+@@ -931,9 +938,11 @@ NEED_EAP_COMMON=y
|
|
+ NEED_RSN_AUTHENTICATOR=y
|
|
+ CFLAGS += -DCONFIG_AP
|
|
+ OBJS += ap.o
|
|
++ifndef MULTICALL
|
|
+ CFLAGS += -DCONFIG_NO_RADIUS
|
|
+ CFLAGS += -DCONFIG_NO_ACCOUNTING
|
|
+ CFLAGS += -DCONFIG_NO_VLAN
|
|
++endif
|
|
+ OBJS += ../src/ap/hostapd.o
|
|
+ OBJS += ../src/ap/wpa_auth_glue.o
|
|
+ OBJS += ../src/ap/utils.o
|
|
+@@ -1022,6 +1031,12 @@ endif
|
|
+ ifdef CONFIG_HS20
|
|
+ OBJS += ../src/ap/hs20.o
|
|
+ endif
|
|
++else
|
|
++ ifdef MULTICALL
|
|
++ OBJS += ../src/eap_server/eap_server.o
|
|
++ OBJS += ../src/eap_server/eap_server_identity.o
|
|
++ OBJS += ../src/eap_server/eap_server_methods.o
|
|
++ endif
|
|
+ endif
|
|
+
|
|
+ ifdef CONFIG_MBO
|
|
+@@ -1030,7 +1045,9 @@ CFLAGS += -DCONFIG_MBO
|
|
+ endif
|
|
+
|
|
+ ifdef NEED_RSN_AUTHENTICATOR
|
|
++ifndef MULTICALL
|
|
+ CFLAGS += -DCONFIG_NO_RADIUS
|
|
++endif
|
|
+ NEED_AES_WRAP=y
|
|
+ OBJS += ../src/ap/wpa_auth.o
|
|
+ OBJS += ../src/ap/wpa_auth_ie.o
|
|
+@@ -2010,6 +2027,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv)
|
|
+
|
|
+ _OBJS_VAR := OBJS
|
|
+ include ../src/objs.mk
|
|
++wpa_supplicant_multi.a: .config $(BCHECK) $(OBJS) $(EXTRA_progs)
|
|
++ $(Q)$(CC) -c -o wpa_supplicant_multi.o -Dmain=wpa_supplicant_main $(CFLAGS) main.c
|
|
++ @$(E) " CC " $<
|
|
++ @rm -f $@
|
|
++ @$(AR) cr $@ wpa_supplicant_multi.o $(OBJS)
|
|
++
|
|
+ wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)
|
|
+ $(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
|
|
+ @$(E) " LD " $@
|
|
+@@ -2142,6 +2165,12 @@ eap_gpsk.so: $(SRC_EAP_GPSK)
|
|
+ $(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@
|
|
+ @$(E) " sed" $<
|
|
+
|
|
++dump_cflags:
|
|
++ @printf "%s " "$(CFLAGS)"
|
|
++
|
|
++dump_ldflags:
|
|
++ @printf "%s " "$(LDFLAGS) $(LIBS) $(EXTRALIBS)"
|
|
++
|
|
+ wpa_supplicant.exe: wpa_supplicant
|
|
+ mv -f $< $@
|
|
+ wpa_cli.exe: wpa_cli
|
|
+--- a/src/drivers/driver.h
|
|
++++ b/src/drivers/driver.h
|
|
+@@ -6651,8 +6651,8 @@ union wpa_event_data {
|
|
+ * Driver wrapper code should call this function whenever an event is received
|
|
+ * from the driver.
|
|
+ */
|
|
+-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|
+- union wpa_event_data *data);
|
|
++extern void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data);
|
|
+
|
|
+ /**
|
|
+ * wpa_supplicant_event_global - Report a driver event for wpa_supplicant
|
|
+@@ -6664,7 +6664,7 @@ void wpa_supplicant_event(void *ctx, enu
|
|
+ * Same as wpa_supplicant_event(), but we search for the interface in
|
|
+ * wpa_global.
|
|
+ */
|
|
+-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
|
|
++extern void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
|
|
+ union wpa_event_data *data);
|
|
+
|
|
+ /*
|
|
+--- a/src/ap/drv_callbacks.c
|
|
++++ b/src/ap/drv_callbacks.c
|
|
+@@ -1994,8 +1994,8 @@ err:
|
|
+ #endif /* CONFIG_OWE */
|
|
+
|
|
+
|
|
+-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|
+- union wpa_event_data *data)
|
|
++void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data)
|
|
+ {
|
|
+ struct hostapd_data *hapd = ctx;
|
|
+ #ifndef CONFIG_NO_STDOUT_DEBUG
|
|
+@@ -2272,7 +2272,7 @@ void wpa_supplicant_event(void *ctx, enu
|
|
+ }
|
|
+
|
|
+
|
|
+-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
|
|
++void hostapd_wpa_event_global(void *ctx, enum wpa_event_type event,
|
|
+ union wpa_event_data *data)
|
|
+ {
|
|
+ struct hapd_interfaces *interfaces = ctx;
|
|
+--- a/wpa_supplicant/wpa_priv.c
|
|
++++ b/wpa_supplicant/wpa_priv.c
|
|
+@@ -1039,8 +1039,8 @@ static void wpa_priv_send_ft_response(st
|
|
+ }
|
|
+
|
|
+
|
|
+-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|
+- union wpa_event_data *data)
|
|
++static void supplicant_event(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data)
|
|
+ {
|
|
+ struct wpa_priv_interface *iface = ctx;
|
|
+
|
|
+@@ -1103,7 +1103,7 @@ void wpa_supplicant_event(void *ctx, enu
|
|
+ }
|
|
+
|
|
+
|
|
+-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
|
|
++void supplicant_event_global(void *ctx, enum wpa_event_type event,
|
|
+ union wpa_event_data *data)
|
|
+ {
|
|
+ struct wpa_priv_global *global = ctx;
|
|
+@@ -1217,6 +1217,8 @@ int main(int argc, char *argv[])
|
|
+ if (os_program_init())
|
|
+ return -1;
|
|
+
|
|
++ wpa_supplicant_event = supplicant_event;
|
|
++ wpa_supplicant_event_global = supplicant_event_global;
|
|
+ wpa_priv_fd_workaround();
|
|
+
|
|
+ os_memset(&global, 0, sizeof(global));
|
|
+--- a/wpa_supplicant/events.c
|
|
++++ b/wpa_supplicant/events.c
|
|
+@@ -5345,8 +5345,8 @@ static void wpas_link_reconfig(struct wp
|
|
+ }
|
|
+
|
|
+
|
|
+-void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
|
|
+- union wpa_event_data *data)
|
|
++void supplicant_event(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data)
|
|
+ {
|
|
+ struct wpa_supplicant *wpa_s = ctx;
|
|
+ int resched;
|
|
+@@ -6264,7 +6264,7 @@ void wpa_supplicant_event(void *ctx, enu
|
|
+ }
|
|
+
|
|
+
|
|
+-void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event,
|
|
++void supplicant_event_global(void *ctx, enum wpa_event_type event,
|
|
+ union wpa_event_data *data)
|
|
+ {
|
|
+ struct wpa_supplicant *wpa_s;
|
|
+--- a/wpa_supplicant/wpa_supplicant.c
|
|
++++ b/wpa_supplicant/wpa_supplicant.c
|
|
+@@ -7435,7 +7435,6 @@ struct wpa_interface * wpa_supplicant_ma
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+-
|
|
+ /**
|
|
+ * wpa_supplicant_match_existing - Match existing interfaces
|
|
+ * @global: Pointer to global data from wpa_supplicant_init()
|
|
+@@ -7470,6 +7469,11 @@ static int wpa_supplicant_match_existing
|
|
+
|
|
+ #endif /* CONFIG_MATCH_IFACE */
|
|
+
|
|
++extern void supplicant_event(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data);
|
|
++
|
|
++extern void supplicant_event_global(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data);
|
|
+
|
|
+ /**
|
|
+ * wpa_supplicant_add_iface - Add a new network interface
|
|
+@@ -7726,6 +7730,8 @@ struct wpa_global * wpa_supplicant_init(
|
|
+ #ifndef CONFIG_NO_WPA_MSG
|
|
+ wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb);
|
|
+ #endif /* CONFIG_NO_WPA_MSG */
|
|
++ wpa_supplicant_event = supplicant_event;
|
|
++ wpa_supplicant_event_global = supplicant_event_global;
|
|
+
|
|
+ if (params->wpa_debug_file_path)
|
|
+ wpa_debug_open_file(params->wpa_debug_file_path);
|
|
+--- a/hostapd/main.c
|
|
++++ b/hostapd/main.c
|
|
+@@ -685,6 +685,11 @@ fail:
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
++void hostapd_wpa_event(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data);
|
|
++
|
|
++void hostapd_wpa_event_global(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data);
|
|
+
|
|
+ #ifdef CONFIG_WPS
|
|
+ static int gen_uuid(const char *txt_addr)
|
|
+@@ -778,6 +783,8 @@ int main(int argc, char *argv[])
|
|
+ return -1;
|
|
+ #endif /* CONFIG_DPP */
|
|
+
|
|
++ wpa_supplicant_event = hostapd_wpa_event;
|
|
++ wpa_supplicant_event_global = hostapd_wpa_event_global;
|
|
+ for (;;) {
|
|
+ c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:q");
|
|
+ if (c < 0)
|
|
+--- a/src/drivers/drivers.c
|
|
++++ b/src/drivers/drivers.c
|
|
+@@ -10,6 +10,10 @@
|
|
+ #include "utils/common.h"
|
|
+ #include "driver.h"
|
|
+
|
|
++void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data);
|
|
++void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data);
|
|
+
|
|
+ const struct wpa_driver_ops *const wpa_drivers[] =
|
|
+ {
|
|
+--- a/wpa_supplicant/eapol_test.c
|
|
++++ b/wpa_supplicant/eapol_test.c
|
|
+@@ -31,7 +31,12 @@
|
|
+ #include "ctrl_iface.h"
|
|
+ #include "pcsc_funcs.h"
|
|
+ #include "wpas_glue.h"
|
|
++#include "drivers/driver.h"
|
|
+
|
|
++void (*wpa_supplicant_event)(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data);
|
|
++void (*wpa_supplicant_event_global)(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data);
|
|
+
|
|
+ const struct wpa_driver_ops *const wpa_drivers[] = { NULL };
|
|
+
|
|
+@@ -1303,6 +1308,10 @@ static void usage(void)
|
|
+ "option several times.\n");
|
|
+ }
|
|
+
|
|
++extern void supplicant_event(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data);
|
|
++extern void supplicant_event_global(void *ctx, enum wpa_event_type event,
|
|
++ union wpa_event_data *data);
|
|
+
|
|
+ int main(int argc, char *argv[])
|
|
+ {
|
|
+@@ -1323,6 +1332,8 @@ int main(int argc, char *argv[])
|
|
+ if (os_program_init())
|
|
+ return -1;
|
|
+
|
|
++ wpa_supplicant_event = supplicant_event;
|
|
++ wpa_supplicant_event_global = supplicant_event_global;
|
|
+ hostapd_logger_register_cb(hostapd_logger_cb);
|
|
+
|
|
+ os_memset(&eapol_test, 0, sizeof(eapol_test));
|
|
diff --git a/package/network/services/hostapd/patches/300-noscan.patch b/package/network/services/hostapd/patches/300-noscan.patch
|
|
new file mode 100644
|
|
index 0000000000..1ea89043e8
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/300-noscan.patch
|
|
@@ -0,0 +1,58 @@
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -3448,6 +3448,10 @@ static int hostapd_config_fill(struct ho
|
|
+ if (bss->ocv && !bss->ieee80211w)
|
|
+ bss->ieee80211w = 1;
|
|
+ #endif /* CONFIG_OCV */
|
|
++ } else if (os_strcmp(buf, "noscan") == 0) {
|
|
++ conf->noscan = atoi(pos);
|
|
++ } else if (os_strcmp(buf, "ht_coex") == 0) {
|
|
++ conf->no_ht_coex = !atoi(pos);
|
|
+ } else if (os_strcmp(buf, "ieee80211n") == 0) {
|
|
+ conf->ieee80211n = atoi(pos);
|
|
+ } else if (os_strcmp(buf, "ht_capab") == 0) {
|
|
+--- a/src/ap/ap_config.h
|
|
++++ b/src/ap/ap_config.h
|
|
+@@ -1072,6 +1072,8 @@ struct hostapd_config {
|
|
+
|
|
+ int ht_op_mode_fixed;
|
|
+ u16 ht_capab;
|
|
++ int noscan;
|
|
++ int no_ht_coex;
|
|
+ int ieee80211n;
|
|
+ int secondary_channel;
|
|
+ int no_pri_sec_switch;
|
|
+--- a/src/ap/hw_features.c
|
|
++++ b/src/ap/hw_features.c
|
|
+@@ -517,7 +517,8 @@ static int ieee80211n_check_40mhz(struct
|
|
+ int ret;
|
|
+
|
|
+ /* Check that HT40 is used and PRI / SEC switch is allowed */
|
|
+- if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch)
|
|
++ if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch ||
|
|
++ iface->conf->noscan)
|
|
+ return 0;
|
|
+
|
|
+ hostapd_set_state(iface, HAPD_IFACE_HT_SCAN);
|
|
+--- a/src/ap/ieee802_11_ht.c
|
|
++++ b/src/ap/ieee802_11_ht.c
|
|
+@@ -239,6 +239,9 @@ void hostapd_2040_coex_action(struct hos
|
|
+ return;
|
|
+ }
|
|
+
|
|
++ if (iface->conf->noscan || iface->conf->no_ht_coex)
|
|
++ return;
|
|
++
|
|
+ if (len < IEEE80211_HDRLEN + 2 + sizeof(*bc_ie)) {
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "Ignore too short 20/40 BSS Coexistence Management frame");
|
|
+@@ -399,6 +402,9 @@ void ht40_intolerant_add(struct hostapd_
|
|
+ if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
|
|
+ return;
|
|
+
|
|
++ if (iface->conf->noscan || iface->conf->no_ht_coex)
|
|
++ return;
|
|
++
|
|
+ wpa_printf(MSG_INFO, "HT: Forty MHz Intolerant is set by STA " MACSTR
|
|
+ " in Association Request", MAC2STR(sta->addr));
|
|
+
|
|
diff --git a/package/network/services/hostapd/patches/301-mesh-noscan.patch b/package/network/services/hostapd/patches/301-mesh-noscan.patch
|
|
new file mode 100644
|
|
index 0000000000..6b5416f0ea
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/301-mesh-noscan.patch
|
|
@@ -0,0 +1,71 @@
|
|
+--- a/wpa_supplicant/config.c
|
|
++++ b/wpa_supplicant/config.c
|
|
+@@ -2600,6 +2600,7 @@ static const struct parse_data ssid_fiel
|
|
+ #else /* CONFIG_MESH */
|
|
+ { INT_RANGE(mode, 0, 4) },
|
|
+ #endif /* CONFIG_MESH */
|
|
++ { INT_RANGE(noscan, 0, 1) },
|
|
+ { INT_RANGE(proactive_key_caching, 0, 1) },
|
|
+ { INT_RANGE(disabled, 0, 2) },
|
|
+ { STR(id_str) },
|
|
+--- a/wpa_supplicant/config_file.c
|
|
++++ b/wpa_supplicant/config_file.c
|
|
+@@ -775,6 +775,7 @@ static void wpa_config_write_network(FIL
|
|
+ #endif /* IEEE8021X_EAPOL */
|
|
+ INT(mode);
|
|
+ INT(no_auto_peer);
|
|
++ INT(noscan);
|
|
+ INT(mesh_fwding);
|
|
+ INT(frequency);
|
|
+ INT(enable_edmg);
|
|
+--- a/wpa_supplicant/mesh.c
|
|
++++ b/wpa_supplicant/mesh.c
|
|
+@@ -506,6 +506,8 @@ static int wpa_supplicant_mesh_init(stru
|
|
+ frequency);
|
|
+ goto out_free;
|
|
+ }
|
|
++ if (ssid->noscan)
|
|
++ conf->noscan = 1;
|
|
+
|
|
+ if (ssid->mesh_basic_rates == NULL) {
|
|
+ /*
|
|
+--- a/wpa_supplicant/wpa_supplicant.c
|
|
++++ b/wpa_supplicant/wpa_supplicant.c
|
|
+@@ -2710,7 +2710,7 @@ static bool ibss_mesh_can_use_vht(struct
|
|
+ const struct wpa_ssid *ssid,
|
|
+ struct hostapd_hw_modes *mode)
|
|
+ {
|
|
+- if (mode->mode != HOSTAPD_MODE_IEEE80211A)
|
|
++ if (mode->mode != HOSTAPD_MODE_IEEE80211A && !(ssid->noscan))
|
|
+ return false;
|
|
+
|
|
+ if (!drv_supports_vht(wpa_s, ssid))
|
|
+@@ -2783,7 +2783,7 @@ static void ibss_mesh_select_40mhz(struc
|
|
+ int i, res;
|
|
+ unsigned int j;
|
|
+ static const int ht40plus[] = {
|
|
+- 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 165, 173,
|
|
++ 1, 2, 3, 4, 5, 6, 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 165, 173,
|
|
+ 184, 192
|
|
+ };
|
|
+ int ht40 = -1;
|
|
+@@ -3033,7 +3033,7 @@ void ibss_mesh_setup_freq(struct wpa_sup
|
|
+ int ieee80211_mode = wpas_mode_to_ieee80211_mode(ssid->mode);
|
|
+ enum hostapd_hw_mode hw_mode;
|
|
+ struct hostapd_hw_modes *mode = NULL;
|
|
+- int i, obss_scan = 1;
|
|
++ int i, obss_scan = !(ssid->noscan);
|
|
+ u8 channel;
|
|
+ bool is_6ghz;
|
|
+ bool dfs_enabled = wpa_s->conf->country[0] && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_RADAR);
|
|
+--- a/wpa_supplicant/config_ssid.h
|
|
++++ b/wpa_supplicant/config_ssid.h
|
|
+@@ -1035,6 +1035,8 @@ struct wpa_ssid {
|
|
+ */
|
|
+ int no_auto_peer;
|
|
+
|
|
++ int noscan;
|
|
++
|
|
+ /**
|
|
+ * mesh_rssi_threshold - Set mesh parameter mesh_rssi_threshold (dBm)
|
|
+ *
|
|
diff --git a/package/network/services/hostapd/patches/310-rescan_immediately.patch b/package/network/services/hostapd/patches/310-rescan_immediately.patch
|
|
new file mode 100644
|
|
index 0000000000..a47546d38f
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/310-rescan_immediately.patch
|
|
@@ -0,0 +1,11 @@
|
|
+--- a/wpa_supplicant/wpa_supplicant.c
|
|
++++ b/wpa_supplicant/wpa_supplicant.c
|
|
+@@ -5740,7 +5740,7 @@ wpa_supplicant_alloc(struct wpa_supplica
|
|
+ if (wpa_s == NULL)
|
|
+ return NULL;
|
|
+ wpa_s->scan_req = INITIAL_SCAN_REQ;
|
|
+- wpa_s->scan_interval = 5;
|
|
++ wpa_s->scan_interval = 1;
|
|
+ wpa_s->new_connection = 1;
|
|
+ wpa_s->parent = parent ? parent : wpa_s;
|
|
+ wpa_s->p2pdev = wpa_s->parent;
|
|
diff --git a/package/network/services/hostapd/patches/320-optional_rfkill.patch b/package/network/services/hostapd/patches/320-optional_rfkill.patch
|
|
new file mode 100644
|
|
index 0000000000..01537790e0
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/320-optional_rfkill.patch
|
|
@@ -0,0 +1,61 @@
|
|
+--- a/src/drivers/drivers.mak
|
|
++++ b/src/drivers/drivers.mak
|
|
+@@ -54,7 +54,6 @@ NEED_SME=y
|
|
+ NEED_AP_MLME=y
|
|
+ NEED_NETLINK=y
|
|
+ NEED_LINUX_IOCTL=y
|
|
+-NEED_RFKILL=y
|
|
+ NEED_RADIOTAP=y
|
|
+ NEED_LIBNL=y
|
|
+ endif
|
|
+@@ -111,7 +110,6 @@ DRV_WPA_CFLAGS += -DCONFIG_DRIVER_WEXT
|
|
+ CONFIG_WIRELESS_EXTENSION=y
|
|
+ NEED_NETLINK=y
|
|
+ NEED_LINUX_IOCTL=y
|
|
+-NEED_RFKILL=y
|
|
+ endif
|
|
+
|
|
+ ifdef CONFIG_DRIVER_NDIS
|
|
+@@ -137,7 +135,6 @@ endif
|
|
+ ifdef CONFIG_WIRELESS_EXTENSION
|
|
+ DRV_WPA_CFLAGS += -DCONFIG_WIRELESS_EXTENSION
|
|
+ DRV_WPA_OBJS += ../src/drivers/driver_wext.o
|
|
+-NEED_RFKILL=y
|
|
+ endif
|
|
+
|
|
+ ifdef NEED_NETLINK
|
|
+@@ -146,6 +143,7 @@ endif
|
|
+
|
|
+ ifdef NEED_RFKILL
|
|
+ DRV_OBJS += ../src/drivers/rfkill.o
|
|
++DRV_WPA_CFLAGS += -DCONFIG_RFKILL
|
|
+ endif
|
|
+
|
|
+ ifdef NEED_RADIOTAP
|
|
+--- a/src/drivers/rfkill.h
|
|
++++ b/src/drivers/rfkill.h
|
|
+@@ -18,8 +18,24 @@ struct rfkill_config {
|
|
+ void (*unblocked_cb)(void *ctx);
|
|
+ };
|
|
+
|
|
++#ifdef CONFIG_RFKILL
|
|
+ struct rfkill_data * rfkill_init(struct rfkill_config *cfg);
|
|
+ void rfkill_deinit(struct rfkill_data *rfkill);
|
|
+ int rfkill_is_blocked(struct rfkill_data *rfkill);
|
|
++#else
|
|
++static inline struct rfkill_data * rfkill_init(struct rfkill_config *cfg)
|
|
++{
|
|
++ return (void *) 1;
|
|
++}
|
|
++
|
|
++static inline void rfkill_deinit(struct rfkill_data *rfkill)
|
|
++{
|
|
++}
|
|
++
|
|
++static inline int rfkill_is_blocked(struct rfkill_data *rfkill)
|
|
++{
|
|
++ return 0;
|
|
++}
|
|
++#endif
|
|
+
|
|
+ #endif /* RFKILL_H */
|
|
diff --git a/package/network/services/hostapd/patches/330-nl80211_fix_set_freq.patch b/package/network/services/hostapd/patches/330-nl80211_fix_set_freq.patch
|
|
new file mode 100644
|
|
index 0000000000..c11c957216
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/330-nl80211_fix_set_freq.patch
|
|
@@ -0,0 +1,11 @@
|
|
+--- a/src/drivers/driver_nl80211.c
|
|
++++ b/src/drivers/driver_nl80211.c
|
|
+@@ -5407,7 +5407,7 @@ static int nl80211_set_channel(struct i8
|
|
+ freq->he_enabled, freq->eht_enabled, freq->bandwidth,
|
|
+ freq->center_freq1, freq->center_freq2);
|
|
+
|
|
+- msg = nl80211_drv_msg(drv, 0, set_chan ? NL80211_CMD_SET_CHANNEL :
|
|
++ msg = nl80211_bss_msg(bss, 0, set_chan ? NL80211_CMD_SET_CHANNEL :
|
|
+ NL80211_CMD_SET_WIPHY);
|
|
+ if (!msg || nl80211_put_freq_params(msg, freq) < 0) {
|
|
+ nlmsg_free(msg);
|
|
diff --git a/package/network/services/hostapd/patches/341-mesh-ctrl-iface-channel-switch.patch b/package/network/services/hostapd/patches/341-mesh-ctrl-iface-channel-switch.patch
|
|
new file mode 100644
|
|
index 0000000000..8784452876
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/341-mesh-ctrl-iface-channel-switch.patch
|
|
@@ -0,0 +1,39 @@
|
|
+--- a/wpa_supplicant/ap.c
|
|
++++ b/wpa_supplicant/ap.c
|
|
+@@ -1825,15 +1825,35 @@ int ap_switch_channel(struct wpa_supplic
|
|
+
|
|
+
|
|
+ #ifdef CONFIG_CTRL_IFACE
|
|
++
|
|
++static int __ap_ctrl_iface_chanswitch(struct hostapd_iface *iface,
|
|
++ struct csa_settings *settings)
|
|
++{
|
|
++#ifdef NEED_AP_MLME
|
|
++ if (!iface || !iface->bss[0])
|
|
++ return 0;
|
|
++
|
|
++ return hostapd_switch_channel(iface->bss[0], settings);
|
|
++#else
|
|
++ return -1;
|
|
++#endif
|
|
++}
|
|
++
|
|
++
|
|
+ int ap_ctrl_iface_chanswitch(struct wpa_supplicant *wpa_s, const char *pos)
|
|
+ {
|
|
+ struct csa_settings settings;
|
|
+ int ret = hostapd_parse_csa_settings(pos, &settings);
|
|
+
|
|
++ if (!(wpa_s->ap_iface && wpa_s->ap_iface->bss[0]) &&
|
|
++ !(wpa_s->ifmsh && wpa_s->ifmsh->bss[0]))
|
|
++ return -1;
|
|
++
|
|
++ ret = __ap_ctrl_iface_chanswitch(wpa_s->ap_iface, &settings);
|
|
+ if (ret)
|
|
+ return ret;
|
|
+
|
|
+- return ap_switch_channel(wpa_s, &settings);
|
|
++ return __ap_ctrl_iface_chanswitch(wpa_s->ifmsh, &settings);
|
|
+ }
|
|
+ #endif /* CONFIG_CTRL_IFACE */
|
|
+
|
|
diff --git a/package/network/services/hostapd/patches/350-nl80211_del_beacon_bss.patch b/package/network/services/hostapd/patches/350-nl80211_del_beacon_bss.patch
|
|
new file mode 100644
|
|
index 0000000000..647ca2cbf9
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/350-nl80211_del_beacon_bss.patch
|
|
@@ -0,0 +1,35 @@
|
|
+--- a/src/drivers/driver_nl80211.c
|
|
++++ b/src/drivers/driver_nl80211.c
|
|
+@@ -3008,12 +3008,12 @@ static int wpa_driver_nl80211_del_beacon
|
|
+ return 0;
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)",
|
|
+- drv->ifindex);
|
|
++ bss->ifindex);
|
|
+ link->beacon_set = 0;
|
|
+ link->freq = 0;
|
|
+
|
|
+ nl80211_put_wiphy_data_ap(bss);
|
|
+- msg = nl80211_drv_msg(drv, 0, NL80211_CMD_DEL_BEACON);
|
|
++ msg = nl80211_bss_msg(bss, 0, NL80211_CMD_DEL_BEACON);
|
|
+ if (!msg)
|
|
+ return -ENOBUFS;
|
|
+
|
|
+@@ -6100,7 +6100,7 @@ static void nl80211_teardown_ap(struct i
|
|
+ nl80211_mgmt_unsubscribe(bss, "AP teardown");
|
|
+
|
|
+ nl80211_put_wiphy_data_ap(bss);
|
|
+- bss->flink->beacon_set = 0;
|
|
++ wpa_driver_nl80211_del_beacon_all(bss);
|
|
+ }
|
|
+
|
|
+
|
|
+@@ -8859,8 +8859,6 @@ static int wpa_driver_nl80211_if_remove(
|
|
+ } else {
|
|
+ wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context");
|
|
+ nl80211_teardown_ap(bss);
|
|
+- if (!bss->added_if && !drv->first_bss->next)
|
|
+- wpa_driver_nl80211_del_beacon_all(bss);
|
|
+ nl80211_destroy_bss(bss);
|
|
+ if (!bss->added_if)
|
|
+ i802_set_iface_flags(bss, 0);
|
|
diff --git a/package/network/services/hostapd/patches/380-disable_ctrl_iface_mib.patch b/package/network/services/hostapd/patches/380-disable_ctrl_iface_mib.patch
|
|
new file mode 100644
|
|
index 0000000000..54a736fe91
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/380-disable_ctrl_iface_mib.patch
|
|
@@ -0,0 +1,239 @@
|
|
+--- a/hostapd/Makefile
|
|
++++ b/hostapd/Makefile
|
|
+@@ -221,6 +221,9 @@ endif
|
|
+ ifdef CONFIG_NO_CTRL_IFACE
|
|
+ CFLAGS += -DCONFIG_NO_CTRL_IFACE
|
|
+ else
|
|
++ifdef CONFIG_CTRL_IFACE_MIB
|
|
++CFLAGS += -DCONFIG_CTRL_IFACE_MIB
|
|
++endif
|
|
+ ifeq ($(CONFIG_CTRL_IFACE), udp)
|
|
+ CFLAGS += -DCONFIG_CTRL_IFACE_UDP
|
|
+ else
|
|
+--- a/hostapd/ctrl_iface.c
|
|
++++ b/hostapd/ctrl_iface.c
|
|
+@@ -3314,6 +3314,7 @@ static int hostapd_ctrl_iface_receive_pr
|
|
+ reply_size);
|
|
+ } else if (os_strcmp(buf, "STATUS-DRIVER") == 0) {
|
|
+ reply_len = hostapd_drv_status(hapd, reply, reply_size);
|
|
++#ifdef CONFIG_CTRL_IFACE_MIB
|
|
+ } else if (os_strcmp(buf, "MIB") == 0) {
|
|
+ reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
|
|
+ if (reply_len >= 0) {
|
|
+@@ -3355,6 +3356,7 @@ static int hostapd_ctrl_iface_receive_pr
|
|
+ } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
|
|
+ reply_len = hostapd_ctrl_iface_sta_next(hapd, buf + 9, reply,
|
|
+ reply_size);
|
|
++#endif
|
|
+ } else if (os_strcmp(buf, "ATTACH") == 0) {
|
|
+ if (hostapd_ctrl_iface_attach(hapd, from, fromlen, NULL))
|
|
+ reply_len = -1;
|
|
+--- a/wpa_supplicant/Makefile
|
|
++++ b/wpa_supplicant/Makefile
|
|
+@@ -983,6 +983,9 @@ ifdef CONFIG_FILS
|
|
+ OBJS += ../src/ap/fils_hlp.o
|
|
+ endif
|
|
+ ifdef CONFIG_CTRL_IFACE
|
|
++ifdef CONFIG_CTRL_IFACE_MIB
|
|
++CFLAGS += -DCONFIG_CTRL_IFACE_MIB
|
|
++endif
|
|
+ OBJS += ../src/ap/ctrl_iface_ap.o
|
|
+ endif
|
|
+
|
|
+--- a/wpa_supplicant/ctrl_iface.c
|
|
++++ b/wpa_supplicant/ctrl_iface.c
|
|
+@@ -2326,7 +2326,7 @@ static int wpa_supplicant_ctrl_iface_sta
|
|
+ pos += ret;
|
|
+ }
|
|
+
|
|
+-#ifdef CONFIG_AP
|
|
++#if defined(CONFIG_AP) && defined(CONFIG_CTRL_IFACE_MIB)
|
|
+ if (wpa_s->ap_iface) {
|
|
+ pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
|
|
+ end - pos,
|
|
+@@ -11964,6 +11964,7 @@ char * wpa_supplicant_ctrl_iface_process
|
|
+ reply_len = -1;
|
|
+ } else if (os_strncmp(buf, "NOTE ", 5) == 0) {
|
|
+ wpa_printf(MSG_INFO, "NOTE: %s", buf + 5);
|
|
++#ifdef CONFIG_CTRL_IFACE_MIB
|
|
+ } else if (os_strcmp(buf, "MIB") == 0) {
|
|
+ reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
|
|
+ if (reply_len >= 0) {
|
|
+@@ -11976,6 +11977,7 @@ char * wpa_supplicant_ctrl_iface_process
|
|
+ reply_size - reply_len);
|
|
+ #endif /* CONFIG_MACSEC */
|
|
+ }
|
|
++#endif
|
|
+ } else if (os_strncmp(buf, "STATUS", 6) == 0) {
|
|
+ reply_len = wpa_supplicant_ctrl_iface_status(
|
|
+ wpa_s, buf + 6, reply, reply_size);
|
|
+@@ -12464,6 +12466,7 @@ char * wpa_supplicant_ctrl_iface_process
|
|
+ reply_len = wpa_supplicant_ctrl_iface_bss(
|
|
+ wpa_s, buf + 4, reply, reply_size);
|
|
+ #ifdef CONFIG_AP
|
|
++#ifdef CONFIG_CTRL_IFACE_MIB
|
|
+ } else if (os_strcmp(buf, "STA-FIRST") == 0) {
|
|
+ reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
|
|
+ } else if (os_strncmp(buf, "STA ", 4) == 0) {
|
|
+@@ -12472,12 +12475,15 @@ char * wpa_supplicant_ctrl_iface_process
|
|
+ } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
|
|
+ reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
|
|
+ reply_size);
|
|
++#endif
|
|
++#ifdef CONFIG_CTRL_IFACE_MIB
|
|
+ } else if (os_strncmp(buf, "DEAUTHENTICATE ", 15) == 0) {
|
|
+ if (ap_ctrl_iface_sta_deauthenticate(wpa_s, buf + 15))
|
|
+ reply_len = -1;
|
|
+ } else if (os_strncmp(buf, "DISASSOCIATE ", 13) == 0) {
|
|
+ if (ap_ctrl_iface_sta_disassociate(wpa_s, buf + 13))
|
|
+ reply_len = -1;
|
|
++#endif
|
|
+ } else if (os_strncmp(buf, "CHAN_SWITCH ", 12) == 0) {
|
|
+ if (ap_ctrl_iface_chanswitch(wpa_s, buf + 12))
|
|
+ reply_len = -1;
|
|
+--- a/src/ap/ctrl_iface_ap.c
|
|
++++ b/src/ap/ctrl_iface_ap.c
|
|
+@@ -26,6 +26,26 @@
|
|
+ #include "taxonomy.h"
|
|
+ #include "wnm_ap.h"
|
|
+
|
|
++static const char * hw_mode_str(enum hostapd_hw_mode mode)
|
|
++{
|
|
++ switch (mode) {
|
|
++ case HOSTAPD_MODE_IEEE80211B:
|
|
++ return "b";
|
|
++ case HOSTAPD_MODE_IEEE80211G:
|
|
++ return "g";
|
|
++ case HOSTAPD_MODE_IEEE80211A:
|
|
++ return "a";
|
|
++ case HOSTAPD_MODE_IEEE80211AD:
|
|
++ return "ad";
|
|
++ case HOSTAPD_MODE_IEEE80211ANY:
|
|
++ return "any";
|
|
++ case NUM_HOSTAPD_MODES:
|
|
++ return "invalid";
|
|
++ }
|
|
++ return "unknown";
|
|
++}
|
|
++
|
|
++#ifdef CONFIG_CTRL_IFACE_MIB
|
|
+
|
|
+ static size_t hostapd_write_ht_mcs_bitmask(char *buf, size_t buflen,
|
|
+ size_t curr_len, const u8 *mcs_set)
|
|
+@@ -212,26 +232,6 @@ static const char * timeout_next_str(int
|
|
+ }
|
|
+
|
|
+
|
|
+-static const char * hw_mode_str(enum hostapd_hw_mode mode)
|
|
+-{
|
|
+- switch (mode) {
|
|
+- case HOSTAPD_MODE_IEEE80211B:
|
|
+- return "b";
|
|
+- case HOSTAPD_MODE_IEEE80211G:
|
|
+- return "g";
|
|
+- case HOSTAPD_MODE_IEEE80211A:
|
|
+- return "a";
|
|
+- case HOSTAPD_MODE_IEEE80211AD:
|
|
+- return "ad";
|
|
+- case HOSTAPD_MODE_IEEE80211ANY:
|
|
+- return "any";
|
|
+- case NUM_HOSTAPD_MODES:
|
|
+- return "invalid";
|
|
+- }
|
|
+- return "unknown";
|
|
+-}
|
|
+-
|
|
+-
|
|
+ static int hostapd_ctrl_iface_sta_mib(struct hostapd_data *hapd,
|
|
+ struct sta_info *sta,
|
|
+ char *buf, size_t buflen)
|
|
+@@ -493,6 +493,7 @@ int hostapd_ctrl_iface_sta_next(struct h
|
|
+ return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen);
|
|
+ }
|
|
+
|
|
++#endif
|
|
+
|
|
+ #ifdef CONFIG_P2P_MANAGER
|
|
+ static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
|
|
+@@ -884,12 +885,12 @@ int hostapd_ctrl_iface_status(struct hos
|
|
+ return len;
|
|
+ len += ret;
|
|
+ }
|
|
+-
|
|
++#ifdef CONFIG_CTRL_IFACE_MIB
|
|
+ if (iface->conf->ieee80211n && !hapd->conf->disable_11n && mode) {
|
|
+ len = hostapd_write_ht_mcs_bitmask(buf, buflen, len,
|
|
+ mode->mcs_set);
|
|
+ }
|
|
+-
|
|
++#endif /* CONFIG_CTRL_IFACE_MIB */
|
|
+ if (iface->current_rates && iface->num_rates) {
|
|
+ ret = os_snprintf(buf + len, buflen - len, "supported_rates=");
|
|
+ if (os_snprintf_error(buflen - len, ret))
|
|
+--- a/src/ap/ieee802_1x.c
|
|
++++ b/src/ap/ieee802_1x.c
|
|
+@@ -2834,6 +2834,7 @@ static const char * bool_txt(bool val)
|
|
+ return val ? "TRUE" : "FALSE";
|
|
+ }
|
|
+
|
|
++#ifdef CONFIG_CTRL_IFACE_MIB
|
|
+
|
|
+ int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
|
|
+ {
|
|
+@@ -3020,6 +3021,7 @@ int ieee802_1x_get_mib_sta(struct hostap
|
|
+ return len;
|
|
+ }
|
|
+
|
|
++#endif
|
|
+
|
|
+ #ifdef CONFIG_HS20
|
|
+ static void ieee802_1x_wnm_notif_send(void *eloop_ctx, void *timeout_ctx)
|
|
+--- a/src/ap/wpa_auth.c
|
|
++++ b/src/ap/wpa_auth.c
|
|
+@@ -5328,6 +5328,7 @@ static const char * wpa_bool_txt(int val
|
|
+ return val ? "TRUE" : "FALSE";
|
|
+ }
|
|
+
|
|
++#ifdef CONFIG_CTRL_IFACE_MIB
|
|
+
|
|
+ #define RSN_SUITE "%02x-%02x-%02x-%d"
|
|
+ #define RSN_SUITE_ARG(s) \
|
|
+@@ -5480,7 +5481,7 @@ int wpa_get_mib_sta(struct wpa_state_mac
|
|
+
|
|
+ return len;
|
|
+ }
|
|
+-
|
|
++#endif
|
|
+
|
|
+ void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth)
|
|
+ {
|
|
+--- a/src/rsn_supp/wpa.c
|
|
++++ b/src/rsn_supp/wpa.c
|
|
+@@ -3834,6 +3834,8 @@ static u32 wpa_key_mgmt_suite(struct wpa
|
|
+ }
|
|
+
|
|
+
|
|
++#ifdef CONFIG_CTRL_IFACE_MIB
|
|
++
|
|
+ #define RSN_SUITE "%02x-%02x-%02x-%d"
|
|
+ #define RSN_SUITE_ARG(s) \
|
|
+ ((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
|
|
+@@ -3915,6 +3917,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch
|
|
+
|
|
+ return (int) len;
|
|
+ }
|
|
++#endif
|
|
+ #endif /* CONFIG_CTRL_IFACE */
|
|
+
|
|
+
|
|
+--- a/wpa_supplicant/ap.c
|
|
++++ b/wpa_supplicant/ap.c
|
|
+@@ -1499,7 +1499,7 @@ int wpas_ap_wps_nfc_report_handover(stru
|
|
+ #endif /* CONFIG_WPS */
|
|
+
|
|
+
|
|
+-#ifdef CONFIG_CTRL_IFACE
|
|
++#if defined(CONFIG_CTRL_IFACE) && defined(CONFIG_CTRL_IFACE_MIB)
|
|
+
|
|
+ int ap_ctrl_iface_sta_first(struct wpa_supplicant *wpa_s,
|
|
+ char *buf, size_t buflen)
|
|
diff --git a/package/network/services/hostapd/patches/381-hostapd_cli_UNKNOWN-COMMAND.patch b/package/network/services/hostapd/patches/381-hostapd_cli_UNKNOWN-COMMAND.patch
|
|
new file mode 100644
|
|
index 0000000000..e9083f6ecc
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/381-hostapd_cli_UNKNOWN-COMMAND.patch
|
|
@@ -0,0 +1,11 @@
|
|
+--- a/hostapd/hostapd_cli.c
|
|
++++ b/hostapd/hostapd_cli.c
|
|
+@@ -757,7 +757,7 @@ static int wpa_ctrl_command_sta(struct w
|
|
+ }
|
|
+
|
|
+ buf[len] = '\0';
|
|
+- if (memcmp(buf, "FAIL", 4) == 0)
|
|
++ if (memcmp(buf, "FAIL", 4) == 0 || memcmp(buf, "UNKNOWN COMMAND", 15) == 0)
|
|
+ return -1;
|
|
+ if (print)
|
|
+ printf("%s", buf);
|
|
diff --git a/package/network/services/hostapd/patches/390-wpa_ie_cap_workaround.patch b/package/network/services/hostapd/patches/390-wpa_ie_cap_workaround.patch
|
|
new file mode 100644
|
|
index 0000000000..40c39ff29c
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/390-wpa_ie_cap_workaround.patch
|
|
@@ -0,0 +1,56 @@
|
|
+--- a/src/common/wpa_common.c
|
|
++++ b/src/common/wpa_common.c
|
|
+@@ -2719,6 +2719,31 @@ u32 wpa_akm_to_suite(int akm)
|
|
+ }
|
|
+
|
|
+
|
|
++static void wpa_fixup_wpa_ie_rsn(u8 *assoc_ie, const u8 *wpa_msg_ie,
|
|
++ size_t rsn_ie_len)
|
|
++{
|
|
++ int pos, count;
|
|
++
|
|
++ pos = sizeof(struct rsn_ie_hdr) + RSN_SELECTOR_LEN;
|
|
++ if (rsn_ie_len < pos + 2)
|
|
++ return;
|
|
++
|
|
++ count = WPA_GET_LE16(wpa_msg_ie + pos);
|
|
++ pos += 2 + count * RSN_SELECTOR_LEN;
|
|
++ if (rsn_ie_len < pos + 2)
|
|
++ return;
|
|
++
|
|
++ count = WPA_GET_LE16(wpa_msg_ie + pos);
|
|
++ pos += 2 + count * RSN_SELECTOR_LEN;
|
|
++ if (rsn_ie_len < pos + 2)
|
|
++ return;
|
|
++
|
|
++ if (!assoc_ie[pos] && !assoc_ie[pos + 1] &&
|
|
++ (wpa_msg_ie[pos] || wpa_msg_ie[pos + 1]))
|
|
++ memcpy(&assoc_ie[pos], &wpa_msg_ie[pos], 2);
|
|
++}
|
|
++
|
|
++
|
|
+ int wpa_compare_rsn_ie(int ft_initial_assoc,
|
|
+ const u8 *ie1, size_t ie1len,
|
|
+ const u8 *ie2, size_t ie2len)
|
|
+@@ -2726,8 +2751,19 @@ int wpa_compare_rsn_ie(int ft_initial_as
|
|
+ if (ie1 == NULL || ie2 == NULL)
|
|
+ return -1;
|
|
+
|
|
+- if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0)
|
|
+- return 0; /* identical IEs */
|
|
++ if (ie1len == ie2len) {
|
|
++ u8 *ie_tmp;
|
|
++
|
|
++ if (os_memcmp(ie1, ie2, ie1len) == 0)
|
|
++ return 0; /* identical IEs */
|
|
++
|
|
++ ie_tmp = alloca(ie1len);
|
|
++ memcpy(ie_tmp, ie1, ie1len);
|
|
++ wpa_fixup_wpa_ie_rsn(ie_tmp, ie2, ie1len);
|
|
++
|
|
++ if (os_memcmp(ie_tmp, ie2, ie1len) == 0)
|
|
++ return 0; /* only mismatch in RSN capabilties */
|
|
++ }
|
|
+
|
|
+ #ifdef CONFIG_IEEE80211R
|
|
+ if (ft_initial_assoc) {
|
|
diff --git a/package/network/services/hostapd/patches/400-wps_single_auth_enc_type.patch b/package/network/services/hostapd/patches/400-wps_single_auth_enc_type.patch
|
|
new file mode 100644
|
|
index 0000000000..edcd985257
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/400-wps_single_auth_enc_type.patch
|
|
@@ -0,0 +1,23 @@
|
|
+--- a/src/ap/wps_hostapd.c
|
|
++++ b/src/ap/wps_hostapd.c
|
|
+@@ -394,9 +394,8 @@ static int hapd_wps_reconfig_in_memory(s
|
|
+ bss->wpa_pairwise |= WPA_CIPHER_GCMP;
|
|
+ else
|
|
+ bss->wpa_pairwise |= WPA_CIPHER_CCMP;
|
|
+- }
|
|
+ #ifndef CONFIG_NO_TKIP
|
|
+- if (cred->encr_type & WPS_ENCR_TKIP)
|
|
++ } else if (cred->encr_type & WPS_ENCR_TKIP)
|
|
+ bss->wpa_pairwise |= WPA_CIPHER_TKIP;
|
|
+ #endif /* CONFIG_NO_TKIP */
|
|
+ bss->rsn_pairwise = bss->wpa_pairwise;
|
|
+@@ -1181,8 +1180,7 @@ int hostapd_init_wps(struct hostapd_data
|
|
+ WPA_CIPHER_GCMP_256)) {
|
|
+ wps->encr_types |= WPS_ENCR_AES;
|
|
+ wps->encr_types_rsn |= WPS_ENCR_AES;
|
|
+- }
|
|
+- if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
|
|
++ } else if (conf->rsn_pairwise & WPA_CIPHER_TKIP) {
|
|
+ #ifdef CONFIG_NO_TKIP
|
|
+ wpa_printf(MSG_INFO, "WPS: TKIP not supported");
|
|
+ goto fail;
|
|
diff --git a/package/network/services/hostapd/patches/410-limit_debug_messages.patch b/package/network/services/hostapd/patches/410-limit_debug_messages.patch
|
|
new file mode 100644
|
|
index 0000000000..48a5589200
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/410-limit_debug_messages.patch
|
|
@@ -0,0 +1,210 @@
|
|
+--- a/src/utils/wpa_debug.c
|
|
++++ b/src/utils/wpa_debug.c
|
|
+@@ -206,7 +206,7 @@ void wpa_debug_close_linux_tracing(void)
|
|
+ *
|
|
+ * Note: New line '\n' is added to the end of the text when printing to stdout.
|
|
+ */
|
|
+-void wpa_printf(int level, const char *fmt, ...)
|
|
++void _wpa_printf(int level, const char *fmt, ...)
|
|
+ {
|
|
+ va_list ap;
|
|
+
|
|
+@@ -255,7 +255,7 @@ void wpa_printf(int level, const char *f
|
|
+ }
|
|
+
|
|
+
|
|
+-static void _wpa_hexdump(int level, const char *title, const u8 *buf,
|
|
++void _wpa_hexdump(int level, const char *title, const u8 *buf,
|
|
+ size_t len, int show, int only_syslog)
|
|
+ {
|
|
+ size_t i;
|
|
+@@ -382,19 +382,7 @@ static void _wpa_hexdump(int level, cons
|
|
+ #endif /* CONFIG_ANDROID_LOG */
|
|
+ }
|
|
+
|
|
+-void wpa_hexdump(int level, const char *title, const void *buf, size_t len)
|
|
+-{
|
|
+- _wpa_hexdump(level, title, buf, len, 1, 0);
|
|
+-}
|
|
+-
|
|
+-
|
|
+-void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len)
|
|
+-{
|
|
+- _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys, 0);
|
|
+-}
|
|
+-
|
|
+-
|
|
+-static void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
|
|
++void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
|
|
+ size_t len, int show)
|
|
+ {
|
|
+ size_t i, llen;
|
|
+@@ -507,20 +495,6 @@ file_done:
|
|
+ }
|
|
+
|
|
+
|
|
+-void wpa_hexdump_ascii(int level, const char *title, const void *buf,
|
|
+- size_t len)
|
|
+-{
|
|
+- _wpa_hexdump_ascii(level, title, buf, len, 1);
|
|
+-}
|
|
+-
|
|
+-
|
|
+-void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
|
|
+- size_t len)
|
|
+-{
|
|
+- _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
|
|
+-}
|
|
+-
|
|
+-
|
|
+ #ifdef CONFIG_DEBUG_FILE
|
|
+ static char *last_path = NULL;
|
|
+ #endif /* CONFIG_DEBUG_FILE */
|
|
+@@ -644,7 +618,7 @@ void wpa_msg_register_ifname_cb(wpa_msg_
|
|
+ }
|
|
+
|
|
+
|
|
+-void wpa_msg(void *ctx, int level, const char *fmt, ...)
|
|
++void _wpa_msg(void *ctx, int level, const char *fmt, ...)
|
|
+ {
|
|
+ va_list ap;
|
|
+ char *buf;
|
|
+@@ -682,7 +656,7 @@ void wpa_msg(void *ctx, int level, const
|
|
+ }
|
|
+
|
|
+
|
|
+-void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
|
|
++void _wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
|
|
+ {
|
|
+ va_list ap;
|
|
+ char *buf;
|
|
+--- a/src/utils/wpa_debug.h
|
|
++++ b/src/utils/wpa_debug.h
|
|
+@@ -51,6 +51,17 @@ void wpa_debug_close_file(void);
|
|
+ void wpa_debug_setup_stdout(void);
|
|
+ void wpa_debug_stop_log(void);
|
|
+
|
|
++/* internal */
|
|
++void _wpa_hexdump(int level, const char *title, const u8 *buf,
|
|
++ size_t len, int show, int only_syslog);
|
|
++void _wpa_hexdump_ascii(int level, const char *title, const void *buf,
|
|
++ size_t len, int show);
|
|
++extern int wpa_debug_show_keys;
|
|
++
|
|
++#ifndef CONFIG_MSG_MIN_PRIORITY
|
|
++#define CONFIG_MSG_MIN_PRIORITY 0
|
|
++#endif
|
|
++
|
|
+ /**
|
|
+ * wpa_debug_printf_timestamp - Print timestamp for debug output
|
|
+ *
|
|
+@@ -71,9 +82,15 @@ void wpa_debug_print_timestamp(void);
|
|
+ *
|
|
+ * Note: New line '\n' is added to the end of the text when printing to stdout.
|
|
+ */
|
|
+-void wpa_printf(int level, const char *fmt, ...)
|
|
++void _wpa_printf(int level, const char *fmt, ...)
|
|
+ PRINTF_FORMAT(2, 3);
|
|
+
|
|
++#define wpa_printf(level, ...) \
|
|
++ do { \
|
|
++ if (level >= CONFIG_MSG_MIN_PRIORITY) \
|
|
++ _wpa_printf(level, __VA_ARGS__); \
|
|
++ } while(0)
|
|
++
|
|
+ /**
|
|
+ * wpa_hexdump - conditional hex dump
|
|
+ * @level: priority level (MSG_*) of the message
|
|
+@@ -85,7 +102,13 @@ PRINTF_FORMAT(2, 3);
|
|
+ * output may be directed to stdout, stderr, and/or syslog based on
|
|
+ * configuration. The contents of buf is printed out has hex dump.
|
|
+ */
|
|
+-void wpa_hexdump(int level, const char *title, const void *buf, size_t len);
|
|
++static inline void wpa_hexdump(int level, const char *title, const void *buf, size_t len)
|
|
++{
|
|
++ if (level < CONFIG_MSG_MIN_PRIORITY)
|
|
++ return;
|
|
++
|
|
++ _wpa_hexdump(level, title, buf, len, 1, 1);
|
|
++}
|
|
+
|
|
+ static inline void wpa_hexdump_buf(int level, const char *title,
|
|
+ const struct wpabuf *buf)
|
|
+@@ -107,7 +130,13 @@ static inline void wpa_hexdump_buf(int l
|
|
+ * like wpa_hexdump(), but by default, does not include secret keys (passwords,
|
|
+ * etc.) in debug output.
|
|
+ */
|
|
+-void wpa_hexdump_key(int level, const char *title, const void *buf, size_t len);
|
|
++static inline void wpa_hexdump_key(int level, const char *title, const u8 *buf, size_t len)
|
|
++{
|
|
++ if (level < CONFIG_MSG_MIN_PRIORITY)
|
|
++ return;
|
|
++
|
|
++ _wpa_hexdump(level, title, buf, len, wpa_debug_show_keys, 1);
|
|
++}
|
|
+
|
|
+ static inline void wpa_hexdump_buf_key(int level, const char *title,
|
|
+ const struct wpabuf *buf)
|
|
+@@ -129,8 +158,14 @@ static inline void wpa_hexdump_buf_key(i
|
|
+ * the hex numbers and ASCII characters (for printable range) are shown. 16
|
|
+ * bytes per line will be shown.
|
|
+ */
|
|
+-void wpa_hexdump_ascii(int level, const char *title, const void *buf,
|
|
+- size_t len);
|
|
++static inline void wpa_hexdump_ascii(int level, const char *title,
|
|
++ const u8 *buf, size_t len)
|
|
++{
|
|
++ if (level < CONFIG_MSG_MIN_PRIORITY)
|
|
++ return;
|
|
++
|
|
++ _wpa_hexdump_ascii(level, title, buf, len, 1);
|
|
++}
|
|
+
|
|
+ /**
|
|
+ * wpa_hexdump_ascii_key - conditional hex dump, hide keys
|
|
+@@ -146,8 +181,14 @@ void wpa_hexdump_ascii(int level, const
|
|
+ * bytes per line will be shown. This works like wpa_hexdump_ascii(), but by
|
|
+ * default, does not include secret keys (passwords, etc.) in debug output.
|
|
+ */
|
|
+-void wpa_hexdump_ascii_key(int level, const char *title, const void *buf,
|
|
+- size_t len);
|
|
++static inline void wpa_hexdump_ascii_key(int level, const char *title,
|
|
++ const u8 *buf, size_t len)
|
|
++{
|
|
++ if (level < CONFIG_MSG_MIN_PRIORITY)
|
|
++ return;
|
|
++
|
|
++ _wpa_hexdump_ascii(level, title, buf, len, wpa_debug_show_keys);
|
|
++}
|
|
+
|
|
+ /*
|
|
+ * wpa_dbg() behaves like wpa_msg(), but it can be removed from build to reduce
|
|
+@@ -184,7 +225,12 @@ void wpa_hexdump_ascii_key(int level, co
|
|
+ *
|
|
+ * Note: New line '\n' is added to the end of the text when printing to stdout.
|
|
+ */
|
|
+-void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);
|
|
++void _wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4);
|
|
++#define wpa_msg(ctx, level, ...) \
|
|
++ do { \
|
|
++ if (level >= CONFIG_MSG_MIN_PRIORITY) \
|
|
++ _wpa_msg(ctx, level, __VA_ARGS__); \
|
|
++ } while(0)
|
|
+
|
|
+ /**
|
|
+ * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors
|
|
+@@ -198,8 +244,13 @@ void wpa_msg(void *ctx, int level, const
|
|
+ * attached ctrl_iface monitors. In other words, it can be used for frequent
|
|
+ * events that do not need to be sent to syslog.
|
|
+ */
|
|
+-void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
|
|
++void _wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...)
|
|
+ PRINTF_FORMAT(3, 4);
|
|
++#define wpa_msg_ctrl(ctx, level, ...) \
|
|
++ do { \
|
|
++ if (level >= CONFIG_MSG_MIN_PRIORITY) \
|
|
++ _wpa_msg_ctrl(ctx, level, __VA_ARGS__); \
|
|
++ } while(0)
|
|
+
|
|
+ /**
|
|
+ * wpa_msg_global - Global printf for ctrl_iface monitors
|
|
diff --git a/package/network/services/hostapd/patches/420-indicate-features.patch b/package/network/services/hostapd/patches/420-indicate-features.patch
|
|
new file mode 100644
|
|
index 0000000000..3b28b6e752
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/420-indicate-features.patch
|
|
@@ -0,0 +1,63 @@
|
|
+--- a/hostapd/main.c
|
|
++++ b/hostapd/main.c
|
|
+@@ -31,7 +31,7 @@
|
|
+ #include "config_file.h"
|
|
+ #include "eap_register.h"
|
|
+ #include "ctrl_iface.h"
|
|
+-
|
|
++#include "build_features.h"
|
|
+
|
|
+ struct hapd_global {
|
|
+ void **drv_priv;
|
|
+@@ -786,7 +786,7 @@ int main(int argc, char *argv[])
|
|
+ wpa_supplicant_event = hostapd_wpa_event;
|
|
+ wpa_supplicant_event_global = hostapd_wpa_event_global;
|
|
+ for (;;) {
|
|
+- c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:vg:G:q");
|
|
++ c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:g:G:qv::");
|
|
+ if (c < 0)
|
|
+ break;
|
|
+ switch (c) {
|
|
+@@ -823,6 +823,8 @@ int main(int argc, char *argv[])
|
|
+ break;
|
|
+ #endif /* CONFIG_DEBUG_LINUX_TRACING */
|
|
+ case 'v':
|
|
++ if (optarg)
|
|
++ exit(!has_feature(optarg));
|
|
+ show_version();
|
|
+ exit(1);
|
|
+ case 'g':
|
|
+--- a/wpa_supplicant/main.c
|
|
++++ b/wpa_supplicant/main.c
|
|
+@@ -12,6 +12,7 @@
|
|
+ #endif /* __linux__ */
|
|
+
|
|
+ #include "common.h"
|
|
++#include "build_features.h"
|
|
+ #include "crypto/crypto.h"
|
|
+ #include "fst/fst.h"
|
|
+ #include "wpa_supplicant_i.h"
|
|
+@@ -202,7 +203,7 @@ int main(int argc, char *argv[])
|
|
+
|
|
+ for (;;) {
|
|
+ c = getopt(argc, argv,
|
|
+- "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
|
|
++ "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuv::W");
|
|
+ if (c < 0)
|
|
+ break;
|
|
+ switch (c) {
|
|
+@@ -302,8 +303,12 @@ int main(int argc, char *argv[])
|
|
+ break;
|
|
+ #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
|
+ case 'v':
|
|
+- printf("%s\n", wpa_supplicant_version);
|
|
+- exitcode = 0;
|
|
++ if (optarg) {
|
|
++ exitcode = !has_feature(optarg);
|
|
++ } else {
|
|
++ printf("%s\n", wpa_supplicant_version);
|
|
++ exitcode = 0;
|
|
++ }
|
|
+ goto out;
|
|
+ case 'W':
|
|
+ params.wait_for_monitor++;
|
|
diff --git a/package/network/services/hostapd/patches/430-hostapd_cli_ifdef.patch b/package/network/services/hostapd/patches/430-hostapd_cli_ifdef.patch
|
|
new file mode 100644
|
|
index 0000000000..a21f0bf7ce
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/430-hostapd_cli_ifdef.patch
|
|
@@ -0,0 +1,56 @@
|
|
+--- a/hostapd/hostapd_cli.c
|
|
++++ b/hostapd/hostapd_cli.c
|
|
+@@ -401,7 +401,6 @@ static int hostapd_cli_cmd_disassociate(
|
|
+ }
|
|
+
|
|
+
|
|
+-#ifdef CONFIG_TAXONOMY
|
|
+ static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc,
|
|
+ char *argv[])
|
|
+ {
|
|
+@@ -414,7 +413,6 @@ static int hostapd_cli_cmd_signature(str
|
|
+ os_snprintf(buf, sizeof(buf), "SIGNATURE %s", argv[0]);
|
|
+ return wpa_ctrl_command(ctrl, buf);
|
|
+ }
|
|
+-#endif /* CONFIG_TAXONOMY */
|
|
+
|
|
+
|
|
+ static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
|
|
+@@ -431,7 +429,6 @@ static int hostapd_cli_cmd_sa_query(stru
|
|
+ }
|
|
+
|
|
+
|
|
+-#ifdef CONFIG_WPS
|
|
+ static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
|
|
+ char *argv[])
|
|
+ {
|
|
+@@ -657,7 +654,6 @@ static int hostapd_cli_cmd_wps_config(st
|
|
+ ssid_hex, argv[1]);
|
|
+ return wpa_ctrl_command(ctrl, buf);
|
|
+ }
|
|
+-#endif /* CONFIG_WPS */
|
|
+
|
|
+
|
|
+ static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
|
|
+@@ -1610,13 +1606,10 @@ static const struct hostapd_cli_cmd host
|
|
+ { "disassociate", hostapd_cli_cmd_disassociate,
|
|
+ hostapd_complete_stations,
|
|
+ "<addr> = disassociate a station" },
|
|
+-#ifdef CONFIG_TAXONOMY
|
|
+ { "signature", hostapd_cli_cmd_signature, hostapd_complete_stations,
|
|
+ "<addr> = get taxonomy signature for a station" },
|
|
+-#endif /* CONFIG_TAXONOMY */
|
|
+ { "sa_query", hostapd_cli_cmd_sa_query, hostapd_complete_stations,
|
|
+ "<addr> = send SA Query to a station" },
|
|
+-#ifdef CONFIG_WPS
|
|
+ { "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
|
|
+ "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
|
|
+ { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
|
|
+@@ -1641,7 +1634,6 @@ static const struct hostapd_cli_cmd host
|
|
+ "<SSID> <auth> <encr> <key> = configure AP" },
|
|
+ { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
|
|
+ "= show current WPS status" },
|
|
+-#endif /* CONFIG_WPS */
|
|
+ { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL,
|
|
+ "= send Disassociation Imminent notification" },
|
|
+ { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL,
|
|
diff --git a/package/network/services/hostapd/patches/431-wpa_cli_ifdef.patch b/package/network/services/hostapd/patches/431-wpa_cli_ifdef.patch
|
|
new file mode 100644
|
|
index 0000000000..65c31c567f
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/431-wpa_cli_ifdef.patch
|
|
@@ -0,0 +1,18 @@
|
|
+--- a/wpa_supplicant/wpa_cli.c
|
|
++++ b/wpa_supplicant/wpa_cli.c
|
|
+@@ -26,6 +26,15 @@
|
|
+ #include <cutils/properties.h>
|
|
+ #endif /* ANDROID */
|
|
+
|
|
++#ifndef CONFIG_P2P
|
|
++#define CONFIG_P2P
|
|
++#endif
|
|
++#ifndef CONFIG_AP
|
|
++#define CONFIG_AP
|
|
++#endif
|
|
++#ifndef CONFIG_MESH
|
|
++#define CONFIG_MESH
|
|
++#endif
|
|
+
|
|
+ static const char *const wpa_cli_version =
|
|
+ "wpa_cli v" VERSION_STR "\n"
|
|
diff --git a/package/network/services/hostapd/patches/460-wpa_supplicant-add-new-config-params-to-be-used-with.patch b/package/network/services/hostapd/patches/460-wpa_supplicant-add-new-config-params-to-be-used-with.patch
|
|
new file mode 100644
|
|
index 0000000000..e50c609d97
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/460-wpa_supplicant-add-new-config-params-to-be-used-with.patch
|
|
@@ -0,0 +1,189 @@
|
|
+From 4bb69d15477e0f2b00e166845341dc933de47c58 Mon Sep 17 00:00:00 2001
|
|
+From: Antonio Quartulli <ordex@autistici.org>
|
|
+Date: Sun, 3 Jun 2012 18:22:56 +0200
|
|
+Subject: [PATCHv2 601/602] wpa_supplicant: add new config params to be used
|
|
+ with the ibss join command
|
|
+
|
|
+Signed-hostap: Antonio Quartulli <ordex@autistici.org>
|
|
+---
|
|
+ src/drivers/driver.h | 6 +++
|
|
+ wpa_supplicant/config.c | 96 +++++++++++++++++++++++++++++++++++++++
|
|
+ wpa_supplicant/config_ssid.h | 6 +++
|
|
+ wpa_supplicant/wpa_supplicant.c | 23 +++++++---
|
|
+ 4 files changed, 124 insertions(+), 7 deletions(-)
|
|
+
|
|
+--- a/src/drivers/driver.h
|
|
++++ b/src/drivers/driver.h
|
|
+@@ -19,6 +19,7 @@
|
|
+
|
|
+ #define WPA_SUPPLICANT_DRIVER_VERSION 4
|
|
+
|
|
++#include "ap/sta_info.h"
|
|
+ #include "common/defs.h"
|
|
+ #include "common/ieee802_11_defs.h"
|
|
+ #include "common/wpa_common.h"
|
|
+@@ -953,6 +954,9 @@ struct wpa_driver_associate_params {
|
|
+ * responsible for selecting with which BSS to associate. */
|
|
+ const u8 *bssid;
|
|
+
|
|
++ unsigned char rates[WLAN_SUPP_RATES_MAX];
|
|
++ int mcast_rate;
|
|
++
|
|
+ /**
|
|
+ * bssid_hint - BSSID of a proposed AP
|
|
+ *
|
|
+--- a/wpa_supplicant/config.c
|
|
++++ b/wpa_supplicant/config.c
|
|
+@@ -18,6 +18,7 @@
|
|
+ #include "eap_peer/eap.h"
|
|
+ #include "p2p/p2p.h"
|
|
+ #include "fst/fst.h"
|
|
++#include "ap/sta_info.h"
|
|
+ #include "config.h"
|
|
+
|
|
+
|
|
+@@ -2389,6 +2390,97 @@ static char * wpa_config_write_mac_value
|
|
+ #endif /* NO_CONFIG_WRITE */
|
|
+
|
|
+
|
|
++static int wpa_config_parse_mcast_rate(const struct parse_data *data,
|
|
++ struct wpa_ssid *ssid, int line,
|
|
++ const char *value)
|
|
++{
|
|
++ ssid->mcast_rate = (int)(strtod(value, NULL) * 10);
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++#ifndef NO_CONFIG_WRITE
|
|
++static char * wpa_config_write_mcast_rate(const struct parse_data *data,
|
|
++ struct wpa_ssid *ssid)
|
|
++{
|
|
++ char *value;
|
|
++ int res;
|
|
++
|
|
++ if (!ssid->mcast_rate == 0)
|
|
++ return NULL;
|
|
++
|
|
++ value = os_malloc(6); /* longest: 300.0 */
|
|
++ if (value == NULL)
|
|
++ return NULL;
|
|
++ res = os_snprintf(value, 5, "%.1f", (double)ssid->mcast_rate / 10);
|
|
++ if (res < 0) {
|
|
++ os_free(value);
|
|
++ return NULL;
|
|
++ }
|
|
++ return value;
|
|
++}
|
|
++#endif /* NO_CONFIG_WRITE */
|
|
++
|
|
++static int wpa_config_parse_rates(const struct parse_data *data,
|
|
++ struct wpa_ssid *ssid, int line,
|
|
++ const char *value)
|
|
++{
|
|
++ int i;
|
|
++ char *pos, *r, *sptr, *end;
|
|
++ double rate;
|
|
++
|
|
++ pos = (char *)value;
|
|
++ r = strtok_r(pos, ",", &sptr);
|
|
++ i = 0;
|
|
++ while (pos && i < WLAN_SUPP_RATES_MAX) {
|
|
++ rate = 0.0;
|
|
++ if (r)
|
|
++ rate = strtod(r, &end);
|
|
++ ssid->rates[i] = rate * 2;
|
|
++ if (*end != '\0' || rate * 2 != ssid->rates[i])
|
|
++ return 1;
|
|
++
|
|
++ i++;
|
|
++ r = strtok_r(NULL, ",", &sptr);
|
|
++ }
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++#ifndef NO_CONFIG_WRITE
|
|
++static char * wpa_config_write_rates(const struct parse_data *data,
|
|
++ struct wpa_ssid *ssid)
|
|
++{
|
|
++ char *value, *pos;
|
|
++ int res, i;
|
|
++
|
|
++ if (ssid->rates[0] <= 0)
|
|
++ return NULL;
|
|
++
|
|
++ value = os_malloc(6 * WLAN_SUPP_RATES_MAX + 1);
|
|
++ if (value == NULL)
|
|
++ return NULL;
|
|
++ pos = value;
|
|
++ for (i = 0; i < WLAN_SUPP_RATES_MAX - 1; i++) {
|
|
++ res = os_snprintf(pos, 6, "%.1f,", (double)ssid->rates[i] / 2);
|
|
++ if (res < 0) {
|
|
++ os_free(value);
|
|
++ return NULL;
|
|
++ }
|
|
++ pos += res;
|
|
++ }
|
|
++ res = os_snprintf(pos, 6, "%.1f",
|
|
++ (double)ssid->rates[WLAN_SUPP_RATES_MAX - 1] / 2);
|
|
++ if (res < 0) {
|
|
++ os_free(value);
|
|
++ return NULL;
|
|
++ }
|
|
++
|
|
++ value[6 * WLAN_SUPP_RATES_MAX] = '\0';
|
|
++ return value;
|
|
++}
|
|
++#endif /* NO_CONFIG_WRITE */
|
|
++
|
|
+ /* Helper macros for network block parser */
|
|
+
|
|
+ #ifdef OFFSET
|
|
+@@ -2674,6 +2766,8 @@ static const struct parse_data ssid_fiel
|
|
+ { INT(ap_max_inactivity) },
|
|
+ { INT(dtim_period) },
|
|
+ { INT(beacon_int) },
|
|
++ { FUNC(rates) },
|
|
++ { FUNC(mcast_rate) },
|
|
+ #ifdef CONFIG_MACSEC
|
|
+ { INT_RANGE(macsec_policy, 0, 1) },
|
|
+ { INT_RANGE(macsec_integ_only, 0, 1) },
|
|
+--- a/wpa_supplicant/config_ssid.h
|
|
++++ b/wpa_supplicant/config_ssid.h
|
|
+@@ -10,8 +10,10 @@
|
|
+ #define CONFIG_SSID_H
|
|
+
|
|
+ #include "common/defs.h"
|
|
++#include "ap/sta_info.h"
|
|
+ #include "utils/list.h"
|
|
+ #include "eap_peer/eap_config.h"
|
|
++#include "drivers/nl80211_copy.h"
|
|
+
|
|
+
|
|
+ #define DEFAULT_EAP_WORKAROUND ((unsigned int) -1)
|
|
+@@ -879,6 +881,9 @@ struct wpa_ssid {
|
|
+ */
|
|
+ void *parent_cred;
|
|
+
|
|
++ unsigned char rates[WLAN_SUPP_RATES_MAX];
|
|
++ double mcast_rate;
|
|
++
|
|
+ #ifdef CONFIG_MACSEC
|
|
+ /**
|
|
+ * macsec_policy - Determines the policy for MACsec secure session
|
|
+--- a/wpa_supplicant/wpa_supplicant.c
|
|
++++ b/wpa_supplicant/wpa_supplicant.c
|
|
+@@ -4149,6 +4149,12 @@ static void wpas_start_assoc_cb(struct w
|
|
+ params.beacon_int = ssid->beacon_int;
|
|
+ else
|
|
+ params.beacon_int = wpa_s->conf->beacon_int;
|
|
++ int i = 0;
|
|
++ while (i < WLAN_SUPP_RATES_MAX) {
|
|
++ params.rates[i] = ssid->rates[i];
|
|
++ i++;
|
|
++ }
|
|
++ params.mcast_rate = ssid->mcast_rate;
|
|
+ }
|
|
+
|
|
+ if (bss && ssid->enable_edmg)
|
|
diff --git a/package/network/services/hostapd/patches/463-add-mcast_rate-to-11s.patch b/package/network/services/hostapd/patches/463-add-mcast_rate-to-11s.patch
|
|
new file mode 100644
|
|
index 0000000000..be9e0507d6
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/463-add-mcast_rate-to-11s.patch
|
|
@@ -0,0 +1,68 @@
|
|
+From: Sven Eckelmann <sven.eckelmann@openmesh.com>
|
|
+Date: Thu, 11 May 2017 08:21:45 +0200
|
|
+Subject: [PATCH] set mcast_rate in mesh mode
|
|
+
|
|
+The wpa_supplicant code for IBSS allows to set the mcast rate. It is
|
|
+recommended to increase this value from 1 or 6 Mbit/s to something higher
|
|
+when using a mesh protocol on top which uses the multicast packet loss as
|
|
+indicator for the link quality.
|
|
+
|
|
+This setting was unfortunately not applied for mesh mode. But it would be
|
|
+beneficial when wpa_supplicant would behave similar to IBSS mode and set
|
|
+this argument during mesh join like authsae already does. At least it is
|
|
+helpful for companies/projects which are currently switching to 802.11s
|
|
+(without mesh_fwding and with mesh_ttl set to 1) as replacement for IBSS
|
|
+because newer drivers seem to support 802.11s but not IBSS anymore.
|
|
+
|
|
+Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
|
|
+Tested-by: Simon Wunderlich <simon.wunderlich@openmesh.com>
|
|
+
|
|
+--- a/src/drivers/driver.h
|
|
++++ b/src/drivers/driver.h
|
|
+@@ -1827,6 +1827,7 @@ struct wpa_driver_mesh_join_params {
|
|
+ #define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008
|
|
+ unsigned int flags;
|
|
+ bool handle_dfs;
|
|
++ int mcast_rate;
|
|
+ };
|
|
+
|
|
+ struct wpa_driver_set_key_params {
|
|
+--- a/src/drivers/driver_nl80211.c
|
|
++++ b/src/drivers/driver_nl80211.c
|
|
+@@ -11626,6 +11626,18 @@ static int nl80211_put_mesh_id(struct nl
|
|
+ }
|
|
+
|
|
+
|
|
++static int nl80211_put_mcast_rate(struct nl_msg *msg, int mcast_rate)
|
|
++{
|
|
++ if (mcast_rate > 0) {
|
|
++ wpa_printf(MSG_DEBUG, " * mcast_rate=%.1f",
|
|
++ (double)mcast_rate / 10);
|
|
++ return nla_put_u32(msg, NL80211_ATTR_MCAST_RATE, mcast_rate);
|
|
++ }
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++
|
|
+ static int nl80211_put_mesh_config(struct nl_msg *msg,
|
|
+ struct wpa_driver_mesh_bss_params *params)
|
|
+ {
|
|
+@@ -11687,6 +11699,7 @@ static int nl80211_join_mesh(struct i802
|
|
+ nl80211_put_basic_rates(msg, params->basic_rates) ||
|
|
+ nl80211_put_mesh_id(msg, params->meshid, params->meshid_len) ||
|
|
+ nl80211_put_beacon_int(msg, params->beacon_int) ||
|
|
++ nl80211_put_mcast_rate(msg, params->mcast_rate) ||
|
|
+ nl80211_put_dtim_period(msg, params->dtim_period))
|
|
+ goto fail;
|
|
+
|
|
+--- a/wpa_supplicant/mesh.c
|
|
++++ b/wpa_supplicant/mesh.c
|
|
+@@ -632,6 +632,7 @@ int wpa_supplicant_join_mesh(struct wpa_
|
|
+
|
|
+ params->meshid = ssid->ssid;
|
|
+ params->meshid_len = ssid->ssid_len;
|
|
++ params->mcast_rate = ssid->mcast_rate;
|
|
+ ibss_mesh_setup_freq(wpa_s, ssid, ¶ms->freq);
|
|
+ wpa_s->mesh_ht_enabled = !!params->freq.ht_enabled;
|
|
+ wpa_s->mesh_vht_enabled = !!params->freq.vht_enabled;
|
|
diff --git a/package/network/services/hostapd/patches/464-fix-mesh-obss-check.patch b/package/network/services/hostapd/patches/464-fix-mesh-obss-check.patch
|
|
new file mode 100644
|
|
index 0000000000..4d7d85f4ab
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/464-fix-mesh-obss-check.patch
|
|
@@ -0,0 +1,13 @@
|
|
+--- a/wpa_supplicant/wpa_supplicant.c
|
|
++++ b/wpa_supplicant/wpa_supplicant.c
|
|
+@@ -3040,6 +3040,10 @@ void ibss_mesh_setup_freq(struct wpa_sup
|
|
+
|
|
+ freq->freq = ssid->frequency;
|
|
+
|
|
++ if (ssid->fixed_freq) {
|
|
++ obss_scan = 0;
|
|
++ }
|
|
++
|
|
+ if (ssid->mode == WPAS_MODE_IBSS && !ssid->fixed_freq) {
|
|
+ struct wpa_bss *bss = ibss_find_existing_bss(wpa_s, ssid);
|
|
+
|
|
diff --git a/package/network/services/hostapd/patches/465-hostapd-config-support-random-BSS-color.patch b/package/network/services/hostapd/patches/465-hostapd-config-support-random-BSS-color.patch
|
|
new file mode 100644
|
|
index 0000000000..7d3d94648e
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/465-hostapd-config-support-random-BSS-color.patch
|
|
@@ -0,0 +1,24 @@
|
|
+From c9304d3303d563ad6d2619f4e07864ed12f96889 Mon Sep 17 00:00:00 2001
|
|
+From: David Bauer <mail@david-bauer.net>
|
|
+Date: Sat, 14 May 2022 21:41:03 +0200
|
|
+Subject: [PATCH] hostapd: config: support random BSS color
|
|
+
|
|
+Configure the HE BSS color to a random value in case the config defines
|
|
+a BSS color which exceeds the max BSS color (63).
|
|
+
|
|
+Signed-off-by: David Bauer <mail@david-bauer.net>
|
|
+---
|
|
+ hostapd/config_file.c | 2 ++
|
|
+ 1 file changed, 2 insertions(+)
|
|
+
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -3500,6 +3500,8 @@ static int hostapd_config_fill(struct ho
|
|
+ } else if (os_strcmp(buf, "he_bss_color") == 0) {
|
|
+ conf->he_op.he_bss_color = atoi(pos) & 0x3f;
|
|
+ conf->he_op.he_bss_color_disabled = 0;
|
|
++ if (atoi(pos) > 63)
|
|
++ conf->he_op.he_bss_color = os_random() % 63 + 1;
|
|
+ } 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) {
|
|
diff --git a/package/network/services/hostapd/patches/470-survey_data_fallback.patch b/package/network/services/hostapd/patches/470-survey_data_fallback.patch
|
|
new file mode 100644
|
|
index 0000000000..79ab48c5c2
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/470-survey_data_fallback.patch
|
|
@@ -0,0 +1,30 @@
|
|
+--- a/src/ap/acs.c
|
|
++++ b/src/ap/acs.c
|
|
+@@ -455,17 +455,17 @@ static int acs_get_bw_center_chan(int fr
|
|
+ static int acs_survey_is_sufficient(struct freq_survey *survey)
|
|
+ {
|
|
+ if (!(survey->filled & SURVEY_HAS_NF)) {
|
|
++ survey->nf = -95;
|
|
+ wpa_printf(MSG_INFO,
|
|
+ "ACS: Survey for freq %d is missing noise floor",
|
|
+ survey->freq);
|
|
+- return 0;
|
|
+ }
|
|
+
|
|
+ if (!(survey->filled & SURVEY_HAS_CHAN_TIME)) {
|
|
++ survey->channel_time = 0;
|
|
+ wpa_printf(MSG_INFO,
|
|
+ "ACS: Survey for freq %d is missing channel time",
|
|
+ survey->freq);
|
|
+- return 0;
|
|
+ }
|
|
+
|
|
+ if (!(survey->filled & SURVEY_HAS_CHAN_TIME_BUSY) &&
|
|
+@@ -473,7 +473,6 @@ static int acs_survey_is_sufficient(stru
|
|
+ wpa_printf(MSG_INFO,
|
|
+ "ACS: Survey for freq %d is missing RX and busy time (at least one is required)",
|
|
+ survey->freq);
|
|
+- return 0;
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
diff --git a/package/network/services/hostapd/patches/500-lto-jobserver-support.patch b/package/network/services/hostapd/patches/500-lto-jobserver-support.patch
|
|
new file mode 100644
|
|
index 0000000000..67312c5004
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/500-lto-jobserver-support.patch
|
|
@@ -0,0 +1,59 @@
|
|
+--- a/hostapd/Makefile
|
|
++++ b/hostapd/Makefile
|
|
+@@ -1396,7 +1396,7 @@ hostapd_multi.a: $(BCHECK) $(OBJS)
|
|
+ @$(AR) cr $@ hostapd_multi.o $(OBJS)
|
|
+
|
|
+ hostapd: $(OBJS)
|
|
+- $(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
|
|
++ +$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
|
|
+ @$(E) " LD " $@
|
|
+
|
|
+ ifdef CONFIG_WPA_TRACE
|
|
+@@ -1407,7 +1407,7 @@ _OBJS_VAR := OBJS_c
|
|
+ include ../src/objs.mk
|
|
+
|
|
+ hostapd_cli: $(OBJS_c)
|
|
+- $(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
|
|
++ +$(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c)
|
|
+ @$(E) " LD " $@
|
|
+
|
|
+ NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS)
|
|
+--- a/wpa_supplicant/Makefile
|
|
++++ b/wpa_supplicant/Makefile
|
|
+@@ -2037,31 +2037,31 @@ wpa_supplicant_multi.a: .config $(BCHECK
|
|
+ @$(AR) cr $@ wpa_supplicant_multi.o $(OBJS)
|
|
+
|
|
+ wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)
|
|
+- $(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
|
|
++ +$(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)
|
|
++ +$(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)
|
|
++ +$(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)
|
|
++ +$(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)
|
|
++ +$(Q)$(LDO) $(LDFLAGS) -o wpa_cli $(OBJS_c) $(LIBS_c)
|
|
+ @$(E) " LD " $@
|
|
+
|
|
+ LIBCTRL += ../src/common/wpa_ctrl.o
|
|
diff --git a/package/network/services/hostapd/patches/590-rrm-wnm-statistics.patch b/package/network/services/hostapd/patches/590-rrm-wnm-statistics.patch
|
|
new file mode 100644
|
|
index 0000000000..0efa6db908
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/590-rrm-wnm-statistics.patch
|
|
@@ -0,0 +1,92 @@
|
|
+--- a/src/ap/hostapd.h
|
|
++++ b/src/ap/hostapd.h
|
|
+@@ -163,6 +163,21 @@ struct hostapd_sae_commit_queue {
|
|
+ };
|
|
+
|
|
+ /**
|
|
++ * struct hostapd_openwrt_stats - OpenWrt custom STA/AP statistics
|
|
++ */
|
|
++struct hostapd_openwrt_stats {
|
|
++ struct {
|
|
++ u64 neighbor_report_tx;
|
|
++ } rrm;
|
|
++
|
|
++ struct {
|
|
++ u64 bss_transition_query_rx;
|
|
++ u64 bss_transition_request_tx;
|
|
++ u64 bss_transition_response_rx;
|
|
++ } wnm;
|
|
++};
|
|
++
|
|
++/**
|
|
+ * struct hostapd_data - hostapd per-BSS data structure
|
|
+ */
|
|
+ struct hostapd_data {
|
|
+@@ -182,6 +197,9 @@ struct hostapd_data {
|
|
+
|
|
+ struct hostapd_data *mld_first_bss;
|
|
+
|
|
++ /* OpenWrt specific statistics */
|
|
++ struct hostapd_openwrt_stats openwrt_stats;
|
|
++
|
|
+ int num_sta; /* number of entries in sta_list */
|
|
+ struct sta_info *sta_list; /* STA info list head */
|
|
+ #define STA_HASH_SIZE 256
|
|
+--- a/src/ap/wnm_ap.c
|
|
++++ b/src/ap/wnm_ap.c
|
|
+@@ -386,6 +386,7 @@ static int ieee802_11_send_bss_trans_mgm
|
|
+ mgmt->u.action.u.bss_tm_req.validity_interval = 1;
|
|
+ pos = mgmt->u.action.u.bss_tm_req.variable;
|
|
+
|
|
++ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
|
|
+ wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request to "
|
|
+ MACSTR " dialog_token=%u req_mode=0x%x disassoc_timer=%u "
|
|
+ "validity_interval=%u",
|
|
+@@ -790,10 +791,12 @@ int ieee802_11_rx_wnm_action_ap(struct h
|
|
+ plen);
|
|
+ return 0;
|
|
+ case WNM_BSS_TRANS_MGMT_QUERY:
|
|
++ hapd->openwrt_stats.wnm.bss_transition_query_rx++;
|
|
+ ieee802_11_rx_bss_trans_mgmt_query(hapd, mgmt->sa, payload,
|
|
+ plen);
|
|
+ return 0;
|
|
+ case WNM_BSS_TRANS_MGMT_RESP:
|
|
++ hapd->openwrt_stats.wnm.bss_transition_response_rx++;
|
|
+ ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload,
|
|
+ plen);
|
|
+ return 0;
|
|
+@@ -840,6 +843,7 @@ int wnm_send_disassoc_imminent(struct ho
|
|
+
|
|
+ pos = mgmt->u.action.u.bss_tm_req.variable;
|
|
+
|
|
++ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
|
|
+ wpa_printf(MSG_DEBUG, "WNM: Send BSS Transition Management Request frame to indicate imminent disassociation (disassoc_timer=%d) to "
|
|
+ MACSTR, disassoc_timer, MAC2STR(sta->addr));
|
|
+ if (hostapd_drv_send_mlme(hapd, buf, pos - buf, 0, NULL, 0, 0) < 0) {
|
|
+@@ -921,6 +925,7 @@ int wnm_send_ess_disassoc_imminent(struc
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
++ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
|
|
+ if (disassoc_timer) {
|
|
+ /* send disassociation frame after time-out */
|
|
+ set_disassoc_timer(hapd, sta, disassoc_timer);
|
|
+@@ -1001,6 +1006,7 @@ int wnm_send_bss_tm_req(struct hostapd_d
|
|
+ }
|
|
+ os_free(buf);
|
|
+
|
|
++ hapd->openwrt_stats.wnm.bss_transition_request_tx++;
|
|
+ if (disassoc_timer) {
|
|
+ /* send disassociation frame after time-out */
|
|
+ set_disassoc_timer(hapd, sta, disassoc_timer);
|
|
+--- a/src/ap/rrm.c
|
|
++++ b/src/ap/rrm.c
|
|
+@@ -269,6 +269,8 @@ static void hostapd_send_nei_report_resp
|
|
+ }
|
|
+ }
|
|
+
|
|
++ hapd->openwrt_stats.rrm.neighbor_report_tx++;
|
|
++
|
|
+ hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
|
|
+ wpabuf_head(buf), wpabuf_len(buf));
|
|
+ wpabuf_free(buf);
|
|
diff --git a/package/network/services/hostapd/patches/599-wpa_supplicant-fix-warnings.patch b/package/network/services/hostapd/patches/599-wpa_supplicant-fix-warnings.patch
|
|
new file mode 100644
|
|
index 0000000000..e70dc61419
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/599-wpa_supplicant-fix-warnings.patch
|
|
@@ -0,0 +1,19 @@
|
|
+--- a/wpa_supplicant/wps_supplicant.h
|
|
++++ b/wpa_supplicant/wps_supplicant.h
|
|
+@@ -9,6 +9,7 @@
|
|
+ #ifndef WPS_SUPPLICANT_H
|
|
+ #define WPS_SUPPLICANT_H
|
|
+
|
|
++struct wpa_bss;
|
|
+ struct wpa_scan_results;
|
|
+
|
|
+ #ifdef CONFIG_WPS
|
|
+@@ -16,8 +17,6 @@ struct wpa_scan_results;
|
|
+ #include "wps/wps.h"
|
|
+ #include "wps/wps_defs.h"
|
|
+
|
|
+-struct wpa_bss;
|
|
+-
|
|
+ struct wps_new_ap_settings {
|
|
+ const char *ssid_hex;
|
|
+ const char *auth;
|
|
diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch b/package/network/services/hostapd/patches/600-ubus_support.patch
|
|
new file mode 100644
|
|
index 0000000000..5b2745a3be
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/600-ubus_support.patch
|
|
@@ -0,0 +1,748 @@
|
|
+--- a/hostapd/Makefile
|
|
++++ b/hostapd/Makefile
|
|
+@@ -166,6 +166,12 @@ OBJS += ../src/common/hw_features_common
|
|
+
|
|
+ OBJS += ../src/eapol_auth/eapol_auth_sm.o
|
|
+
|
|
++ifdef CONFIG_UBUS
|
|
++CFLAGS += -DUBUS_SUPPORT
|
|
++OBJS += ../src/utils/uloop.o
|
|
++OBJS += ../src/ap/ubus.o
|
|
++LIBS += -lubox -lubus
|
|
++endif
|
|
+
|
|
+ ifdef CONFIG_CODE_COVERAGE
|
|
+ CFLAGS += -O0 -fprofile-arcs -ftest-coverage
|
|
+--- a/src/ap/hostapd.h
|
|
++++ b/src/ap/hostapd.h
|
|
+@@ -18,6 +18,7 @@
|
|
+ #include "utils/list.h"
|
|
+ #include "ap_config.h"
|
|
+ #include "drivers/driver.h"
|
|
++#include "ubus.h"
|
|
+
|
|
+ #define OCE_STA_CFON_ENABLED(hapd) \
|
|
+ ((hapd->conf->oce & OCE_STA_CFON) && \
|
|
+@@ -184,6 +185,7 @@ struct hostapd_data {
|
|
+ struct hostapd_iface *iface;
|
|
+ struct hostapd_config *iconf;
|
|
+ struct hostapd_bss_config *conf;
|
|
++ struct hostapd_ubus_bss ubus;
|
|
+ int interface_added; /* virtual interface added for this BSS */
|
|
+ unsigned int started:1;
|
|
+ unsigned int disabled:1;
|
|
+@@ -695,6 +697,7 @@ hostapd_alloc_bss_data(struct hostapd_if
|
|
+ struct hostapd_bss_config *bss);
|
|
+ int hostapd_setup_interface(struct hostapd_iface *iface);
|
|
+ int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err);
|
|
++void hostapd_set_own_neighbor_report(struct hostapd_data *hapd);
|
|
+ void hostapd_interface_deinit(struct hostapd_iface *iface);
|
|
+ void hostapd_interface_free(struct hostapd_iface *iface);
|
|
+ struct hostapd_iface * hostapd_alloc_iface(void);
|
|
+--- a/src/ap/hostapd.c
|
|
++++ b/src/ap/hostapd.c
|
|
+@@ -435,6 +435,7 @@ void hostapd_free_hapd_data(struct hosta
|
|
+ hapd->beacon_set_done = 0;
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
|
|
++ hostapd_ubus_free_bss(hapd);
|
|
+ accounting_deinit(hapd);
|
|
+ hostapd_deinit_wpa(hapd);
|
|
+ vlan_deinit(hapd);
|
|
+@@ -1187,6 +1188,8 @@ static int hostapd_start_beacon(struct h
|
|
+ if (hapd->driver && hapd->driver->set_operstate)
|
|
+ hapd->driver->set_operstate(hapd->drv_priv, 1);
|
|
+
|
|
++ hostapd_ubus_add_bss(hapd);
|
|
++
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+@@ -2275,6 +2278,7 @@ static int hostapd_setup_interface_compl
|
|
+ if (err)
|
|
+ goto fail;
|
|
+
|
|
++ hostapd_ubus_add_iface(iface);
|
|
+ wpa_printf(MSG_DEBUG, "Completing interface initialization");
|
|
+ if (iface->freq) {
|
|
+ #ifdef NEED_AP_MLME
|
|
+@@ -2494,6 +2498,7 @@ dfs_offload:
|
|
+
|
|
+ fail:
|
|
+ wpa_printf(MSG_ERROR, "Interface initialization failed");
|
|
++ hostapd_ubus_free_iface(iface);
|
|
+
|
|
+ if (iface->is_no_ir) {
|
|
+ hostapd_set_state(iface, HAPD_IFACE_NO_IR);
|
|
+@@ -2984,6 +2989,7 @@ void hostapd_interface_deinit_free(struc
|
|
+ (unsigned int) iface->conf->num_bss);
|
|
+ driver = iface->bss[0]->driver;
|
|
+ drv_priv = iface->bss[0]->drv_priv;
|
|
++ hostapd_ubus_free_iface(iface);
|
|
+ hostapd_interface_deinit(iface);
|
|
+ wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
|
|
+ __func__, driver, drv_priv);
|
|
+--- a/src/ap/ieee802_11.c
|
|
++++ b/src/ap/ieee802_11.c
|
|
+@@ -2778,7 +2778,7 @@ static void handle_auth(struct hostapd_d
|
|
+ u16 auth_alg, auth_transaction, status_code;
|
|
+ u16 resp = WLAN_STATUS_SUCCESS;
|
|
+ struct sta_info *sta = NULL;
|
|
+- int res, reply_res;
|
|
++ int res, reply_res, ubus_resp;
|
|
+ u16 fc;
|
|
+ const u8 *challenge = NULL;
|
|
+ u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
|
|
+@@ -2787,6 +2787,11 @@ static void handle_auth(struct hostapd_d
|
|
+ struct radius_sta rad_info;
|
|
+ const u8 *dst, *sa, *bssid;
|
|
+ bool mld_sta = false;
|
|
++ struct hostapd_ubus_request req = {
|
|
++ .type = HOSTAPD_UBUS_AUTH_REQ,
|
|
++ .mgmt_frame = mgmt,
|
|
++ .ssi_signal = rssi,
|
|
++ };
|
|
+
|
|
+ if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
|
|
+ wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
|
|
+@@ -2978,6 +2983,13 @@ static void handle_auth(struct hostapd_d
|
|
+ resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
|
+ goto fail;
|
|
+ }
|
|
++ ubus_resp = hostapd_ubus_handle_event(hapd, &req);
|
|
++ if (ubus_resp) {
|
|
++ wpa_printf(MSG_DEBUG, "Station " MACSTR " rejected by ubus handler.\n",
|
|
++ MAC2STR(mgmt->sa));
|
|
++ resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE;
|
|
++ goto fail;
|
|
++ }
|
|
+ if (res == HOSTAPD_ACL_PENDING)
|
|
+ return;
|
|
+
|
|
+@@ -5141,7 +5153,7 @@ static void handle_assoc(struct hostapd_
|
|
+ int resp = WLAN_STATUS_SUCCESS;
|
|
+ u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE;
|
|
+ const u8 *pos;
|
|
+- int left, i;
|
|
++ int left, i, ubus_resp;
|
|
+ struct sta_info *sta;
|
|
+ u8 *tmp = NULL;
|
|
+ #ifdef CONFIG_FILS
|
|
+@@ -5354,6 +5366,11 @@ static void handle_assoc(struct hostapd_
|
|
+ left = res;
|
|
+ }
|
|
+ #endif /* CONFIG_FILS */
|
|
++ struct hostapd_ubus_request req = {
|
|
++ .type = HOSTAPD_UBUS_ASSOC_REQ,
|
|
++ .mgmt_frame = mgmt,
|
|
++ .ssi_signal = rssi,
|
|
++ };
|
|
+
|
|
+ /* followed by SSID and Supported rates; and HT capabilities if 802.11n
|
|
+ * is used */
|
|
+@@ -5452,6 +5469,13 @@ static void handle_assoc(struct hostapd_
|
|
+ }
|
|
+ #endif /* CONFIG_FILS */
|
|
+
|
|
++ ubus_resp = hostapd_ubus_handle_event(hapd, &req);
|
|
++ if (ubus_resp) {
|
|
++ wpa_printf(MSG_DEBUG, "Station " MACSTR " assoc rejected by ubus handler.\n",
|
|
++ MAC2STR(mgmt->sa));
|
|
++ resp = ubus_resp > 0 ? (u16) ubus_resp : WLAN_STATUS_UNSPECIFIED_FAILURE;
|
|
++ goto fail;
|
|
++ }
|
|
+ fail:
|
|
+
|
|
+ /*
|
|
+@@ -5733,6 +5757,7 @@ static void handle_disassoc(struct hosta
|
|
+ (unsigned long) len);
|
|
+ return;
|
|
+ }
|
|
++ hostapd_ubus_notify(hapd, "disassoc", mgmt->sa);
|
|
+
|
|
+ sta = ap_get_sta(hapd, mgmt->sa);
|
|
+ if (!sta) {
|
|
+@@ -5764,6 +5789,8 @@ static void handle_deauth(struct hostapd
|
|
+ /* Clear the PTKSA cache entries for PASN */
|
|
+ ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE);
|
|
+
|
|
++ hostapd_ubus_notify(hapd, "deauth", mgmt->sa);
|
|
++
|
|
+ sta = ap_get_sta(hapd, mgmt->sa);
|
|
+ if (!sta) {
|
|
+ wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR
|
|
+--- a/src/ap/beacon.c
|
|
++++ b/src/ap/beacon.c
|
|
+@@ -1036,6 +1036,12 @@ void handle_probe_req(struct hostapd_dat
|
|
+ u16 csa_offs[2];
|
|
+ size_t csa_offs_len;
|
|
+ struct radius_sta rad_info;
|
|
++ struct hostapd_ubus_request req = {
|
|
++ .type = HOSTAPD_UBUS_PROBE_REQ,
|
|
++ .mgmt_frame = mgmt,
|
|
++ .ssi_signal = ssi_signal,
|
|
++ .elems = &elems,
|
|
++ };
|
|
+
|
|
+ if (hapd->iconf->rssi_ignore_probe_request && ssi_signal &&
|
|
+ ssi_signal < hapd->iconf->rssi_ignore_probe_request)
|
|
+@@ -1222,6 +1228,12 @@ void handle_probe_req(struct hostapd_dat
|
|
+ }
|
|
+ #endif /* CONFIG_P2P */
|
|
+
|
|
++ if (hostapd_ubus_handle_event(hapd, &req)) {
|
|
++ wpa_printf(MSG_DEBUG, "Probe request for " MACSTR " rejected by ubus handler.\n",
|
|
++ MAC2STR(mgmt->sa));
|
|
++ return;
|
|
++ }
|
|
++
|
|
+ /* TODO: verify that supp_rates contains at least one matching rate
|
|
+ * with AP configuration */
|
|
+
|
|
+--- a/src/ap/drv_callbacks.c
|
|
++++ b/src/ap/drv_callbacks.c
|
|
+@@ -145,6 +145,10 @@ int hostapd_notif_assoc(struct hostapd_d
|
|
+ u16 reason = WLAN_REASON_UNSPECIFIED;
|
|
+ int status = WLAN_STATUS_SUCCESS;
|
|
+ const u8 *p2p_dev_addr = NULL;
|
|
++ struct hostapd_ubus_request req = {
|
|
++ .type = HOSTAPD_UBUS_ASSOC_REQ,
|
|
++ .addr = addr,
|
|
++ };
|
|
+
|
|
+ if (addr == NULL) {
|
|
+ /*
|
|
+@@ -237,6 +241,12 @@ int hostapd_notif_assoc(struct hostapd_d
|
|
+ goto fail;
|
|
+ }
|
|
+
|
|
++ if (hostapd_ubus_handle_event(hapd, &req)) {
|
|
++ wpa_printf(MSG_DEBUG, "Station " MACSTR " assoc rejected by ubus handler.\n",
|
|
++ MAC2STR(req.addr));
|
|
++ goto fail;
|
|
++ }
|
|
++
|
|
+ #ifdef CONFIG_P2P
|
|
+ if (elems.p2p) {
|
|
+ wpabuf_free(sta->p2p_ie);
|
|
+--- a/src/ap/sta_info.c
|
|
++++ b/src/ap/sta_info.c
|
|
+@@ -471,6 +471,7 @@ void ap_handle_timer(void *eloop_ctx, vo
|
|
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
|
+ HOSTAPD_LEVEL_INFO, "deauthenticated due to "
|
|
+ "local deauth request");
|
|
++ hostapd_ubus_notify(hapd, "local-deauth", sta->addr);
|
|
+ ap_free_sta(hapd, sta);
|
|
+ return;
|
|
+ }
|
|
+@@ -626,6 +627,7 @@ skip_poll:
|
|
+ mlme_deauthenticate_indication(
|
|
+ hapd, sta,
|
|
+ WLAN_REASON_PREV_AUTH_NOT_VALID);
|
|
++ hostapd_ubus_notify(hapd, "inactive-deauth", sta->addr);
|
|
+ ap_free_sta(hapd, sta);
|
|
+ break;
|
|
+ }
|
|
+@@ -1344,15 +1346,28 @@ void ap_sta_set_authorized(struct hostap
|
|
+ sta->addr, authorized, dev_addr);
|
|
+
|
|
+ if (authorized) {
|
|
++ static const char * const auth_algs[] = {
|
|
++ [WLAN_AUTH_OPEN] = "open",
|
|
++ [WLAN_AUTH_SHARED_KEY] = "shared",
|
|
++ [WLAN_AUTH_FT] = "ft",
|
|
++ [WLAN_AUTH_SAE] = "sae",
|
|
++ [WLAN_AUTH_FILS_SK] = "fils-sk",
|
|
++ [WLAN_AUTH_FILS_SK_PFS] = "fils-sk-pfs",
|
|
++ [WLAN_AUTH_FILS_PK] = "fils-pk",
|
|
++ [WLAN_AUTH_PASN] = "pasn",
|
|
++ };
|
|
++ const char *auth_alg = NULL;
|
|
+ const u8 *dpp_pkhash;
|
|
+ const char *keyid;
|
|
+ char dpp_pkhash_buf[100];
|
|
+ char keyid_buf[100];
|
|
+ char ip_addr[100];
|
|
++ char alg_buf[100];
|
|
+
|
|
+ dpp_pkhash_buf[0] = '\0';
|
|
+ keyid_buf[0] = '\0';
|
|
+ ip_addr[0] = '\0';
|
|
++ alg_buf[0] = '\0';
|
|
+ #ifdef CONFIG_P2P
|
|
+ if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) {
|
|
+ os_snprintf(ip_addr, sizeof(ip_addr),
|
|
+@@ -1362,6 +1377,13 @@ void ap_sta_set_authorized(struct hostap
|
|
+ }
|
|
+ #endif /* CONFIG_P2P */
|
|
+
|
|
++ if (sta->auth_alg < ARRAY_SIZE(auth_algs))
|
|
++ auth_alg = auth_algs[sta->auth_alg];
|
|
++
|
|
++ if (auth_alg)
|
|
++ os_snprintf(alg_buf, sizeof(alg_buf),
|
|
++ " auth_alg=%s", auth_alg);
|
|
++
|
|
+ keyid = ap_sta_wpa_get_keyid(hapd, sta);
|
|
+ if (keyid) {
|
|
+ os_snprintf(keyid_buf, sizeof(keyid_buf),
|
|
+@@ -1380,17 +1402,19 @@ void ap_sta_set_authorized(struct hostap
|
|
+ dpp_pkhash, SHA256_MAC_LEN);
|
|
+ }
|
|
+
|
|
+- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s",
|
|
+- buf, ip_addr, keyid_buf, dpp_pkhash_buf);
|
|
++ hostapd_ubus_notify_authorized(hapd, sta, auth_alg);
|
|
++ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s%s",
|
|
++ buf, ip_addr, keyid_buf, dpp_pkhash_buf, alg_buf);
|
|
+
|
|
+ if (hapd->msg_ctx_parent &&
|
|
+ hapd->msg_ctx_parent != hapd->msg_ctx)
|
|
+ wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO,
|
|
+- AP_STA_CONNECTED "%s%s%s%s",
|
|
++ AP_STA_CONNECTED "%s%s%s%s%s",
|
|
+ buf, ip_addr, keyid_buf,
|
|
+- dpp_pkhash_buf);
|
|
++ dpp_pkhash_buf, alg_buf);
|
|
+ } else {
|
|
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf);
|
|
++ hostapd_ubus_notify(hapd, "disassoc", sta->addr);
|
|
+
|
|
+ if (hapd->msg_ctx_parent &&
|
|
+ hapd->msg_ctx_parent != hapd->msg_ctx)
|
|
+--- a/src/ap/wpa_auth_glue.c
|
|
++++ b/src/ap/wpa_auth_glue.c
|
|
+@@ -269,6 +269,7 @@ static void hostapd_wpa_auth_psk_failure
|
|
+ struct hostapd_data *hapd = ctx;
|
|
+ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR,
|
|
+ MAC2STR(addr));
|
|
++ hostapd_ubus_notify(hapd, "key-mismatch", addr);
|
|
+ }
|
|
+
|
|
+
|
|
+--- a/wpa_supplicant/Makefile
|
|
++++ b/wpa_supplicant/Makefile
|
|
+@@ -192,6 +192,13 @@ ifdef CONFIG_EAPOL_TEST
|
|
+ CFLAGS += -Werror -DEAPOL_TEST
|
|
+ endif
|
|
+
|
|
++ifdef CONFIG_UBUS
|
|
++CFLAGS += -DUBUS_SUPPORT
|
|
++OBJS += ubus.o
|
|
++OBJS += ../src/utils/uloop.o
|
|
++LIBS += -lubox -lubus
|
|
++endif
|
|
++
|
|
+ ifdef CONFIG_CODE_COVERAGE
|
|
+ CFLAGS += -O0 -fprofile-arcs -ftest-coverage
|
|
+ LIBS += -lgcov
|
|
+@@ -987,6 +994,9 @@ ifdef CONFIG_CTRL_IFACE_MIB
|
|
+ CFLAGS += -DCONFIG_CTRL_IFACE_MIB
|
|
+ endif
|
|
+ OBJS += ../src/ap/ctrl_iface_ap.o
|
|
++ifdef CONFIG_UBUS
|
|
++OBJS += ../src/ap/ubus.o
|
|
++endif
|
|
+ endif
|
|
+
|
|
+ CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
|
|
+--- a/wpa_supplicant/wpa_supplicant.c
|
|
++++ b/wpa_supplicant/wpa_supplicant.c
|
|
+@@ -7566,6 +7566,8 @@ struct wpa_supplicant * wpa_supplicant_a
|
|
+ }
|
|
+ #endif /* CONFIG_P2P */
|
|
+
|
|
++ wpas_ubus_add_bss(wpa_s);
|
|
++
|
|
+ return wpa_s;
|
|
+ }
|
|
+
|
|
+@@ -7592,6 +7594,8 @@ int wpa_supplicant_remove_iface(struct w
|
|
+ struct wpa_supplicant *parent = wpa_s->parent;
|
|
+ #endif /* CONFIG_MESH */
|
|
+
|
|
++ wpas_ubus_free_bss(wpa_s);
|
|
++
|
|
+ /* Remove interface from the global list of interfaces */
|
|
+ prev = global->ifaces;
|
|
+ if (prev == wpa_s) {
|
|
+@@ -7938,8 +7942,12 @@ int wpa_supplicant_run(struct wpa_global
|
|
+ eloop_register_signal_terminate(wpa_supplicant_terminate, global);
|
|
+ eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
|
|
+
|
|
++ wpas_ubus_add(global);
|
|
++
|
|
+ eloop_run();
|
|
+
|
|
++ wpas_ubus_free(global);
|
|
++
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+--- a/wpa_supplicant/wpa_supplicant_i.h
|
|
++++ b/wpa_supplicant/wpa_supplicant_i.h
|
|
+@@ -21,6 +21,7 @@
|
|
+ #include "config_ssid.h"
|
|
+ #include "wmm_ac.h"
|
|
+ #include "pasn/pasn_common.h"
|
|
++#include "ubus.h"
|
|
+
|
|
+ extern const char *const wpa_supplicant_version;
|
|
+ extern const char *const wpa_supplicant_license;
|
|
+@@ -319,6 +320,8 @@ struct wpa_global {
|
|
+ #endif /* CONFIG_WIFI_DISPLAY */
|
|
+
|
|
+ struct psk_list_entry *add_psk; /* From group formation */
|
|
++
|
|
++ struct ubus_object ubus_global;
|
|
+ };
|
|
+
|
|
+
|
|
+@@ -650,6 +653,7 @@ struct wpa_supplicant {
|
|
+ unsigned char own_addr[ETH_ALEN];
|
|
+ unsigned char perm_addr[ETH_ALEN];
|
|
+ char ifname[100];
|
|
++ struct wpas_ubus_bss ubus;
|
|
+ #ifdef CONFIG_MATCH_IFACE
|
|
+ int matched;
|
|
+ #endif /* CONFIG_MATCH_IFACE */
|
|
+--- a/wpa_supplicant/wps_supplicant.c
|
|
++++ b/wpa_supplicant/wps_supplicant.c
|
|
+@@ -33,6 +33,7 @@
|
|
+ #include "p2p/p2p.h"
|
|
+ #include "p2p_supplicant.h"
|
|
+ #include "wps_supplicant.h"
|
|
++#include "ubus.h"
|
|
+
|
|
+
|
|
+ #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG
|
|
+@@ -402,6 +403,8 @@ static int wpa_supplicant_wps_cred(void
|
|
+ wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
|
|
+ cred->cred_attr, cred->cred_attr_len);
|
|
+
|
|
++ wpas_ubus_notify(wpa_s, cred);
|
|
++
|
|
+ if (wpa_s->conf->wps_cred_processing == 1)
|
|
+ return 0;
|
|
+
|
|
+--- a/wpa_supplicant/main.c
|
|
++++ b/wpa_supplicant/main.c
|
|
+@@ -203,7 +203,7 @@ int main(int argc, char *argv[])
|
|
+
|
|
+ for (;;) {
|
|
+ c = getopt(argc, argv,
|
|
+- "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuv::W");
|
|
++ "b:Bc:C:D:de:f:g:G:hi:I:KLMm:nNo:O:p:P:qsTtuv::W");
|
|
+ if (c < 0)
|
|
+ break;
|
|
+ switch (c) {
|
|
+@@ -268,6 +268,9 @@ int main(int argc, char *argv[])
|
|
+ params.conf_p2p_dev = optarg;
|
|
+ break;
|
|
+ #endif /* CONFIG_P2P */
|
|
++ case 'n':
|
|
++ iface_count = 0;
|
|
++ break;
|
|
+ case 'o':
|
|
+ params.override_driver = optarg;
|
|
+ break;
|
|
+--- a/src/ap/rrm.c
|
|
++++ b/src/ap/rrm.c
|
|
+@@ -89,6 +89,9 @@ static void hostapd_handle_beacon_report
|
|
+ return;
|
|
+ wpa_msg(hapd->msg_ctx, MSG_INFO, BEACON_RESP_RX MACSTR " %u %02x %s",
|
|
+ MAC2STR(addr), token, rep_mode, report);
|
|
++ if (len < sizeof(struct rrm_measurement_beacon_report))
|
|
++ return;
|
|
++ hostapd_ubus_notify_beacon_report(hapd, addr, token, rep_mode, (struct rrm_measurement_beacon_report*) pos, len);
|
|
+ }
|
|
+
|
|
+
|
|
+@@ -352,6 +355,9 @@ void hostapd_handle_radio_measurement(st
|
|
+ mgmt->u.action.u.rrm.action, MAC2STR(mgmt->sa));
|
|
+
|
|
+ switch (mgmt->u.action.u.rrm.action) {
|
|
++ case WLAN_RRM_LINK_MEASUREMENT_REPORT:
|
|
++ hostapd_ubus_handle_link_measurement(hapd, buf, len);
|
|
++ break;
|
|
+ case WLAN_RRM_RADIO_MEASUREMENT_REPORT:
|
|
+ hostapd_handle_radio_msmt_report(hapd, buf, len);
|
|
+ break;
|
|
+--- a/src/ap/vlan_init.c
|
|
++++ b/src/ap/vlan_init.c
|
|
+@@ -22,6 +22,7 @@
|
|
+ static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
|
|
+ int existsok)
|
|
+ {
|
|
++ bool vlan_exists = iface_exists(vlan->ifname);
|
|
+ int ret;
|
|
+ #ifdef CONFIG_WEP
|
|
+ int i;
|
|
+@@ -36,7 +37,7 @@ static int vlan_if_add(struct hostapd_da
|
|
+ }
|
|
+ #endif /* CONFIG_WEP */
|
|
+
|
|
+- if (!iface_exists(vlan->ifname))
|
|
++ if (!vlan_exists)
|
|
+ ret = hostapd_vlan_if_add(hapd, vlan->ifname);
|
|
+ else if (!existsok)
|
|
+ return -1;
|
|
+@@ -51,6 +52,9 @@ static int vlan_if_add(struct hostapd_da
|
|
+ if (hapd->wpa_auth)
|
|
+ ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
|
|
+
|
|
++ if (!ret && !vlan_exists)
|
|
++ hostapd_ubus_add_vlan(hapd, vlan);
|
|
++
|
|
+ if (ret == 0)
|
|
+ return ret;
|
|
+
|
|
+@@ -77,6 +81,8 @@ int vlan_if_remove(struct hostapd_data *
|
|
+ "WPA deinitialization for VLAN %d failed (%d)",
|
|
+ vlan->vlan_id, ret);
|
|
+
|
|
++ hostapd_ubus_remove_vlan(hapd, vlan);
|
|
++
|
|
+ return hostapd_vlan_if_remove(hapd, vlan->ifname);
|
|
+ }
|
|
+
|
|
+--- a/src/ap/dfs.c
|
|
++++ b/src/ap/dfs.c
|
|
+@@ -1211,6 +1211,8 @@ int hostapd_dfs_pre_cac_expired(struct h
|
|
+ "freq=%d ht_enabled=%d chan_offset=%d chan_width=%d cf1=%d cf2=%d",
|
|
+ freq, ht_enabled, chan_offset, chan_width, cf1, cf2);
|
|
+
|
|
++ hostapd_ubus_notify_radar_detected(iface, freq, chan_width, cf1, cf2);
|
|
++
|
|
+ /* Proceed only if DFS is not offloaded to the driver */
|
|
+ if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
|
|
+ return 0;
|
|
+--- a/src/ap/airtime_policy.c
|
|
++++ b/src/ap/airtime_policy.c
|
|
+@@ -112,8 +112,14 @@ static void set_sta_weights(struct hosta
|
|
+ {
|
|
+ struct sta_info *sta;
|
|
+
|
|
+- for (sta = hapd->sta_list; sta; sta = sta->next)
|
|
+- sta_set_airtime_weight(hapd, sta, weight);
|
|
++ for (sta = hapd->sta_list; sta; sta = sta->next) {
|
|
++ unsigned int sta_weight = weight;
|
|
++
|
|
++ if (sta->dyn_airtime_weight)
|
|
++ sta_weight = (weight * sta->dyn_airtime_weight) / 256;
|
|
++
|
|
++ sta_set_airtime_weight(hapd, sta, sta_weight);
|
|
++ }
|
|
+ }
|
|
+
|
|
+
|
|
+@@ -244,7 +250,10 @@ int airtime_policy_new_sta(struct hostap
|
|
+ unsigned int weight;
|
|
+
|
|
+ if (hapd->iconf->airtime_mode == AIRTIME_MODE_STATIC) {
|
|
+- weight = get_weight_for_sta(hapd, sta->addr);
|
|
++ if (sta->dyn_airtime_weight)
|
|
++ weight = sta->dyn_airtime_weight;
|
|
++ else
|
|
++ weight = get_weight_for_sta(hapd, sta->addr);
|
|
+ if (weight)
|
|
+ return sta_set_airtime_weight(hapd, sta, weight);
|
|
+ }
|
|
+--- a/src/ap/sta_info.h
|
|
++++ b/src/ap/sta_info.h
|
|
+@@ -322,6 +322,7 @@ struct sta_info {
|
|
+ #endif /* CONFIG_TESTING_OPTIONS */
|
|
+ #ifdef CONFIG_AIRTIME_POLICY
|
|
+ unsigned int airtime_weight;
|
|
++ unsigned int dyn_airtime_weight;
|
|
+ struct os_reltime backlogged_until;
|
|
+ #endif /* CONFIG_AIRTIME_POLICY */
|
|
+
|
|
+--- a/src/ap/wnm_ap.c
|
|
++++ b/src/ap/wnm_ap.c
|
|
+@@ -455,7 +455,8 @@ static void ieee802_11_rx_bss_trans_mgmt
|
|
+ MAC2STR(addr), reason, hex ? " neighbor=" : "", hex);
|
|
+ os_free(hex);
|
|
+
|
|
+- ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token);
|
|
++ if (!hostapd_ubus_notify_bss_transition_query(hapd, addr, dialog_token, reason, pos, end - pos))
|
|
++ ieee802_11_send_bss_trans_mgmt_request(hapd, addr, dialog_token);
|
|
+ }
|
|
+
|
|
+
|
|
+@@ -477,7 +478,7 @@ static void ieee802_11_rx_bss_trans_mgmt
|
|
+ size_t len)
|
|
+ {
|
|
+ u8 dialog_token, status_code, bss_termination_delay;
|
|
+- const u8 *pos, *end;
|
|
++ const u8 *pos, *end, *target_bssid = NULL;
|
|
+ int enabled = hapd->conf->bss_transition;
|
|
+ struct sta_info *sta;
|
|
+
|
|
+@@ -524,6 +525,7 @@ static void ieee802_11_rx_bss_trans_mgmt
|
|
+ wpa_printf(MSG_DEBUG, "WNM: not enough room for Target BSSID field");
|
|
+ return;
|
|
+ }
|
|
++ target_bssid = pos;
|
|
+ sta->agreed_to_steer = 1;
|
|
+ eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta);
|
|
+ eloop_register_timeout(2, 0, ap_sta_reset_steer_flag_timer,
|
|
+@@ -543,6 +545,10 @@ static void ieee802_11_rx_bss_trans_mgmt
|
|
+ MAC2STR(addr), status_code, bss_termination_delay);
|
|
+ }
|
|
+
|
|
++ hostapd_ubus_notify_bss_transition_response(hapd, sta->addr, dialog_token,
|
|
++ status_code, bss_termination_delay,
|
|
++ target_bssid, pos, end - pos);
|
|
++
|
|
+ wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
|
|
+ pos, end - pos);
|
|
+ }
|
|
+--- a/src/utils/eloop.c
|
|
++++ b/src/utils/eloop.c
|
|
+@@ -77,6 +77,9 @@ struct eloop_sock_table {
|
|
+ struct eloop_data {
|
|
+ int max_sock;
|
|
+
|
|
++ eloop_timeout_poll_handler timeout_poll_cb;
|
|
++ eloop_poll_handler poll_cb;
|
|
++
|
|
+ size_t count; /* sum of all table counts */
|
|
+ #ifdef CONFIG_ELOOP_POLL
|
|
+ size_t max_pollfd_map; /* number of pollfds_map currently allocated */
|
|
+@@ -1121,6 +1124,12 @@ void eloop_run(void)
|
|
+ os_reltime_sub(&timeout->time, &now, &tv);
|
|
+ else
|
|
+ tv.sec = tv.usec = 0;
|
|
++ }
|
|
++
|
|
++ if (eloop.timeout_poll_cb && eloop.timeout_poll_cb(&tv, !!timeout))
|
|
++ timeout = (void *)1;
|
|
++
|
|
++ if (timeout) {
|
|
+ #if defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL)
|
|
+ timeout_ms = tv.sec * 1000 + tv.usec / 1000;
|
|
+ #endif /* defined(CONFIG_ELOOP_POLL) || defined(CONFIG_ELOOP_EPOLL) */
|
|
+@@ -1190,7 +1199,8 @@ void eloop_run(void)
|
|
+ eloop.exceptions.changed = 0;
|
|
+
|
|
+ eloop_process_pending_signals();
|
|
+-
|
|
++ if (eloop.poll_cb)
|
|
++ eloop.poll_cb();
|
|
+
|
|
+ /* check if some registered timeouts have occurred */
|
|
+ timeout = dl_list_first(&eloop.timeout, struct eloop_timeout,
|
|
+@@ -1252,6 +1262,14 @@ out:
|
|
+ return;
|
|
+ }
|
|
+
|
|
++int eloop_register_cb(eloop_poll_handler poll_cb,
|
|
++ eloop_timeout_poll_handler timeout_cb)
|
|
++{
|
|
++ eloop.poll_cb = poll_cb;
|
|
++ eloop.timeout_poll_cb = timeout_cb;
|
|
++
|
|
++ return 0;
|
|
++}
|
|
+
|
|
+ void eloop_terminate(void)
|
|
+ {
|
|
+--- a/src/utils/eloop.h
|
|
++++ b/src/utils/eloop.h
|
|
+@@ -65,6 +65,9 @@ typedef void (*eloop_timeout_handler)(vo
|
|
+ */
|
|
+ typedef void (*eloop_signal_handler)(int sig, void *signal_ctx);
|
|
+
|
|
++typedef bool (*eloop_timeout_poll_handler)(struct os_reltime *tv, bool tv_set);
|
|
++typedef void (*eloop_poll_handler)(void);
|
|
++
|
|
+ /**
|
|
+ * eloop_init() - Initialize global event loop data
|
|
+ * Returns: 0 on success, -1 on failure
|
|
+@@ -73,6 +76,9 @@ typedef void (*eloop_signal_handler)(int
|
|
+ */
|
|
+ int eloop_init(void);
|
|
+
|
|
++int eloop_register_cb(eloop_poll_handler poll_cb,
|
|
++ eloop_timeout_poll_handler timeout_cb);
|
|
++
|
|
+ /**
|
|
+ * eloop_register_read_sock - Register handler for read events
|
|
+ * @sock: File descriptor number for the socket
|
|
+@@ -320,6 +326,8 @@ int eloop_register_signal_reconfig(eloop
|
|
+ */
|
|
+ int eloop_sock_requeue(void);
|
|
+
|
|
++void eloop_add_uloop(void);
|
|
++
|
|
+ /**
|
|
+ * eloop_run - Start the event loop
|
|
+ *
|
|
+--- /dev/null
|
|
++++ b/src/utils/uloop.c
|
|
+@@ -0,0 +1,64 @@
|
|
++#include <libubox/uloop.h>
|
|
++#include "includes.h"
|
|
++#include "common.h"
|
|
++#include "eloop.h"
|
|
++
|
|
++static void eloop_uloop_event_cb(int sock, void *eloop_ctx, void *sock_ctx)
|
|
++{
|
|
++}
|
|
++
|
|
++static void eloop_uloop_fd_cb(struct uloop_fd *fd, unsigned int events)
|
|
++{
|
|
++ unsigned int changed = events ^ fd->flags;
|
|
++
|
|
++ if (changed & ULOOP_READ) {
|
|
++ if (events & ULOOP_READ)
|
|
++ eloop_register_sock(fd->fd, EVENT_TYPE_READ, eloop_uloop_event_cb, fd, fd);
|
|
++ else
|
|
++ eloop_unregister_sock(fd->fd, EVENT_TYPE_READ);
|
|
++ }
|
|
++
|
|
++ if (changed & ULOOP_WRITE) {
|
|
++ if (events & ULOOP_WRITE)
|
|
++ eloop_register_sock(fd->fd, EVENT_TYPE_WRITE, eloop_uloop_event_cb, fd, fd);
|
|
++ else
|
|
++ eloop_unregister_sock(fd->fd, EVENT_TYPE_WRITE);
|
|
++ }
|
|
++}
|
|
++
|
|
++static bool uloop_timeout_poll_handler(struct os_reltime *tv, bool tv_set)
|
|
++{
|
|
++ struct os_reltime tv_uloop;
|
|
++ int timeout_ms = uloop_get_next_timeout();
|
|
++
|
|
++ if (timeout_ms < 0)
|
|
++ return false;
|
|
++
|
|
++ tv_uloop.sec = timeout_ms / 1000;
|
|
++ tv_uloop.usec = (timeout_ms % 1000) * 1000;
|
|
++
|
|
++ if (!tv_set || os_reltime_before(&tv_uloop, tv)) {
|
|
++ *tv = tv_uloop;
|
|
++ return true;
|
|
++ }
|
|
++
|
|
++ return false;
|
|
++}
|
|
++
|
|
++static void uloop_poll_handler(void)
|
|
++{
|
|
++ uloop_run_timeout(0);
|
|
++}
|
|
++
|
|
++void eloop_add_uloop(void)
|
|
++{
|
|
++ static bool init_done = false;
|
|
++
|
|
++ if (!init_done) {
|
|
++ uloop_init();
|
|
++ uloop_fd_set_cb = eloop_uloop_fd_cb;
|
|
++ init_done = true;
|
|
++ }
|
|
++
|
|
++ eloop_register_cb(uloop_poll_handler, uloop_timeout_poll_handler);
|
|
++}
|
|
diff --git a/package/network/services/hostapd/patches/601-ucode_support.patch b/package/network/services/hostapd/patches/601-ucode_support.patch
|
|
new file mode 100644
|
|
index 0000000000..e0bbf1337d
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/601-ucode_support.patch
|
|
@@ -0,0 +1,333 @@
|
|
+--- a/hostapd/Makefile
|
|
++++ b/hostapd/Makefile
|
|
+@@ -168,9 +168,21 @@ OBJS += ../src/eapol_auth/eapol_auth_sm.
|
|
+
|
|
+ ifdef CONFIG_UBUS
|
|
+ CFLAGS += -DUBUS_SUPPORT
|
|
+-OBJS += ../src/utils/uloop.o
|
|
+ OBJS += ../src/ap/ubus.o
|
|
+-LIBS += -lubox -lubus
|
|
++LIBS += -lubus
|
|
++NEED_ULOOP:=y
|
|
++endif
|
|
++
|
|
++ifdef CONFIG_UCODE
|
|
++CFLAGS += -DUCODE_SUPPORT
|
|
++OBJS += ../src/utils/ucode.o
|
|
++OBJS += ../src/ap/ucode.o
|
|
++NEED_ULOOP:=y
|
|
++endif
|
|
++
|
|
++ifdef NEED_ULOOP
|
|
++OBJS += ../src/utils/uloop.o
|
|
++LIBS += -lubox
|
|
+ endif
|
|
+
|
|
+ ifdef CONFIG_CODE_COVERAGE
|
|
+--- a/hostapd/main.c
|
|
++++ b/hostapd/main.c
|
|
+@@ -994,6 +994,7 @@ int main(int argc, char *argv[])
|
|
+ }
|
|
+
|
|
+ hostapd_global_ctrl_iface_init(&interfaces);
|
|
++ hostapd_ucode_init(&interfaces);
|
|
+
|
|
+ if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
|
|
+ wpa_printf(MSG_ERROR, "Failed to start eloop");
|
|
+@@ -1003,6 +1004,7 @@ int main(int argc, char *argv[])
|
|
+ ret = 0;
|
|
+
|
|
+ out:
|
|
++ hostapd_ucode_free();
|
|
+ hostapd_global_ctrl_iface_deinit(&interfaces);
|
|
+ /* Deinitialize all interfaces */
|
|
+ for (i = 0; i < interfaces.count; i++) {
|
|
+--- a/src/ap/hostapd.h
|
|
++++ b/src/ap/hostapd.h
|
|
+@@ -19,6 +19,7 @@
|
|
+ #include "ap_config.h"
|
|
+ #include "drivers/driver.h"
|
|
+ #include "ubus.h"
|
|
++#include "ucode.h"
|
|
+
|
|
+ #define OCE_STA_CFON_ENABLED(hapd) \
|
|
+ ((hapd->conf->oce & OCE_STA_CFON) && \
|
|
+@@ -51,6 +52,10 @@ struct hapd_interfaces {
|
|
+ struct hostapd_config * (*config_read_cb)(const char *config_fname);
|
|
+ int (*ctrl_iface_init)(struct hostapd_data *hapd);
|
|
+ void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
|
|
++ int (*ctrl_iface_recv)(struct hostapd_data *hapd,
|
|
++ char *buf, char *reply, int reply_size,
|
|
++ struct sockaddr_storage *from,
|
|
++ socklen_t fromlen);
|
|
+ int (*for_each_interface)(struct hapd_interfaces *interfaces,
|
|
+ int (*cb)(struct hostapd_iface *iface,
|
|
+ void *ctx), void *ctx);
|
|
+@@ -186,6 +191,7 @@ struct hostapd_data {
|
|
+ struct hostapd_config *iconf;
|
|
+ struct hostapd_bss_config *conf;
|
|
+ struct hostapd_ubus_bss ubus;
|
|
++ struct hostapd_ucode_bss ucode;
|
|
+ int interface_added; /* virtual interface added for this BSS */
|
|
+ unsigned int started:1;
|
|
+ unsigned int disabled:1;
|
|
+@@ -506,6 +512,7 @@ struct hostapd_sta_info {
|
|
+ */
|
|
+ struct hostapd_iface {
|
|
+ struct hapd_interfaces *interfaces;
|
|
++ struct hostapd_ucode_iface ucode;
|
|
+ void *owner;
|
|
+ char *config_fname;
|
|
+ struct hostapd_config *conf;
|
|
+@@ -706,6 +713,8 @@ struct hostapd_iface * hostapd_init(stru
|
|
+ struct hostapd_iface *
|
|
+ hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
|
|
+ const char *config_fname, int debug);
|
|
++int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon);
|
|
++void hostapd_bss_deinit(struct hostapd_data *hapd);
|
|
+ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
|
+ int reassoc);
|
|
+ void hostapd_interface_deinit_free(struct hostapd_iface *iface);
|
|
+--- a/src/ap/hostapd.c
|
|
++++ b/src/ap/hostapd.c
|
|
+@@ -252,6 +252,8 @@ int hostapd_reload_config(struct hostapd
|
|
+ struct hostapd_config *newconf, *oldconf;
|
|
+ size_t j;
|
|
+
|
|
++ hostapd_ucode_reload_bss(hapd);
|
|
++
|
|
+ if (iface->config_fname == NULL) {
|
|
+ /* Only in-memory config in use - assume it has been updated */
|
|
+ hostapd_clear_old(iface);
|
|
+@@ -435,6 +437,7 @@ void hostapd_free_hapd_data(struct hosta
|
|
+ hapd->beacon_set_done = 0;
|
|
+
|
|
+ wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
|
|
++ hostapd_ucode_free_bss(hapd);
|
|
+ hostapd_ubus_free_bss(hapd);
|
|
+ accounting_deinit(hapd);
|
|
+ hostapd_deinit_wpa(hapd);
|
|
+@@ -599,6 +602,7 @@ void hostapd_cleanup_iface_partial(struc
|
|
+ static void hostapd_cleanup_iface(struct hostapd_iface *iface)
|
|
+ {
|
|
+ wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
|
|
++ hostapd_ucode_free_iface(iface);
|
|
+ eloop_cancel_timeout(channel_list_update_timeout, iface, NULL);
|
|
+ eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface,
|
|
+ NULL);
|
|
+@@ -1189,6 +1193,7 @@ static int hostapd_start_beacon(struct h
|
|
+ hapd->driver->set_operstate(hapd->drv_priv, 1);
|
|
+
|
|
+ hostapd_ubus_add_bss(hapd);
|
|
++ hostapd_ucode_add_bss(hapd);
|
|
+
|
|
+ return 0;
|
|
+ }
|
|
+@@ -1211,8 +1216,7 @@ static int hostapd_start_beacon(struct h
|
|
+ * initialized. Most of the modules that are initialized here will be
|
|
+ * deinitialized in hostapd_cleanup().
|
|
+ */
|
|
+-static int hostapd_setup_bss(struct hostapd_data *hapd, int first,
|
|
+- bool start_beacon)
|
|
++int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon)
|
|
+ {
|
|
+ struct hostapd_bss_config *conf = hapd->conf;
|
|
+ u8 ssid[SSID_MAX_LEN + 1];
|
|
+@@ -2698,7 +2702,7 @@ hostapd_alloc_bss_data(struct hostapd_if
|
|
+ }
|
|
+
|
|
+
|
|
+-static void hostapd_bss_deinit(struct hostapd_data *hapd)
|
|
++void hostapd_bss_deinit(struct hostapd_data *hapd)
|
|
+ {
|
|
+ if (!hapd)
|
|
+ return;
|
|
+--- a/wpa_supplicant/Makefile
|
|
++++ b/wpa_supplicant/Makefile
|
|
+@@ -195,8 +195,20 @@ endif
|
|
+ ifdef CONFIG_UBUS
|
|
+ CFLAGS += -DUBUS_SUPPORT
|
|
+ OBJS += ubus.o
|
|
++LIBS += -lubus
|
|
++NEED_ULOOP:=y
|
|
++endif
|
|
++
|
|
++ifdef CONFIG_UCODE
|
|
++CFLAGS += -DUCODE_SUPPORT
|
|
++OBJS += ../src/utils/ucode.o
|
|
++OBJS += ucode.o
|
|
++NEED_ULOOP:=y
|
|
++endif
|
|
++
|
|
++ifdef NEED_ULOOP
|
|
+ OBJS += ../src/utils/uloop.o
|
|
+-LIBS += -lubox -lubus
|
|
++LIBS += -lubox
|
|
+ endif
|
|
+
|
|
+ ifdef CONFIG_CODE_COVERAGE
|
|
+@@ -997,6 +1009,9 @@ OBJS += ../src/ap/ctrl_iface_ap.o
|
|
+ ifdef CONFIG_UBUS
|
|
+ OBJS += ../src/ap/ubus.o
|
|
+ endif
|
|
++ifdef CONFIG_UCODE
|
|
++OBJS += ../src/ap/ucode.o
|
|
++endif
|
|
+ endif
|
|
+
|
|
+ CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
|
|
+--- a/wpa_supplicant/wpa_supplicant.c
|
|
++++ b/wpa_supplicant/wpa_supplicant.c
|
|
+@@ -1044,6 +1044,7 @@ void wpa_supplicant_set_state(struct wpa
|
|
+ sme_sched_obss_scan(wpa_s, 0);
|
|
+ }
|
|
+ wpa_s->wpa_state = state;
|
|
++ wpas_ucode_update_state(wpa_s);
|
|
+
|
|
+ #ifdef CONFIG_BGSCAN
|
|
+ if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
|
|
+@@ -7567,6 +7568,7 @@ struct wpa_supplicant * wpa_supplicant_a
|
|
+ #endif /* CONFIG_P2P */
|
|
+
|
|
+ wpas_ubus_add_bss(wpa_s);
|
|
++ wpas_ucode_add_bss(wpa_s);
|
|
+
|
|
+ return wpa_s;
|
|
+ }
|
|
+@@ -7594,6 +7596,7 @@ int wpa_supplicant_remove_iface(struct w
|
|
+ struct wpa_supplicant *parent = wpa_s->parent;
|
|
+ #endif /* CONFIG_MESH */
|
|
+
|
|
++ wpas_ucode_free_bss(wpa_s);
|
|
+ wpas_ubus_free_bss(wpa_s);
|
|
+
|
|
+ /* Remove interface from the global list of interfaces */
|
|
+@@ -7904,6 +7907,7 @@ struct wpa_global * wpa_supplicant_init(
|
|
+
|
|
+ eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
|
|
+ wpas_periodic, global, NULL);
|
|
++ wpas_ucode_init(global);
|
|
+
|
|
+ return global;
|
|
+ }
|
|
+@@ -7942,12 +7946,8 @@ int wpa_supplicant_run(struct wpa_global
|
|
+ eloop_register_signal_terminate(wpa_supplicant_terminate, global);
|
|
+ eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
|
|
+
|
|
+- wpas_ubus_add(global);
|
|
+-
|
|
+ eloop_run();
|
|
+
|
|
+- wpas_ubus_free(global);
|
|
+-
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+@@ -7980,6 +7980,8 @@ void wpa_supplicant_deinit(struct wpa_gl
|
|
+
|
|
+ wpas_notify_supplicant_deinitialized(global);
|
|
+
|
|
++ wpas_ucode_free();
|
|
++
|
|
+ eap_peer_unregister_methods();
|
|
+ #ifdef CONFIG_AP
|
|
+ eap_server_unregister_methods();
|
|
+--- a/wpa_supplicant/wpa_supplicant_i.h
|
|
++++ b/wpa_supplicant/wpa_supplicant_i.h
|
|
+@@ -22,6 +22,7 @@
|
|
+ #include "wmm_ac.h"
|
|
+ #include "pasn/pasn_common.h"
|
|
+ #include "ubus.h"
|
|
++#include "ucode.h"
|
|
+
|
|
+ extern const char *const wpa_supplicant_version;
|
|
+ extern const char *const wpa_supplicant_license;
|
|
+@@ -654,6 +655,7 @@ struct wpa_supplicant {
|
|
+ unsigned char perm_addr[ETH_ALEN];
|
|
+ char ifname[100];
|
|
+ struct wpas_ubus_bss ubus;
|
|
++ struct wpas_ucode_bss ucode;
|
|
+ #ifdef CONFIG_MATCH_IFACE
|
|
+ int matched;
|
|
+ #endif /* CONFIG_MATCH_IFACE */
|
|
+--- a/hostapd/ctrl_iface.c
|
|
++++ b/hostapd/ctrl_iface.c
|
|
+@@ -4856,6 +4856,7 @@ try_again:
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
++ interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process;
|
|
+ wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
|
|
+
|
|
+ return 0;
|
|
+@@ -4957,6 +4958,7 @@ fail:
|
|
+ os_free(fname);
|
|
+
|
|
+ interface->global_ctrl_sock = s;
|
|
++ interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process;
|
|
+ eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
|
|
+ interface, NULL);
|
|
+
|
|
+--- a/src/drivers/driver.h
|
|
++++ b/src/drivers/driver.h
|
|
+@@ -6426,6 +6426,7 @@ union wpa_event_data {
|
|
+
|
|
+ /**
|
|
+ * struct ch_switch
|
|
++ * @count: Count until channel switch activates
|
|
+ * @freq: Frequency of new channel in MHz
|
|
+ * @ht_enabled: Whether this is an HT channel
|
|
+ * @ch_offset: Secondary channel offset
|
|
+@@ -6436,6 +6437,7 @@ union wpa_event_data {
|
|
+ * @punct_bitmap: Puncturing bitmap
|
|
+ */
|
|
+ struct ch_switch {
|
|
++ int count;
|
|
+ int freq;
|
|
+ int ht_enabled;
|
|
+ int ch_offset;
|
|
+--- a/src/drivers/driver_nl80211_event.c
|
|
++++ b/src/drivers/driver_nl80211_event.c
|
|
+@@ -1202,6 +1202,7 @@ static void mlme_event_ch_switch(struct
|
|
+ struct nlattr *bw, struct nlattr *cf1,
|
|
+ struct nlattr *cf2,
|
|
+ struct nlattr *punct_bitmap,
|
|
++ struct nlattr *count,
|
|
+ int finished)
|
|
+ {
|
|
+ struct i802_bss *bss;
|
|
+@@ -1265,6 +1266,8 @@ static void mlme_event_ch_switch(struct
|
|
+ data.ch_switch.cf1 = nla_get_u32(cf1);
|
|
+ if (cf2)
|
|
+ data.ch_switch.cf2 = nla_get_u32(cf2);
|
|
++ if (count)
|
|
++ data.ch_switch.count = nla_get_u32(count);
|
|
+
|
|
+ if (finished)
|
|
+ bss->flink->freq = data.ch_switch.freq;
|
|
+@@ -3848,6 +3851,7 @@ static void do_process_drv_event(struct
|
|
+ tb[NL80211_ATTR_CENTER_FREQ1],
|
|
+ tb[NL80211_ATTR_CENTER_FREQ2],
|
|
+ tb[NL80211_ATTR_PUNCT_BITMAP],
|
|
++ tb[NL80211_ATTR_CH_SWITCH_COUNT],
|
|
+ 0);
|
|
+ break;
|
|
+ case NL80211_CMD_CH_SWITCH_NOTIFY:
|
|
+@@ -3860,6 +3864,7 @@ static void do_process_drv_event(struct
|
|
+ tb[NL80211_ATTR_CENTER_FREQ1],
|
|
+ tb[NL80211_ATTR_CENTER_FREQ2],
|
|
+ tb[NL80211_ATTR_PUNCT_BITMAP],
|
|
++ NULL,
|
|
+ 1);
|
|
+ break;
|
|
+ case NL80211_CMD_DISCONNECT:
|
|
+--- a/wpa_supplicant/events.c
|
|
++++ b/wpa_supplicant/events.c
|
|
+@@ -5381,6 +5381,7 @@ void supplicant_event(void *ctx, enum wp
|
|
+ event_to_string(event), event);
|
|
+ #endif /* CONFIG_NO_STDOUT_DEBUG */
|
|
+
|
|
++ wpas_ucode_event(wpa_s, event, data);
|
|
+ switch (event) {
|
|
+ case EVENT_AUTH:
|
|
+ #ifdef CONFIG_FST
|
|
diff --git a/package/network/services/hostapd/patches/610-hostapd_cli_ujail_permission.patch b/package/network/services/hostapd/patches/610-hostapd_cli_ujail_permission.patch
|
|
new file mode 100644
|
|
index 0000000000..a03fcc9f92
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/610-hostapd_cli_ujail_permission.patch
|
|
@@ -0,0 +1,33 @@
|
|
+--- a/src/common/wpa_ctrl.c
|
|
++++ b/src/common/wpa_ctrl.c
|
|
+@@ -135,7 +135,7 @@ try_again:
|
|
+ return NULL;
|
|
+ }
|
|
+ tries++;
|
|
+-#ifdef ANDROID
|
|
++
|
|
+ /* Set client socket file permissions so that bind() creates the client
|
|
+ * socket with these permissions and there is no need to try to change
|
|
+ * them with chmod() after bind() which would have potential issues with
|
|
+@@ -147,7 +147,7 @@ try_again:
|
|
+ * operations to allow the response to go through. Those are using the
|
|
+ * no-deference-symlinks version to avoid races. */
|
|
+ fchmod(ctrl->s, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
|
+-#endif /* ANDROID */
|
|
++
|
|
+ if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
|
|
+ sizeof(ctrl->local)) < 0) {
|
|
+ if (errno == EADDRINUSE && tries < 2) {
|
|
+@@ -165,7 +165,11 @@ try_again:
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+-#ifdef ANDROID
|
|
++#ifndef ANDROID
|
|
++ /* Set group even if we do not have privileges to change owner */
|
|
++ lchown(ctrl->local.sun_path, -1, 101);
|
|
++ lchown(ctrl->local.sun_path, 101, 101);
|
|
++#else
|
|
+ /* Set group even if we do not have privileges to change owner */
|
|
+ lchown(ctrl->local.sun_path, -1, AID_WIFI);
|
|
+ lchown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
|
|
diff --git a/package/network/services/hostapd/patches/701-reload_config_inline.patch b/package/network/services/hostapd/patches/701-reload_config_inline.patch
|
|
new file mode 100644
|
|
index 0000000000..44c8892bae
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/701-reload_config_inline.patch
|
|
@@ -0,0 +1,33 @@
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -4810,7 +4810,12 @@ struct hostapd_config * hostapd_config_r
|
|
+ int errors = 0;
|
|
+ size_t i;
|
|
+
|
|
+- f = fopen(fname, "r");
|
|
++ if (!strncmp(fname, "data:", 5)) {
|
|
++ f = fmemopen((void *)(fname + 5), strlen(fname + 5), "r");
|
|
++ fname = "<inline>";
|
|
++ } else {
|
|
++ f = fopen(fname, "r");
|
|
++ }
|
|
+ if (f == NULL) {
|
|
+ wpa_printf(MSG_ERROR, "Could not open configuration file '%s' "
|
|
+ "for reading.", fname);
|
|
+--- a/wpa_supplicant/config_file.c
|
|
++++ b/wpa_supplicant/config_file.c
|
|
+@@ -326,8 +326,13 @@ struct wpa_config * wpa_config_read(cons
|
|
+ while (cred_tail && cred_tail->next)
|
|
+ cred_tail = cred_tail->next;
|
|
+
|
|
++ if (!strncmp(name, "data:", 5)) {
|
|
++ f = fmemopen((void *)(name + 5), strlen(name + 5), "r");
|
|
++ name = "<inline>";
|
|
++ } else {
|
|
++ f = fopen(name, "r");
|
|
++ }
|
|
+ wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
|
|
+- f = fopen(name, "r");
|
|
+ if (f == NULL) {
|
|
+ wpa_printf(MSG_ERROR, "Failed to open config file '%s', "
|
|
+ "error: %s", name, strerror(errno));
|
|
diff --git a/package/network/services/hostapd/patches/710-vlan_no_bridge.patch b/package/network/services/hostapd/patches/710-vlan_no_bridge.patch
|
|
new file mode 100644
|
|
index 0000000000..63d1b8a3b8
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/710-vlan_no_bridge.patch
|
|
@@ -0,0 +1,41 @@
|
|
+--- a/src/ap/ap_config.h
|
|
++++ b/src/ap/ap_config.h
|
|
+@@ -121,6 +121,7 @@ struct hostapd_ssid {
|
|
+ #define DYNAMIC_VLAN_OPTIONAL 1
|
|
+ #define DYNAMIC_VLAN_REQUIRED 2
|
|
+ int dynamic_vlan;
|
|
++ int vlan_no_bridge;
|
|
+ #define DYNAMIC_VLAN_NAMING_WITHOUT_DEVICE 0
|
|
+ #define DYNAMIC_VLAN_NAMING_WITH_DEVICE 1
|
|
+ #define DYNAMIC_VLAN_NAMING_END 2
|
|
+--- a/src/ap/vlan_full.c
|
|
++++ b/src/ap/vlan_full.c
|
|
+@@ -475,6 +475,9 @@ void vlan_newlink(const char *ifname, st
|
|
+ if (!vlan)
|
|
+ return;
|
|
+
|
|
++ if (hapd->conf->ssid.vlan_no_bridge)
|
|
++ goto out;
|
|
++
|
|
+ vlan->configured = 1;
|
|
+
|
|
+ notempty = vlan->vlan_desc.notempty;
|
|
+@@ -506,6 +509,7 @@ void vlan_newlink(const char *ifname, st
|
|
+ ifname, br_name, tagged[i], hapd);
|
|
+ }
|
|
+
|
|
++out:
|
|
+ ifconfig_up(ifname);
|
|
+ }
|
|
+
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -3351,6 +3351,8 @@ static int hostapd_config_fill(struct ho
|
|
+ #ifndef CONFIG_NO_VLAN
|
|
+ } else if (os_strcmp(buf, "dynamic_vlan") == 0) {
|
|
+ bss->ssid.dynamic_vlan = atoi(pos);
|
|
++ } else if (os_strcmp(buf, "vlan_no_bridge") == 0) {
|
|
++ bss->ssid.vlan_no_bridge = atoi(pos);
|
|
+ } else if (os_strcmp(buf, "per_sta_vif") == 0) {
|
|
+ bss->ssid.per_sta_vif = atoi(pos);
|
|
+ } else if (os_strcmp(buf, "vlan_file") == 0) {
|
|
diff --git a/package/network/services/hostapd/patches/711-wds_bridge_force.patch b/package/network/services/hostapd/patches/711-wds_bridge_force.patch
|
|
new file mode 100644
|
|
index 0000000000..c0f2c31c44
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/711-wds_bridge_force.patch
|
|
@@ -0,0 +1,22 @@
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -2318,6 +2318,8 @@ static int hostapd_config_fill(struct ho
|
|
+ sizeof(conf->bss[0]->iface));
|
|
+ } else if (os_strcmp(buf, "bridge") == 0) {
|
|
+ os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
|
|
++ if (!bss->wds_bridge[0])
|
|
++ os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
|
|
+ } else if (os_strcmp(buf, "bridge_hairpin") == 0) {
|
|
+ bss->bridge_hairpin = atoi(pos);
|
|
+ } else if (os_strcmp(buf, "vlan_bridge") == 0) {
|
|
+--- a/src/ap/ap_drv_ops.c
|
|
++++ b/src/ap/ap_drv_ops.c
|
|
+@@ -348,8 +348,6 @@ int hostapd_set_wds_sta(struct hostapd_d
|
|
+ return -1;
|
|
+ if (hapd->conf->wds_bridge[0])
|
|
+ bridge = hapd->conf->wds_bridge;
|
|
+- else if (hapd->conf->bridge[0])
|
|
+- bridge = hapd->conf->bridge;
|
|
+ return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val,
|
|
+ bridge, ifname_wds);
|
|
+ }
|
|
diff --git a/package/network/services/hostapd/patches/720-iface_max_num_sta.patch b/package/network/services/hostapd/patches/720-iface_max_num_sta.patch
|
|
new file mode 100644
|
|
index 0000000000..1aa4456a5f
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/720-iface_max_num_sta.patch
|
|
@@ -0,0 +1,81 @@
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -2848,6 +2848,14 @@ static int hostapd_config_fill(struct ho
|
|
+ line, bss->max_num_sta, MAX_STA_COUNT);
|
|
+ return 1;
|
|
+ }
|
|
++ } else if (os_strcmp(buf, "iface_max_num_sta") == 0) {
|
|
++ conf->max_num_sta = atoi(pos);
|
|
++ if (conf->max_num_sta < 0 ||
|
|
++ conf->max_num_sta > MAX_STA_COUNT) {
|
|
++ wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d",
|
|
++ line, conf->max_num_sta, MAX_STA_COUNT);
|
|
++ return 1;
|
|
++ }
|
|
+ } else if (os_strcmp(buf, "wpa") == 0) {
|
|
+ bss->wpa = atoi(pos);
|
|
+ } else if (os_strcmp(buf, "extended_key_id") == 0) {
|
|
+--- a/src/ap/hostapd.h
|
|
++++ b/src/ap/hostapd.h
|
|
+@@ -742,6 +742,7 @@ void hostapd_cleanup_cs_params(struct ho
|
|
+ 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);
|
|
++int hostapd_check_max_sta(struct hostapd_data *hapd);
|
|
+
|
|
+ void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap);
|
|
+ void hostapd_cleanup_cca_params(struct hostapd_data *hapd);
|
|
+--- a/src/ap/hostapd.c
|
|
++++ b/src/ap/hostapd.c
|
|
+@@ -244,6 +244,29 @@ static int hostapd_iface_conf_changed(st
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
++static inline int hostapd_iface_num_sta(struct hostapd_iface *iface)
|
|
++{
|
|
++ int num_sta = 0;
|
|
++ int i;
|
|
++
|
|
++ for (i = 0; i < iface->num_bss; i++)
|
|
++ num_sta += iface->bss[i]->num_sta;
|
|
++
|
|
++ return num_sta;
|
|
++}
|
|
++
|
|
++
|
|
++int hostapd_check_max_sta(struct hostapd_data *hapd)
|
|
++{
|
|
++ if (hapd->num_sta >= hapd->conf->max_num_sta)
|
|
++ return 1;
|
|
++
|
|
++ if (hapd->iconf->max_num_sta &&
|
|
++ hostapd_iface_num_sta(hapd->iface) >= hapd->iconf->max_num_sta)
|
|
++ return 1;
|
|
++
|
|
++ return 0;
|
|
++}
|
|
+
|
|
+ int hostapd_reload_config(struct hostapd_iface *iface)
|
|
+ {
|
|
+--- a/src/ap/beacon.c
|
|
++++ b/src/ap/beacon.c
|
|
+@@ -1252,7 +1252,7 @@ void handle_probe_req(struct hostapd_dat
|
|
+ if (hapd->conf->no_probe_resp_if_max_sta &&
|
|
+ is_multicast_ether_addr(mgmt->da) &&
|
|
+ is_multicast_ether_addr(mgmt->bssid) &&
|
|
+- hapd->num_sta >= hapd->conf->max_num_sta &&
|
|
++ hostapd_check_max_sta(hapd) &&
|
|
+ !ap_get_sta(hapd, mgmt->sa)) {
|
|
+ wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR
|
|
+ " since no room for additional STA",
|
|
+--- a/src/ap/ap_config.h
|
|
++++ b/src/ap/ap_config.h
|
|
+@@ -1036,6 +1036,8 @@ struct hostapd_config {
|
|
+ unsigned int track_sta_max_num;
|
|
+ unsigned int track_sta_max_age;
|
|
+
|
|
++ int max_num_sta;
|
|
++
|
|
+ char country[3]; /* first two octets: country code as described in
|
|
+ * ISO/IEC 3166-1. Third octet:
|
|
+ * ' ' (ascii 32): all environments
|
|
diff --git a/package/network/services/hostapd/patches/730-ft_iface.patch b/package/network/services/hostapd/patches/730-ft_iface.patch
|
|
new file mode 100644
|
|
index 0000000000..0795ed15a1
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/730-ft_iface.patch
|
|
@@ -0,0 +1,38 @@
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -3007,6 +3007,8 @@ static int hostapd_config_fill(struct ho
|
|
+ wpa_printf(MSG_INFO,
|
|
+ "Line %d: Obsolete peerkey parameter ignored", line);
|
|
+ #ifdef CONFIG_IEEE80211R_AP
|
|
++ } else if (os_strcmp(buf, "ft_iface") == 0) {
|
|
++ os_strlcpy(bss->ft_iface, pos, sizeof(bss->ft_iface));
|
|
+ } else if (os_strcmp(buf, "mobility_domain") == 0) {
|
|
+ if (os_strlen(pos) != 2 * MOBILITY_DOMAIN_ID_LEN ||
|
|
+ hexstr2bin(pos, bss->mobility_domain,
|
|
+--- a/src/ap/ap_config.h
|
|
++++ b/src/ap/ap_config.h
|
|
+@@ -283,6 +283,7 @@ struct airtime_sta_weight {
|
|
+ struct hostapd_bss_config {
|
|
+ char iface[IFNAMSIZ + 1];
|
|
+ char bridge[IFNAMSIZ + 1];
|
|
++ char ft_iface[IFNAMSIZ + 1];
|
|
+ char vlan_bridge[IFNAMSIZ + 1];
|
|
+ char wds_bridge[IFNAMSIZ + 1];
|
|
+ int bridge_hairpin; /* hairpin_mode on bridge members */
|
|
+--- a/src/ap/wpa_auth_glue.c
|
|
++++ b/src/ap/wpa_auth_glue.c
|
|
+@@ -1727,8 +1727,12 @@ int hostapd_setup_wpa(struct hostapd_dat
|
|
+ wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt)) {
|
|
+ const char *ft_iface;
|
|
+
|
|
+- ft_iface = hapd->conf->bridge[0] ? hapd->conf->bridge :
|
|
+- hapd->conf->iface;
|
|
++ if (hapd->conf->ft_iface[0])
|
|
++ ft_iface = hapd->conf->ft_iface;
|
|
++ else if (hapd->conf->bridge[0])
|
|
++ ft_iface = hapd->conf->bridge;
|
|
++ else
|
|
++ ft_iface = hapd->conf->iface;
|
|
+ hapd->l2 = l2_packet_init(ft_iface, NULL, ETH_P_RRB,
|
|
+ hostapd_rrb_receive, hapd, 1);
|
|
+ if (!hapd->l2) {
|
|
diff --git a/package/network/services/hostapd/patches/740-snoop_iface.patch b/package/network/services/hostapd/patches/740-snoop_iface.patch
|
|
new file mode 100644
|
|
index 0000000000..6b6cc0fad7
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/740-snoop_iface.patch
|
|
@@ -0,0 +1,66 @@
|
|
+--- a/src/ap/ap_config.h
|
|
++++ b/src/ap/ap_config.h
|
|
+@@ -284,6 +284,7 @@ struct hostapd_bss_config {
|
|
+ char iface[IFNAMSIZ + 1];
|
|
+ char bridge[IFNAMSIZ + 1];
|
|
+ char ft_iface[IFNAMSIZ + 1];
|
|
++ char snoop_iface[IFNAMSIZ + 1];
|
|
+ char vlan_bridge[IFNAMSIZ + 1];
|
|
+ char wds_bridge[IFNAMSIZ + 1];
|
|
+ int bridge_hairpin; /* hairpin_mode on bridge members */
|
|
+--- a/src/ap/x_snoop.c
|
|
++++ b/src/ap/x_snoop.c
|
|
+@@ -33,14 +33,16 @@ int x_snoop_init(struct hostapd_data *ha
|
|
+
|
|
+ hapd->x_snoop_initialized = true;
|
|
+
|
|
+- if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE,
|
|
++ if (!conf->snoop_iface[0] &&
|
|
++ hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_HAIRPIN_MODE,
|
|
+ 1)) {
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "x_snoop: Failed to enable hairpin_mode on the bridge port");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+- if (hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 1)) {
|
|
++ if (!conf->snoop_iface[0] &&
|
|
++ hostapd_drv_br_port_set_attr(hapd, DRV_BR_PORT_ATTR_PROXYARP, 1)) {
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "x_snoop: Failed to enable proxyarp on the bridge port");
|
|
+ return -1;
|
|
+@@ -54,7 +56,8 @@ int x_snoop_init(struct hostapd_data *ha
|
|
+ }
|
|
+
|
|
+ #ifdef CONFIG_IPV6
|
|
+- if (hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) {
|
|
++ if (!conf->snoop_iface[0] &&
|
|
++ hostapd_drv_br_set_net_param(hapd, DRV_BR_MULTICAST_SNOOPING, 1)) {
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "x_snoop: Failed to enable multicast snooping on the bridge");
|
|
+ return -1;
|
|
+@@ -73,8 +76,12 @@ x_snoop_get_l2_packet(struct hostapd_dat
|
|
+ {
|
|
+ struct hostapd_bss_config *conf = hapd->conf;
|
|
+ struct l2_packet_data *l2;
|
|
++ const char *ifname = conf->bridge;
|
|
+
|
|
+- l2 = l2_packet_init(conf->bridge, NULL, ETH_P_ALL, handler, hapd, 1);
|
|
++ if (conf->snoop_iface[0])
|
|
++ ifname = conf->snoop_iface;
|
|
++
|
|
++ l2 = l2_packet_init(ifname, NULL, ETH_P_ALL, handler, hapd, 1);
|
|
+ if (l2 == NULL) {
|
|
+ wpa_printf(MSG_DEBUG,
|
|
+ "x_snoop: Failed to initialize L2 packet processing %s",
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -2322,6 +2322,8 @@ static int hostapd_config_fill(struct ho
|
|
+ os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
|
|
+ } else if (os_strcmp(buf, "bridge_hairpin") == 0) {
|
|
+ bss->bridge_hairpin = atoi(pos);
|
|
++ } else if (os_strcmp(buf, "snoop_iface") == 0) {
|
|
++ os_strlcpy(bss->snoop_iface, pos, sizeof(bss->snoop_iface));
|
|
+ } else if (os_strcmp(buf, "vlan_bridge") == 0) {
|
|
+ os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
|
|
+ } else if (os_strcmp(buf, "wds_bridge") == 0) {
|
|
diff --git a/package/network/services/hostapd/patches/750-qos_map_set_without_interworking.patch b/package/network/services/hostapd/patches/750-qos_map_set_without_interworking.patch
|
|
new file mode 100644
|
|
index 0000000000..97c32df704
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/750-qos_map_set_without_interworking.patch
|
|
@@ -0,0 +1,97 @@
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -1604,6 +1604,8 @@ static int parse_anqp_elem(struct hostap
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
++#endif /* CONFIG_INTERWORKING */
|
|
++
|
|
+
|
|
+ static int parse_qos_map_set(struct hostapd_bss_config *bss,
|
|
+ char *buf, int line)
|
|
+@@ -1645,8 +1647,6 @@ static int parse_qos_map_set(struct host
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+-#endif /* CONFIG_INTERWORKING */
|
|
+-
|
|
+
|
|
+ #ifdef CONFIG_HS20
|
|
+ static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
|
|
+@@ -4062,10 +4062,10 @@ static int hostapd_config_fill(struct ho
|
|
+ bss->gas_frag_limit = val;
|
|
+ } else if (os_strcmp(buf, "gas_comeback_delay") == 0) {
|
|
+ bss->gas_comeback_delay = atoi(pos);
|
|
++#endif /* CONFIG_INTERWORKING */
|
|
+ } else if (os_strcmp(buf, "qos_map_set") == 0) {
|
|
+ if (parse_qos_map_set(bss, pos, line) < 0)
|
|
+ return 1;
|
|
+-#endif /* CONFIG_INTERWORKING */
|
|
+ #ifdef CONFIG_RADIUS_TEST
|
|
+ } else if (os_strcmp(buf, "dump_msk_file") == 0) {
|
|
+ os_free(bss->dump_msk_file);
|
|
+--- a/src/ap/hostapd.c
|
|
++++ b/src/ap/hostapd.c
|
|
+@@ -1486,6 +1486,7 @@ int hostapd_setup_bss(struct hostapd_dat
|
|
+ wpa_printf(MSG_ERROR, "GAS server initialization failed");
|
|
+ return -1;
|
|
+ }
|
|
++#endif /* CONFIG_INTERWORKING */
|
|
+
|
|
+ if (conf->qos_map_set_len &&
|
|
+ hostapd_drv_set_qos_map(hapd, conf->qos_map_set,
|
|
+@@ -1493,7 +1494,6 @@ int hostapd_setup_bss(struct hostapd_dat
|
|
+ wpa_printf(MSG_ERROR, "Failed to initialize QoS Map");
|
|
+ return -1;
|
|
+ }
|
|
+-#endif /* CONFIG_INTERWORKING */
|
|
+
|
|
+ if (conf->bss_load_update_period && bss_load_update_init(hapd)) {
|
|
+ wpa_printf(MSG_ERROR, "BSS Load initialization failed");
|
|
+--- a/wpa_supplicant/events.c
|
|
++++ b/wpa_supplicant/events.c
|
|
+@@ -2683,8 +2683,6 @@ void wnm_bss_keep_alive_deinit(struct wp
|
|
+ }
|
|
+
|
|
+
|
|
+-#ifdef CONFIG_INTERWORKING
|
|
+-
|
|
+ static int wpas_qos_map_set(struct wpa_supplicant *wpa_s, const u8 *qos_map,
|
|
+ size_t len)
|
|
+ {
|
|
+@@ -2717,8 +2715,6 @@ static void interworking_process_assoc_r
|
|
+ }
|
|
+ }
|
|
+
|
|
+-#endif /* CONFIG_INTERWORKING */
|
|
+-
|
|
+
|
|
+ static void wpa_supplicant_set_4addr_mode(struct wpa_supplicant *wpa_s)
|
|
+ {
|
|
+@@ -3098,10 +3094,8 @@ static int wpa_supplicant_event_associnf
|
|
+ wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
|
|
+ data->assoc_info.resp_ies_len);
|
|
+ #endif /* CONFIG_WNM */
|
|
+-#ifdef CONFIG_INTERWORKING
|
|
+ interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies,
|
|
+ data->assoc_info.resp_ies_len);
|
|
+-#endif /* CONFIG_INTERWORKING */
|
|
+ if (wpa_s->hw_capab == CAPAB_VHT &&
|
|
+ get_ie(data->assoc_info.resp_ies,
|
|
+ data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP))
|
|
+--- a/src/ap/ieee802_11_shared.c
|
|
++++ b/src/ap/ieee802_11_shared.c
|
|
+@@ -1116,13 +1116,11 @@ u8 * hostapd_eid_rsnxe(struct hostapd_da
|
|
+ u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta,
|
|
+ const u8 *ext_capab_ie, size_t ext_capab_ie_len)
|
|
+ {
|
|
+-#ifdef CONFIG_INTERWORKING
|
|
+ /* check for QoS Map support */
|
|
+ if (ext_capab_ie_len >= 5) {
|
|
+ if (ext_capab_ie[4] & 0x01)
|
|
+ sta->qos_map_enabled = 1;
|
|
+ }
|
|
+-#endif /* CONFIG_INTERWORKING */
|
|
+
|
|
+ if (ext_capab_ie_len > 0) {
|
|
+ sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2));
|
|
diff --git a/package/network/services/hostapd/patches/751-qos_map_ignore_when_unsupported.patch b/package/network/services/hostapd/patches/751-qos_map_ignore_when_unsupported.patch
|
|
new file mode 100644
|
|
index 0000000000..f5ebab70d1
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/751-qos_map_ignore_when_unsupported.patch
|
|
@@ -0,0 +1,12 @@
|
|
+--- a/src/ap/ap_drv_ops.c
|
|
++++ b/src/ap/ap_drv_ops.c
|
|
+@@ -927,7 +927,8 @@ int hostapd_start_dfs_cac(struct hostapd
|
|
+ int hostapd_drv_set_qos_map(struct hostapd_data *hapd,
|
|
+ const u8 *qos_map_set, u8 qos_map_set_len)
|
|
+ {
|
|
+- if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv)
|
|
++ if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv ||
|
|
++ !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_QOS_MAPPING))
|
|
+ return 0;
|
|
+ return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set,
|
|
+ qos_map_set_len);
|
|
diff --git a/package/network/services/hostapd/patches/760-dynamic_own_ip.patch b/package/network/services/hostapd/patches/760-dynamic_own_ip.patch
|
|
new file mode 100644
|
|
index 0000000000..2c705a68cf
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/760-dynamic_own_ip.patch
|
|
@@ -0,0 +1,109 @@
|
|
+--- a/src/ap/ap_config.h
|
|
++++ b/src/ap/ap_config.h
|
|
+@@ -310,6 +310,7 @@ struct hostapd_bss_config {
|
|
+ unsigned int eap_sim_db_timeout;
|
|
+ int eap_server_erp; /* Whether ERP is enabled on internal EAP server */
|
|
+ struct hostapd_ip_addr own_ip_addr;
|
|
++ int dynamic_own_ip_addr;
|
|
+ char *nas_identifier;
|
|
+ struct hostapd_radius_servers *radius;
|
|
+ int acct_interim_interval;
|
|
+--- a/src/radius/radius_client.c
|
|
++++ b/src/radius/radius_client.c
|
|
+@@ -163,6 +163,8 @@ struct radius_client_data {
|
|
+ */
|
|
+ void *ctx;
|
|
+
|
|
++ struct hostapd_ip_addr local_ip;
|
|
++
|
|
+ /**
|
|
+ * conf - RADIUS client configuration (list of RADIUS servers to use)
|
|
+ */
|
|
+@@ -720,6 +722,30 @@ static void radius_client_list_add(struc
|
|
+
|
|
+
|
|
+ /**
|
|
++ * radius_client_send - Get local address for the RADIUS auth socket
|
|
++ * @radius: RADIUS client context from radius_client_init()
|
|
++ * @addr: pointer to store the address
|
|
++ *
|
|
++ * This function returns the local address for the connection to the RADIUS
|
|
++ * auth server. It also opens the socket if it's not available yet.
|
|
++ */
|
|
++int radius_client_get_local_addr(struct radius_client_data *radius,
|
|
++ struct hostapd_ip_addr *addr)
|
|
++{
|
|
++ struct hostapd_radius_servers *conf = radius->conf;
|
|
++
|
|
++ if (conf->auth_server && radius->auth_sock < 0)
|
|
++ radius_client_init_auth(radius);
|
|
++
|
|
++ if (radius->auth_sock < 0)
|
|
++ return -1;
|
|
++
|
|
++ memcpy(addr, &radius->local_ip, sizeof(*addr));
|
|
++
|
|
++ return 0;
|
|
++}
|
|
++
|
|
++/**
|
|
+ * radius_client_send - Send a RADIUS request
|
|
+ * @radius: RADIUS client context from radius_client_init()
|
|
+ * @msg: RADIUS message to be sent
|
|
+@@ -1238,6 +1264,10 @@ radius_change_server(struct radius_clien
|
|
+ wpa_printf(MSG_DEBUG, "RADIUS local address: %s:%u",
|
|
+ inet_ntoa(claddr.sin_addr),
|
|
+ ntohs(claddr.sin_port));
|
|
++ if (auth) {
|
|
++ radius->local_ip.af = AF_INET;
|
|
++ radius->local_ip.u.v4 = claddr.sin_addr;
|
|
++ }
|
|
+ }
|
|
+ break;
|
|
+ #ifdef CONFIG_IPV6
|
|
+@@ -1249,6 +1279,10 @@ radius_change_server(struct radius_clien
|
|
+ inet_ntop(AF_INET6, &claddr6.sin6_addr,
|
|
+ abuf, sizeof(abuf)),
|
|
+ ntohs(claddr6.sin6_port));
|
|
++ if (auth) {
|
|
++ radius->local_ip.af = AF_INET6;
|
|
++ radius->local_ip.u.v6 = claddr6.sin6_addr;
|
|
++ }
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+--- a/src/radius/radius_client.h
|
|
++++ b/src/radius/radius_client.h
|
|
+@@ -249,6 +249,8 @@ int radius_client_register(struct radius
|
|
+ void radius_client_set_interim_error_cb(struct radius_client_data *radius,
|
|
+ void (*cb)(const u8 *addr, void *ctx),
|
|
+ void *ctx);
|
|
++int radius_client_get_local_addr(struct radius_client_data *radius,
|
|
++ struct hostapd_ip_addr * addr);
|
|
+ int radius_client_send(struct radius_client_data *radius,
|
|
+ struct radius_msg *msg,
|
|
+ RadiusType msg_type, const u8 *addr);
|
|
+--- a/src/ap/ieee802_1x.c
|
|
++++ b/src/ap/ieee802_1x.c
|
|
+@@ -598,6 +598,10 @@ int add_common_radius_attr(struct hostap
|
|
+ struct hostapd_radius_attr *attr;
|
|
+ int len;
|
|
+
|
|
++ if (hapd->conf->dynamic_own_ip_addr)
|
|
++ radius_client_get_local_addr(hapd->radius,
|
|
++ &hapd->conf->own_ip_addr);
|
|
++
|
|
+ if (!hostapd_config_get_radius_attr(req_attr,
|
|
+ RADIUS_ATTR_NAS_IP_ADDRESS) &&
|
|
+ hapd->conf->own_ip_addr.af == AF_INET &&
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -2688,6 +2688,8 @@ static int hostapd_config_fill(struct ho
|
|
+ } else if (os_strcmp(buf, "iapp_interface") == 0) {
|
|
+ wpa_printf(MSG_INFO, "DEPRECATED: iapp_interface not used");
|
|
+ #endif /* CONFIG_IAPP */
|
|
++ } else if (os_strcmp(buf, "dynamic_own_ip_addr") == 0) {
|
|
++ bss->dynamic_own_ip_addr = atoi(pos);
|
|
+ } else if (os_strcmp(buf, "own_ip_addr") == 0) {
|
|
+ if (hostapd_parse_ip_addr(pos, &bss->own_ip_addr)) {
|
|
+ wpa_printf(MSG_ERROR,
|
|
diff --git a/package/network/services/hostapd/patches/761-shared_das_port.patch b/package/network/services/hostapd/patches/761-shared_das_port.patch
|
|
new file mode 100644
|
|
index 0000000000..cbb2a1be3c
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/761-shared_das_port.patch
|
|
@@ -0,0 +1,298 @@
|
|
+--- a/src/radius/radius_das.h
|
|
++++ b/src/radius/radius_das.h
|
|
+@@ -44,6 +44,7 @@ struct radius_das_attrs {
|
|
+ struct radius_das_conf {
|
|
+ int port;
|
|
+ const u8 *shared_secret;
|
|
++ const u8 *nas_identifier;
|
|
+ size_t shared_secret_len;
|
|
+ const struct hostapd_ip_addr *client_addr;
|
|
+ unsigned int time_window;
|
|
+--- a/src/ap/hostapd.c
|
|
++++ b/src/ap/hostapd.c
|
|
+@@ -1423,6 +1423,7 @@ int hostapd_setup_bss(struct hostapd_dat
|
|
+
|
|
+ os_memset(&das_conf, 0, sizeof(das_conf));
|
|
+ das_conf.port = conf->radius_das_port;
|
|
++ das_conf.nas_identifier = conf->nas_identifier;
|
|
+ das_conf.shared_secret = conf->radius_das_shared_secret;
|
|
+ das_conf.shared_secret_len =
|
|
+ conf->radius_das_shared_secret_len;
|
|
+--- a/src/radius/radius_das.c
|
|
++++ b/src/radius/radius_das.c
|
|
+@@ -12,13 +12,26 @@
|
|
+ #include "utils/common.h"
|
|
+ #include "utils/eloop.h"
|
|
+ #include "utils/ip_addr.h"
|
|
++#include "utils/list.h"
|
|
+ #include "radius.h"
|
|
+ #include "radius_das.h"
|
|
+
|
|
+
|
|
+-struct radius_das_data {
|
|
++static struct dl_list das_ports = DL_LIST_HEAD_INIT(das_ports);
|
|
++
|
|
++struct radius_das_port {
|
|
++ struct dl_list list;
|
|
++ struct dl_list das_data;
|
|
++
|
|
++ int port;
|
|
+ int sock;
|
|
++};
|
|
++
|
|
++struct radius_das_data {
|
|
++ struct dl_list list;
|
|
++ struct radius_das_port *port;
|
|
+ u8 *shared_secret;
|
|
++ u8 *nas_identifier;
|
|
+ size_t shared_secret_len;
|
|
+ struct hostapd_ip_addr client_addr;
|
|
+ unsigned int time_window;
|
|
+@@ -378,56 +391,17 @@ fail:
|
|
+ }
|
|
+
|
|
+
|
|
+-static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
|
++static void
|
|
++radius_das_receive_msg(struct radius_das_data *das, struct radius_msg *msg,
|
|
++ struct sockaddr *from, socklen_t fromlen,
|
|
++ char *abuf, int from_port)
|
|
+ {
|
|
+- struct radius_das_data *das = eloop_ctx;
|
|
+- u8 buf[1500];
|
|
+- union {
|
|
+- struct sockaddr_storage ss;
|
|
+- struct sockaddr_in sin;
|
|
+-#ifdef CONFIG_IPV6
|
|
+- struct sockaddr_in6 sin6;
|
|
+-#endif /* CONFIG_IPV6 */
|
|
+- } from;
|
|
+- char abuf[50];
|
|
+- int from_port = 0;
|
|
+- socklen_t fromlen;
|
|
+- int len;
|
|
+- struct radius_msg *msg, *reply = NULL;
|
|
++ struct radius_msg *reply = NULL;
|
|
+ struct radius_hdr *hdr;
|
|
+ struct wpabuf *rbuf;
|
|
++ struct os_time now;
|
|
+ u32 val;
|
|
+ int res;
|
|
+- struct os_time now;
|
|
+-
|
|
+- fromlen = sizeof(from);
|
|
+- len = recvfrom(sock, buf, sizeof(buf), 0,
|
|
+- (struct sockaddr *) &from.ss, &fromlen);
|
|
+- if (len < 0) {
|
|
+- wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno));
|
|
+- return;
|
|
+- }
|
|
+-
|
|
+- os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
|
|
+- from_port = ntohs(from.sin.sin_port);
|
|
+-
|
|
+- wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d",
|
|
+- len, abuf, from_port);
|
|
+- if (das->client_addr.u.v4.s_addr &&
|
|
+- das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr) {
|
|
+- wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
|
|
+- return;
|
|
+- }
|
|
+-
|
|
+- msg = radius_msg_parse(buf, len);
|
|
+- if (msg == NULL) {
|
|
+- wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet "
|
|
+- "from %s:%d failed", abuf, from_port);
|
|
+- return;
|
|
+- }
|
|
+-
|
|
+- if (wpa_debug_level <= MSG_MSGDUMP)
|
|
+- radius_msg_dump(msg);
|
|
+
|
|
+ if (radius_msg_verify_das_req(msg, das->shared_secret,
|
|
+ das->shared_secret_len,
|
|
+@@ -494,9 +468,8 @@ static void radius_das_receive(int sock,
|
|
+ radius_msg_dump(reply);
|
|
+
|
|
+ rbuf = radius_msg_get_buf(reply);
|
|
+- res = sendto(das->sock, wpabuf_head(rbuf),
|
|
+- wpabuf_len(rbuf), 0,
|
|
+- (struct sockaddr *) &from.ss, fromlen);
|
|
++ res = sendto(das->port->sock, wpabuf_head(rbuf),
|
|
++ wpabuf_len(rbuf), 0, from, fromlen);
|
|
+ if (res < 0) {
|
|
+ wpa_printf(MSG_ERROR, "DAS: sendto(to %s:%d): %s",
|
|
+ abuf, from_port, strerror(errno));
|
|
+@@ -508,6 +481,72 @@ fail:
|
|
+ radius_msg_free(reply);
|
|
+ }
|
|
+
|
|
++static void radius_das_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
|
++{
|
|
++ struct radius_das_port *p = eloop_ctx;
|
|
++ struct radius_das_data *das;
|
|
++ u8 buf[1500];
|
|
++ union {
|
|
++ struct sockaddr_storage ss;
|
|
++ struct sockaddr_in sin;
|
|
++#ifdef CONFIG_IPV6
|
|
++ struct sockaddr_in6 sin6;
|
|
++#endif /* CONFIG_IPV6 */
|
|
++ } from;
|
|
++ struct radius_msg *msg;
|
|
++ size_t nasid_len = 0;
|
|
++ u8 *nasid_buf = NULL;
|
|
++ char abuf[50];
|
|
++ int from_port = 0;
|
|
++ socklen_t fromlen;
|
|
++ int found = 0;
|
|
++ int len;
|
|
++
|
|
++ fromlen = sizeof(from);
|
|
++ len = recvfrom(sock, buf, sizeof(buf), 0,
|
|
++ (struct sockaddr *) &from.ss, &fromlen);
|
|
++ if (len < 0) {
|
|
++ wpa_printf(MSG_ERROR, "DAS: recvfrom: %s", strerror(errno));
|
|
++ return;
|
|
++ }
|
|
++
|
|
++ os_strlcpy(abuf, inet_ntoa(from.sin.sin_addr), sizeof(abuf));
|
|
++ from_port = ntohs(from.sin.sin_port);
|
|
++
|
|
++ msg = radius_msg_parse(buf, len);
|
|
++ if (msg == NULL) {
|
|
++ wpa_printf(MSG_DEBUG, "DAS: Parsing incoming RADIUS packet "
|
|
++ "from %s:%d failed", abuf, from_port);
|
|
++ return;
|
|
++ }
|
|
++
|
|
++ wpa_printf(MSG_DEBUG, "DAS: Received %d bytes from %s:%d",
|
|
++ len, abuf, from_port);
|
|
++
|
|
++ if (wpa_debug_level <= MSG_MSGDUMP)
|
|
++ radius_msg_dump(msg);
|
|
++
|
|
++ radius_msg_get_attr_ptr(msg, RADIUS_ATTR_NAS_IDENTIFIER,
|
|
++ &nasid_buf, &nasid_len, NULL);
|
|
++ dl_list_for_each(das, &p->das_data, struct radius_das_data, list) {
|
|
++ if (das->client_addr.u.v4.s_addr &&
|
|
++ das->client_addr.u.v4.s_addr != from.sin.sin_addr.s_addr)
|
|
++ continue;
|
|
++
|
|
++ if (das->nas_identifier && nasid_buf &&
|
|
++ (nasid_len != os_strlen(das->nas_identifier) ||
|
|
++ os_memcmp(das->nas_identifier, nasid_buf, nasid_len) != 0))
|
|
++ continue;
|
|
++
|
|
++ found = 1;
|
|
++ radius_das_receive_msg(das, msg, (struct sockaddr *)&from.ss,
|
|
++ fromlen, abuf, from_port);
|
|
++ }
|
|
++
|
|
++ if (!found)
|
|
++ wpa_printf(MSG_DEBUG, "DAS: Drop message from unknown client");
|
|
++}
|
|
++
|
|
+
|
|
+ static int radius_das_open_socket(int port)
|
|
+ {
|
|
+@@ -533,6 +572,49 @@ static int radius_das_open_socket(int po
|
|
+ }
|
|
+
|
|
+
|
|
++static struct radius_das_port *
|
|
++radius_das_open_port(int port)
|
|
++{
|
|
++ struct radius_das_port *p;
|
|
++
|
|
++ dl_list_for_each(p, &das_ports, struct radius_das_port, list) {
|
|
++ if (p->port == port)
|
|
++ return p;
|
|
++ }
|
|
++
|
|
++ p = os_zalloc(sizeof(*p));
|
|
++ if (p == NULL)
|
|
++ return NULL;
|
|
++
|
|
++ dl_list_init(&p->das_data);
|
|
++ p->port = port;
|
|
++ p->sock = radius_das_open_socket(port);
|
|
++ if (p->sock < 0)
|
|
++ goto free_port;
|
|
++
|
|
++ if (eloop_register_read_sock(p->sock, radius_das_receive, p, NULL))
|
|
++ goto close_port;
|
|
++
|
|
++ dl_list_add(&das_ports, &p->list);
|
|
++
|
|
++ return p;
|
|
++
|
|
++close_port:
|
|
++ close(p->sock);
|
|
++free_port:
|
|
++ os_free(p);
|
|
++
|
|
++ return NULL;
|
|
++}
|
|
++
|
|
++static void radius_das_close_port(struct radius_das_port *p)
|
|
++{
|
|
++ dl_list_del(&p->list);
|
|
++ eloop_unregister_read_sock(p->sock);
|
|
++ close(p->sock);
|
|
++ free(p);
|
|
++}
|
|
++
|
|
+ struct radius_das_data *
|
|
+ radius_das_init(struct radius_das_conf *conf)
|
|
+ {
|
|
+@@ -553,6 +635,8 @@ radius_das_init(struct radius_das_conf *
|
|
+ das->ctx = conf->ctx;
|
|
+ das->disconnect = conf->disconnect;
|
|
+ das->coa = conf->coa;
|
|
++ if (conf->nas_identifier)
|
|
++ das->nas_identifier = os_strdup(conf->nas_identifier);
|
|
+
|
|
+ os_memcpy(&das->client_addr, conf->client_addr,
|
|
+ sizeof(das->client_addr));
|
|
+@@ -565,19 +649,15 @@ radius_das_init(struct radius_das_conf *
|
|
+ }
|
|
+ das->shared_secret_len = conf->shared_secret_len;
|
|
+
|
|
+- das->sock = radius_das_open_socket(conf->port);
|
|
+- if (das->sock < 0) {
|
|
++ das->port = radius_das_open_port(conf->port);
|
|
++ if (!das->port) {
|
|
+ wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS "
|
|
+ "DAS");
|
|
+ radius_das_deinit(das);
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+- if (eloop_register_read_sock(das->sock, radius_das_receive, das, NULL))
|
|
+- {
|
|
+- radius_das_deinit(das);
|
|
+- return NULL;
|
|
+- }
|
|
++ dl_list_add(&das->port->das_data, &das->list);
|
|
+
|
|
+ return das;
|
|
+ }
|
|
+@@ -588,11 +668,14 @@ void radius_das_deinit(struct radius_das
|
|
+ if (das == NULL)
|
|
+ return;
|
|
+
|
|
+- if (das->sock >= 0) {
|
|
+- eloop_unregister_read_sock(das->sock);
|
|
+- close(das->sock);
|
|
++ if (das->port) {
|
|
++ dl_list_del(&das->list);
|
|
++
|
|
++ if (dl_list_empty(&das->port->das_data))
|
|
++ radius_das_close_port(das->port);
|
|
+ }
|
|
+
|
|
++ os_free(das->nas_identifier);
|
|
+ os_free(das->shared_secret);
|
|
+ os_free(das);
|
|
+ }
|
|
diff --git a/package/network/services/hostapd/patches/770-radius_server.patch b/package/network/services/hostapd/patches/770-radius_server.patch
|
|
new file mode 100644
|
|
index 0000000000..e4690c76b8
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/770-radius_server.patch
|
|
@@ -0,0 +1,154 @@
|
|
+--- a/hostapd/Makefile
|
|
++++ b/hostapd/Makefile
|
|
+@@ -63,6 +63,10 @@ endif
|
|
+ OBJS += main.o
|
|
+ OBJS += config_file.o
|
|
+
|
|
++ifdef CONFIG_RADIUS_SERVER
|
|
++OBJS += radius.o
|
|
++endif
|
|
++
|
|
+ OBJS += ../src/ap/hostapd.o
|
|
+ OBJS += ../src/ap/wpa_auth_glue.o
|
|
+ OBJS += ../src/ap/drv_callbacks.o
|
|
+--- a/hostapd/main.c
|
|
++++ b/hostapd/main.c
|
|
+@@ -40,6 +40,7 @@ struct hapd_global {
|
|
+
|
|
+ static struct hapd_global global;
|
|
+
|
|
++extern int radius_main(int argc, char **argv);
|
|
+
|
|
+ #ifndef CONFIG_NO_HOSTAPD_LOGGER
|
|
+ static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
|
|
+@@ -758,6 +759,11 @@ int main(int argc, char *argv[])
|
|
+ if (os_program_init())
|
|
+ return -1;
|
|
+
|
|
++#ifdef RADIUS_SERVER
|
|
++ if (strstr(argv[0], "radius"))
|
|
++ return radius_main(argc, argv);
|
|
++#endif
|
|
++
|
|
+ os_memset(&interfaces, 0, sizeof(interfaces));
|
|
+ interfaces.reload_config = hostapd_reload_config;
|
|
+ interfaces.config_read_cb = hostapd_config_read;
|
|
+--- a/src/radius/radius_server.c
|
|
++++ b/src/radius/radius_server.c
|
|
+@@ -63,6 +63,12 @@ struct radius_server_counters {
|
|
+ u32 unknown_acct_types;
|
|
+ };
|
|
+
|
|
++struct radius_accept_attr {
|
|
++ u8 type;
|
|
++ u16 len;
|
|
++ void *data;
|
|
++};
|
|
++
|
|
+ /**
|
|
+ * struct radius_session - Internal RADIUS server data for a session
|
|
+ */
|
|
+@@ -90,7 +96,7 @@ struct radius_session {
|
|
+ unsigned int macacl:1;
|
|
+ unsigned int t_c_filtering:1;
|
|
+
|
|
+- struct hostapd_radius_attr *accept_attr;
|
|
++ struct radius_accept_attr *accept_attr;
|
|
+
|
|
+ u32 t_c_timestamp; /* Last read T&C timestamp from user DB */
|
|
+ };
|
|
+@@ -394,6 +400,7 @@ static void radius_server_session_free(s
|
|
+ radius_msg_free(sess->last_reply);
|
|
+ os_free(sess->username);
|
|
+ os_free(sess->nas_ip);
|
|
++ os_free(sess->accept_attr);
|
|
+ os_free(sess);
|
|
+ data->num_sess--;
|
|
+ }
|
|
+@@ -554,6 +561,36 @@ radius_server_erp_find_key(struct radius
|
|
+ }
|
|
+ #endif /* CONFIG_ERP */
|
|
+
|
|
++static struct radius_accept_attr *
|
|
++radius_server_copy_attr(const struct hostapd_radius_attr *data)
|
|
++{
|
|
++ const struct hostapd_radius_attr *attr;
|
|
++ struct radius_accept_attr *attr_new;
|
|
++ size_t data_size = 0;
|
|
++ void *data_buf;
|
|
++ int n_attr = 1;
|
|
++
|
|
++ for (attr = data; attr; attr = attr->next) {
|
|
++ n_attr++;
|
|
++ data_size += wpabuf_len(attr->val);
|
|
++ }
|
|
++
|
|
++ attr_new = os_zalloc(n_attr * sizeof(*attr) + data_size);
|
|
++ if (!attr_new)
|
|
++ return NULL;
|
|
++
|
|
++ data_buf = &attr_new[n_attr];
|
|
++ for (n_attr = 0, attr = data; attr; attr = attr->next) {
|
|
++ struct radius_accept_attr *cur = &attr_new[n_attr++];
|
|
++
|
|
++ cur->type = attr->type;
|
|
++ cur->len = wpabuf_len(attr->val);
|
|
++ cur->data = memcpy(data_buf, wpabuf_head(attr->val), cur->len);
|
|
++ data_buf += cur->len;
|
|
++ }
|
|
++
|
|
++ return attr_new;
|
|
++}
|
|
+
|
|
+ static struct radius_session *
|
|
+ radius_server_get_new_session(struct radius_server_data *data,
|
|
+@@ -607,7 +644,7 @@ radius_server_get_new_session(struct rad
|
|
+ eap_user_free(tmp);
|
|
+ return NULL;
|
|
+ }
|
|
+- sess->accept_attr = tmp->accept_attr;
|
|
++ sess->accept_attr = radius_server_copy_attr(tmp->accept_attr);
|
|
+ sess->macacl = tmp->macacl;
|
|
+ eap_user_free(tmp);
|
|
+
|
|
+@@ -1118,11 +1155,10 @@ radius_server_encapsulate_eap(struct rad
|
|
+ }
|
|
+
|
|
+ if (code == RADIUS_CODE_ACCESS_ACCEPT) {
|
|
+- struct hostapd_radius_attr *attr;
|
|
+- for (attr = sess->accept_attr; attr; attr = attr->next) {
|
|
+- if (!radius_msg_add_attr(msg, attr->type,
|
|
+- wpabuf_head(attr->val),
|
|
+- wpabuf_len(attr->val))) {
|
|
++ struct radius_accept_attr *attr;
|
|
++ for (attr = sess->accept_attr; attr->data; attr++) {
|
|
++ if (!radius_msg_add_attr(msg, attr->type, attr->data,
|
|
++ attr->len)) {
|
|
+ wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
|
|
+ radius_msg_free(msg);
|
|
+ return NULL;
|
|
+@@ -1211,11 +1247,10 @@ radius_server_macacl(struct radius_serve
|
|
+ }
|
|
+
|
|
+ if (code == RADIUS_CODE_ACCESS_ACCEPT) {
|
|
+- struct hostapd_radius_attr *attr;
|
|
+- for (attr = sess->accept_attr; attr; attr = attr->next) {
|
|
+- if (!radius_msg_add_attr(msg, attr->type,
|
|
+- wpabuf_head(attr->val),
|
|
+- wpabuf_len(attr->val))) {
|
|
++ struct radius_accept_attr *attr;
|
|
++ for (attr = sess->accept_attr; attr->data; attr++) {
|
|
++ if (!radius_msg_add_attr(msg, attr->type, attr->data,
|
|
++ attr->len)) {
|
|
+ wpa_printf(MSG_ERROR, "Could not add RADIUS attribute");
|
|
+ radius_msg_free(msg);
|
|
+ return NULL;
|
|
+@@ -2512,7 +2547,7 @@ static int radius_server_get_eap_user(vo
|
|
+ ret = data->get_eap_user(data->conf_ctx, identity, identity_len,
|
|
+ phase2, user);
|
|
+ if (ret == 0 && user) {
|
|
+- sess->accept_attr = user->accept_attr;
|
|
++ sess->accept_attr = radius_server_copy_attr(user->accept_attr);
|
|
+ sess->remediation = user->remediation;
|
|
+ sess->macacl = user->macacl;
|
|
+ sess->t_c_timestamp = user->t_c_timestamp;
|
|
diff --git a/package/network/services/hostapd/patches/990-ctrl-make-WNM_AP-functions-dependant-on-CONFIG_AP.patch b/package/network/services/hostapd/patches/990-ctrl-make-WNM_AP-functions-dependant-on-CONFIG_AP.patch
|
|
new file mode 100644
|
|
index 0000000000..51690def09
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/990-ctrl-make-WNM_AP-functions-dependant-on-CONFIG_AP.patch
|
|
@@ -0,0 +1,33 @@
|
|
+From f0e9f5aab52b3eab85d28338cc996972ced4c39c Mon Sep 17 00:00:00 2001
|
|
+From: David Bauer <mail@david-bauer.net>
|
|
+Date: Tue, 17 May 2022 23:07:59 +0200
|
|
+Subject: [PATCH] ctrl: make WNM_AP functions dependant on CONFIG_AP
|
|
+
|
|
+This fixes linking errors found when compiling wpa_supplicant with
|
|
+CONFIG_WNM_AP enabled but CONFIG_AP disabled.
|
|
+
|
|
+Signed-off-by: David Bauer <mail@david-bauer.net>
|
|
+---
|
|
+ wpa_supplicant/ctrl_iface.c | 4 ++--
|
|
+ 1 file changed, 2 insertions(+), 2 deletions(-)
|
|
+
|
|
+--- a/wpa_supplicant/ctrl_iface.c
|
|
++++ b/wpa_supplicant/ctrl_iface.c
|
|
+@@ -12640,7 +12640,7 @@ char * wpa_supplicant_ctrl_iface_process
|
|
+ if (wpas_ctrl_iface_coloc_intf_report(wpa_s, buf + 18))
|
|
+ reply_len = -1;
|
|
+ #endif /* CONFIG_WNM */
|
|
+-#ifdef CONFIG_WNM_AP
|
|
++#if defined(CONFIG_AP) && defined(CONFIG_WNM_AP)
|
|
+ } else if (os_strncmp(buf, "DISASSOC_IMMINENT ", 18) == 0) {
|
|
+ if (ap_ctrl_iface_disassoc_imminent(wpa_s, buf + 18))
|
|
+ reply_len = -1;
|
|
+@@ -12650,7 +12650,7 @@ char * wpa_supplicant_ctrl_iface_process
|
|
+ } else if (os_strncmp(buf, "BSS_TM_REQ ", 11) == 0) {
|
|
+ if (ap_ctrl_iface_bss_tm_req(wpa_s, buf + 11))
|
|
+ reply_len = -1;
|
|
+-#endif /* CONFIG_WNM_AP */
|
|
++#endif /* CONFIG_AP && CONFIG_WNM_AP */
|
|
+ } else if (os_strcmp(buf, "FLUSH") == 0) {
|
|
+ wpa_supplicant_ctrl_iface_flush(wpa_s);
|
|
+ } else if (os_strncmp(buf, "RADIO_WORK ", 11) == 0) {
|
|
diff --git a/package/network/services/hostapd/src/hostapd/radius.c b/package/network/services/hostapd/src/hostapd/radius.c
|
|
new file mode 100644
|
|
index 0000000000..362a22c276
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/hostapd/radius.c
|
|
@@ -0,0 +1,715 @@
|
|
+#include "utils/includes.h"
|
|
+#include "utils/common.h"
|
|
+#include "utils/eloop.h"
|
|
+#include "crypto/crypto.h"
|
|
+#include "crypto/tls.h"
|
|
+
|
|
+#include "ap/ap_config.h"
|
|
+#include "eap_server/eap.h"
|
|
+#include "radius/radius.h"
|
|
+#include "radius/radius_server.h"
|
|
+#include "eap_register.h"
|
|
+
|
|
+#include <libubox/blobmsg_json.h>
|
|
+#include <libubox/blobmsg.h>
|
|
+#include <libubox/avl.h>
|
|
+#include <libubox/avl-cmp.h>
|
|
+#include <libubox/kvlist.h>
|
|
+
|
|
+#include <sys/stat.h>
|
|
+#include <fnmatch.h>
|
|
+
|
|
+#define VENDOR_ID_WISPR 14122
|
|
+#define VENDOR_ATTR_SIZE 6
|
|
+
|
|
+struct radius_parse_attr_data {
|
|
+ unsigned int vendor;
|
|
+ u8 type;
|
|
+ int size;
|
|
+ char format;
|
|
+ const char *data;
|
|
+};
|
|
+
|
|
+struct radius_parse_attr_state {
|
|
+ struct hostapd_radius_attr *prev;
|
|
+ struct hostapd_radius_attr *attr;
|
|
+ struct wpabuf *buf;
|
|
+ void *attrdata;
|
|
+};
|
|
+
|
|
+struct radius_user_state {
|
|
+ struct avl_node node;
|
|
+ struct eap_user data;
|
|
+};
|
|
+
|
|
+struct radius_user_data {
|
|
+ struct kvlist users;
|
|
+ struct avl_tree user_state;
|
|
+ struct blob_attr *wildcard;
|
|
+};
|
|
+
|
|
+struct radius_state {
|
|
+ struct radius_server_data *radius;
|
|
+ struct eap_config eap;
|
|
+
|
|
+ struct radius_user_data phase1, phase2;
|
|
+ const char *user_file;
|
|
+ time_t user_file_ts;
|
|
+
|
|
+ int n_attrs;
|
|
+ struct hostapd_radius_attr *attrs;
|
|
+};
|
|
+
|
|
+struct radius_config {
|
|
+ struct tls_connection_params tls;
|
|
+ struct radius_server_conf radius;
|
|
+};
|
|
+
|
|
+enum {
|
|
+ USER_ATTR_PASSWORD,
|
|
+ USER_ATTR_HASH,
|
|
+ USER_ATTR_SALT,
|
|
+ USER_ATTR_METHODS,
|
|
+ USER_ATTR_RADIUS,
|
|
+ USER_ATTR_VLAN,
|
|
+ USER_ATTR_MAX_RATE_UP,
|
|
+ USER_ATTR_MAX_RATE_DOWN,
|
|
+ __USER_ATTR_MAX
|
|
+};
|
|
+
|
|
+static void radius_tls_event(void *ctx, enum tls_event ev,
|
|
+ union tls_event_data *data)
|
|
+{
|
|
+ switch (ev) {
|
|
+ case TLS_CERT_CHAIN_SUCCESS:
|
|
+ wpa_printf(MSG_DEBUG, "radius: remote certificate verification success");
|
|
+ break;
|
|
+ case TLS_CERT_CHAIN_FAILURE:
|
|
+ wpa_printf(MSG_INFO, "radius: certificate chain failure: reason=%d depth=%d subject='%s' err='%s'",
|
|
+ data->cert_fail.reason,
|
|
+ data->cert_fail.depth,
|
|
+ data->cert_fail.subject,
|
|
+ data->cert_fail.reason_txt);
|
|
+ break;
|
|
+ case TLS_PEER_CERTIFICATE:
|
|
+ wpa_printf(MSG_DEBUG, "radius: peer certificate: depth=%d serial_num=%s subject=%s",
|
|
+ data->peer_cert.depth,
|
|
+ data->peer_cert.serial_num ? data->peer_cert.serial_num : "N/A",
|
|
+ data->peer_cert.subject);
|
|
+ break;
|
|
+ case TLS_ALERT:
|
|
+ if (data->alert.is_local)
|
|
+ wpa_printf(MSG_DEBUG, "radius: local TLS alert: %s",
|
|
+ data->alert.description);
|
|
+ else
|
|
+ wpa_printf(MSG_DEBUG, "radius: remote TLS alert: %s",
|
|
+ data->alert.description);
|
|
+ break;
|
|
+ case TLS_UNSAFE_RENEGOTIATION_DISABLED:
|
|
+ /* Not applicable to TLS server */
|
|
+ break;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void radius_userdata_init(struct radius_user_data *u)
|
|
+{
|
|
+ kvlist_init(&u->users, kvlist_blob_len);
|
|
+ avl_init(&u->user_state, avl_strcmp, false, NULL);
|
|
+}
|
|
+
|
|
+static void radius_userdata_free(struct radius_user_data *u)
|
|
+{
|
|
+ struct radius_user_state *s, *tmp;
|
|
+
|
|
+ kvlist_free(&u->users);
|
|
+ free(u->wildcard);
|
|
+ u->wildcard = NULL;
|
|
+ avl_remove_all_elements(&u->user_state, s, node, tmp)
|
|
+ free(s);
|
|
+}
|
|
+
|
|
+static void
|
|
+radius_userdata_load(struct radius_user_data *u, struct blob_attr *data)
|
|
+{
|
|
+ enum {
|
|
+ USERSTATE_USERS,
|
|
+ USERSTATE_WILDCARD,
|
|
+ __USERSTATE_MAX,
|
|
+ };
|
|
+ static const struct blobmsg_policy policy[__USERSTATE_MAX] = {
|
|
+ [USERSTATE_USERS] = { "users", BLOBMSG_TYPE_TABLE },
|
|
+ [USERSTATE_WILDCARD] = { "wildcard", BLOBMSG_TYPE_ARRAY },
|
|
+ };
|
|
+ struct blob_attr *tb[__USERSTATE_MAX], *cur;
|
|
+ int rem;
|
|
+
|
|
+ if (!data)
|
|
+ return;
|
|
+
|
|
+ blobmsg_parse(policy, __USERSTATE_MAX, tb, blobmsg_data(data), blobmsg_len(data));
|
|
+
|
|
+ blobmsg_for_each_attr(cur, tb[USERSTATE_USERS], rem)
|
|
+ kvlist_set(&u->users, blobmsg_name(cur), cur);
|
|
+
|
|
+ if (tb[USERSTATE_WILDCARD])
|
|
+ u->wildcard = blob_memdup(tb[USERSTATE_WILDCARD]);
|
|
+}
|
|
+
|
|
+static void
|
|
+load_userfile(struct radius_state *s)
|
|
+{
|
|
+ enum {
|
|
+ USERDATA_PHASE1,
|
|
+ USERDATA_PHASE2,
|
|
+ __USERDATA_MAX
|
|
+ };
|
|
+ static const struct blobmsg_policy policy[__USERDATA_MAX] = {
|
|
+ [USERDATA_PHASE1] = { "phase1", BLOBMSG_TYPE_TABLE },
|
|
+ [USERDATA_PHASE2] = { "phase2", BLOBMSG_TYPE_TABLE },
|
|
+ };
|
|
+ struct blob_attr *tb[__USERDATA_MAX], *cur;
|
|
+ static struct blob_buf b;
|
|
+ struct stat st;
|
|
+ int rem;
|
|
+
|
|
+ if (stat(s->user_file, &st))
|
|
+ return;
|
|
+
|
|
+ if (s->user_file_ts == st.st_mtime)
|
|
+ return;
|
|
+
|
|
+ s->user_file_ts = st.st_mtime;
|
|
+ radius_userdata_free(&s->phase1);
|
|
+ radius_userdata_free(&s->phase2);
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_json_from_file(&b, s->user_file);
|
|
+ blobmsg_parse(policy, __USERDATA_MAX, tb, blob_data(b.head), blob_len(b.head));
|
|
+ radius_userdata_load(&s->phase1, tb[USERDATA_PHASE1]);
|
|
+ radius_userdata_load(&s->phase2, tb[USERDATA_PHASE2]);
|
|
+
|
|
+ blob_buf_free(&b);
|
|
+}
|
|
+
|
|
+static struct blob_attr *
|
|
+radius_user_get(struct radius_user_data *s, const char *name)
|
|
+{
|
|
+ struct blob_attr *cur;
|
|
+ int rem;
|
|
+
|
|
+ cur = kvlist_get(&s->users, name);
|
|
+ if (cur)
|
|
+ return cur;
|
|
+
|
|
+ blobmsg_for_each_attr(cur, s->wildcard, rem) {
|
|
+ static const struct blobmsg_policy policy = {
|
|
+ "name", BLOBMSG_TYPE_STRING
|
|
+ };
|
|
+ struct blob_attr *pattern;
|
|
+
|
|
+ if (blobmsg_type(cur) != BLOBMSG_TYPE_TABLE)
|
|
+ continue;
|
|
+
|
|
+ blobmsg_parse(&policy, 1, &pattern, blobmsg_data(cur), blobmsg_len(cur));
|
|
+ if (!name)
|
|
+ continue;
|
|
+
|
|
+ if (!fnmatch(blobmsg_get_string(pattern), name, 0))
|
|
+ return cur;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static struct radius_parse_attr_data *
|
|
+radius_parse_attr(struct blob_attr *attr)
|
|
+{
|
|
+ static const struct blobmsg_policy policy[4] = {
|
|
+ { .type = BLOBMSG_TYPE_INT32 },
|
|
+ { .type = BLOBMSG_TYPE_INT32 },
|
|
+ { .type = BLOBMSG_TYPE_STRING },
|
|
+ { .type = BLOBMSG_TYPE_STRING },
|
|
+ };
|
|
+ static struct radius_parse_attr_data data;
|
|
+ struct blob_attr *tb[4];
|
|
+ const char *format;
|
|
+
|
|
+ blobmsg_parse_array(policy, ARRAY_SIZE(policy), tb, blobmsg_data(attr), blobmsg_len(attr));
|
|
+
|
|
+ if (!tb[0] || !tb[1] || !tb[2] || !tb[3])
|
|
+ return NULL;
|
|
+
|
|
+ format = blobmsg_get_string(tb[2]);
|
|
+ if (strlen(format) != 1)
|
|
+ return NULL;
|
|
+
|
|
+ data.vendor = blobmsg_get_u32(tb[0]);
|
|
+ data.type = blobmsg_get_u32(tb[1]);
|
|
+ data.format = format[0];
|
|
+ data.data = blobmsg_get_string(tb[3]);
|
|
+ data.size = strlen(data.data);
|
|
+
|
|
+ switch (data.format) {
|
|
+ case 's':
|
|
+ break;
|
|
+ case 'x':
|
|
+ if (data.size & 1)
|
|
+ return NULL;
|
|
+ data.size /= 2;
|
|
+ break;
|
|
+ case 'd':
|
|
+ data.size = 4;
|
|
+ break;
|
|
+ default:
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ return &data;
|
|
+}
|
|
+
|
|
+static void
|
|
+radius_count_attrs(struct blob_attr **tb, int *n_attr, size_t *attr_size)
|
|
+{
|
|
+ struct blob_attr *data = tb[USER_ATTR_RADIUS];
|
|
+ struct blob_attr *cur;
|
|
+ int rem;
|
|
+
|
|
+ blobmsg_for_each_attr(cur, data, rem) {
|
|
+ struct radius_parse_attr_data *data;
|
|
+ size_t prev = *attr_size;
|
|
+
|
|
+ data = radius_parse_attr(cur);
|
|
+ if (!data)
|
|
+ continue;
|
|
+
|
|
+ *attr_size += data->size;
|
|
+ if (data->vendor)
|
|
+ *attr_size += VENDOR_ATTR_SIZE;
|
|
+
|
|
+ (*n_attr)++;
|
|
+ }
|
|
+
|
|
+ *n_attr += !!tb[USER_ATTR_VLAN] * 3 +
|
|
+ !!tb[USER_ATTR_MAX_RATE_UP] +
|
|
+ !!tb[USER_ATTR_MAX_RATE_DOWN];
|
|
+ *attr_size += !!tb[USER_ATTR_VLAN] * (4 + 4 + 5) +
|
|
+ !!tb[USER_ATTR_MAX_RATE_UP] * (4 + VENDOR_ATTR_SIZE) +
|
|
+ !!tb[USER_ATTR_MAX_RATE_DOWN] * (4 + VENDOR_ATTR_SIZE);
|
|
+}
|
|
+
|
|
+static void *
|
|
+radius_add_attr(struct radius_parse_attr_state *state,
|
|
+ u32 vendor, u8 type, u8 len)
|
|
+{
|
|
+ struct hostapd_radius_attr *attr;
|
|
+ struct wpabuf *buf;
|
|
+ void *val;
|
|
+
|
|
+ val = state->attrdata;
|
|
+
|
|
+ buf = state->buf++;
|
|
+ buf->buf = val;
|
|
+
|
|
+ attr = state->attr++;
|
|
+ attr->val = buf;
|
|
+ attr->type = type;
|
|
+
|
|
+ if (state->prev)
|
|
+ state->prev->next = attr;
|
|
+ state->prev = attr;
|
|
+
|
|
+ if (vendor) {
|
|
+ u8 *vendor_hdr = val + 4;
|
|
+
|
|
+ WPA_PUT_BE32(val, vendor);
|
|
+ vendor_hdr[0] = type;
|
|
+ vendor_hdr[1] = len + 2;
|
|
+
|
|
+ len += VENDOR_ATTR_SIZE;
|
|
+ val += VENDOR_ATTR_SIZE;
|
|
+ attr->type = RADIUS_ATTR_VENDOR_SPECIFIC;
|
|
+ }
|
|
+
|
|
+ buf->size = buf->used = len;
|
|
+ state->attrdata += len;
|
|
+
|
|
+ return val;
|
|
+}
|
|
+
|
|
+static void
|
|
+radius_parse_attrs(struct blob_attr **tb, struct radius_parse_attr_state *state)
|
|
+{
|
|
+ struct blob_attr *data = tb[USER_ATTR_RADIUS];
|
|
+ struct hostapd_radius_attr *prev = NULL;
|
|
+ struct blob_attr *cur;
|
|
+ int len, rem;
|
|
+ void *val;
|
|
+
|
|
+ if ((cur = tb[USER_ATTR_VLAN]) != NULL && blobmsg_get_u32(cur) < 4096) {
|
|
+ char buf[5];
|
|
+
|
|
+ val = radius_add_attr(state, 0, RADIUS_ATTR_TUNNEL_TYPE, 4);
|
|
+ WPA_PUT_BE32(val, RADIUS_TUNNEL_TYPE_VLAN);
|
|
+
|
|
+ val = radius_add_attr(state, 0, RADIUS_ATTR_TUNNEL_MEDIUM_TYPE, 4);
|
|
+ WPA_PUT_BE32(val, RADIUS_TUNNEL_MEDIUM_TYPE_802);
|
|
+
|
|
+ len = snprintf(buf, sizeof(buf), "%d", blobmsg_get_u32(cur));
|
|
+ val = radius_add_attr(state, 0, RADIUS_ATTR_TUNNEL_PRIVATE_GROUP_ID, len);
|
|
+ memcpy(val, buf, len);
|
|
+ }
|
|
+
|
|
+ if ((cur = tb[USER_ATTR_MAX_RATE_UP]) != NULL) {
|
|
+ val = radius_add_attr(state, VENDOR_ID_WISPR, 7, 4);
|
|
+ WPA_PUT_BE32(val, blobmsg_get_u32(cur));
|
|
+ }
|
|
+
|
|
+ if ((cur = tb[USER_ATTR_MAX_RATE_DOWN]) != NULL) {
|
|
+ val = radius_add_attr(state, VENDOR_ID_WISPR, 8, 4);
|
|
+ WPA_PUT_BE32(val, blobmsg_get_u32(cur));
|
|
+ }
|
|
+
|
|
+ blobmsg_for_each_attr(cur, data, rem) {
|
|
+ struct radius_parse_attr_data *data;
|
|
+ void *val;
|
|
+ int size;
|
|
+
|
|
+ data = radius_parse_attr(cur);
|
|
+ if (!data)
|
|
+ continue;
|
|
+
|
|
+ val = radius_add_attr(state, data->vendor, data->type, data->size);
|
|
+ switch (data->format) {
|
|
+ case 's':
|
|
+ memcpy(val, data->data, data->size);
|
|
+ break;
|
|
+ case 'x':
|
|
+ hexstr2bin(data->data, val, data->size);
|
|
+ break;
|
|
+ case 'd':
|
|
+ WPA_PUT_BE32(val, atoi(data->data));
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+radius_user_parse_methods(struct eap_user *eap, struct blob_attr *data)
|
|
+{
|
|
+ struct blob_attr *cur;
|
|
+ int rem, n = 0;
|
|
+
|
|
+ if (!data)
|
|
+ return;
|
|
+
|
|
+ blobmsg_for_each_attr(cur, data, rem) {
|
|
+ const char *method;
|
|
+
|
|
+ if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING)
|
|
+ continue;
|
|
+
|
|
+ if (n == EAP_MAX_METHODS)
|
|
+ break;
|
|
+
|
|
+ method = blobmsg_get_string(cur);
|
|
+ eap->methods[n].method = eap_server_get_type(method, &eap->methods[n].vendor);
|
|
+ if (eap->methods[n].vendor == EAP_VENDOR_IETF &&
|
|
+ eap->methods[n].method == EAP_TYPE_NONE) {
|
|
+ if (!strcmp(method, "TTLS-PAP")) {
|
|
+ eap->ttls_auth |= EAP_TTLS_AUTH_PAP;
|
|
+ continue;
|
|
+ }
|
|
+ if (!strcmp(method, "TTLS-CHAP")) {
|
|
+ eap->ttls_auth |= EAP_TTLS_AUTH_CHAP;
|
|
+ continue;
|
|
+ }
|
|
+ if (!strcmp(method, "TTLS-MSCHAP")) {
|
|
+ eap->ttls_auth |= EAP_TTLS_AUTH_MSCHAP;
|
|
+ continue;
|
|
+ }
|
|
+ if (!strcmp(method, "TTLS-MSCHAPV2")) {
|
|
+ eap->ttls_auth |= EAP_TTLS_AUTH_MSCHAPV2;
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+ n++;
|
|
+ }
|
|
+}
|
|
+
|
|
+static struct eap_user *
|
|
+radius_user_get_state(struct radius_user_data *u, struct blob_attr *data,
|
|
+ const char *id)
|
|
+{
|
|
+ static const struct blobmsg_policy policy[__USER_ATTR_MAX] = {
|
|
+ [USER_ATTR_PASSWORD] = { "password", BLOBMSG_TYPE_STRING },
|
|
+ [USER_ATTR_HASH] = { "hash", BLOBMSG_TYPE_STRING },
|
|
+ [USER_ATTR_SALT] = { "salt", BLOBMSG_TYPE_STRING },
|
|
+ [USER_ATTR_METHODS] = { "methods", BLOBMSG_TYPE_ARRAY },
|
|
+ [USER_ATTR_RADIUS] = { "radius", BLOBMSG_TYPE_ARRAY },
|
|
+ [USER_ATTR_VLAN] = { "vlan-id", BLOBMSG_TYPE_INT32 },
|
|
+ [USER_ATTR_MAX_RATE_UP] = { "max-rate-up", BLOBMSG_TYPE_INT32 },
|
|
+ [USER_ATTR_MAX_RATE_DOWN] = { "max-rate-down", BLOBMSG_TYPE_INT32 },
|
|
+ };
|
|
+ struct blob_attr *tb[__USER_ATTR_MAX], *cur;
|
|
+ char *password_buf, *salt_buf, *name_buf;
|
|
+ struct radius_parse_attr_state astate = {};
|
|
+ struct hostapd_radius_attr *attr;
|
|
+ struct radius_user_state *state;
|
|
+ int pw_len = 0, salt_len = 0;
|
|
+ struct eap_user *eap;
|
|
+ struct wpabuf *val;
|
|
+ size_t attrsize = 0;
|
|
+ void *attrdata;
|
|
+ int n_attr = 0;
|
|
+
|
|
+ state = avl_find_element(&u->user_state, id, state, node);
|
|
+ if (state)
|
|
+ return &state->data;
|
|
+
|
|
+ blobmsg_parse(policy, __USER_ATTR_MAX, tb, blobmsg_data(data), blobmsg_len(data));
|
|
+
|
|
+ if ((cur = tb[USER_ATTR_SALT]) != NULL)
|
|
+ salt_len = strlen(blobmsg_get_string(cur)) / 2;
|
|
+ if ((cur = tb[USER_ATTR_HASH]) != NULL)
|
|
+ pw_len = strlen(blobmsg_get_string(cur)) / 2;
|
|
+ else if ((cur = tb[USER_ATTR_PASSWORD]) != NULL)
|
|
+ pw_len = blobmsg_len(cur) - 1;
|
|
+ radius_count_attrs(tb, &n_attr, &attrsize);
|
|
+
|
|
+ state = calloc_a(sizeof(*state), &name_buf, strlen(id) + 1,
|
|
+ &password_buf, pw_len,
|
|
+ &salt_buf, salt_len,
|
|
+ &astate.attr, n_attr * sizeof(*astate.attr),
|
|
+ &astate.buf, n_attr * sizeof(*astate.buf),
|
|
+ &astate.attrdata, attrsize);
|
|
+ eap = &state->data;
|
|
+ eap->salt = salt_len ? salt_buf : NULL;
|
|
+ eap->salt_len = salt_len;
|
|
+ eap->password = pw_len ? password_buf : NULL;
|
|
+ eap->password_len = pw_len;
|
|
+ eap->force_version = -1;
|
|
+
|
|
+ if ((cur = tb[USER_ATTR_SALT]) != NULL)
|
|
+ hexstr2bin(blobmsg_get_string(cur), salt_buf, salt_len);
|
|
+ if ((cur = tb[USER_ATTR_PASSWORD]) != NULL)
|
|
+ memcpy(password_buf, blobmsg_get_string(cur), pw_len);
|
|
+ else if ((cur = tb[USER_ATTR_HASH]) != NULL) {
|
|
+ hexstr2bin(blobmsg_get_string(cur), password_buf, pw_len);
|
|
+ eap->password_hash = 1;
|
|
+ }
|
|
+ radius_user_parse_methods(eap, tb[USER_ATTR_METHODS]);
|
|
+
|
|
+ if (n_attr > 0) {
|
|
+ cur = tb[USER_ATTR_RADIUS];
|
|
+ eap->accept_attr = astate.attr;
|
|
+ radius_parse_attrs(tb, &astate);
|
|
+ }
|
|
+
|
|
+ state->node.key = strcpy(name_buf, id);
|
|
+ avl_insert(&u->user_state, &state->node);
|
|
+
|
|
+ return &state->data;
|
|
+
|
|
+free:
|
|
+ free(state);
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static int radius_get_eap_user(void *ctx, const u8 *identity,
|
|
+ size_t identity_len, int phase2,
|
|
+ struct eap_user *user)
|
|
+{
|
|
+ struct radius_state *s = ctx;
|
|
+ struct radius_user_data *u = phase2 ? &s->phase2 : &s->phase1;
|
|
+ struct blob_attr *entry;
|
|
+ struct eap_user *data;
|
|
+ char *id;
|
|
+
|
|
+ if (identity_len > 512)
|
|
+ return -1;
|
|
+
|
|
+ load_userfile(s);
|
|
+
|
|
+ id = alloca(identity_len + 1);
|
|
+ memcpy(id, identity, identity_len);
|
|
+ id[identity_len] = 0;
|
|
+
|
|
+ entry = radius_user_get(u, id);
|
|
+ if (!entry)
|
|
+ return -1;
|
|
+
|
|
+ if (!user)
|
|
+ return 0;
|
|
+
|
|
+ data = radius_user_get_state(u, entry, id);
|
|
+ if (!data)
|
|
+ return -1;
|
|
+
|
|
+ *user = *data;
|
|
+ if (user->password_len > 0)
|
|
+ user->password = os_memdup(user->password, user->password_len);
|
|
+ if (user->salt_len > 0)
|
|
+ user->salt = os_memdup(user->salt, user->salt_len);
|
|
+ user->phase2 = phase2;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int radius_setup(struct radius_state *s, struct radius_config *c)
|
|
+{
|
|
+ struct eap_config *eap = &s->eap;
|
|
+ struct tls_config conf = {
|
|
+ .event_cb = radius_tls_event,
|
|
+ .tls_flags = TLS_CONN_DISABLE_TLSv1_3,
|
|
+ .cb_ctx = s,
|
|
+ };
|
|
+
|
|
+ eap->eap_server = 1;
|
|
+ eap->max_auth_rounds = 100;
|
|
+ eap->max_auth_rounds_short = 50;
|
|
+ eap->ssl_ctx = tls_init(&conf);
|
|
+ if (!eap->ssl_ctx) {
|
|
+ wpa_printf(MSG_INFO, "TLS init failed\n");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ if (tls_global_set_params(eap->ssl_ctx, &c->tls)) {
|
|
+ wpa_printf(MSG_INFO, "failed to set TLS parameters\n");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ c->radius.eap_cfg = eap;
|
|
+ c->radius.conf_ctx = s;
|
|
+ c->radius.get_eap_user = radius_get_eap_user;
|
|
+ s->radius = radius_server_init(&c->radius);
|
|
+ if (!s->radius) {
|
|
+ wpa_printf(MSG_INFO, "failed to initialize radius server\n");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int radius_init(struct radius_state *s)
|
|
+{
|
|
+ memset(s, 0, sizeof(*s));
|
|
+ radius_userdata_init(&s->phase1);
|
|
+ radius_userdata_init(&s->phase2);
|
|
+}
|
|
+
|
|
+static void radius_deinit(struct radius_state *s)
|
|
+{
|
|
+ if (s->radius)
|
|
+ radius_server_deinit(s->radius);
|
|
+
|
|
+ if (s->eap.ssl_ctx)
|
|
+ tls_deinit(s->eap.ssl_ctx);
|
|
+
|
|
+ radius_userdata_free(&s->phase1);
|
|
+ radius_userdata_free(&s->phase2);
|
|
+}
|
|
+
|
|
+static int usage(const char *progname)
|
|
+{
|
|
+ fprintf(stderr, "Usage: %s <options>\n",
|
|
+ progname);
|
|
+}
|
|
+
|
|
+int radius_main(int argc, char **argv)
|
|
+{
|
|
+ static struct radius_state state = {};
|
|
+ static struct radius_config config = {};
|
|
+ const char *progname = argv[0];
|
|
+ int ret = 0;
|
|
+ int ch;
|
|
+
|
|
+ wpa_debug_setup_stdout();
|
|
+ wpa_debug_level = 0;
|
|
+
|
|
+ if (eloop_init()) {
|
|
+ wpa_printf(MSG_ERROR, "Failed to initialize event loop");
|
|
+ return 1;
|
|
+ }
|
|
+
|
|
+ eap_server_register_methods();
|
|
+ radius_init(&state);
|
|
+
|
|
+ while ((ch = getopt(argc, argv, "6C:c:d:i:k:K:p:P:s:u:")) != -1) {
|
|
+ switch (ch) {
|
|
+ case '6':
|
|
+ config.radius.ipv6 = 1;
|
|
+ break;
|
|
+ case 'C':
|
|
+ config.tls.ca_cert = optarg;
|
|
+ break;
|
|
+ case 'c':
|
|
+ if (config.tls.client_cert2)
|
|
+ return usage(progname);
|
|
+
|
|
+ if (config.tls.client_cert)
|
|
+ config.tls.client_cert2 = optarg;
|
|
+ else
|
|
+ config.tls.client_cert = optarg;
|
|
+ break;
|
|
+ case 'd':
|
|
+ config.tls.dh_file = optarg;
|
|
+ break;
|
|
+ case 'i':
|
|
+ state.eap.server_id = optarg;
|
|
+ state.eap.server_id_len = strlen(optarg);
|
|
+ break;
|
|
+ case 'k':
|
|
+ if (config.tls.private_key2)
|
|
+ return usage(progname);
|
|
+
|
|
+ if (config.tls.private_key)
|
|
+ config.tls.private_key2 = optarg;
|
|
+ else
|
|
+ config.tls.private_key = optarg;
|
|
+ break;
|
|
+ case 'K':
|
|
+ if (config.tls.private_key_passwd2)
|
|
+ return usage(progname);
|
|
+
|
|
+ if (config.tls.private_key_passwd)
|
|
+ config.tls.private_key_passwd2 = optarg;
|
|
+ else
|
|
+ config.tls.private_key_passwd = optarg;
|
|
+ break;
|
|
+ case 'p':
|
|
+ config.radius.auth_port = atoi(optarg);
|
|
+ break;
|
|
+ case 'P':
|
|
+ config.radius.acct_port = atoi(optarg);
|
|
+ break;
|
|
+ case 's':
|
|
+ config.radius.client_file = optarg;
|
|
+ break;
|
|
+ case 'u':
|
|
+ state.user_file = optarg;
|
|
+ break;
|
|
+ default:
|
|
+ return usage(progname);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!config.tls.client_cert || !config.tls.private_key ||
|
|
+ !config.radius.client_file || !state.eap.server_id ||
|
|
+ !state.user_file) {
|
|
+ wpa_printf(MSG_INFO, "missing options\n");
|
|
+ goto out;
|
|
+ }
|
|
+
|
|
+ ret = radius_setup(&state, &config);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+
|
|
+ load_userfile(&state);
|
|
+ eloop_run();
|
|
+
|
|
+out:
|
|
+ radius_deinit(&state);
|
|
+ os_program_deinit();
|
|
+
|
|
+ return ret;
|
|
+}
|
|
diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c
|
|
new file mode 100644
|
|
index 0000000000..6ff2257c32
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/src/ap/ubus.c
|
|
@@ -0,0 +1,2002 @@
|
|
+/*
|
|
+ * hostapd / ubus support
|
|
+ * Copyright (c) 2013, Felix Fietkau <nbd@nbd.name>
|
|
+ *
|
|
+ * 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 "utils/wpabuf.h"
|
|
+#include "common/ieee802_11_defs.h"
|
|
+#include "common/hw_features_common.h"
|
|
+#include "hostapd.h"
|
|
+#include "neighbor_db.h"
|
|
+#include "wps_hostapd.h"
|
|
+#include "sta_info.h"
|
|
+#include "ubus.h"
|
|
+#include "ap_drv_ops.h"
|
|
+#include "beacon.h"
|
|
+#include "rrm.h"
|
|
+#include "wnm_ap.h"
|
|
+#include "taxonomy.h"
|
|
+#include "airtime_policy.h"
|
|
+#include "hw_features.h"
|
|
+
|
|
+static struct ubus_context *ctx;
|
|
+static struct blob_buf b;
|
|
+static int ctx_ref;
|
|
+
|
|
+static inline struct hostapd_data *get_hapd_from_object(struct ubus_object *obj)
|
|
+{
|
|
+ return container_of(obj, struct hostapd_data, ubus.obj);
|
|
+}
|
|
+
|
|
+struct ubus_banned_client {
|
|
+ struct avl_node avl;
|
|
+ u8 addr[ETH_ALEN];
|
|
+};
|
|
+
|
|
+static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx)
|
|
+{
|
|
+ if (ubus_reconnect(ctx, NULL)) {
|
|
+ eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ubus_add_uloop(ctx);
|
|
+}
|
|
+
|
|
+static void hostapd_ubus_connection_lost(struct ubus_context *ctx)
|
|
+{
|
|
+ uloop_fd_delete(&ctx->sock);
|
|
+ eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL);
|
|
+}
|
|
+
|
|
+static bool hostapd_ubus_init(void)
|
|
+{
|
|
+ if (ctx)
|
|
+ return true;
|
|
+
|
|
+ eloop_add_uloop();
|
|
+ ctx = ubus_connect(NULL);
|
|
+ if (!ctx)
|
|
+ return false;
|
|
+
|
|
+ ctx->connection_lost = hostapd_ubus_connection_lost;
|
|
+ ubus_add_uloop(ctx);
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static void hostapd_ubus_ref_inc(void)
|
|
+{
|
|
+ ctx_ref++;
|
|
+}
|
|
+
|
|
+static void hostapd_ubus_ref_dec(void)
|
|
+{
|
|
+ ctx_ref--;
|
|
+ if (!ctx)
|
|
+ return;
|
|
+
|
|
+ if (ctx_ref)
|
|
+ return;
|
|
+
|
|
+ uloop_fd_delete(&ctx->sock);
|
|
+ ubus_free(ctx);
|
|
+ ctx = NULL;
|
|
+}
|
|
+
|
|
+void hostapd_ubus_add_iface(struct hostapd_iface *iface)
|
|
+{
|
|
+ if (!hostapd_ubus_init())
|
|
+ return;
|
|
+}
|
|
+
|
|
+void hostapd_ubus_free_iface(struct hostapd_iface *iface)
|
|
+{
|
|
+ if (!ctx)
|
|
+ return;
|
|
+}
|
|
+
|
|
+static void hostapd_notify_ubus(struct ubus_object *obj, char *bssname, char *event)
|
|
+{
|
|
+ char *event_type;
|
|
+
|
|
+ if (!ctx || !obj)
|
|
+ return;
|
|
+
|
|
+ if (asprintf(&event_type, "bss.%s", event) < 0)
|
|
+ return;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_string(&b, "name", bssname);
|
|
+ ubus_notify(ctx, obj, event_type, b.head, -1);
|
|
+ free(event_type);
|
|
+}
|
|
+
|
|
+static void
|
|
+hostapd_bss_del_ban(void *eloop_data, void *user_ctx)
|
|
+{
|
|
+ struct ubus_banned_client *ban = eloop_data;
|
|
+ struct hostapd_data *hapd = user_ctx;
|
|
+
|
|
+ avl_delete(&hapd->ubus.banned, &ban->avl);
|
|
+ free(ban);
|
|
+}
|
|
+
|
|
+static void
|
|
+hostapd_bss_ban_client(struct hostapd_data *hapd, u8 *addr, int time)
|
|
+{
|
|
+ struct ubus_banned_client *ban;
|
|
+
|
|
+ if (time < 0)
|
|
+ time = 0;
|
|
+
|
|
+ ban = avl_find_element(&hapd->ubus.banned, addr, ban, avl);
|
|
+ if (!ban) {
|
|
+ if (!time)
|
|
+ return;
|
|
+
|
|
+ ban = os_zalloc(sizeof(*ban));
|
|
+ memcpy(ban->addr, addr, sizeof(ban->addr));
|
|
+ ban->avl.key = ban->addr;
|
|
+ avl_insert(&hapd->ubus.banned, &ban->avl);
|
|
+ } else {
|
|
+ eloop_cancel_timeout(hostapd_bss_del_ban, ban, hapd);
|
|
+ if (!time) {
|
|
+ hostapd_bss_del_ban(ban, hapd);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ eloop_register_timeout(0, time * 1000, hostapd_bss_del_ban, ban, hapd);
|
|
+}
|
|
+
|
|
+static int
|
|
+hostapd_bss_reload(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+
|
|
+ return hostapd_reload_config(hapd->iface);
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+hostapd_parse_vht_map_blobmsg(uint16_t map)
|
|
+{
|
|
+ char label[4];
|
|
+ int16_t val;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < 8; i++) {
|
|
+ snprintf(label, 4, "%dss", i + 1);
|
|
+
|
|
+ val = (map & (BIT(1) | BIT(0))) + 7;
|
|
+ blobmsg_add_u16(&b, label, val == 10 ? -1 : val);
|
|
+ map = map >> 2;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+hostapd_parse_vht_capab_blobmsg(struct ieee80211_vht_capabilities *vhtc)
|
|
+{
|
|
+ void *supported_mcs;
|
|
+ void *map;
|
|
+ int i;
|
|
+
|
|
+ static const struct {
|
|
+ const char *name;
|
|
+ uint32_t flag;
|
|
+ } vht_capas[] = {
|
|
+ { "su_beamformee", VHT_CAP_SU_BEAMFORMEE_CAPABLE },
|
|
+ { "mu_beamformee", VHT_CAP_MU_BEAMFORMEE_CAPABLE },
|
|
+ };
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(vht_capas); i++)
|
|
+ blobmsg_add_u8(&b, vht_capas[i].name,
|
|
+ !!(vhtc->vht_capabilities_info & vht_capas[i].flag));
|
|
+
|
|
+ supported_mcs = blobmsg_open_table(&b, "mcs_map");
|
|
+
|
|
+ /* RX map */
|
|
+ map = blobmsg_open_table(&b, "rx");
|
|
+ hostapd_parse_vht_map_blobmsg(le_to_host16(vhtc->vht_supported_mcs_set.rx_map));
|
|
+ blobmsg_close_table(&b, map);
|
|
+
|
|
+ /* TX map */
|
|
+ map = blobmsg_open_table(&b, "tx");
|
|
+ hostapd_parse_vht_map_blobmsg(le_to_host16(vhtc->vht_supported_mcs_set.tx_map));
|
|
+ blobmsg_close_table(&b, map);
|
|
+
|
|
+ blobmsg_close_table(&b, supported_mcs);
|
|
+}
|
|
+
|
|
+static void
|
|
+hostapd_parse_capab_blobmsg(struct sta_info *sta)
|
|
+{
|
|
+ void *r, *v;
|
|
+
|
|
+ v = blobmsg_open_table(&b, "capabilities");
|
|
+
|
|
+ if (sta->vht_capabilities) {
|
|
+ r = blobmsg_open_table(&b, "vht");
|
|
+ hostapd_parse_vht_capab_blobmsg(sta->vht_capabilities);
|
|
+ blobmsg_close_table(&b, r);
|
|
+ }
|
|
+
|
|
+ /* ToDo: Add HT / HE capability parsing */
|
|
+
|
|
+ blobmsg_close_table(&b, v);
|
|
+}
|
|
+
|
|
+static int
|
|
+hostapd_bss_get_clients(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+ struct hostap_sta_driver_data sta_driver_data;
|
|
+ struct sta_info *sta;
|
|
+ void *list, *c;
|
|
+ char mac_buf[20];
|
|
+ static const struct {
|
|
+ const char *name;
|
|
+ uint32_t flag;
|
|
+ } sta_flags[] = {
|
|
+ { "auth", WLAN_STA_AUTH },
|
|
+ { "assoc", WLAN_STA_ASSOC },
|
|
+ { "authorized", WLAN_STA_AUTHORIZED },
|
|
+ { "preauth", WLAN_STA_PREAUTH },
|
|
+ { "wds", WLAN_STA_WDS },
|
|
+ { "wmm", WLAN_STA_WMM },
|
|
+ { "ht", WLAN_STA_HT },
|
|
+ { "vht", WLAN_STA_VHT },
|
|
+ { "he", WLAN_STA_HE },
|
|
+ { "wps", WLAN_STA_WPS },
|
|
+ { "mfp", WLAN_STA_MFP },
|
|
+ };
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_u32(&b, "freq", hapd->iface->freq);
|
|
+ list = blobmsg_open_table(&b, "clients");
|
|
+ for (sta = hapd->sta_list; sta; sta = sta->next) {
|
|
+ void *r;
|
|
+ int i;
|
|
+
|
|
+ sprintf(mac_buf, MACSTR, MAC2STR(sta->addr));
|
|
+ c = blobmsg_open_table(&b, mac_buf);
|
|
+ for (i = 0; i < ARRAY_SIZE(sta_flags); i++)
|
|
+ blobmsg_add_u8(&b, sta_flags[i].name,
|
|
+ !!(sta->flags & sta_flags[i].flag));
|
|
+
|
|
+#ifdef CONFIG_MBO
|
|
+ blobmsg_add_u8(&b, "mbo", !!(sta->cell_capa));
|
|
+#endif
|
|
+
|
|
+ r = blobmsg_open_array(&b, "rrm");
|
|
+ for (i = 0; i < ARRAY_SIZE(sta->rrm_enabled_capa); i++)
|
|
+ blobmsg_add_u32(&b, "", sta->rrm_enabled_capa[i]);
|
|
+ blobmsg_close_array(&b, r);
|
|
+
|
|
+ r = blobmsg_open_array(&b, "extended_capabilities");
|
|
+ /* Check if client advertises extended capabilities */
|
|
+ if (sta->ext_capability && sta->ext_capability[0] > 0) {
|
|
+ for (i = 0; i < sta->ext_capability[0]; i++) {
|
|
+ blobmsg_add_u32(&b, "", sta->ext_capability[1 + i]);
|
|
+ }
|
|
+ }
|
|
+ blobmsg_close_array(&b, r);
|
|
+
|
|
+ blobmsg_add_u32(&b, "aid", sta->aid);
|
|
+#ifdef CONFIG_TAXONOMY
|
|
+ r = blobmsg_alloc_string_buffer(&b, "signature", 1024);
|
|
+ if (retrieve_sta_taxonomy(hapd, sta, r, 1024) > 0)
|
|
+ blobmsg_add_string_buffer(&b);
|
|
+#endif
|
|
+
|
|
+ /* Driver information */
|
|
+ if (hostapd_drv_read_sta_data(hapd, &sta_driver_data, sta->addr) >= 0) {
|
|
+ r = blobmsg_open_table(&b, "bytes");
|
|
+ blobmsg_add_u64(&b, "rx", sta_driver_data.rx_bytes);
|
|
+ blobmsg_add_u64(&b, "tx", sta_driver_data.tx_bytes);
|
|
+ blobmsg_close_table(&b, r);
|
|
+ r = blobmsg_open_table(&b, "airtime");
|
|
+ blobmsg_add_u64(&b, "rx", sta_driver_data.rx_airtime);
|
|
+ blobmsg_add_u64(&b, "tx", sta_driver_data.tx_airtime);
|
|
+ blobmsg_close_table(&b, r);
|
|
+ r = blobmsg_open_table(&b, "packets");
|
|
+ blobmsg_add_u32(&b, "rx", sta_driver_data.rx_packets);
|
|
+ blobmsg_add_u32(&b, "tx", sta_driver_data.tx_packets);
|
|
+ blobmsg_close_table(&b, r);
|
|
+ r = blobmsg_open_table(&b, "rate");
|
|
+ /* Rate in kbits */
|
|
+ blobmsg_add_u32(&b, "rx", sta_driver_data.current_rx_rate * 100);
|
|
+ blobmsg_add_u32(&b, "tx", sta_driver_data.current_tx_rate * 100);
|
|
+ blobmsg_close_table(&b, r);
|
|
+ blobmsg_add_u32(&b, "signal", sta_driver_data.signal);
|
|
+ }
|
|
+
|
|
+ hostapd_parse_capab_blobmsg(sta);
|
|
+
|
|
+ blobmsg_close_table(&b, c);
|
|
+ }
|
|
+ blobmsg_close_array(&b, list);
|
|
+ ubus_send_reply(ctx, req, b.head);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+hostapd_bss_get_features(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_u8(&b, "ht_supported", ht_supported(hapd->iface->hw_features));
|
|
+ blobmsg_add_u8(&b, "vht_supported", vht_supported(hapd->iface->hw_features));
|
|
+ ubus_send_reply(ctx, req, b.head);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+ void *airtime_table, *dfs_table, *rrm_table, *wnm_table;
|
|
+ struct os_reltime now;
|
|
+ char ssid[SSID_MAX_LEN + 1];
|
|
+ char phy_name[17];
|
|
+ size_t ssid_len = SSID_MAX_LEN;
|
|
+ u8 channel = 0, op_class = 0;
|
|
+
|
|
+ if (hapd->conf->ssid.ssid_len < SSID_MAX_LEN)
|
|
+ ssid_len = hapd->conf->ssid.ssid_len;
|
|
+
|
|
+ ieee80211_freq_to_channel_ext(hapd->iface->freq,
|
|
+ hapd->iconf->secondary_channel,
|
|
+ hostapd_get_oper_chwidth(hapd->iconf),
|
|
+ &op_class, &channel);
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_string(&b, "status", hostapd_state_text(hapd->iface->state));
|
|
+ blobmsg_printf(&b, "bssid", MACSTR, MAC2STR(hapd->conf->bssid));
|
|
+
|
|
+ memset(ssid, 0, SSID_MAX_LEN + 1);
|
|
+ memcpy(ssid, hapd->conf->ssid.ssid, ssid_len);
|
|
+ blobmsg_add_string(&b, "ssid", ssid);
|
|
+
|
|
+ blobmsg_add_u32(&b, "freq", hapd->iface->freq);
|
|
+ blobmsg_add_u32(&b, "channel", channel);
|
|
+ blobmsg_add_u32(&b, "op_class", op_class);
|
|
+ blobmsg_add_u32(&b, "beacon_interval", hapd->iconf->beacon_int);
|
|
+#ifdef CONFIG_IEEE80211AX
|
|
+ blobmsg_add_u32(&b, "bss_color", hapd->iface->conf->he_op.he_bss_color_disabled ? -1 :
|
|
+ hapd->iface->conf->he_op.he_bss_color);
|
|
+#else
|
|
+ blobmsg_add_u32(&b, "bss_color", -1);
|
|
+#endif
|
|
+
|
|
+ snprintf(phy_name, 17, "%s", hapd->iface->phy);
|
|
+ blobmsg_add_string(&b, "phy", phy_name);
|
|
+
|
|
+ /* RRM */
|
|
+ rrm_table = blobmsg_open_table(&b, "rrm");
|
|
+ blobmsg_add_u64(&b, "neighbor_report_tx", hapd->openwrt_stats.rrm.neighbor_report_tx);
|
|
+ blobmsg_close_table(&b, rrm_table);
|
|
+
|
|
+ /* WNM */
|
|
+ wnm_table = blobmsg_open_table(&b, "wnm");
|
|
+ blobmsg_add_u64(&b, "bss_transition_query_rx", hapd->openwrt_stats.wnm.bss_transition_query_rx);
|
|
+ blobmsg_add_u64(&b, "bss_transition_request_tx", hapd->openwrt_stats.wnm.bss_transition_request_tx);
|
|
+ blobmsg_add_u64(&b, "bss_transition_response_rx", hapd->openwrt_stats.wnm.bss_transition_response_rx);
|
|
+ blobmsg_close_table(&b, wnm_table);
|
|
+
|
|
+ /* Airtime */
|
|
+ airtime_table = blobmsg_open_table(&b, "airtime");
|
|
+ blobmsg_add_u64(&b, "time", hapd->iface->last_channel_time);
|
|
+ blobmsg_add_u64(&b, "time_busy", hapd->iface->last_channel_time_busy);
|
|
+ blobmsg_add_u16(&b, "utilization", hapd->iface->channel_utilization);
|
|
+ blobmsg_close_table(&b, airtime_table);
|
|
+
|
|
+ /* DFS */
|
|
+ dfs_table = blobmsg_open_table(&b, "dfs");
|
|
+ blobmsg_add_u32(&b, "cac_seconds", hapd->iface->dfs_cac_ms / 1000);
|
|
+ blobmsg_add_u8(&b, "cac_active", !!(hapd->iface->cac_started));
|
|
+ os_reltime_age(&hapd->iface->dfs_cac_start, &now);
|
|
+ blobmsg_add_u32(&b, "cac_seconds_left",
|
|
+ hapd->iface->cac_started ? hapd->iface->dfs_cac_ms / 1000 - now.sec : 0);
|
|
+ blobmsg_close_table(&b, dfs_table);
|
|
+
|
|
+ ubus_send_reply(ctx, req, b.head);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+enum {
|
|
+ NOTIFY_RESPONSE,
|
|
+ __NOTIFY_MAX
|
|
+};
|
|
+
|
|
+static const struct blobmsg_policy notify_policy[__NOTIFY_MAX] = {
|
|
+ [NOTIFY_RESPONSE] = { "notify_response", BLOBMSG_TYPE_INT32 },
|
|
+};
|
|
+
|
|
+static int
|
|
+hostapd_notify_response(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct blob_attr *tb[__NOTIFY_MAX];
|
|
+ struct hostapd_data *hapd = get_hapd_from_object(obj);
|
|
+ struct wpabuf *elems;
|
|
+ const char *pos;
|
|
+ size_t len;
|
|
+
|
|
+ blobmsg_parse(notify_policy, __NOTIFY_MAX, tb,
|
|
+ blob_data(msg), blob_len(msg));
|
|
+
|
|
+ if (!tb[NOTIFY_RESPONSE])
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ hapd->ubus.notify_response = blobmsg_get_u32(tb[NOTIFY_RESPONSE]);
|
|
+
|
|
+ return UBUS_STATUS_OK;
|
|
+}
|
|
+
|
|
+enum {
|
|
+ DEL_CLIENT_ADDR,
|
|
+ DEL_CLIENT_REASON,
|
|
+ DEL_CLIENT_DEAUTH,
|
|
+ DEL_CLIENT_BAN_TIME,
|
|
+ __DEL_CLIENT_MAX
|
|
+};
|
|
+
|
|
+static const struct blobmsg_policy del_policy[__DEL_CLIENT_MAX] = {
|
|
+ [DEL_CLIENT_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
|
|
+ [DEL_CLIENT_REASON] = { "reason", BLOBMSG_TYPE_INT32 },
|
|
+ [DEL_CLIENT_DEAUTH] = { "deauth", BLOBMSG_TYPE_INT8 },
|
|
+ [DEL_CLIENT_BAN_TIME] = { "ban_time", BLOBMSG_TYPE_INT32 },
|
|
+};
|
|
+
|
|
+static int
|
|
+hostapd_bss_del_client(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct blob_attr *tb[__DEL_CLIENT_MAX];
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+ struct sta_info *sta;
|
|
+ bool deauth = false;
|
|
+ int reason;
|
|
+ u8 addr[ETH_ALEN];
|
|
+
|
|
+ blobmsg_parse(del_policy, __DEL_CLIENT_MAX, tb, blob_data(msg), blob_len(msg));
|
|
+
|
|
+ if (!tb[DEL_CLIENT_ADDR])
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ if (hwaddr_aton(blobmsg_data(tb[DEL_CLIENT_ADDR]), addr))
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ if (tb[DEL_CLIENT_REASON])
|
|
+ reason = blobmsg_get_u32(tb[DEL_CLIENT_REASON]);
|
|
+
|
|
+ if (tb[DEL_CLIENT_DEAUTH])
|
|
+ deauth = blobmsg_get_bool(tb[DEL_CLIENT_DEAUTH]);
|
|
+
|
|
+ sta = ap_get_sta(hapd, addr);
|
|
+ if (sta) {
|
|
+ if (deauth) {
|
|
+ hostapd_drv_sta_deauth(hapd, addr, reason);
|
|
+ ap_sta_deauthenticate(hapd, sta, reason);
|
|
+ } else {
|
|
+ hostapd_drv_sta_disassoc(hapd, addr, reason);
|
|
+ ap_sta_disassociate(hapd, sta, reason);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (tb[DEL_CLIENT_BAN_TIME])
|
|
+ hostapd_bss_ban_client(hapd, addr, blobmsg_get_u32(tb[DEL_CLIENT_BAN_TIME]));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void
|
|
+blobmsg_add_macaddr(struct blob_buf *buf, const char *name, const u8 *addr)
|
|
+{
|
|
+ char *s;
|
|
+
|
|
+ s = blobmsg_alloc_string_buffer(buf, name, 20);
|
|
+ sprintf(s, MACSTR, MAC2STR(addr));
|
|
+ blobmsg_add_string_buffer(buf);
|
|
+}
|
|
+
|
|
+static int
|
|
+hostapd_bss_list_bans(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+ struct ubus_banned_client *ban;
|
|
+ void *c;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ c = blobmsg_open_array(&b, "clients");
|
|
+ avl_for_each_element(&hapd->ubus.banned, ban, avl)
|
|
+ blobmsg_add_macaddr(&b, NULL, ban->addr);
|
|
+ blobmsg_close_array(&b, c);
|
|
+ ubus_send_reply(ctx, req, b.head);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#ifdef CONFIG_WPS
|
|
+static int
|
|
+hostapd_bss_wps_start(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ int rc;
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+
|
|
+ rc = hostapd_wps_button_pushed(hapd, NULL);
|
|
+
|
|
+ if (rc != 0)
|
|
+ return UBUS_STATUS_NOT_SUPPORTED;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static const char * pbc_status_enum_str(enum pbc_status status)
|
|
+{
|
|
+ switch (status) {
|
|
+ case WPS_PBC_STATUS_DISABLE:
|
|
+ return "Disabled";
|
|
+ case WPS_PBC_STATUS_ACTIVE:
|
|
+ return "Active";
|
|
+ case WPS_PBC_STATUS_TIMEOUT:
|
|
+ return "Timed-out";
|
|
+ case WPS_PBC_STATUS_OVERLAP:
|
|
+ return "Overlap";
|
|
+ default:
|
|
+ return "Unknown";
|
|
+ }
|
|
+}
|
|
+
|
|
+static int
|
|
+hostapd_bss_wps_status(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ int rc;
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+
|
|
+ blobmsg_add_string(&b, "pbc_status", pbc_status_enum_str(hapd->wps_stats.pbc_status));
|
|
+ blobmsg_add_string(&b, "last_wps_result",
|
|
+ (hapd->wps_stats.status == WPS_STATUS_SUCCESS ?
|
|
+ "Success":
|
|
+ (hapd->wps_stats.status == WPS_STATUS_FAILURE ?
|
|
+ "Failed" : "None")));
|
|
+
|
|
+ /* If status == Failure - Add possible Reasons */
|
|
+ if(hapd->wps_stats.status == WPS_STATUS_FAILURE &&
|
|
+ hapd->wps_stats.failure_reason > 0)
|
|
+ blobmsg_add_string(&b, "reason", wps_ei_str(hapd->wps_stats.failure_reason));
|
|
+
|
|
+ if (hapd->wps_stats.status)
|
|
+ blobmsg_printf(&b, "peer_address", MACSTR, MAC2STR(hapd->wps_stats.peer_addr));
|
|
+
|
|
+ ubus_send_reply(ctx, req, b.head);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+hostapd_bss_wps_cancel(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ int rc;
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+
|
|
+ rc = hostapd_wps_cancel(hapd);
|
|
+
|
|
+ if (rc != 0)
|
|
+ return UBUS_STATUS_NOT_SUPPORTED;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif /* CONFIG_WPS */
|
|
+
|
|
+static int
|
|
+hostapd_bss_update_beacon(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ int rc;
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+
|
|
+ rc = ieee802_11_set_beacon(hapd);
|
|
+
|
|
+ if (rc != 0)
|
|
+ return UBUS_STATUS_NOT_SUPPORTED;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+enum {
|
|
+ CONFIG_IFACE,
|
|
+ CONFIG_FILE,
|
|
+ __CONFIG_MAX
|
|
+};
|
|
+
|
|
+enum {
|
|
+ CSA_FREQ,
|
|
+ CSA_BCN_COUNT,
|
|
+ CSA_CENTER_FREQ1,
|
|
+ CSA_CENTER_FREQ2,
|
|
+ CSA_BANDWIDTH,
|
|
+ CSA_SEC_CHANNEL_OFFSET,
|
|
+ CSA_HT,
|
|
+ CSA_VHT,
|
|
+ CSA_HE,
|
|
+ CSA_BLOCK_TX,
|
|
+ CSA_FORCE,
|
|
+ __CSA_MAX
|
|
+};
|
|
+
|
|
+static const struct blobmsg_policy csa_policy[__CSA_MAX] = {
|
|
+ [CSA_FREQ] = { "freq", BLOBMSG_TYPE_INT32 },
|
|
+ [CSA_BCN_COUNT] = { "bcn_count", BLOBMSG_TYPE_INT32 },
|
|
+ [CSA_CENTER_FREQ1] = { "center_freq1", BLOBMSG_TYPE_INT32 },
|
|
+ [CSA_CENTER_FREQ2] = { "center_freq2", BLOBMSG_TYPE_INT32 },
|
|
+ [CSA_BANDWIDTH] = { "bandwidth", BLOBMSG_TYPE_INT32 },
|
|
+ [CSA_SEC_CHANNEL_OFFSET] = { "sec_channel_offset", BLOBMSG_TYPE_INT32 },
|
|
+ [CSA_HT] = { "ht", BLOBMSG_TYPE_BOOL },
|
|
+ [CSA_VHT] = { "vht", BLOBMSG_TYPE_BOOL },
|
|
+ [CSA_HE] = { "he", BLOBMSG_TYPE_BOOL },
|
|
+ [CSA_BLOCK_TX] = { "block_tx", BLOBMSG_TYPE_BOOL },
|
|
+ [CSA_FORCE] = { "force", BLOBMSG_TYPE_BOOL },
|
|
+};
|
|
+
|
|
+
|
|
+static void switch_chan_fallback_cb(void *eloop_data, void *user_ctx)
|
|
+{
|
|
+ struct hostapd_iface *iface = eloop_data;
|
|
+ struct hostapd_freq_params *freq_params = user_ctx;
|
|
+
|
|
+ hostapd_switch_channel_fallback(iface, freq_params);
|
|
+}
|
|
+
|
|
+#ifdef NEED_AP_MLME
|
|
+static int
|
|
+hostapd_switch_chan(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct blob_attr *tb[__CSA_MAX];
|
|
+ struct hostapd_data *hapd = get_hapd_from_object(obj);
|
|
+ struct hostapd_config *iconf = hapd->iface->conf;
|
|
+ struct hostapd_freq_params *freq_params;
|
|
+ struct hostapd_hw_modes *mode = hapd->iface->current_mode;
|
|
+ struct csa_settings css = {
|
|
+ .freq_params = {
|
|
+ .ht_enabled = iconf->ieee80211n,
|
|
+ .vht_enabled = iconf->ieee80211ac,
|
|
+ .he_enabled = iconf->ieee80211ax,
|
|
+ .sec_channel_offset = iconf->secondary_channel,
|
|
+ }
|
|
+ };
|
|
+ u8 chwidth = hostapd_get_oper_chwidth(iconf);
|
|
+ u8 seg0 = 0, seg1 = 0;
|
|
+ int ret = UBUS_STATUS_OK;
|
|
+ int i;
|
|
+
|
|
+ blobmsg_parse(csa_policy, __CSA_MAX, tb, blob_data(msg), blob_len(msg));
|
|
+
|
|
+ if (!tb[CSA_FREQ])
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ switch (iconf->vht_oper_chwidth) {
|
|
+ case CHANWIDTH_USE_HT:
|
|
+ if (iconf->secondary_channel)
|
|
+ css.freq_params.bandwidth = 40;
|
|
+ else
|
|
+ css.freq_params.bandwidth = 20;
|
|
+ break;
|
|
+ case CHANWIDTH_160MHZ:
|
|
+ css.freq_params.bandwidth = 160;
|
|
+ break;
|
|
+ default:
|
|
+ css.freq_params.bandwidth = 80;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ css.freq_params.freq = blobmsg_get_u32(tb[CSA_FREQ]);
|
|
+
|
|
+#define SET_CSA_SETTING(name, field, type) \
|
|
+ do { \
|
|
+ if (tb[name]) \
|
|
+ css.field = blobmsg_get_ ## type(tb[name]); \
|
|
+ } while(0)
|
|
+
|
|
+ SET_CSA_SETTING(CSA_BCN_COUNT, cs_count, u32);
|
|
+ SET_CSA_SETTING(CSA_CENTER_FREQ1, freq_params.center_freq1, u32);
|
|
+ SET_CSA_SETTING(CSA_CENTER_FREQ2, freq_params.center_freq2, u32);
|
|
+ SET_CSA_SETTING(CSA_BANDWIDTH, freq_params.bandwidth, u32);
|
|
+ SET_CSA_SETTING(CSA_SEC_CHANNEL_OFFSET, freq_params.sec_channel_offset, u32);
|
|
+ SET_CSA_SETTING(CSA_HT, freq_params.ht_enabled, bool);
|
|
+ SET_CSA_SETTING(CSA_VHT, freq_params.vht_enabled, bool);
|
|
+ SET_CSA_SETTING(CSA_HE, freq_params.he_enabled, bool);
|
|
+ SET_CSA_SETTING(CSA_BLOCK_TX, block_tx, bool);
|
|
+
|
|
+ css.freq_params.channel = hostapd_hw_get_channel(hapd, css.freq_params.freq);
|
|
+ if (!css.freq_params.channel)
|
|
+ return UBUS_STATUS_NOT_SUPPORTED;
|
|
+
|
|
+ switch (css.freq_params.bandwidth) {
|
|
+ case 160:
|
|
+ chwidth = CHANWIDTH_160MHZ;
|
|
+ break;
|
|
+ case 80:
|
|
+ chwidth = css.freq_params.center_freq2 ? CHANWIDTH_80P80MHZ : CHANWIDTH_80MHZ;
|
|
+ break;
|
|
+ default:
|
|
+ chwidth = CHANWIDTH_USE_HT;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ hostapd_set_freq_params(&css.freq_params, iconf->hw_mode,
|
|
+ css.freq_params.freq,
|
|
+ css.freq_params.channel, iconf->enable_edmg,
|
|
+ iconf->edmg_channel,
|
|
+ css.freq_params.ht_enabled,
|
|
+ css.freq_params.vht_enabled,
|
|
+ css.freq_params.he_enabled,
|
|
+ css.freq_params.eht_enabled,
|
|
+ css.freq_params.sec_channel_offset,
|
|
+ chwidth, seg0, seg1,
|
|
+ iconf->vht_capab,
|
|
+ mode ? &mode->he_capab[IEEE80211_MODE_AP] :
|
|
+ NULL,
|
|
+ mode ? &mode->eht_capab[IEEE80211_MODE_AP] :
|
|
+ NULL);
|
|
+
|
|
+ for (i = 0; i < hapd->iface->num_bss; i++) {
|
|
+ struct hostapd_data *bss = hapd->iface->bss[i];
|
|
+
|
|
+ if (hostapd_switch_channel(bss, &css) != 0)
|
|
+ ret = UBUS_STATUS_NOT_SUPPORTED;
|
|
+ }
|
|
+
|
|
+ if (!ret || !tb[CSA_FORCE] || !blobmsg_get_bool(tb[CSA_FORCE]))
|
|
+ return ret;
|
|
+
|
|
+ freq_params = malloc(sizeof(*freq_params));
|
|
+ memcpy(freq_params, &css.freq_params, sizeof(*freq_params));
|
|
+ eloop_register_timeout(0, 1, switch_chan_fallback_cb,
|
|
+ hapd->iface, freq_params);
|
|
+
|
|
+ return 0;
|
|
+#undef SET_CSA_SETTING
|
|
+}
|
|
+#endif
|
|
+
|
|
+enum {
|
|
+ VENDOR_ELEMENTS,
|
|
+ __VENDOR_ELEMENTS_MAX
|
|
+};
|
|
+
|
|
+static const struct blobmsg_policy ve_policy[__VENDOR_ELEMENTS_MAX] = {
|
|
+ /* vendor elements are provided as hex-string */
|
|
+ [VENDOR_ELEMENTS] = { "vendor_elements", BLOBMSG_TYPE_STRING },
|
|
+};
|
|
+
|
|
+static int
|
|
+hostapd_vendor_elements(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct blob_attr *tb[__VENDOR_ELEMENTS_MAX];
|
|
+ struct hostapd_data *hapd = get_hapd_from_object(obj);
|
|
+ struct hostapd_bss_config *bss = hapd->conf;
|
|
+ struct wpabuf *elems;
|
|
+ const char *pos;
|
|
+ size_t len;
|
|
+
|
|
+ blobmsg_parse(ve_policy, __VENDOR_ELEMENTS_MAX, tb,
|
|
+ blob_data(msg), blob_len(msg));
|
|
+
|
|
+ if (!tb[VENDOR_ELEMENTS])
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ pos = blobmsg_data(tb[VENDOR_ELEMENTS]);
|
|
+ len = os_strlen(pos);
|
|
+ if (len & 0x01)
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ len /= 2;
|
|
+ if (len == 0) {
|
|
+ wpabuf_free(bss->vendor_elements);
|
|
+ bss->vendor_elements = NULL;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ elems = wpabuf_alloc(len);
|
|
+ if (elems == NULL)
|
|
+ return 1;
|
|
+
|
|
+ if (hexstr2bin(pos, wpabuf_put(elems, len), len)) {
|
|
+ wpabuf_free(elems);
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+ }
|
|
+
|
|
+ wpabuf_free(bss->vendor_elements);
|
|
+ bss->vendor_elements = elems;
|
|
+
|
|
+ /* update beacons if vendor elements were set successfully */
|
|
+ if (ieee802_11_update_beacons(hapd->iface) != 0)
|
|
+ return UBUS_STATUS_NOT_SUPPORTED;
|
|
+ return UBUS_STATUS_OK;
|
|
+}
|
|
+
|
|
+static void
|
|
+hostapd_rrm_print_nr(struct hostapd_neighbor_entry *nr)
|
|
+{
|
|
+ const u8 *data;
|
|
+ char *str;
|
|
+ int len;
|
|
+
|
|
+ blobmsg_printf(&b, "", MACSTR, MAC2STR(nr->bssid));
|
|
+
|
|
+ str = blobmsg_alloc_string_buffer(&b, "", nr->ssid.ssid_len + 1);
|
|
+ memcpy(str, nr->ssid.ssid, nr->ssid.ssid_len);
|
|
+ str[nr->ssid.ssid_len] = 0;
|
|
+ blobmsg_add_string_buffer(&b);
|
|
+
|
|
+ len = wpabuf_len(nr->nr);
|
|
+ str = blobmsg_alloc_string_buffer(&b, "", 2 * len + 1);
|
|
+ wpa_snprintf_hex(str, 2 * len + 1, wpabuf_head_u8(nr->nr), len);
|
|
+ blobmsg_add_string_buffer(&b);
|
|
+}
|
|
+
|
|
+enum {
|
|
+ BSS_MGMT_EN_NEIGHBOR,
|
|
+ BSS_MGMT_EN_BEACON,
|
|
+ BSS_MGMT_EN_LINK_MEASUREMENT,
|
|
+#ifdef CONFIG_WNM_AP
|
|
+ BSS_MGMT_EN_BSS_TRANSITION,
|
|
+#endif
|
|
+ __BSS_MGMT_EN_MAX
|
|
+};
|
|
+
|
|
+static bool
|
|
+__hostapd_bss_mgmt_enable_f(struct hostapd_data *hapd, int flag)
|
|
+{
|
|
+ struct hostapd_bss_config *bss = hapd->conf;
|
|
+ uint32_t flags;
|
|
+
|
|
+ switch (flag) {
|
|
+ case BSS_MGMT_EN_NEIGHBOR:
|
|
+ if (bss->radio_measurements[0] &
|
|
+ WLAN_RRM_CAPS_NEIGHBOR_REPORT)
|
|
+ return false;
|
|
+
|
|
+ bss->radio_measurements[0] |=
|
|
+ WLAN_RRM_CAPS_NEIGHBOR_REPORT;
|
|
+ hostapd_neighbor_set_own_report(hapd);
|
|
+ return true;
|
|
+ case BSS_MGMT_EN_BEACON:
|
|
+ flags = WLAN_RRM_CAPS_BEACON_REPORT_PASSIVE |
|
|
+ WLAN_RRM_CAPS_BEACON_REPORT_ACTIVE |
|
|
+ WLAN_RRM_CAPS_BEACON_REPORT_TABLE;
|
|
+
|
|
+ if (bss->radio_measurements[0] & flags == flags)
|
|
+ return false;
|
|
+
|
|
+ bss->radio_measurements[0] |= (u8) flags;
|
|
+ return true;
|
|
+ case BSS_MGMT_EN_LINK_MEASUREMENT:
|
|
+ flags = WLAN_RRM_CAPS_LINK_MEASUREMENT;
|
|
+
|
|
+ if (bss->radio_measurements[0] & flags == flags)
|
|
+ return false;
|
|
+
|
|
+ bss->radio_measurements[0] |= (u8) flags;
|
|
+ return true;
|
|
+#ifdef CONFIG_WNM_AP
|
|
+ case BSS_MGMT_EN_BSS_TRANSITION:
|
|
+ if (bss->bss_transition)
|
|
+ return false;
|
|
+
|
|
+ bss->bss_transition = 1;
|
|
+ return true;
|
|
+#endif
|
|
+ }
|
|
+}
|
|
+
|
|
+static void
|
|
+__hostapd_bss_mgmt_enable(struct hostapd_data *hapd, uint32_t flags)
|
|
+{
|
|
+ bool update = false;
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < __BSS_MGMT_EN_MAX; i++) {
|
|
+ if (!(flags & (1 << i)))
|
|
+ continue;
|
|
+
|
|
+ update |= __hostapd_bss_mgmt_enable_f(hapd, i);
|
|
+ }
|
|
+
|
|
+ if (update)
|
|
+ ieee802_11_update_beacons(hapd->iface);
|
|
+}
|
|
+
|
|
+
|
|
+static const struct blobmsg_policy bss_mgmt_enable_policy[__BSS_MGMT_EN_MAX] = {
|
|
+ [BSS_MGMT_EN_NEIGHBOR] = { "neighbor_report", BLOBMSG_TYPE_BOOL },
|
|
+ [BSS_MGMT_EN_BEACON] = { "beacon_report", BLOBMSG_TYPE_BOOL },
|
|
+ [BSS_MGMT_EN_LINK_MEASUREMENT] = { "link_measurement", BLOBMSG_TYPE_BOOL },
|
|
+#ifdef CONFIG_WNM_AP
|
|
+ [BSS_MGMT_EN_BSS_TRANSITION] = { "bss_transition", BLOBMSG_TYPE_BOOL },
|
|
+#endif
|
|
+};
|
|
+
|
|
+static int
|
|
+hostapd_bss_mgmt_enable(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+
|
|
+{
|
|
+ struct hostapd_data *hapd = get_hapd_from_object(obj);
|
|
+ struct blob_attr *tb[__BSS_MGMT_EN_MAX];
|
|
+ struct blob_attr *cur;
|
|
+ uint32_t flags = 0;
|
|
+ int i;
|
|
+ bool neigh = false, beacon = false;
|
|
+
|
|
+ blobmsg_parse(bss_mgmt_enable_policy, __BSS_MGMT_EN_MAX, tb, blob_data(msg), blob_len(msg));
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(tb); i++) {
|
|
+ if (!tb[i] || !blobmsg_get_bool(tb[i]))
|
|
+ continue;
|
|
+
|
|
+ flags |= (1 << i);
|
|
+ }
|
|
+
|
|
+ __hostapd_bss_mgmt_enable(hapd, flags);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+hostapd_rrm_nr_enable(struct hostapd_data *hapd)
|
|
+{
|
|
+ __hostapd_bss_mgmt_enable(hapd, 1 << BSS_MGMT_EN_NEIGHBOR);
|
|
+}
|
|
+
|
|
+static int
|
|
+hostapd_rrm_nr_get_own(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct hostapd_data *hapd = get_hapd_from_object(obj);
|
|
+ struct hostapd_neighbor_entry *nr;
|
|
+ void *c;
|
|
+
|
|
+ hostapd_rrm_nr_enable(hapd);
|
|
+
|
|
+ nr = hostapd_neighbor_get(hapd, hapd->own_addr, NULL);
|
|
+ if (!nr)
|
|
+ return UBUS_STATUS_NOT_FOUND;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+
|
|
+ c = blobmsg_open_array(&b, "value");
|
|
+ hostapd_rrm_print_nr(nr);
|
|
+ blobmsg_close_array(&b, c);
|
|
+
|
|
+ ubus_send_reply(ctx, req, b.head);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+hostapd_rrm_nr_list(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct hostapd_data *hapd = get_hapd_from_object(obj);
|
|
+ struct hostapd_neighbor_entry *nr;
|
|
+ void *c;
|
|
+
|
|
+ hostapd_rrm_nr_enable(hapd);
|
|
+ blob_buf_init(&b, 0);
|
|
+
|
|
+ c = blobmsg_open_array(&b, "list");
|
|
+ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry, list) {
|
|
+ void *cur;
|
|
+
|
|
+ if (!memcmp(nr->bssid, hapd->own_addr, ETH_ALEN))
|
|
+ continue;
|
|
+
|
|
+ cur = blobmsg_open_array(&b, NULL);
|
|
+ hostapd_rrm_print_nr(nr);
|
|
+ blobmsg_close_array(&b, cur);
|
|
+ }
|
|
+ blobmsg_close_array(&b, c);
|
|
+
|
|
+ ubus_send_reply(ctx, req, b.head);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+enum {
|
|
+ NR_SET_LIST,
|
|
+ __NR_SET_LIST_MAX
|
|
+};
|
|
+
|
|
+static const struct blobmsg_policy nr_set_policy[__NR_SET_LIST_MAX] = {
|
|
+ [NR_SET_LIST] = { "list", BLOBMSG_TYPE_ARRAY },
|
|
+};
|
|
+
|
|
+
|
|
+static void
|
|
+hostapd_rrm_nr_clear(struct hostapd_data *hapd)
|
|
+{
|
|
+ struct hostapd_neighbor_entry *nr;
|
|
+
|
|
+restart:
|
|
+ dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry, list) {
|
|
+ if (!memcmp(nr->bssid, hapd->own_addr, ETH_ALEN))
|
|
+ continue;
|
|
+
|
|
+ hostapd_neighbor_remove(hapd, nr->bssid, &nr->ssid);
|
|
+ goto restart;
|
|
+ }
|
|
+}
|
|
+
|
|
+static int
|
|
+hostapd_rrm_nr_set(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ static const struct blobmsg_policy nr_e_policy[] = {
|
|
+ { .type = BLOBMSG_TYPE_STRING },
|
|
+ { .type = BLOBMSG_TYPE_STRING },
|
|
+ { .type = BLOBMSG_TYPE_STRING },
|
|
+ };
|
|
+ struct hostapd_data *hapd = get_hapd_from_object(obj);
|
|
+ struct blob_attr *tb_l[__NR_SET_LIST_MAX];
|
|
+ struct blob_attr *tb[ARRAY_SIZE(nr_e_policy)];
|
|
+ struct blob_attr *cur;
|
|
+ int rem;
|
|
+
|
|
+ hostapd_rrm_nr_enable(hapd);
|
|
+
|
|
+ blobmsg_parse(nr_set_policy, __NR_SET_LIST_MAX, tb_l, blob_data(msg), blob_len(msg));
|
|
+ if (!tb_l[NR_SET_LIST])
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ hostapd_rrm_nr_clear(hapd);
|
|
+ blobmsg_for_each_attr(cur, tb_l[NR_SET_LIST], rem) {
|
|
+ struct wpa_ssid_value ssid;
|
|
+ struct wpabuf *data;
|
|
+ u8 bssid[ETH_ALEN];
|
|
+ char *s, *nr_s;
|
|
+
|
|
+ blobmsg_parse_array(nr_e_policy, ARRAY_SIZE(nr_e_policy), tb, blobmsg_data(cur), blobmsg_data_len(cur));
|
|
+ if (!tb[0] || !tb[1] || !tb[2])
|
|
+ goto invalid;
|
|
+
|
|
+ /* Neighbor Report binary */
|
|
+ nr_s = blobmsg_get_string(tb[2]);
|
|
+ data = wpabuf_parse_bin(nr_s);
|
|
+ if (!data)
|
|
+ goto invalid;
|
|
+
|
|
+ /* BSSID */
|
|
+ s = blobmsg_get_string(tb[0]);
|
|
+ if (strlen(s) == 0) {
|
|
+ /* Copy BSSID from neighbor report */
|
|
+ if (hwaddr_compact_aton(nr_s, bssid))
|
|
+ goto invalid;
|
|
+ } else if (hwaddr_aton(s, bssid)) {
|
|
+ goto invalid;
|
|
+ }
|
|
+
|
|
+ /* SSID */
|
|
+ s = blobmsg_get_string(tb[1]);
|
|
+ if (strlen(s) == 0) {
|
|
+ /* Copy SSID from hostapd BSS conf */
|
|
+ memcpy(&ssid, &hapd->conf->ssid, sizeof(ssid));
|
|
+ } else {
|
|
+ ssid.ssid_len = strlen(s);
|
|
+ if (ssid.ssid_len > sizeof(ssid.ssid))
|
|
+ goto invalid;
|
|
+
|
|
+ memcpy(&ssid, s, ssid.ssid_len);
|
|
+ }
|
|
+
|
|
+ hostapd_neighbor_set(hapd, bssid, &ssid, data, NULL, NULL, 0, 0);
|
|
+ wpabuf_free(data);
|
|
+ continue;
|
|
+
|
|
+invalid:
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+enum {
|
|
+ BEACON_REQ_ADDR,
|
|
+ BEACON_REQ_MODE,
|
|
+ BEACON_REQ_OP_CLASS,
|
|
+ BEACON_REQ_CHANNEL,
|
|
+ BEACON_REQ_DURATION,
|
|
+ BEACON_REQ_BSSID,
|
|
+ BEACON_REQ_SSID,
|
|
+ __BEACON_REQ_MAX,
|
|
+};
|
|
+
|
|
+static const struct blobmsg_policy beacon_req_policy[__BEACON_REQ_MAX] = {
|
|
+ [BEACON_REQ_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
|
|
+ [BEACON_REQ_OP_CLASS] { "op_class", BLOBMSG_TYPE_INT32 },
|
|
+ [BEACON_REQ_CHANNEL] { "channel", BLOBMSG_TYPE_INT32 },
|
|
+ [BEACON_REQ_DURATION] { "duration", BLOBMSG_TYPE_INT32 },
|
|
+ [BEACON_REQ_MODE] { "mode", BLOBMSG_TYPE_INT32 },
|
|
+ [BEACON_REQ_BSSID] { "bssid", BLOBMSG_TYPE_STRING },
|
|
+ [BEACON_REQ_SSID] { "ssid", BLOBMSG_TYPE_STRING },
|
|
+};
|
|
+
|
|
+static int
|
|
+hostapd_rrm_beacon_req(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *ureq, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+ struct blob_attr *tb[__BEACON_REQ_MAX];
|
|
+ struct blob_attr *cur;
|
|
+ struct wpabuf *req;
|
|
+ u8 bssid[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
|
|
+ u8 addr[ETH_ALEN];
|
|
+ int mode, rem, ret;
|
|
+ int buf_len = 13;
|
|
+
|
|
+ blobmsg_parse(beacon_req_policy, __BEACON_REQ_MAX, tb, blob_data(msg), blob_len(msg));
|
|
+
|
|
+ if (!tb[BEACON_REQ_ADDR] || !tb[BEACON_REQ_MODE] || !tb[BEACON_REQ_DURATION] ||
|
|
+ !tb[BEACON_REQ_OP_CLASS] || !tb[BEACON_REQ_CHANNEL])
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ if (tb[BEACON_REQ_SSID])
|
|
+ buf_len += blobmsg_data_len(tb[BEACON_REQ_SSID]) + 2 - 1;
|
|
+
|
|
+ mode = blobmsg_get_u32(tb[BEACON_REQ_MODE]);
|
|
+ if (hwaddr_aton(blobmsg_data(tb[BEACON_REQ_ADDR]), addr))
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ if (tb[BEACON_REQ_BSSID] &&
|
|
+ hwaddr_aton(blobmsg_data(tb[BEACON_REQ_BSSID]), bssid))
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ req = wpabuf_alloc(buf_len);
|
|
+ if (!req)
|
|
+ return UBUS_STATUS_UNKNOWN_ERROR;
|
|
+
|
|
+ /* 1: regulatory class */
|
|
+ wpabuf_put_u8(req, blobmsg_get_u32(tb[BEACON_REQ_OP_CLASS]));
|
|
+
|
|
+ /* 2: channel number */
|
|
+ wpabuf_put_u8(req, blobmsg_get_u32(tb[BEACON_REQ_CHANNEL]));
|
|
+
|
|
+ /* 3-4: randomization interval */
|
|
+ wpabuf_put_le16(req, 0);
|
|
+
|
|
+ /* 5-6: duration */
|
|
+ wpabuf_put_le16(req, blobmsg_get_u32(tb[BEACON_REQ_DURATION]));
|
|
+
|
|
+ /* 7: mode */
|
|
+ wpabuf_put_u8(req, blobmsg_get_u32(tb[BEACON_REQ_MODE]));
|
|
+
|
|
+ /* 8-13: BSSID */
|
|
+ wpabuf_put_data(req, bssid, ETH_ALEN);
|
|
+
|
|
+ if ((cur = tb[BEACON_REQ_SSID]) != NULL) {
|
|
+ wpabuf_put_u8(req, WLAN_EID_SSID);
|
|
+ wpabuf_put_u8(req, blobmsg_data_len(cur) - 1);
|
|
+ wpabuf_put_data(req, blobmsg_data(cur), blobmsg_data_len(cur) - 1);
|
|
+ }
|
|
+
|
|
+ ret = hostapd_send_beacon_req(hapd, addr, 0, req);
|
|
+ if (ret < 0)
|
|
+ return -ret;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+enum {
|
|
+ LM_REQ_ADDR,
|
|
+ LM_REQ_TX_POWER_USED,
|
|
+ LM_REQ_TX_POWER_MAX,
|
|
+ __LM_REQ_MAX,
|
|
+};
|
|
+
|
|
+static const struct blobmsg_policy lm_req_policy[__LM_REQ_MAX] = {
|
|
+ [LM_REQ_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
|
|
+ [LM_REQ_TX_POWER_USED] = { "tx-power-used", BLOBMSG_TYPE_INT32 },
|
|
+ [LM_REQ_TX_POWER_MAX] = { "tx-power-max", BLOBMSG_TYPE_INT32 },
|
|
+};
|
|
+
|
|
+static int
|
|
+hostapd_rrm_lm_req(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *ureq, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+ struct blob_attr *tb[__LM_REQ_MAX];
|
|
+ struct wpabuf *buf;
|
|
+ u8 addr[ETH_ALEN];
|
|
+ int ret;
|
|
+ int8_t txp_used, txp_max;
|
|
+
|
|
+ txp_used = 0;
|
|
+ txp_max = 0;
|
|
+
|
|
+ blobmsg_parse(lm_req_policy, __LM_REQ_MAX, tb, blob_data(msg), blob_len(msg));
|
|
+
|
|
+ if (!tb[LM_REQ_ADDR])
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ if (tb[LM_REQ_TX_POWER_USED])
|
|
+ txp_used = (int8_t) blobmsg_get_u32(tb[LM_REQ_TX_POWER_USED]);
|
|
+
|
|
+ if (tb[LM_REQ_TX_POWER_MAX])
|
|
+ txp_max = (int8_t) blobmsg_get_u32(tb[LM_REQ_TX_POWER_MAX]);
|
|
+
|
|
+ if (hwaddr_aton(blobmsg_data(tb[LM_REQ_ADDR]), addr))
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ buf = wpabuf_alloc(5);
|
|
+ if (!buf)
|
|
+ return UBUS_STATUS_UNKNOWN_ERROR;
|
|
+
|
|
+ wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT);
|
|
+ wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REQUEST);
|
|
+ wpabuf_put_u8(buf, 1);
|
|
+ /* TX-Power used */
|
|
+ wpabuf_put_u8(buf, txp_used);
|
|
+ /* Max TX Power */
|
|
+ wpabuf_put_u8(buf, txp_max);
|
|
+
|
|
+ ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
|
|
+ wpabuf_head(buf), wpabuf_len(buf));
|
|
+
|
|
+ wpabuf_free(buf);
|
|
+ if (ret < 0)
|
|
+ return -ret;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+void hostapd_ubus_handle_link_measurement(struct hostapd_data *hapd, const u8 *data, size_t len)
|
|
+{
|
|
+ const struct ieee80211_mgmt *mgmt = (const struct ieee80211_mgmt *) data;
|
|
+ const u8 *pos, *end;
|
|
+ u8 token;
|
|
+
|
|
+ end = data + len;
|
|
+ token = mgmt->u.action.u.rrm.dialog_token;
|
|
+ pos = mgmt->u.action.u.rrm.variable;
|
|
+
|
|
+ if (end - pos < 8)
|
|
+ return;
|
|
+
|
|
+ if (!hapd->ubus.obj.has_subscribers)
|
|
+ return;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_macaddr(&b, "address", mgmt->sa);
|
|
+ blobmsg_add_u16(&b, "dialog-token", token);
|
|
+ blobmsg_add_u16(&b, "rx-antenna-id", pos[4]);
|
|
+ blobmsg_add_u16(&b, "tx-antenna-id", pos[5]);
|
|
+ blobmsg_add_u16(&b, "rcpi", pos[6]);
|
|
+ blobmsg_add_u16(&b, "rsni", pos[7]);
|
|
+
|
|
+ ubus_notify(ctx, &hapd->ubus.obj, "link-measurement-report", b.head, -1);
|
|
+}
|
|
+
|
|
+
|
|
+#ifdef CONFIG_WNM_AP
|
|
+
|
|
+static int
|
|
+hostapd_bss_tr_send(struct hostapd_data *hapd, u8 *addr, bool disassoc_imminent, bool abridged,
|
|
+ u16 disassoc_timer, u8 validity_period, u8 dialog_token,
|
|
+ struct blob_attr *neighbors, u8 mbo_reason, u8 cell_pref, u8 reassoc_delay)
|
|
+{
|
|
+ struct blob_attr *cur;
|
|
+ struct sta_info *sta;
|
|
+ int nr_len = 0;
|
|
+ int rem;
|
|
+ u8 *nr = NULL;
|
|
+ u8 req_mode = 0;
|
|
+ u8 mbo[10];
|
|
+ size_t mbo_len = 0;
|
|
+
|
|
+ sta = ap_get_sta(hapd, addr);
|
|
+ if (!sta)
|
|
+ return UBUS_STATUS_NOT_FOUND;
|
|
+
|
|
+ if (neighbors) {
|
|
+ u8 *nr_cur;
|
|
+
|
|
+ if (blobmsg_check_array(neighbors,
|
|
+ BLOBMSG_TYPE_STRING) < 0)
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ blobmsg_for_each_attr(cur, neighbors, rem) {
|
|
+ int len = strlen(blobmsg_get_string(cur));
|
|
+
|
|
+ if (len % 2)
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ nr_len += (len / 2) + 2;
|
|
+ }
|
|
+
|
|
+ if (nr_len) {
|
|
+ nr = os_zalloc(nr_len);
|
|
+ if (!nr)
|
|
+ return UBUS_STATUS_UNKNOWN_ERROR;
|
|
+ }
|
|
+
|
|
+ nr_cur = nr;
|
|
+ blobmsg_for_each_attr(cur, neighbors, rem) {
|
|
+ int len = strlen(blobmsg_get_string(cur)) / 2;
|
|
+
|
|
+ *nr_cur++ = WLAN_EID_NEIGHBOR_REPORT;
|
|
+ *nr_cur++ = (u8) len;
|
|
+ if (hexstr2bin(blobmsg_data(cur), nr_cur, len)) {
|
|
+ free(nr);
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+ }
|
|
+
|
|
+ nr_cur += len;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (nr)
|
|
+ req_mode |= WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED;
|
|
+
|
|
+ if (abridged)
|
|
+ req_mode |= WNM_BSS_TM_REQ_ABRIDGED;
|
|
+
|
|
+ if (disassoc_imminent)
|
|
+ req_mode |= WNM_BSS_TM_REQ_DISASSOC_IMMINENT;
|
|
+
|
|
+#ifdef CONFIG_MBO
|
|
+ u8 *mbo_pos = mbo;
|
|
+
|
|
+ if (mbo_reason > MBO_TRANSITION_REASON_PREMIUM_AP)
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ if (cell_pref != 0 && cell_pref != 1 && cell_pref != 255)
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ if (reassoc_delay > 65535 || (reassoc_delay && !disassoc_imminent))
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ *mbo_pos++ = MBO_ATTR_ID_TRANSITION_REASON;
|
|
+ *mbo_pos++ = 1;
|
|
+ *mbo_pos++ = mbo_reason;
|
|
+ *mbo_pos++ = MBO_ATTR_ID_CELL_DATA_PREF;
|
|
+ *mbo_pos++ = 1;
|
|
+ *mbo_pos++ = cell_pref;
|
|
+
|
|
+ if (reassoc_delay) {
|
|
+ *mbo_pos++ = MBO_ATTR_ID_ASSOC_RETRY_DELAY;
|
|
+ *mbo_pos++ = 2;
|
|
+ WPA_PUT_LE16(mbo_pos, reassoc_delay);
|
|
+ mbo_pos += 2;
|
|
+ }
|
|
+
|
|
+ mbo_len = mbo_pos - mbo;
|
|
+#endif
|
|
+
|
|
+ if (wnm_send_bss_tm_req(hapd, sta, req_mode, disassoc_timer, validity_period, NULL,
|
|
+ dialog_token, NULL, nr, nr_len, mbo_len ? mbo : NULL, mbo_len))
|
|
+ return UBUS_STATUS_UNKNOWN_ERROR;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+enum {
|
|
+ BSS_TR_ADDR,
|
|
+ BSS_TR_DA_IMMINENT,
|
|
+ BSS_TR_DA_TIMER,
|
|
+ BSS_TR_VALID_PERIOD,
|
|
+ BSS_TR_NEIGHBORS,
|
|
+ BSS_TR_ABRIDGED,
|
|
+ BSS_TR_DIALOG_TOKEN,
|
|
+#ifdef CONFIG_MBO
|
|
+ BSS_TR_MBO_REASON,
|
|
+ BSS_TR_CELL_PREF,
|
|
+ BSS_TR_REASSOC_DELAY,
|
|
+#endif
|
|
+ __BSS_TR_DISASSOC_MAX
|
|
+};
|
|
+
|
|
+static const struct blobmsg_policy bss_tr_policy[__BSS_TR_DISASSOC_MAX] = {
|
|
+ [BSS_TR_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
|
|
+ [BSS_TR_DA_IMMINENT] = { "disassociation_imminent", BLOBMSG_TYPE_BOOL },
|
|
+ [BSS_TR_DA_TIMER] = { "disassociation_timer", BLOBMSG_TYPE_INT32 },
|
|
+ [BSS_TR_VALID_PERIOD] = { "validity_period", BLOBMSG_TYPE_INT32 },
|
|
+ [BSS_TR_NEIGHBORS] = { "neighbors", BLOBMSG_TYPE_ARRAY },
|
|
+ [BSS_TR_ABRIDGED] = { "abridged", BLOBMSG_TYPE_BOOL },
|
|
+ [BSS_TR_DIALOG_TOKEN] = { "dialog_token", BLOBMSG_TYPE_INT32 },
|
|
+#ifdef CONFIG_MBO
|
|
+ [BSS_TR_MBO_REASON] = { "mbo_reason", BLOBMSG_TYPE_INT32 },
|
|
+ [BSS_TR_CELL_PREF] = { "cell_pref", BLOBMSG_TYPE_INT32 },
|
|
+ [BSS_TR_REASSOC_DELAY] = { "reassoc_delay", BLOBMSG_TYPE_INT32 },
|
|
+#endif
|
|
+};
|
|
+
|
|
+static int
|
|
+hostapd_bss_transition_request(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *ureq, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+ struct blob_attr *tb[__BSS_TR_DISASSOC_MAX];
|
|
+ struct sta_info *sta;
|
|
+ u32 da_timer = 0;
|
|
+ u32 valid_period = 0;
|
|
+ u8 addr[ETH_ALEN];
|
|
+ u32 dialog_token = 1;
|
|
+ bool abridged;
|
|
+ bool da_imminent;
|
|
+ u8 mbo_reason;
|
|
+ u8 cell_pref;
|
|
+ u8 reassoc_delay;
|
|
+
|
|
+ blobmsg_parse(bss_tr_policy, __BSS_TR_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg));
|
|
+
|
|
+ if (!tb[BSS_TR_ADDR])
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ if (hwaddr_aton(blobmsg_data(tb[BSS_TR_ADDR]), addr))
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ if (tb[BSS_TR_DA_TIMER])
|
|
+ da_timer = blobmsg_get_u32(tb[BSS_TR_DA_TIMER]);
|
|
+
|
|
+ if (tb[BSS_TR_VALID_PERIOD])
|
|
+ valid_period = blobmsg_get_u32(tb[BSS_TR_VALID_PERIOD]);
|
|
+
|
|
+ if (tb[BSS_TR_DIALOG_TOKEN])
|
|
+ dialog_token = blobmsg_get_u32(tb[BSS_TR_DIALOG_TOKEN]);
|
|
+
|
|
+ da_imminent = !!(tb[BSS_TR_DA_IMMINENT] && blobmsg_get_bool(tb[BSS_TR_DA_IMMINENT]));
|
|
+ abridged = !!(tb[BSS_TR_ABRIDGED] && blobmsg_get_bool(tb[BSS_TR_ABRIDGED]));
|
|
+
|
|
+#ifdef CONFIG_MBO
|
|
+ if (tb[BSS_TR_MBO_REASON])
|
|
+ mbo_reason = blobmsg_get_u32(tb[BSS_TR_MBO_REASON]);
|
|
+
|
|
+ if (tb[BSS_TR_CELL_PREF])
|
|
+ cell_pref = blobmsg_get_u32(tb[BSS_TR_CELL_PREF]);
|
|
+
|
|
+ if (tb[BSS_TR_REASSOC_DELAY])
|
|
+ reassoc_delay = blobmsg_get_u32(tb[BSS_TR_REASSOC_DELAY]);
|
|
+#endif
|
|
+
|
|
+ return hostapd_bss_tr_send(hapd, addr, da_imminent, abridged, da_timer, valid_period,
|
|
+ dialog_token, tb[BSS_TR_NEIGHBORS], mbo_reason, cell_pref, reassoc_delay);
|
|
+}
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_AIRTIME_POLICY
|
|
+enum {
|
|
+ UPDATE_AIRTIME_STA,
|
|
+ UPDATE_AIRTIME_WEIGHT,
|
|
+ __UPDATE_AIRTIME_MAX,
|
|
+};
|
|
+
|
|
+
|
|
+static const struct blobmsg_policy airtime_policy[__UPDATE_AIRTIME_MAX] = {
|
|
+ [UPDATE_AIRTIME_STA] = { "sta", BLOBMSG_TYPE_STRING },
|
|
+ [UPDATE_AIRTIME_WEIGHT] = { "weight", BLOBMSG_TYPE_INT32 },
|
|
+};
|
|
+
|
|
+static int
|
|
+hostapd_bss_update_airtime(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *ureq, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+ struct blob_attr *tb[__UPDATE_AIRTIME_MAX];
|
|
+ struct sta_info *sta = NULL;
|
|
+ u8 addr[ETH_ALEN];
|
|
+ int weight;
|
|
+
|
|
+ blobmsg_parse(airtime_policy, __UPDATE_AIRTIME_MAX, tb, blob_data(msg), blob_len(msg));
|
|
+
|
|
+ if (!tb[UPDATE_AIRTIME_WEIGHT])
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ weight = blobmsg_get_u32(tb[UPDATE_AIRTIME_WEIGHT]);
|
|
+
|
|
+ if (!tb[UPDATE_AIRTIME_STA]) {
|
|
+ if (!weight)
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ hapd->conf->airtime_weight = weight;
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (hwaddr_aton(blobmsg_data(tb[UPDATE_AIRTIME_STA]), addr))
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ sta = ap_get_sta(hapd, addr);
|
|
+ if (!sta)
|
|
+ return UBUS_STATUS_NOT_FOUND;
|
|
+
|
|
+ sta->dyn_airtime_weight = weight;
|
|
+ airtime_policy_new_sta(hapd, sta);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
+#ifdef CONFIG_TAXONOMY
|
|
+static const struct blobmsg_policy addr_policy[] = {
|
|
+ { "address", BLOBMSG_TYPE_STRING }
|
|
+};
|
|
+
|
|
+static bool
|
|
+hostapd_add_b64_data(const char *name, const struct wpabuf *buf)
|
|
+{
|
|
+ char *str;
|
|
+
|
|
+ if (!buf)
|
|
+ return false;
|
|
+
|
|
+ str = blobmsg_alloc_string_buffer(&b, name, B64_ENCODE_LEN(wpabuf_len(buf)));
|
|
+ b64_encode(wpabuf_head(buf), wpabuf_len(buf), str, B64_ENCODE_LEN(wpabuf_len(buf)));
|
|
+ blobmsg_add_string_buffer(&b);
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static int
|
|
+hostapd_bss_get_sta_ies(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
+ struct blob_attr *tb;
|
|
+ struct sta_info *sta;
|
|
+ u8 addr[ETH_ALEN];
|
|
+
|
|
+ blobmsg_parse(addr_policy, 1, &tb, blobmsg_data(msg), blobmsg_len(msg));
|
|
+
|
|
+ if (!tb || hwaddr_aton(blobmsg_data(tb), addr))
|
|
+ return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+
|
|
+ sta = ap_get_sta(hapd, addr);
|
|
+ if (!sta || (!sta->probe_ie_taxonomy && !sta->assoc_ie_taxonomy))
|
|
+ return UBUS_STATUS_NOT_FOUND;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ hostapd_add_b64_data("probe_ie", sta->probe_ie_taxonomy);
|
|
+ hostapd_add_b64_data("assoc_ie", sta->assoc_ie_taxonomy);
|
|
+ ubus_send_reply(ctx, req, b.head);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
+
|
|
+static const struct ubus_method bss_methods[] = {
|
|
+ UBUS_METHOD_NOARG("reload", hostapd_bss_reload),
|
|
+ UBUS_METHOD_NOARG("get_clients", hostapd_bss_get_clients),
|
|
+#ifdef CONFIG_TAXONOMY
|
|
+ UBUS_METHOD("get_sta_ies", hostapd_bss_get_sta_ies, addr_policy),
|
|
+#endif
|
|
+ UBUS_METHOD_NOARG("get_status", hostapd_bss_get_status),
|
|
+ UBUS_METHOD("del_client", hostapd_bss_del_client, del_policy),
|
|
+#ifdef CONFIG_AIRTIME_POLICY
|
|
+ UBUS_METHOD("update_airtime", hostapd_bss_update_airtime, airtime_policy),
|
|
+#endif
|
|
+ UBUS_METHOD_NOARG("list_bans", hostapd_bss_list_bans),
|
|
+#ifdef CONFIG_WPS
|
|
+ UBUS_METHOD_NOARG("wps_start", hostapd_bss_wps_start),
|
|
+ UBUS_METHOD_NOARG("wps_status", hostapd_bss_wps_status),
|
|
+ UBUS_METHOD_NOARG("wps_cancel", hostapd_bss_wps_cancel),
|
|
+#endif
|
|
+ UBUS_METHOD_NOARG("update_beacon", hostapd_bss_update_beacon),
|
|
+ UBUS_METHOD_NOARG("get_features", hostapd_bss_get_features),
|
|
+#ifdef NEED_AP_MLME
|
|
+ UBUS_METHOD("switch_chan", hostapd_switch_chan, csa_policy),
|
|
+#endif
|
|
+ UBUS_METHOD("set_vendor_elements", hostapd_vendor_elements, ve_policy),
|
|
+ UBUS_METHOD("notify_response", hostapd_notify_response, notify_policy),
|
|
+ UBUS_METHOD("bss_mgmt_enable", hostapd_bss_mgmt_enable, bss_mgmt_enable_policy),
|
|
+ UBUS_METHOD_NOARG("rrm_nr_get_own", hostapd_rrm_nr_get_own),
|
|
+ UBUS_METHOD_NOARG("rrm_nr_list", hostapd_rrm_nr_list),
|
|
+ UBUS_METHOD("rrm_nr_set", hostapd_rrm_nr_set, nr_set_policy),
|
|
+ UBUS_METHOD("rrm_beacon_req", hostapd_rrm_beacon_req, beacon_req_policy),
|
|
+ UBUS_METHOD("link_measurement_req", hostapd_rrm_lm_req, lm_req_policy),
|
|
+#ifdef CONFIG_WNM_AP
|
|
+ UBUS_METHOD("bss_transition_request", hostapd_bss_transition_request, bss_tr_policy),
|
|
+#endif
|
|
+};
|
|
+
|
|
+static struct ubus_object_type bss_object_type =
|
|
+ UBUS_OBJECT_TYPE("hostapd_bss", bss_methods);
|
|
+
|
|
+static int avl_compare_macaddr(const void *k1, const void *k2, void *ptr)
|
|
+{
|
|
+ return memcmp(k1, k2, ETH_ALEN);
|
|
+}
|
|
+
|
|
+void hostapd_ubus_add_bss(struct hostapd_data *hapd)
|
|
+{
|
|
+ struct ubus_object *obj = &hapd->ubus.obj;
|
|
+ char *name;
|
|
+ int ret;
|
|
+
|
|
+#ifdef CONFIG_MESH
|
|
+ if (hapd->conf->mesh & MESH_ENABLED)
|
|
+ return;
|
|
+#endif
|
|
+
|
|
+ if (!hostapd_ubus_init())
|
|
+ return;
|
|
+
|
|
+ if (asprintf(&name, "hostapd.%s", hapd->conf->iface) < 0)
|
|
+ return;
|
|
+
|
|
+ avl_init(&hapd->ubus.banned, avl_compare_macaddr, false, NULL);
|
|
+ obj->name = name;
|
|
+ obj->type = &bss_object_type;
|
|
+ obj->methods = bss_object_type.methods;
|
|
+ obj->n_methods = bss_object_type.n_methods;
|
|
+ ret = ubus_add_object(ctx, obj);
|
|
+ hostapd_ubus_ref_inc();
|
|
+}
|
|
+
|
|
+void hostapd_ubus_free_bss(struct hostapd_data *hapd)
|
|
+{
|
|
+ struct ubus_object *obj = &hapd->ubus.obj;
|
|
+ char *name = (char *) obj->name;
|
|
+
|
|
+#ifdef CONFIG_MESH
|
|
+ if (hapd->conf->mesh & MESH_ENABLED)
|
|
+ return;
|
|
+#endif
|
|
+
|
|
+ if (!ctx)
|
|
+ return;
|
|
+
|
|
+ if (obj->id) {
|
|
+ ubus_remove_object(ctx, obj);
|
|
+ hostapd_ubus_ref_dec();
|
|
+ }
|
|
+
|
|
+ free(name);
|
|
+}
|
|
+
|
|
+static void
|
|
+hostapd_ubus_vlan_action(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
|
|
+ const char *action)
|
|
+{
|
|
+ struct vlan_description *desc = &vlan->vlan_desc;
|
|
+ void *c;
|
|
+ int i;
|
|
+
|
|
+ if (!hapd->ubus.obj.has_subscribers)
|
|
+ return;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_string(&b, "ifname", vlan->ifname);
|
|
+ blobmsg_add_string(&b, "bridge", vlan->bridge);
|
|
+ blobmsg_add_u32(&b, "vlan_id", vlan->vlan_id);
|
|
+
|
|
+ if (desc->notempty) {
|
|
+ blobmsg_add_u32(&b, "untagged", desc->untagged);
|
|
+ c = blobmsg_open_array(&b, "tagged");
|
|
+ for (i = 0; i < ARRAY_SIZE(desc->tagged) && desc->tagged[i]; i++)
|
|
+ blobmsg_add_u32(&b, "", desc->tagged[i]);
|
|
+ blobmsg_close_array(&b, c);
|
|
+ }
|
|
+
|
|
+ ubus_notify(ctx, &hapd->ubus.obj, action, b.head, -1);
|
|
+}
|
|
+
|
|
+void hostapd_ubus_add_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
|
|
+{
|
|
+ hostapd_ubus_vlan_action(hapd, vlan, "vlan_add");
|
|
+}
|
|
+
|
|
+void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
|
|
+{
|
|
+ hostapd_ubus_vlan_action(hapd, vlan, "vlan_remove");
|
|
+}
|
|
+
|
|
+struct ubus_event_req {
|
|
+ struct ubus_notify_request nreq;
|
|
+ int resp;
|
|
+};
|
|
+
|
|
+static void
|
|
+ubus_event_cb(struct ubus_notify_request *req, int idx, int ret)
|
|
+{
|
|
+ struct ubus_event_req *ureq = container_of(req, struct ubus_event_req, nreq);
|
|
+
|
|
+ ureq->resp = ret;
|
|
+}
|
|
+
|
|
+int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req)
|
|
+{
|
|
+ struct ubus_banned_client *ban;
|
|
+ const char *types[HOSTAPD_UBUS_TYPE_MAX] = {
|
|
+ [HOSTAPD_UBUS_PROBE_REQ] = "probe",
|
|
+ [HOSTAPD_UBUS_AUTH_REQ] = "auth",
|
|
+ [HOSTAPD_UBUS_ASSOC_REQ] = "assoc",
|
|
+ };
|
|
+ const char *type = "mgmt";
|
|
+ struct ubus_event_req ureq = {};
|
|
+ const u8 *addr;
|
|
+
|
|
+ if (req->mgmt_frame)
|
|
+ addr = req->mgmt_frame->sa;
|
|
+ else
|
|
+ addr = req->addr;
|
|
+
|
|
+ ban = avl_find_element(&hapd->ubus.banned, addr, ban, avl);
|
|
+ if (ban)
|
|
+ return WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
|
|
+
|
|
+ if (!hapd->ubus.obj.has_subscribers)
|
|
+ return WLAN_STATUS_SUCCESS;
|
|
+
|
|
+ if (req->type < ARRAY_SIZE(types))
|
|
+ type = types[req->type];
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_macaddr(&b, "address", addr);
|
|
+ if (req->mgmt_frame)
|
|
+ blobmsg_add_macaddr(&b, "target", req->mgmt_frame->da);
|
|
+ if (req->ssi_signal)
|
|
+ blobmsg_add_u32(&b, "signal", req->ssi_signal);
|
|
+ blobmsg_add_u32(&b, "freq", hapd->iface->freq);
|
|
+
|
|
+ if (req->elems) {
|
|
+ if(req->elems->ht_capabilities)
|
|
+ {
|
|
+ struct ieee80211_ht_capabilities *ht_capabilities;
|
|
+ void *ht_cap, *ht_cap_mcs_set, *mcs_set;
|
|
+
|
|
+
|
|
+ ht_capabilities = (struct ieee80211_ht_capabilities*) req->elems->ht_capabilities;
|
|
+ ht_cap = blobmsg_open_table(&b, "ht_capabilities");
|
|
+ blobmsg_add_u16(&b, "ht_capabilities_info", ht_capabilities->ht_capabilities_info);
|
|
+ ht_cap_mcs_set = blobmsg_open_table(&b, "supported_mcs_set");
|
|
+ blobmsg_add_u16(&b, "a_mpdu_params", ht_capabilities->a_mpdu_params);
|
|
+ blobmsg_add_u16(&b, "ht_extended_capabilities", ht_capabilities->ht_extended_capabilities);
|
|
+ blobmsg_add_u32(&b, "tx_bf_capability_info", ht_capabilities->tx_bf_capability_info);
|
|
+ blobmsg_add_u16(&b, "asel_capabilities", ht_capabilities->asel_capabilities);
|
|
+ mcs_set = blobmsg_open_array(&b, "supported_mcs_set");
|
|
+ for (int i = 0; i < 16; i++) {
|
|
+ blobmsg_add_u16(&b, NULL, (u16) ht_capabilities->supported_mcs_set[i]);
|
|
+ }
|
|
+ blobmsg_close_array(&b, mcs_set);
|
|
+ blobmsg_close_table(&b, ht_cap_mcs_set);
|
|
+ blobmsg_close_table(&b, ht_cap);
|
|
+ }
|
|
+ if(req->elems->vht_capabilities)
|
|
+ {
|
|
+ struct ieee80211_vht_capabilities *vht_capabilities;
|
|
+ void *vht_cap, *vht_cap_mcs_set;
|
|
+
|
|
+ vht_capabilities = (struct ieee80211_vht_capabilities*) req->elems->vht_capabilities;
|
|
+ vht_cap = blobmsg_open_table(&b, "vht_capabilities");
|
|
+ blobmsg_add_u32(&b, "vht_capabilities_info", vht_capabilities->vht_capabilities_info);
|
|
+ vht_cap_mcs_set = blobmsg_open_table(&b, "vht_supported_mcs_set");
|
|
+ blobmsg_add_u16(&b, "rx_map", vht_capabilities->vht_supported_mcs_set.rx_map);
|
|
+ blobmsg_add_u16(&b, "rx_highest", vht_capabilities->vht_supported_mcs_set.rx_highest);
|
|
+ blobmsg_add_u16(&b, "tx_map", vht_capabilities->vht_supported_mcs_set.tx_map);
|
|
+ blobmsg_add_u16(&b, "tx_highest", vht_capabilities->vht_supported_mcs_set.tx_highest);
|
|
+ blobmsg_close_table(&b, vht_cap_mcs_set);
|
|
+ blobmsg_close_table(&b, vht_cap);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!hapd->ubus.notify_response) {
|
|
+ ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1);
|
|
+ return WLAN_STATUS_SUCCESS;
|
|
+ }
|
|
+
|
|
+ if (ubus_notify_async(ctx, &hapd->ubus.obj, type, b.head, &ureq.nreq))
|
|
+ return WLAN_STATUS_SUCCESS;
|
|
+
|
|
+ ureq.nreq.status_cb = ubus_event_cb;
|
|
+ ubus_complete_request(ctx, &ureq.nreq.req, 100);
|
|
+
|
|
+ if (ureq.resp)
|
|
+ return ureq.resp;
|
|
+
|
|
+ return WLAN_STATUS_SUCCESS;
|
|
+}
|
|
+
|
|
+void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *addr)
|
|
+{
|
|
+ if (!hapd->ubus.obj.has_subscribers)
|
|
+ return;
|
|
+
|
|
+ if (!addr)
|
|
+ return;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_macaddr(&b, "address", addr);
|
|
+
|
|
+ ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1);
|
|
+}
|
|
+
|
|
+void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta,
|
|
+ const char *auth_alg)
|
|
+{
|
|
+ if (!hapd->ubus.obj.has_subscribers)
|
|
+ return;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_macaddr(&b, "address", sta->addr);
|
|
+ if (auth_alg)
|
|
+ blobmsg_add_string(&b, "auth-alg", auth_alg);
|
|
+
|
|
+ ubus_notify(ctx, &hapd->ubus.obj, "sta-authorized", b.head, -1);
|
|
+}
|
|
+
|
|
+void hostapd_ubus_notify_beacon_report(
|
|
+ struct hostapd_data *hapd, const u8 *addr, u8 token, u8 rep_mode,
|
|
+ struct rrm_measurement_beacon_report *rep, size_t len)
|
|
+{
|
|
+ if (!hapd->ubus.obj.has_subscribers)
|
|
+ return;
|
|
+
|
|
+ if (!addr || !rep)
|
|
+ return;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_macaddr(&b, "address", addr);
|
|
+ blobmsg_add_u16(&b, "op-class", rep->op_class);
|
|
+ blobmsg_add_u16(&b, "channel", rep->channel);
|
|
+ blobmsg_add_u64(&b, "start-time", rep->start_time);
|
|
+ blobmsg_add_u16(&b, "duration", rep->duration);
|
|
+ blobmsg_add_u16(&b, "report-info", rep->report_info);
|
|
+ blobmsg_add_u16(&b, "rcpi", rep->rcpi);
|
|
+ blobmsg_add_u16(&b, "rsni", rep->rsni);
|
|
+ blobmsg_add_macaddr(&b, "bssid", rep->bssid);
|
|
+ blobmsg_add_u16(&b, "antenna-id", rep->antenna_id);
|
|
+ blobmsg_add_u16(&b, "parent-tsf", rep->parent_tsf);
|
|
+ blobmsg_add_u16(&b, "rep-mode", rep_mode);
|
|
+
|
|
+ ubus_notify(ctx, &hapd->ubus.obj, "beacon-report", b.head, -1);
|
|
+}
|
|
+
|
|
+void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequency,
|
|
+ int chan_width, int cf1, int cf2)
|
|
+{
|
|
+ struct hostapd_data *hapd;
|
|
+ int i;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_u16(&b, "frequency", frequency);
|
|
+ blobmsg_add_u16(&b, "width", chan_width);
|
|
+ blobmsg_add_u16(&b, "center1", cf1);
|
|
+ blobmsg_add_u16(&b, "center2", cf2);
|
|
+
|
|
+ for (i = 0; i < iface->num_bss; i++) {
|
|
+ hapd = iface->bss[i];
|
|
+ ubus_notify(ctx, &hapd->ubus.obj, "radar-detected", b.head, -1);
|
|
+ }
|
|
+}
|
|
+
|
|
+#ifdef CONFIG_WNM_AP
|
|
+static void hostapd_ubus_notify_bss_transition_add_candidate_list(
|
|
+ const u8 *candidate_list, u16 candidate_list_len)
|
|
+{
|
|
+ char *cl_str;
|
|
+ int i;
|
|
+
|
|
+ if (candidate_list_len == 0)
|
|
+ return;
|
|
+
|
|
+ cl_str = blobmsg_alloc_string_buffer(&b, "candidate-list", candidate_list_len * 2 + 1);
|
|
+ for (i = 0; i < candidate_list_len; i++)
|
|
+ snprintf(&cl_str[i*2], 3, "%02X", candidate_list[i]);
|
|
+ blobmsg_add_string_buffer(&b);
|
|
+
|
|
+}
|
|
+#endif
|
|
+
|
|
+void hostapd_ubus_notify_bss_transition_response(
|
|
+ struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 status_code,
|
|
+ u8 bss_termination_delay, const u8 *target_bssid,
|
|
+ const u8 *candidate_list, u16 candidate_list_len)
|
|
+{
|
|
+#ifdef CONFIG_WNM_AP
|
|
+ u16 i;
|
|
+
|
|
+ if (!hapd->ubus.obj.has_subscribers)
|
|
+ return;
|
|
+
|
|
+ if (!addr)
|
|
+ return;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_macaddr(&b, "address", addr);
|
|
+ blobmsg_add_u8(&b, "dialog-token", dialog_token);
|
|
+ blobmsg_add_u8(&b, "status-code", status_code);
|
|
+ blobmsg_add_u8(&b, "bss-termination-delay", bss_termination_delay);
|
|
+ if (target_bssid)
|
|
+ blobmsg_add_macaddr(&b, "target-bssid", target_bssid);
|
|
+
|
|
+ hostapd_ubus_notify_bss_transition_add_candidate_list(candidate_list, candidate_list_len);
|
|
+
|
|
+ ubus_notify(ctx, &hapd->ubus.obj, "bss-transition-response", b.head, -1);
|
|
+#endif
|
|
+}
|
|
+
|
|
+int hostapd_ubus_notify_bss_transition_query(
|
|
+ struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason,
|
|
+ const u8 *candidate_list, u16 candidate_list_len)
|
|
+{
|
|
+#ifdef CONFIG_WNM_AP
|
|
+ struct ubus_event_req ureq = {};
|
|
+ char *cl_str;
|
|
+ u16 i;
|
|
+
|
|
+ if (!hapd->ubus.obj.has_subscribers)
|
|
+ return 0;
|
|
+
|
|
+ if (!addr)
|
|
+ return 0;
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_macaddr(&b, "address", addr);
|
|
+ blobmsg_add_u8(&b, "dialog-token", dialog_token);
|
|
+ blobmsg_add_u8(&b, "reason", reason);
|
|
+ hostapd_ubus_notify_bss_transition_add_candidate_list(candidate_list, candidate_list_len);
|
|
+
|
|
+ if (!hapd->ubus.notify_response) {
|
|
+ ubus_notify(ctx, &hapd->ubus.obj, "bss-transition-query", b.head, -1);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (ubus_notify_async(ctx, &hapd->ubus.obj, "bss-transition-query", b.head, &ureq.nreq))
|
|
+ return 0;
|
|
+
|
|
+ ureq.nreq.status_cb = ubus_event_cb;
|
|
+ ubus_complete_request(ctx, &ureq.nreq.req, 100);
|
|
+
|
|
+ return ureq.resp;
|
|
+#endif
|
|
+}
|
|
diff --git a/package/network/services/hostapd/src/src/ap/ubus.h b/package/network/services/hostapd/src/src/ap/ubus.h
|
|
new file mode 100644
|
|
index 0000000000..b0f7c44ab5
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/src/ap/ubus.h
|
|
@@ -0,0 +1,154 @@
|
|
+/*
|
|
+ * hostapd / ubus support
|
|
+ * Copyright (c) 2013, Felix Fietkau <nbd@nbd.name>
|
|
+ *
|
|
+ * This software may be distributed under the terms of the BSD license.
|
|
+ * See README for more details.
|
|
+ */
|
|
+#ifndef __HOSTAPD_UBUS_H
|
|
+#define __HOSTAPD_UBUS_H
|
|
+
|
|
+enum hostapd_ubus_event_type {
|
|
+ HOSTAPD_UBUS_PROBE_REQ,
|
|
+ HOSTAPD_UBUS_AUTH_REQ,
|
|
+ HOSTAPD_UBUS_ASSOC_REQ,
|
|
+ HOSTAPD_UBUS_TYPE_MAX
|
|
+};
|
|
+
|
|
+struct hostapd_ubus_request {
|
|
+ enum hostapd_ubus_event_type type;
|
|
+ const struct ieee80211_mgmt *mgmt_frame;
|
|
+ const struct ieee802_11_elems *elems;
|
|
+ int ssi_signal; /* dBm */
|
|
+ const u8 *addr;
|
|
+};
|
|
+
|
|
+struct hostapd_iface;
|
|
+struct hostapd_data;
|
|
+struct hapd_interfaces;
|
|
+struct rrm_measurement_beacon_report;
|
|
+
|
|
+#ifdef UBUS_SUPPORT
|
|
+
|
|
+#include <libubox/avl.h>
|
|
+#include <libubus.h>
|
|
+
|
|
+struct hostapd_ubus_bss {
|
|
+ struct ubus_object obj;
|
|
+ struct avl_tree banned;
|
|
+ int notify_response;
|
|
+};
|
|
+
|
|
+void hostapd_ubus_add_iface(struct hostapd_iface *iface);
|
|
+void hostapd_ubus_free_iface(struct hostapd_iface *iface);
|
|
+void hostapd_ubus_add_bss(struct hostapd_data *hapd);
|
|
+void hostapd_ubus_free_bss(struct hostapd_data *hapd);
|
|
+void hostapd_ubus_add_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan);
|
|
+void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan);
|
|
+
|
|
+int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req);
|
|
+void hostapd_ubus_handle_link_measurement(struct hostapd_data *hapd, const u8 *data, size_t len);
|
|
+void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac);
|
|
+void hostapd_ubus_notify_beacon_report(struct hostapd_data *hapd,
|
|
+ const u8 *addr, u8 token, u8 rep_mode,
|
|
+ struct rrm_measurement_beacon_report *rep,
|
|
+ size_t len);
|
|
+void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequency,
|
|
+ int chan_width, int cf1, int cf2);
|
|
+
|
|
+void hostapd_ubus_notify_bss_transition_response(
|
|
+ struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 status_code,
|
|
+ u8 bss_termination_delay, const u8 *target_bssid,
|
|
+ const u8 *candidate_list, u16 candidate_list_len);
|
|
+void hostapd_ubus_add(struct hapd_interfaces *interfaces);
|
|
+void hostapd_ubus_free(struct hapd_interfaces *interfaces);
|
|
+int hostapd_ubus_notify_bss_transition_query(
|
|
+ struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason,
|
|
+ const u8 *candidate_list, u16 candidate_list_len);
|
|
+void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta,
|
|
+ const char *auth_alg);
|
|
+
|
|
+#else
|
|
+
|
|
+struct hostapd_ubus_bss {};
|
|
+
|
|
+static inline void hostapd_ubus_add_iface(struct hostapd_iface *iface)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void hostapd_ubus_free_iface(struct hostapd_iface *iface)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void hostapd_ubus_add_bss(struct hostapd_data *hapd)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void hostapd_ubus_free_bss(struct hostapd_data *hapd)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void hostapd_ubus_add_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline void hostapd_ubus_handle_link_measurement(struct hostapd_data *hapd, const u8 *data, size_t len)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void hostapd_ubus_notify_beacon_report(struct hostapd_data *hapd,
|
|
+ const u8 *addr, u8 token,
|
|
+ u8 rep_mode,
|
|
+ struct rrm_measurement_beacon_report *rep,
|
|
+ size_t len)
|
|
+{
|
|
+}
|
|
+static inline void hostapd_ubus_notify_radar_detected(struct hostapd_iface *iface, int frequency,
|
|
+ int chan_width, int cf1, int cf2)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void hostapd_ubus_notify_bss_transition_response(
|
|
+ struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 status_code,
|
|
+ u8 bss_termination_delay, const u8 *target_bssid,
|
|
+ const u8 *candidate_list, u16 candidate_list_len)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void hostapd_ubus_add(struct hapd_interfaces *interfaces)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void hostapd_ubus_free(struct hapd_interfaces *interfaces)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline int hostapd_ubus_notify_bss_transition_query(
|
|
+ struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 reason,
|
|
+ const u8 *candidate_list, u16 candidate_list_len)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline void
|
|
+hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta,
|
|
+ const char *auth_alg)
|
|
+{
|
|
+}
|
|
+
|
|
+#endif
|
|
+
|
|
+#endif
|
|
diff --git a/package/network/services/hostapd/src/src/ap/ucode.c b/package/network/services/hostapd/src/src/ap/ucode.c
|
|
new file mode 100644
|
|
index 0000000000..053171b142
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/src/ap/ucode.c
|
|
@@ -0,0 +1,545 @@
|
|
+#include <sys/un.h>
|
|
+
|
|
+#include "utils/includes.h"
|
|
+#include "utils/common.h"
|
|
+#include "utils/ucode.h"
|
|
+#include "hostapd.h"
|
|
+#include "beacon.h"
|
|
+#include "hw_features.h"
|
|
+#include "ap_drv_ops.h"
|
|
+#include <libubox/uloop.h>
|
|
+
|
|
+static uc_resource_type_t *global_type, *bss_type, *iface_type;
|
|
+static struct hapd_interfaces *interfaces;
|
|
+static uc_value_t *global, *bss_registry, *iface_registry;
|
|
+static uc_vm_t *vm;
|
|
+
|
|
+static uc_value_t *
|
|
+hostapd_ucode_bss_get_uval(struct hostapd_data *hapd)
|
|
+{
|
|
+ uc_value_t *val;
|
|
+
|
|
+ if (hapd->ucode.idx)
|
|
+ return wpa_ucode_registry_get(bss_registry, hapd->ucode.idx);
|
|
+
|
|
+ val = uc_resource_new(bss_type, hapd);
|
|
+ hapd->ucode.idx = wpa_ucode_registry_add(bss_registry, val);
|
|
+
|
|
+ return val;
|
|
+}
|
|
+
|
|
+static uc_value_t *
|
|
+hostapd_ucode_iface_get_uval(struct hostapd_iface *hapd)
|
|
+{
|
|
+ uc_value_t *val;
|
|
+
|
|
+ if (hapd->ucode.idx)
|
|
+ return wpa_ucode_registry_get(iface_registry, hapd->ucode.idx);
|
|
+
|
|
+ val = uc_resource_new(iface_type, hapd);
|
|
+ hapd->ucode.idx = wpa_ucode_registry_add(iface_registry, val);
|
|
+
|
|
+ return val;
|
|
+}
|
|
+
|
|
+static void
|
|
+hostapd_ucode_update_bss_list(struct hostapd_iface *iface, uc_value_t *if_bss, uc_value_t *bss)
|
|
+{
|
|
+ uc_value_t *list;
|
|
+ int i;
|
|
+
|
|
+ list = ucv_array_new(vm);
|
|
+ for (i = 0; i < iface->num_bss; i++) {
|
|
+ struct hostapd_data *hapd = iface->bss[i];
|
|
+ uc_value_t *val = hostapd_ucode_bss_get_uval(hapd);
|
|
+
|
|
+ ucv_array_set(list, i, ucv_get(ucv_string_new(hapd->conf->iface)));
|
|
+ ucv_object_add(bss, hapd->conf->iface, ucv_get(val));
|
|
+ }
|
|
+ ucv_object_add(if_bss, iface->phy, ucv_get(list));
|
|
+}
|
|
+
|
|
+static void
|
|
+hostapd_ucode_update_interfaces(void)
|
|
+{
|
|
+ uc_value_t *ifs = ucv_object_new(vm);
|
|
+ uc_value_t *if_bss = ucv_array_new(vm);
|
|
+ uc_value_t *bss = ucv_object_new(vm);
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < interfaces->count; i++) {
|
|
+ struct hostapd_iface *iface = interfaces->iface[i];
|
|
+
|
|
+ ucv_object_add(ifs, iface->phy, ucv_get(hostapd_ucode_iface_get_uval(iface)));
|
|
+ hostapd_ucode_update_bss_list(iface, if_bss, bss);
|
|
+ }
|
|
+
|
|
+ ucv_object_add(ucv_prototype_get(global), "interfaces", ucv_get(ifs));
|
|
+ ucv_object_add(ucv_prototype_get(global), "interface_bss", ucv_get(if_bss));
|
|
+ ucv_object_add(ucv_prototype_get(global), "bss", ucv_get(bss));
|
|
+ ucv_gc(vm);
|
|
+}
|
|
+
|
|
+static uc_value_t *
|
|
+uc_hostapd_add_iface(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ uc_value_t *iface = uc_fn_arg(0);
|
|
+ int ret;
|
|
+
|
|
+ if (ucv_type(iface) != UC_STRING)
|
|
+ return ucv_int64_new(-1);
|
|
+
|
|
+ ret = hostapd_add_iface(interfaces, ucv_string_get(iface));
|
|
+ hostapd_ucode_update_interfaces();
|
|
+
|
|
+ return ucv_int64_new(ret);
|
|
+}
|
|
+
|
|
+static uc_value_t *
|
|
+uc_hostapd_remove_iface(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ uc_value_t *iface = uc_fn_arg(0);
|
|
+
|
|
+ if (ucv_type(iface) != UC_STRING)
|
|
+ return NULL;
|
|
+
|
|
+ hostapd_remove_iface(interfaces, ucv_string_get(iface));
|
|
+ hostapd_ucode_update_interfaces();
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static uc_value_t *
|
|
+uc_hostapd_bss_set_config(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ struct hostapd_data *hapd = uc_fn_thisval("hostapd.bss");
|
|
+ struct hostapd_bss_config *old_bss;
|
|
+ struct hostapd_iface *iface;
|
|
+ struct hostapd_config *conf;
|
|
+ uc_value_t *file = uc_fn_arg(0);
|
|
+ uc_value_t *index = uc_fn_arg(1);
|
|
+ unsigned int i, idx = 0;
|
|
+ int ret = -1;
|
|
+
|
|
+ if (!hapd || ucv_type(file) != UC_STRING)
|
|
+ goto out;
|
|
+
|
|
+ if (ucv_type(index) == UC_INTEGER)
|
|
+ idx = ucv_int64_get(index);
|
|
+
|
|
+ iface = hapd->iface;
|
|
+ conf = interfaces->config_read_cb(ucv_string_get(file));
|
|
+ if (!conf || idx > conf->num_bss || !conf->bss[idx])
|
|
+ goto out;
|
|
+
|
|
+ hostapd_bss_deinit_no_free(hapd);
|
|
+ hostapd_drv_stop_ap(hapd);
|
|
+ hostapd_free_hapd_data(hapd);
|
|
+
|
|
+ old_bss = hapd->conf;
|
|
+ for (i = 0; i < iface->conf->num_bss; i++)
|
|
+ if (iface->conf->bss[i] == hapd->conf)
|
|
+ iface->conf->bss[i] = conf->bss[idx];
|
|
+ hapd->conf = conf->bss[idx];
|
|
+ conf->bss[idx] = old_bss;
|
|
+ hostapd_config_free(conf);
|
|
+
|
|
+ hostapd_setup_bss(hapd, hapd == iface->bss[0], !iface->conf->mbssid);
|
|
+
|
|
+ ret = 0;
|
|
+
|
|
+out:
|
|
+ return ucv_int64_new(ret);
|
|
+}
|
|
+
|
|
+static void
|
|
+hostapd_remove_iface_bss_conf(struct hostapd_config *iconf,
|
|
+ struct hostapd_bss_config *conf)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < iconf->num_bss; i++)
|
|
+ if (iconf->bss[i] == conf)
|
|
+ break;
|
|
+
|
|
+ if (i == iconf->num_bss)
|
|
+ return;
|
|
+
|
|
+ for (i++; i < iconf->num_bss; i++)
|
|
+ iconf->bss[i - 1] = iconf->bss[i];
|
|
+ iconf->num_bss--;
|
|
+}
|
|
+
|
|
+
|
|
+static uc_value_t *
|
|
+uc_hostapd_bss_delete(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ struct hostapd_data *hapd = uc_fn_thisval("hostapd.bss");
|
|
+ struct hostapd_iface *iface;
|
|
+ int i, idx;
|
|
+
|
|
+ if (!hapd || hapd == hapd->iface->bss[0])
|
|
+ return NULL;
|
|
+
|
|
+ iface = hapd->iface;
|
|
+ for (idx = 0; idx < iface->num_bss; idx++)
|
|
+ if (iface->bss[idx] == hapd)
|
|
+ break;
|
|
+
|
|
+ if (idx == iface->num_bss)
|
|
+ return NULL;
|
|
+
|
|
+ for (i = idx + 1; i < iface->num_bss; i++)
|
|
+ iface->bss[i - 1] = iface->bss[i];
|
|
+ iface->num_bss--;
|
|
+
|
|
+ hostapd_drv_stop_ap(hapd);
|
|
+ hostapd_bss_deinit(hapd);
|
|
+ hostapd_remove_iface_bss_conf(iface->conf, hapd->conf);
|
|
+ hostapd_config_free_bss(hapd->conf);
|
|
+ os_free(hapd);
|
|
+
|
|
+ hostapd_ucode_update_interfaces();
|
|
+ ucv_gc(vm);
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static uc_value_t *
|
|
+uc_hostapd_iface_add_bss(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
|
|
+ struct hostapd_bss_config *bss;
|
|
+ struct hostapd_config *conf;
|
|
+ struct hostapd_data *hapd;
|
|
+ uc_value_t *file = uc_fn_arg(0);
|
|
+ uc_value_t *index = uc_fn_arg(1);
|
|
+ unsigned int idx = 0;
|
|
+ uc_value_t *ret = NULL;
|
|
+
|
|
+ if (!iface || ucv_type(file) != UC_STRING)
|
|
+ goto out;
|
|
+
|
|
+ if (ucv_type(index) == UC_INTEGER)
|
|
+ idx = ucv_int64_get(index);
|
|
+
|
|
+ conf = interfaces->config_read_cb(ucv_string_get(file));
|
|
+ if (!conf || idx > conf->num_bss || !conf->bss[idx])
|
|
+ goto out;
|
|
+
|
|
+ bss = conf->bss[idx];
|
|
+ hapd = hostapd_alloc_bss_data(iface, iface->conf, bss);
|
|
+ if (!hapd)
|
|
+ goto out;
|
|
+
|
|
+ hapd->driver = iface->bss[0]->driver;
|
|
+ hapd->drv_priv = iface->bss[0]->drv_priv;
|
|
+ if (interfaces->ctrl_iface_init &&
|
|
+ interfaces->ctrl_iface_init(hapd) < 0)
|
|
+ goto free_hapd;
|
|
+
|
|
+ if (iface->state == HAPD_IFACE_ENABLED &&
|
|
+ hostapd_setup_bss(hapd, -1, true))
|
|
+ goto deinit_ctrl;
|
|
+
|
|
+ iface->bss = os_realloc_array(iface->bss, iface->num_bss + 1,
|
|
+ sizeof(*iface->bss));
|
|
+ iface->bss[iface->num_bss++] = hapd;
|
|
+
|
|
+ iface->conf->bss = os_realloc_array(iface->conf->bss,
|
|
+ iface->conf->num_bss + 1,
|
|
+ sizeof(*iface->conf->bss));
|
|
+ iface->conf->bss[iface->conf->num_bss] = bss;
|
|
+ conf->bss[idx] = NULL;
|
|
+ ret = hostapd_ucode_bss_get_uval(hapd);
|
|
+ hostapd_ucode_update_interfaces();
|
|
+ goto out;
|
|
+
|
|
+deinit_ctrl:
|
|
+ if (interfaces->ctrl_iface_deinit)
|
|
+ interfaces->ctrl_iface_deinit(hapd);
|
|
+free_hapd:
|
|
+ hostapd_free_hapd_data(hapd);
|
|
+ os_free(hapd);
|
|
+out:
|
|
+ hostapd_config_free(conf);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static uc_value_t *
|
|
+uc_hostapd_bss_ctrl(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ struct hostapd_data *hapd = uc_fn_thisval("hostapd.bss");
|
|
+ uc_value_t *arg = uc_fn_arg(0);
|
|
+ struct sockaddr_storage from = {};
|
|
+ static char reply[4096];
|
|
+ int reply_len;
|
|
+
|
|
+ if (!hapd || !interfaces->ctrl_iface_recv ||
|
|
+ ucv_type(arg) != UC_STRING)
|
|
+ return NULL;
|
|
+
|
|
+ reply_len = interfaces->ctrl_iface_recv(hapd, ucv_string_get(arg),
|
|
+ reply, sizeof(reply),
|
|
+ &from, sizeof(from));
|
|
+ if (reply_len < 0)
|
|
+ return NULL;
|
|
+
|
|
+ if (reply_len && reply[reply_len - 1] == '\n')
|
|
+ reply_len--;
|
|
+
|
|
+ return ucv_string_new_length(reply, reply_len);
|
|
+}
|
|
+
|
|
+static uc_value_t *
|
|
+uc_hostapd_iface_stop(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < iface->num_bss; i++) {
|
|
+ struct hostapd_data *hapd = iface->bss[i];
|
|
+
|
|
+ hostapd_drv_stop_ap(hapd);
|
|
+ hapd->started = 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+static uc_value_t *
|
|
+uc_hostapd_iface_start(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
|
|
+ uc_value_t *info = uc_fn_arg(0);
|
|
+ struct hostapd_config *conf;
|
|
+ uint64_t intval;
|
|
+ int i;
|
|
+
|
|
+ if (!iface)
|
|
+ return NULL;
|
|
+
|
|
+ if (!info)
|
|
+ goto out;
|
|
+
|
|
+ if (ucv_type(info) != UC_OBJECT)
|
|
+ return NULL;
|
|
+
|
|
+ conf = iface->conf;
|
|
+ if ((intval = ucv_int64_get(ucv_object_get(info, "op_class", NULL))) && !errno)
|
|
+ conf->op_class = intval;
|
|
+ if ((intval = ucv_int64_get(ucv_object_get(info, "hw_mode", NULL))) && !errno)
|
|
+ conf->hw_mode = intval;
|
|
+ if ((intval = ucv_int64_get(ucv_object_get(info, "channel", NULL))) && !errno)
|
|
+ conf->channel = intval;
|
|
+ if ((intval = ucv_int64_get(ucv_object_get(info, "sec_channel", NULL))) && !errno)
|
|
+ conf->secondary_channel = intval;
|
|
+#ifdef CONFIG_IEEE80211AC
|
|
+ if ((intval = ucv_int64_get(ucv_object_get(info, "center_seg0_idx", NULL))) && !errno) {
|
|
+ conf->vht_oper_centr_freq_seg0_idx = intval;
|
|
+#ifdef CONFIG_IEEE80211AX
|
|
+ conf->he_oper_centr_freq_seg0_idx = intval;
|
|
+#endif
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ conf->eht_oper_centr_freq_seg0_idx = intval;
|
|
+#endif
|
|
+ }
|
|
+ if ((intval = ucv_int64_get(ucv_object_get(info, "center_seg1_idx", NULL))) && !errno) {
|
|
+ conf->vht_oper_centr_freq_seg1_idx = intval;
|
|
+#ifdef CONFIG_IEEE80211AX
|
|
+ conf->he_oper_centr_freq_seg1_idx = intval;
|
|
+#endif
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ conf->eht_oper_centr_freq_seg1_idx = intval;
|
|
+#endif
|
|
+ }
|
|
+ intval = ucv_int64_get(ucv_object_get(info, "oper_chwidth", NULL));
|
|
+ if (!errno) {
|
|
+ conf->vht_oper_chwidth = intval;
|
|
+#ifdef CONFIG_IEEE80211AX
|
|
+ conf->he_oper_chwidth = intval;
|
|
+#endif
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ conf->eht_oper_chwidth = intval;
|
|
+#endif
|
|
+ }
|
|
+#endif
|
|
+
|
|
+out:
|
|
+ if (conf->channel)
|
|
+ iface->freq = hostapd_hw_get_freq(iface->bss[0], conf->channel);
|
|
+
|
|
+ for (i = 0; i < iface->num_bss; i++) {
|
|
+ struct hostapd_data *hapd = iface->bss[i];
|
|
+ int ret;
|
|
+
|
|
+ hapd->started = 1;
|
|
+ hostapd_set_freq(hapd, conf->hw_mode, iface->freq,
|
|
+ conf->channel,
|
|
+ conf->enable_edmg,
|
|
+ conf->edmg_channel,
|
|
+ conf->ieee80211n,
|
|
+ conf->ieee80211ac,
|
|
+ conf->ieee80211ax,
|
|
+ conf->ieee80211be,
|
|
+ conf->secondary_channel,
|
|
+ hostapd_get_oper_chwidth(conf),
|
|
+ hostapd_get_oper_centr_freq_seg0_idx(conf),
|
|
+ hostapd_get_oper_centr_freq_seg1_idx(conf));
|
|
+
|
|
+ ieee802_11_set_beacon(hapd);
|
|
+ }
|
|
+
|
|
+ return ucv_boolean_new(true);
|
|
+}
|
|
+
|
|
+static uc_value_t *
|
|
+uc_hostapd_iface_switch_channel(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ struct hostapd_iface *iface = uc_fn_thisval("hostapd.iface");
|
|
+ uc_value_t *info = uc_fn_arg(0);
|
|
+ struct hostapd_config *conf;
|
|
+ struct csa_settings csa = {};
|
|
+ uint64_t intval;
|
|
+ int i, ret = 0;
|
|
+
|
|
+ if (!iface || ucv_type(info) != UC_OBJECT)
|
|
+ return NULL;
|
|
+
|
|
+ conf = iface->conf;
|
|
+ if ((intval = ucv_int64_get(ucv_object_get(info, "csa_count", NULL))) && !errno)
|
|
+ csa.cs_count = intval;
|
|
+ if ((intval = ucv_int64_get(ucv_object_get(info, "sec_channel", NULL))) && !errno)
|
|
+ csa.freq_params.sec_channel_offset = intval;
|
|
+
|
|
+ csa.freq_params.ht_enabled = conf->ieee80211n;
|
|
+ csa.freq_params.vht_enabled = conf->ieee80211ac;
|
|
+ csa.freq_params.he_enabled = conf->ieee80211ax;
|
|
+#ifdef CONFIG_IEEE80211BE
|
|
+ csa.freq_params.eht_enabled = conf->ieee80211be;
|
|
+#endif
|
|
+ intval = ucv_int64_get(ucv_object_get(info, "oper_chwidth", NULL));
|
|
+ if (errno)
|
|
+ intval = hostapd_get_oper_chwidth(conf);
|
|
+ if (intval)
|
|
+ csa.freq_params.bandwidth = 40 << intval;
|
|
+ else
|
|
+ csa.freq_params.bandwidth = csa.freq_params.sec_channel_offset ? 40 : 20;
|
|
+
|
|
+ if ((intval = ucv_int64_get(ucv_object_get(info, "frequency", NULL))) && !errno)
|
|
+ csa.freq_params.freq = intval;
|
|
+ if ((intval = ucv_int64_get(ucv_object_get(info, "center_freq1", NULL))) && !errno)
|
|
+ csa.freq_params.center_freq1 = intval;
|
|
+ if ((intval = ucv_int64_get(ucv_object_get(info, "center_freq2", NULL))) && !errno)
|
|
+ csa.freq_params.center_freq2 = intval;
|
|
+
|
|
+ for (i = 0; i < iface->num_bss; i++)
|
|
+ ret = hostapd_switch_channel(iface->bss[i], &csa);
|
|
+
|
|
+ return ucv_boolean_new(!ret);
|
|
+}
|
|
+
|
|
+int hostapd_ucode_init(struct hapd_interfaces *ifaces)
|
|
+{
|
|
+ static const uc_function_list_t global_fns[] = {
|
|
+ { "printf", uc_wpa_printf },
|
|
+ { "getpid", uc_wpa_getpid },
|
|
+ { "sha1", uc_wpa_sha1 },
|
|
+ { "freq_info", uc_wpa_freq_info },
|
|
+ { "add_iface", uc_hostapd_add_iface },
|
|
+ { "remove_iface", uc_hostapd_remove_iface },
|
|
+ };
|
|
+ static const uc_function_list_t bss_fns[] = {
|
|
+ { "ctrl", uc_hostapd_bss_ctrl },
|
|
+ { "set_config", uc_hostapd_bss_set_config },
|
|
+ { "delete", uc_hostapd_bss_delete },
|
|
+ };
|
|
+ static const uc_function_list_t iface_fns[] = {
|
|
+ { "add_bss", uc_hostapd_iface_add_bss },
|
|
+ { "stop", uc_hostapd_iface_stop },
|
|
+ { "start", uc_hostapd_iface_start },
|
|
+ { "switch_channel", uc_hostapd_iface_switch_channel },
|
|
+ };
|
|
+ uc_value_t *data, *proto;
|
|
+
|
|
+ interfaces = ifaces;
|
|
+ vm = wpa_ucode_create_vm();
|
|
+
|
|
+ global_type = uc_type_declare(vm, "hostapd.global", global_fns, NULL);
|
|
+ bss_type = uc_type_declare(vm, "hostapd.bss", bss_fns, NULL);
|
|
+ iface_type = uc_type_declare(vm, "hostapd.iface", iface_fns, NULL);
|
|
+
|
|
+ bss_registry = ucv_array_new(vm);
|
|
+ uc_vm_registry_set(vm, "hostap.bss_registry", bss_registry);
|
|
+
|
|
+ iface_registry = ucv_array_new(vm);
|
|
+ uc_vm_registry_set(vm, "hostap.iface_registry", iface_registry);
|
|
+
|
|
+ global = wpa_ucode_global_init("hostapd", global_type);
|
|
+
|
|
+ if (wpa_ucode_run(HOSTAPD_UC_PATH "hostapd.uc"))
|
|
+ goto free_vm;
|
|
+ ucv_gc(vm);
|
|
+
|
|
+ return 0;
|
|
+
|
|
+free_vm:
|
|
+ wpa_ucode_free_vm();
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+void hostapd_ucode_free(void)
|
|
+{
|
|
+ if (wpa_ucode_call_prepare("shutdown") == 0)
|
|
+ ucv_put(wpa_ucode_call(0));
|
|
+ wpa_ucode_free_vm();
|
|
+}
|
|
+
|
|
+void hostapd_ucode_free_iface(struct hostapd_iface *iface)
|
|
+{
|
|
+ wpa_ucode_registry_remove(iface_registry, iface->ucode.idx);
|
|
+}
|
|
+
|
|
+void hostapd_ucode_add_bss(struct hostapd_data *hapd)
|
|
+{
|
|
+ uc_value_t *val;
|
|
+
|
|
+ if (wpa_ucode_call_prepare("bss_add"))
|
|
+ return;
|
|
+
|
|
+ val = hostapd_ucode_bss_get_uval(hapd);
|
|
+ uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface)));
|
|
+ uc_value_push(ucv_get(val));
|
|
+ ucv_put(wpa_ucode_call(2));
|
|
+ ucv_gc(vm);
|
|
+}
|
|
+
|
|
+void hostapd_ucode_reload_bss(struct hostapd_data *hapd)
|
|
+{
|
|
+ uc_value_t *val;
|
|
+
|
|
+ if (wpa_ucode_call_prepare("bss_reload"))
|
|
+ return;
|
|
+
|
|
+ val = hostapd_ucode_bss_get_uval(hapd);
|
|
+ uc_value_push(ucv_get(ucv_string_new(hapd->conf->iface)));
|
|
+ uc_value_push(ucv_get(val));
|
|
+ ucv_put(wpa_ucode_call(2));
|
|
+ ucv_gc(vm);
|
|
+}
|
|
+
|
|
+void hostapd_ucode_free_bss(struct hostapd_data *hapd)
|
|
+{
|
|
+ uc_value_t *val;
|
|
+
|
|
+ val = wpa_ucode_registry_remove(bss_registry, hapd->ucode.idx);
|
|
+ if (!val)
|
|
+ return;
|
|
+
|
|
+ hapd->ucode.idx = 0;
|
|
+ if (wpa_ucode_call_prepare("bss_remove"))
|
|
+ return;
|
|
+
|
|
+ uc_value_push(ucv_string_new(hapd->conf->iface));
|
|
+ uc_value_push(ucv_get(val));
|
|
+ ucv_put(wpa_ucode_call(2));
|
|
+ ucv_gc(vm);
|
|
+}
|
|
diff --git a/package/network/services/hostapd/src/src/ap/ucode.h b/package/network/services/hostapd/src/src/ap/ucode.h
|
|
new file mode 100644
|
|
index 0000000000..d00b787169
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/src/ap/ucode.h
|
|
@@ -0,0 +1,54 @@
|
|
+#ifndef __HOSTAPD_AP_UCODE_H
|
|
+#define __HOSTAPD_AP_UCODE_H
|
|
+
|
|
+#include "utils/ucode.h"
|
|
+
|
|
+struct hostapd_data;
|
|
+
|
|
+struct hostapd_ucode_bss {
|
|
+#ifdef UCODE_SUPPORT
|
|
+ int idx;
|
|
+#endif
|
|
+};
|
|
+
|
|
+struct hostapd_ucode_iface {
|
|
+#ifdef UCODE_SUPPORT
|
|
+ int idx;
|
|
+#endif
|
|
+};
|
|
+
|
|
+#ifdef UCODE_SUPPORT
|
|
+
|
|
+int hostapd_ucode_init(struct hapd_interfaces *ifaces);
|
|
+
|
|
+void hostapd_ucode_free(void);
|
|
+void hostapd_ucode_free_iface(struct hostapd_iface *iface);
|
|
+void hostapd_ucode_add_bss(struct hostapd_data *hapd);
|
|
+void hostapd_ucode_free_bss(struct hostapd_data *hapd);
|
|
+void hostapd_ucode_reload_bss(struct hostapd_data *hapd);
|
|
+
|
|
+#else
|
|
+
|
|
+static inline int hostapd_ucode_init(struct hapd_interfaces *ifaces)
|
|
+{
|
|
+ return -EINVAL;
|
|
+}
|
|
+static inline void hostapd_ucode_free(void)
|
|
+{
|
|
+}
|
|
+static inline void hostapd_ucode_free_iface(struct hostapd_iface *iface)
|
|
+{
|
|
+}
|
|
+static inline void hostapd_ucode_reload_bss(struct hostapd_data *hapd)
|
|
+{
|
|
+}
|
|
+static inline void hostapd_ucode_add_bss(struct hostapd_data *hapd)
|
|
+{
|
|
+}
|
|
+static inline void hostapd_ucode_free_bss(struct hostapd_data *hapd)
|
|
+{
|
|
+}
|
|
+
|
|
+#endif
|
|
+
|
|
+#endif
|
|
diff --git a/package/network/services/hostapd/src/src/utils/build_features.h b/package/network/services/hostapd/src/src/utils/build_features.h
|
|
new file mode 100644
|
|
index 0000000000..553769eceb
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/src/utils/build_features.h
|
|
@@ -0,0 +1,65 @@
|
|
+#ifndef BUILD_FEATURES_H
|
|
+#define BUILD_FEATURES_H
|
|
+
|
|
+static inline int has_feature(const char *feat)
|
|
+{
|
|
+#if defined(IEEE8021X_EAPOL) || (defined(HOSTAPD) && !defined(CONFIG_NO_RADIUS))
|
|
+ if (!strcmp(feat, "eap"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_IEEE80211AC
|
|
+ if (!strcmp(feat, "11ac"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_IEEE80211AX
|
|
+ if (!strcmp(feat, "11ax"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_IEEE80211R
|
|
+ if (!strcmp(feat, "11r"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_ACS
|
|
+ if (!strcmp(feat, "acs"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_SAE
|
|
+ if (!strcmp(feat, "sae"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_OWE
|
|
+ if (!strcmp(feat, "owe"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_SUITEB192
|
|
+ if (!strcmp(feat, "suiteb192"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_WEP
|
|
+ if (!strcmp(feat, "wep"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_HS20
|
|
+ if (!strcmp(feat, "hs20"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_WPS
|
|
+ if (!strcmp(feat, "wps"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_FILS
|
|
+ if (!strcmp(feat, "fils"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_OCV
|
|
+ if (!strcmp(feat, "ocv"))
|
|
+ return 1;
|
|
+#endif
|
|
+#ifdef CONFIG_MESH
|
|
+ if (!strcmp(feat, "mesh"))
|
|
+ return 1;
|
|
+#endif
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#endif /* BUILD_FEATURES_H */
|
|
diff --git a/package/network/services/hostapd/src/src/utils/ucode.c b/package/network/services/hostapd/src/src/utils/ucode.c
|
|
new file mode 100644
|
|
index 0000000000..44169f0bf0
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/src/utils/ucode.c
|
|
@@ -0,0 +1,326 @@
|
|
+#include <unistd.h>
|
|
+#include "ucode.h"
|
|
+#include "utils/eloop.h"
|
|
+#include "crypto/crypto.h"
|
|
+#include "crypto/sha1.h"
|
|
+#include "common/ieee802_11_common.h"
|
|
+#include <libubox/uloop.h>
|
|
+#include <ucode/compiler.h>
|
|
+
|
|
+static uc_value_t *registry;
|
|
+static uc_vm_t vm;
|
|
+static struct uloop_timeout gc_timer;
|
|
+
|
|
+static void uc_gc_timer(struct uloop_timeout *timeout)
|
|
+{
|
|
+ ucv_gc(&vm);
|
|
+}
|
|
+
|
|
+uc_value_t *uc_wpa_printf(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ uc_value_t *level = uc_fn_arg(0);
|
|
+ uc_value_t *ret, **args;
|
|
+ uc_cfn_ptr_t _sprintf;
|
|
+ int l = MSG_INFO;
|
|
+ int i, start = 0;
|
|
+
|
|
+ _sprintf = uc_stdlib_function("sprintf");
|
|
+ if (!sprintf)
|
|
+ return NULL;
|
|
+
|
|
+ if (ucv_type(level) == UC_INTEGER) {
|
|
+ l = ucv_int64_get(level);
|
|
+ start++;
|
|
+ }
|
|
+
|
|
+ if (nargs <= start)
|
|
+ return NULL;
|
|
+
|
|
+ ret = _sprintf(vm, nargs - start);
|
|
+ if (ucv_type(ret) != UC_STRING)
|
|
+ return NULL;
|
|
+
|
|
+ wpa_printf(l, "%s", ucv_string_get(ret));
|
|
+ ucv_put(ret);
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+uc_value_t *uc_wpa_freq_info(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ uc_value_t *freq = uc_fn_arg(0);
|
|
+ uc_value_t *sec = uc_fn_arg(1);
|
|
+ int width = ucv_uint64_get(uc_fn_arg(2));
|
|
+ int freq_val, center_idx, center_ofs;
|
|
+ enum oper_chan_width chanwidth;
|
|
+ enum hostapd_hw_mode hw_mode;
|
|
+ u8 op_class, channel, tmp_channel;
|
|
+ const char *modestr;
|
|
+ int sec_channel = 0;
|
|
+ uc_value_t *ret;
|
|
+
|
|
+ if (ucv_type(freq) != UC_INTEGER)
|
|
+ return NULL;
|
|
+
|
|
+ freq_val = ucv_int64_get(freq);
|
|
+ if (ucv_type(sec) == UC_INTEGER)
|
|
+ sec_channel = ucv_int64_get(sec);
|
|
+ else if (sec)
|
|
+ return NULL;
|
|
+ else if (freq_val > 4000)
|
|
+ sec_channel = (freq_val / 20) & 1 ? 1 : -1;
|
|
+ else
|
|
+ sec_channel = freq_val < 2442 ? 1 : -1;
|
|
+
|
|
+ if (sec_channel != -1 && sec_channel != 1 && sec_channel != 0)
|
|
+ return NULL;
|
|
+
|
|
+ switch (width) {
|
|
+ case 0:
|
|
+ chanwidth = CONF_OPER_CHWIDTH_USE_HT;
|
|
+ break;
|
|
+ case 1:
|
|
+ chanwidth = CONF_OPER_CHWIDTH_80MHZ;
|
|
+ break;
|
|
+ case 2:
|
|
+ chanwidth = CONF_OPER_CHWIDTH_160MHZ;
|
|
+ break;
|
|
+ default:
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ hw_mode = ieee80211_freq_to_channel_ext(freq_val, sec_channel,
|
|
+ chanwidth, &op_class, &channel);
|
|
+ switch (hw_mode) {
|
|
+ case HOSTAPD_MODE_IEEE80211B:
|
|
+ modestr = "b";
|
|
+ break;
|
|
+ case HOSTAPD_MODE_IEEE80211G:
|
|
+ modestr = "g";
|
|
+ break;
|
|
+ case HOSTAPD_MODE_IEEE80211A:
|
|
+ modestr = "a";
|
|
+ break;
|
|
+ case HOSTAPD_MODE_IEEE80211AD:
|
|
+ modestr = "ad";
|
|
+ break;
|
|
+ default:
|
|
+ return NULL;
|
|
+ }
|
|
+
|
|
+ ret = ucv_object_new(vm);
|
|
+ ucv_object_add(ret, "op_class", ucv_int64_new(op_class));
|
|
+ ucv_object_add(ret, "channel", ucv_int64_new(channel));
|
|
+ ucv_object_add(ret, "hw_mode", ucv_int64_new(hw_mode));
|
|
+ ucv_object_add(ret, "hw_mode_str", ucv_get(ucv_string_new(modestr)));
|
|
+ ucv_object_add(ret, "sec_channel", ucv_int64_new(sec_channel));
|
|
+ ucv_object_add(ret, "frequency", ucv_int64_new(freq_val));
|
|
+
|
|
+ if (!sec_channel)
|
|
+ return ret;
|
|
+
|
|
+ if (freq_val >= 5900)
|
|
+ center_ofs = 0;
|
|
+ else if (freq_val >= 5745)
|
|
+ center_ofs = 20;
|
|
+ else
|
|
+ center_ofs = 35;
|
|
+ tmp_channel = channel - center_ofs;
|
|
+ tmp_channel &= ~((8 << width) - 1);
|
|
+ center_idx = tmp_channel + center_ofs + (4 << width) - 1;
|
|
+
|
|
+ ucv_object_add(ret, "center_seg0_idx", ucv_int64_new(center_idx));
|
|
+ center_idx = (center_idx - channel) * 5 + freq_val;
|
|
+ ucv_object_add(ret, "center_freq1", ucv_int64_new(center_idx));
|
|
+
|
|
+out:
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+uc_value_t *uc_wpa_getpid(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ return ucv_int64_new(getpid());
|
|
+}
|
|
+
|
|
+uc_value_t *uc_wpa_sha1(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ u8 hash[SHA1_MAC_LEN];
|
|
+ char hash_hex[2 * ARRAY_SIZE(hash) + 1];
|
|
+ uc_value_t *val;
|
|
+ size_t *lens;
|
|
+ const u8 **args;
|
|
+ int i;
|
|
+
|
|
+ if (!nargs)
|
|
+ return NULL;
|
|
+
|
|
+ args = alloca(nargs * sizeof(*args));
|
|
+ lens = alloca(nargs * sizeof(*lens));
|
|
+ for (i = 0; i < nargs; i++) {
|
|
+ val = uc_fn_arg(i);
|
|
+ if (ucv_type(val) != UC_STRING)
|
|
+ return NULL;
|
|
+
|
|
+ args[i] = ucv_string_get(val);
|
|
+ lens[i] = ucv_string_length(val);
|
|
+ }
|
|
+
|
|
+ if (sha1_vector(nargs, args, lens, hash))
|
|
+ return NULL;
|
|
+
|
|
+ for (i = 0; i < ARRAY_SIZE(hash); i++)
|
|
+ sprintf(hash_hex + 2 * i, "%02x", hash[i]);
|
|
+
|
|
+ return ucv_string_new_length(hash_hex, 2 * ARRAY_SIZE(hash));
|
|
+}
|
|
+
|
|
+uc_vm_t *wpa_ucode_create_vm(void)
|
|
+{
|
|
+ static uc_parse_config_t config = {
|
|
+ .strict_declarations = true,
|
|
+ .lstrip_blocks = true,
|
|
+ .trim_blocks = true,
|
|
+ .raw_mode = true
|
|
+ };
|
|
+
|
|
+ uc_search_path_init(&config.module_search_path);
|
|
+ uc_search_path_add(&config.module_search_path, HOSTAPD_UC_PATH "*.so");
|
|
+ uc_search_path_add(&config.module_search_path, HOSTAPD_UC_PATH "*.uc");
|
|
+
|
|
+ uc_vm_init(&vm, &config);
|
|
+
|
|
+ uc_stdlib_load(uc_vm_scope_get(&vm));
|
|
+ eloop_add_uloop();
|
|
+ gc_timer.cb = uc_gc_timer;
|
|
+
|
|
+ return &vm;
|
|
+}
|
|
+
|
|
+int wpa_ucode_run(const char *script)
|
|
+{
|
|
+ uc_source_t *source;
|
|
+ uc_program_t *prog;
|
|
+ uc_value_t *ops;
|
|
+ char *err;
|
|
+ int ret;
|
|
+
|
|
+ source = uc_source_new_file(script);
|
|
+ if (!source)
|
|
+ return -1;
|
|
+
|
|
+ prog = uc_compile(vm.config, source, &err);
|
|
+ uc_source_put(source);
|
|
+ if (!prog) {
|
|
+ wpa_printf(MSG_ERROR, "Error loading ucode: %s\n", err);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ ret = uc_vm_execute(&vm, prog, &ops);
|
|
+ uc_program_put(prog);
|
|
+ if (ret || !ops)
|
|
+ return -1;
|
|
+
|
|
+ registry = ucv_array_new(&vm);
|
|
+ uc_vm_registry_set(&vm, "hostap.registry", registry);
|
|
+ ucv_array_set(registry, 0, ucv_get(ops));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+int wpa_ucode_call_prepare(const char *fname)
|
|
+{
|
|
+ uc_value_t *obj, *func;
|
|
+
|
|
+ if (!registry)
|
|
+ return -1;
|
|
+
|
|
+ obj = ucv_array_get(registry, 0);
|
|
+ if (!obj)
|
|
+ return -1;
|
|
+
|
|
+ func = ucv_object_get(obj, fname, NULL);
|
|
+ if (!ucv_is_callable(func))
|
|
+ return -1;
|
|
+
|
|
+ uc_vm_stack_push(&vm, ucv_get(obj));
|
|
+ uc_vm_stack_push(&vm, ucv_get(func));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+uc_value_t *wpa_ucode_global_init(const char *name, uc_resource_type_t *global_type)
|
|
+{
|
|
+ uc_value_t *global = uc_resource_new(global_type, NULL);
|
|
+ uc_value_t *proto;
|
|
+
|
|
+ uc_vm_registry_set(&vm, "hostap.global", global);
|
|
+ proto = ucv_prototype_get(global);
|
|
+ ucv_object_add(proto, "data", ucv_get(ucv_object_new(&vm)));
|
|
+
|
|
+#define ADD_CONST(x) ucv_object_add(proto, #x, ucv_int64_new(x))
|
|
+ ADD_CONST(MSG_EXCESSIVE);
|
|
+ ADD_CONST(MSG_MSGDUMP);
|
|
+ ADD_CONST(MSG_DEBUG);
|
|
+ ADD_CONST(MSG_INFO);
|
|
+ ADD_CONST(MSG_WARNING);
|
|
+ ADD_CONST(MSG_ERROR);
|
|
+#undef ADD_CONST
|
|
+
|
|
+ ucv_object_add(uc_vm_scope_get(&vm), name, ucv_get(global));
|
|
+
|
|
+ return global;
|
|
+}
|
|
+
|
|
+int wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val)
|
|
+{
|
|
+ uc_value_t *data;
|
|
+ int i = 0;
|
|
+
|
|
+ while (ucv_array_get(reg, i))
|
|
+ i++;
|
|
+
|
|
+ ucv_array_set(reg, i, ucv_get(val));
|
|
+
|
|
+ return i + 1;
|
|
+}
|
|
+
|
|
+uc_value_t *wpa_ucode_registry_get(uc_value_t *reg, int idx)
|
|
+{
|
|
+ if (!idx)
|
|
+ return NULL;
|
|
+
|
|
+ return ucv_array_get(reg, idx - 1);
|
|
+}
|
|
+
|
|
+uc_value_t *wpa_ucode_registry_remove(uc_value_t *reg, int idx)
|
|
+{
|
|
+ uc_value_t *val = wpa_ucode_registry_get(reg, idx);
|
|
+
|
|
+ if (val)
|
|
+ ucv_array_set(reg, idx - 1, NULL);
|
|
+
|
|
+ return val;
|
|
+}
|
|
+
|
|
+
|
|
+uc_value_t *wpa_ucode_call(size_t nargs)
|
|
+{
|
|
+ if (uc_vm_call(&vm, true, nargs) != EXCEPTION_NONE)
|
|
+ return NULL;
|
|
+
|
|
+ if (!gc_timer.pending)
|
|
+ uloop_timeout_set(&gc_timer, 10);
|
|
+
|
|
+ return uc_vm_stack_pop(&vm);
|
|
+}
|
|
+
|
|
+void wpa_ucode_free_vm(void)
|
|
+{
|
|
+ if (!vm.config)
|
|
+ return;
|
|
+
|
|
+ uc_search_path_free(&vm.config->module_search_path);
|
|
+ uc_vm_free(&vm);
|
|
+ registry = NULL;
|
|
+ vm = (uc_vm_t){};
|
|
+}
|
|
diff --git a/package/network/services/hostapd/src/src/utils/ucode.h b/package/network/services/hostapd/src/src/utils/ucode.h
|
|
new file mode 100644
|
|
index 0000000000..2c1886976e
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/src/utils/ucode.h
|
|
@@ -0,0 +1,29 @@
|
|
+#ifndef __HOSTAPD_UTILS_UCODE_H
|
|
+#define __HOSTAPD_UTILS_UCODE_H
|
|
+
|
|
+#include "utils/includes.h"
|
|
+#include "utils/common.h"
|
|
+#include <ucode/lib.h>
|
|
+#include <ucode/vm.h>
|
|
+
|
|
+#define HOSTAPD_UC_PATH "/usr/share/hostap/"
|
|
+
|
|
+extern uc_value_t *uc_registry;
|
|
+uc_vm_t *wpa_ucode_create_vm(void);
|
|
+int wpa_ucode_run(const char *script);
|
|
+int wpa_ucode_call_prepare(const char *fname);
|
|
+uc_value_t *wpa_ucode_call(size_t nargs);
|
|
+void wpa_ucode_free_vm(void);
|
|
+
|
|
+uc_value_t *wpa_ucode_global_init(const char *name, uc_resource_type_t *global_type);
|
|
+
|
|
+int wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val);
|
|
+uc_value_t *wpa_ucode_registry_get(uc_value_t *reg, int idx);
|
|
+uc_value_t *wpa_ucode_registry_remove(uc_value_t *reg, int idx);
|
|
+
|
|
+uc_value_t *uc_wpa_printf(uc_vm_t *vm, size_t nargs);
|
|
+uc_value_t *uc_wpa_getpid(uc_vm_t *vm, size_t nargs);
|
|
+uc_value_t *uc_wpa_sha1(uc_vm_t *vm, size_t nargs);
|
|
+uc_value_t *uc_wpa_freq_info(uc_vm_t *vm, size_t nargs);
|
|
+
|
|
+#endif
|
|
diff --git a/package/network/services/hostapd/src/wpa_supplicant/ubus.c b/package/network/services/hostapd/src/wpa_supplicant/ubus.c
|
|
new file mode 100644
|
|
index 0000000000..1c477f0c0c
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/wpa_supplicant/ubus.c
|
|
@@ -0,0 +1,280 @@
|
|
+/*
|
|
+ * wpa_supplicant / ubus support
|
|
+ * Copyright (c) 2018, Daniel Golle <daniel@makrotopia.org>
|
|
+ * Copyright (c) 2013, Felix Fietkau <nbd@nbd.name>
|
|
+ *
|
|
+ * 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 "utils/wpabuf.h"
|
|
+#include "common/ieee802_11_defs.h"
|
|
+#include "wpa_supplicant_i.h"
|
|
+#include "wps_supplicant.h"
|
|
+#include "ubus.h"
|
|
+
|
|
+static struct ubus_context *ctx;
|
|
+static struct blob_buf b;
|
|
+static int ctx_ref;
|
|
+
|
|
+static inline struct wpa_global *get_wpa_global_from_object(struct ubus_object *obj)
|
|
+{
|
|
+ return container_of(obj, struct wpa_global, ubus_global);
|
|
+}
|
|
+
|
|
+static inline struct wpa_supplicant *get_wpas_from_object(struct ubus_object *obj)
|
|
+{
|
|
+ return container_of(obj, struct wpa_supplicant, ubus.obj);
|
|
+}
|
|
+
|
|
+static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx)
|
|
+{
|
|
+ if (ubus_reconnect(ctx, NULL)) {
|
|
+ eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ubus_add_uloop(ctx);
|
|
+}
|
|
+
|
|
+static void wpas_ubus_connection_lost(struct ubus_context *ctx)
|
|
+{
|
|
+ uloop_fd_delete(&ctx->sock);
|
|
+ eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL);
|
|
+}
|
|
+
|
|
+static bool wpas_ubus_init(void)
|
|
+{
|
|
+ if (ctx)
|
|
+ return true;
|
|
+
|
|
+ eloop_add_uloop();
|
|
+ ctx = ubus_connect(NULL);
|
|
+ if (!ctx)
|
|
+ return false;
|
|
+
|
|
+ ctx->connection_lost = wpas_ubus_connection_lost;
|
|
+ ubus_add_uloop(ctx);
|
|
+
|
|
+ return true;
|
|
+}
|
|
+
|
|
+static void wpas_ubus_ref_inc(void)
|
|
+{
|
|
+ ctx_ref++;
|
|
+}
|
|
+
|
|
+static void wpas_ubus_ref_dec(void)
|
|
+{
|
|
+ ctx_ref--;
|
|
+ if (!ctx)
|
|
+ return;
|
|
+
|
|
+ if (ctx_ref)
|
|
+ return;
|
|
+
|
|
+ uloop_fd_delete(&ctx->sock);
|
|
+ ubus_free(ctx);
|
|
+ ctx = NULL;
|
|
+}
|
|
+
|
|
+static int
|
|
+wpas_bss_get_features(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct wpa_supplicant *wpa_s = get_wpas_from_object(obj);
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+ blobmsg_add_u8(&b, "ht_supported", ht_supported(wpa_s->hw.modes));
|
|
+ blobmsg_add_u8(&b, "vht_supported", vht_supported(wpa_s->hw.modes));
|
|
+ ubus_send_reply(ctx, req, b.head);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+wpas_bss_reload(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ struct wpa_supplicant *wpa_s = get_wpas_from_object(obj);
|
|
+
|
|
+ if (wpa_supplicant_reload_configuration(wpa_s))
|
|
+ return UBUS_STATUS_UNKNOWN_ERROR;
|
|
+ else
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#ifdef CONFIG_WPS
|
|
+enum {
|
|
+ WPS_START_MULTI_AP,
|
|
+ __WPS_START_MAX
|
|
+};
|
|
+
|
|
+static const struct blobmsg_policy wps_start_policy[] = {
|
|
+ [WPS_START_MULTI_AP] = { "multi_ap", BLOBMSG_TYPE_BOOL },
|
|
+};
|
|
+
|
|
+static int
|
|
+wpas_bss_wps_start(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ int rc;
|
|
+ struct wpa_supplicant *wpa_s = get_wpas_from_object(obj);
|
|
+ struct blob_attr *tb[__WPS_START_MAX], *cur;
|
|
+ int multi_ap = 0;
|
|
+
|
|
+ blobmsg_parse(wps_start_policy, __WPS_START_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg));
|
|
+
|
|
+ if (tb[WPS_START_MULTI_AP])
|
|
+ multi_ap = blobmsg_get_bool(tb[WPS_START_MULTI_AP]);
|
|
+
|
|
+ rc = wpas_wps_start_pbc(wpa_s, NULL, 0, multi_ap);
|
|
+
|
|
+ if (rc != 0)
|
|
+ return UBUS_STATUS_NOT_SUPPORTED;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int
|
|
+wpas_bss_wps_cancel(struct ubus_context *ctx, struct ubus_object *obj,
|
|
+ struct ubus_request_data *req, const char *method,
|
|
+ struct blob_attr *msg)
|
|
+{
|
|
+ int rc;
|
|
+ struct wpa_supplicant *wpa_s = get_wpas_from_object(obj);
|
|
+
|
|
+ rc = wpas_wps_cancel(wpa_s);
|
|
+
|
|
+ if (rc != 0)
|
|
+ return UBUS_STATUS_NOT_SUPPORTED;
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif
|
|
+
|
|
+static const struct ubus_method bss_methods[] = {
|
|
+ UBUS_METHOD_NOARG("reload", wpas_bss_reload),
|
|
+ UBUS_METHOD_NOARG("get_features", wpas_bss_get_features),
|
|
+#ifdef CONFIG_WPS
|
|
+ UBUS_METHOD_NOARG("wps_start", wpas_bss_wps_start),
|
|
+ UBUS_METHOD_NOARG("wps_cancel", wpas_bss_wps_cancel),
|
|
+#endif
|
|
+};
|
|
+
|
|
+static struct ubus_object_type bss_object_type =
|
|
+ UBUS_OBJECT_TYPE("wpas_bss", bss_methods);
|
|
+
|
|
+void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s)
|
|
+{
|
|
+ struct ubus_object *obj = &wpa_s->ubus.obj;
|
|
+ char *name;
|
|
+ int ret;
|
|
+
|
|
+ if (!wpas_ubus_init())
|
|
+ return;
|
|
+
|
|
+ if (asprintf(&name, "wpa_supplicant.%s", wpa_s->ifname) < 0)
|
|
+ return;
|
|
+
|
|
+ obj->name = name;
|
|
+ obj->type = &bss_object_type;
|
|
+ obj->methods = bss_object_type.methods;
|
|
+ obj->n_methods = bss_object_type.n_methods;
|
|
+ ret = ubus_add_object(ctx, obj);
|
|
+ wpas_ubus_ref_inc();
|
|
+}
|
|
+
|
|
+void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s)
|
|
+{
|
|
+ struct ubus_object *obj = &wpa_s->ubus.obj;
|
|
+ char *name = (char *) obj->name;
|
|
+
|
|
+ if (!ctx)
|
|
+ return;
|
|
+
|
|
+ if (obj->id) {
|
|
+ ubus_remove_object(ctx, obj);
|
|
+ wpas_ubus_ref_dec();
|
|
+ }
|
|
+
|
|
+ free(name);
|
|
+}
|
|
+
|
|
+#ifdef CONFIG_WPS
|
|
+void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred)
|
|
+{
|
|
+ u16 auth_type;
|
|
+ char *ifname, *encryption, *ssid, *key;
|
|
+ size_t ifname_len;
|
|
+
|
|
+ if (!cred)
|
|
+ return;
|
|
+
|
|
+ auth_type = cred->auth_type;
|
|
+
|
|
+ if (auth_type == (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK))
|
|
+ auth_type = WPS_AUTH_WPA2PSK;
|
|
+
|
|
+ if (auth_type != WPS_AUTH_OPEN &&
|
|
+ auth_type != WPS_AUTH_WPAPSK &&
|
|
+ auth_type != WPS_AUTH_WPA2PSK) {
|
|
+ wpa_printf(MSG_DEBUG, "WPS: Ignored credentials for "
|
|
+ "unsupported authentication type 0x%x",
|
|
+ auth_type);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (auth_type == WPS_AUTH_WPAPSK || auth_type == WPS_AUTH_WPA2PSK) {
|
|
+ if (cred->key_len < 8 || cred->key_len > 2 * PMK_LEN) {
|
|
+ wpa_printf(MSG_ERROR, "WPS: Reject PSK credential with "
|
|
+ "invalid Network Key length %lu",
|
|
+ (unsigned long) cred->key_len);
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ blob_buf_init(&b, 0);
|
|
+
|
|
+ ifname_len = strlen(wpa_s->ifname);
|
|
+ ifname = blobmsg_alloc_string_buffer(&b, "ifname", ifname_len + 1);
|
|
+ memcpy(ifname, wpa_s->ifname, ifname_len + 1);
|
|
+ ifname[ifname_len] = '\0';
|
|
+ blobmsg_add_string_buffer(&b);
|
|
+
|
|
+ switch (auth_type) {
|
|
+ case WPS_AUTH_WPA2PSK:
|
|
+ encryption = "psk2";
|
|
+ break;
|
|
+ case WPS_AUTH_WPAPSK:
|
|
+ encryption = "psk";
|
|
+ break;
|
|
+ default:
|
|
+ encryption = "none";
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ blobmsg_add_string(&b, "encryption", encryption);
|
|
+
|
|
+ ssid = blobmsg_alloc_string_buffer(&b, "ssid", cred->ssid_len + 1);
|
|
+ memcpy(ssid, cred->ssid, cred->ssid_len);
|
|
+ ssid[cred->ssid_len] = '\0';
|
|
+ blobmsg_add_string_buffer(&b);
|
|
+
|
|
+ if (cred->key_len > 0) {
|
|
+ key = blobmsg_alloc_string_buffer(&b, "key", cred->key_len + 1);
|
|
+ memcpy(key, cred->key, cred->key_len);
|
|
+ key[cred->key_len] = '\0';
|
|
+ blobmsg_add_string_buffer(&b);
|
|
+ }
|
|
+
|
|
+// ubus_notify(ctx, &wpa_s->ubus.obj, "wps_credentials", b.head, -1);
|
|
+ ubus_send_event(ctx, "wps_credentials", b.head);
|
|
+}
|
|
+#endif /* CONFIG_WPS */
|
|
diff --git a/package/network/services/hostapd/src/wpa_supplicant/ubus.h b/package/network/services/hostapd/src/wpa_supplicant/ubus.h
|
|
new file mode 100644
|
|
index 0000000000..f6681cb26d
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/wpa_supplicant/ubus.h
|
|
@@ -0,0 +1,55 @@
|
|
+/*
|
|
+ * wpa_supplicant / ubus support
|
|
+ * Copyright (c) 2018, Daniel Golle <daniel@makrotopia.org>
|
|
+ * Copyright (c) 2013, Felix Fietkau <nbd@nbd.name>
|
|
+ *
|
|
+ * This software may be distributed under the terms of the BSD license.
|
|
+ * See README for more details.
|
|
+ */
|
|
+#ifndef __WPAS_UBUS_H
|
|
+#define __WPAS_UBUS_H
|
|
+
|
|
+struct wpa_supplicant;
|
|
+struct wpa_global;
|
|
+
|
|
+#include "wps_supplicant.h"
|
|
+
|
|
+#ifdef UBUS_SUPPORT
|
|
+#include <libubus.h>
|
|
+
|
|
+struct wpas_ubus_bss {
|
|
+ struct ubus_object obj;
|
|
+};
|
|
+
|
|
+void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s);
|
|
+void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s);
|
|
+
|
|
+#ifdef CONFIG_WPS
|
|
+void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred);
|
|
+#endif
|
|
+
|
|
+#else
|
|
+struct wpas_ubus_bss {};
|
|
+
|
|
+static inline void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void wpas_ubus_notify(struct wpa_supplicant *wpa_s, struct wps_credential *cred)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void wpas_ubus_add(struct wpa_global *global)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void wpas_ubus_free(struct wpa_global *global)
|
|
+{
|
|
+}
|
|
+#endif
|
|
+
|
|
+#endif
|
|
diff --git a/package/network/services/hostapd/src/wpa_supplicant/ucode.c b/package/network/services/hostapd/src/wpa_supplicant/ucode.c
|
|
new file mode 100644
|
|
index 0000000000..d0a78d1625
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/wpa_supplicant/ucode.c
|
|
@@ -0,0 +1,270 @@
|
|
+#include "utils/includes.h"
|
|
+#include "utils/common.h"
|
|
+#include "utils/ucode.h"
|
|
+#include "drivers/driver.h"
|
|
+#include "wpa_supplicant_i.h"
|
|
+#include "wps_supplicant.h"
|
|
+#include "bss.h"
|
|
+#include "ucode.h"
|
|
+
|
|
+static struct wpa_global *wpa_global;
|
|
+static uc_resource_type_t *global_type, *iface_type;
|
|
+static uc_value_t *global, *iface_registry;
|
|
+static uc_vm_t *vm;
|
|
+
|
|
+static uc_value_t *
|
|
+wpas_ucode_iface_get_uval(struct wpa_supplicant *wpa_s)
|
|
+{
|
|
+ uc_value_t *val;
|
|
+
|
|
+ if (wpa_s->ucode.idx)
|
|
+ return wpa_ucode_registry_get(iface_registry, wpa_s->ucode.idx);
|
|
+
|
|
+ val = uc_resource_new(iface_type, wpa_s);
|
|
+ wpa_s->ucode.idx = wpa_ucode_registry_add(iface_registry, val);
|
|
+
|
|
+ return val;
|
|
+}
|
|
+
|
|
+static void
|
|
+wpas_ucode_update_interfaces(void)
|
|
+{
|
|
+ uc_value_t *ifs = ucv_object_new(vm);
|
|
+ struct wpa_supplicant *wpa_s;
|
|
+ int i;
|
|
+
|
|
+ for (wpa_s = wpa_global->ifaces; wpa_s; wpa_s = wpa_s->next)
|
|
+ ucv_object_add(ifs, wpa_s->ifname, ucv_get(wpas_ucode_iface_get_uval(wpa_s)));
|
|
+
|
|
+ ucv_object_add(ucv_prototype_get(global), "interfaces", ucv_get(ifs));
|
|
+ ucv_gc(vm);
|
|
+}
|
|
+
|
|
+void wpas_ucode_add_bss(struct wpa_supplicant *wpa_s)
|
|
+{
|
|
+ uc_value_t *val;
|
|
+
|
|
+ if (wpa_ucode_call_prepare("iface_add"))
|
|
+ return;
|
|
+
|
|
+ uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname)));
|
|
+ uc_value_push(ucv_get(wpas_ucode_iface_get_uval(wpa_s)));
|
|
+ ucv_put(wpa_ucode_call(2));
|
|
+ ucv_gc(vm);
|
|
+}
|
|
+
|
|
+void wpas_ucode_free_bss(struct wpa_supplicant *wpa_s)
|
|
+{
|
|
+ uc_value_t *val;
|
|
+
|
|
+ val = wpa_ucode_registry_remove(iface_registry, wpa_s->ucode.idx);
|
|
+ if (!val)
|
|
+ return;
|
|
+
|
|
+ wpa_s->ucode.idx = 0;
|
|
+ if (wpa_ucode_call_prepare("iface_remove"))
|
|
+ return;
|
|
+
|
|
+ uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname)));
|
|
+ uc_value_push(ucv_get(val));
|
|
+ ucv_put(wpa_ucode_call(2));
|
|
+ ucv_gc(vm);
|
|
+}
|
|
+
|
|
+void wpas_ucode_update_state(struct wpa_supplicant *wpa_s)
|
|
+{
|
|
+ const char *state;
|
|
+ uc_value_t *val;
|
|
+
|
|
+ val = wpa_ucode_registry_get(iface_registry, wpa_s->ucode.idx);
|
|
+ if (!val)
|
|
+ return;
|
|
+
|
|
+ if (wpa_ucode_call_prepare("state"))
|
|
+ return;
|
|
+
|
|
+ state = wpa_supplicant_state_txt(wpa_s->wpa_state);
|
|
+ uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname)));
|
|
+ uc_value_push(ucv_get(val));
|
|
+ uc_value_push(ucv_get(ucv_string_new(state)));
|
|
+ ucv_put(wpa_ucode_call(3));
|
|
+ ucv_gc(vm);
|
|
+}
|
|
+
|
|
+void wpas_ucode_event(struct wpa_supplicant *wpa_s, int event, union wpa_event_data *data)
|
|
+{
|
|
+ const char *state;
|
|
+ uc_value_t *val;
|
|
+
|
|
+ if (event != EVENT_CH_SWITCH_STARTED)
|
|
+ return;
|
|
+
|
|
+ val = wpa_ucode_registry_get(iface_registry, wpa_s->ucode.idx);
|
|
+ if (!val)
|
|
+ return;
|
|
+
|
|
+ if (wpa_ucode_call_prepare("event"))
|
|
+ return;
|
|
+
|
|
+ uc_value_push(ucv_get(ucv_string_new(wpa_s->ifname)));
|
|
+ uc_value_push(ucv_get(val));
|
|
+ uc_value_push(ucv_get(ucv_string_new(event_to_string(event))));
|
|
+ val = ucv_object_new(vm);
|
|
+ uc_value_push(ucv_get(val));
|
|
+
|
|
+ if (event == EVENT_CH_SWITCH_STARTED) {
|
|
+ ucv_object_add(val, "csa_count", ucv_int64_new(data->ch_switch.count));
|
|
+ ucv_object_add(val, "frequency", ucv_int64_new(data->ch_switch.freq));
|
|
+ ucv_object_add(val, "sec_chan_offset", ucv_int64_new(data->ch_switch.ch_offset));
|
|
+ ucv_object_add(val, "center_freq1", ucv_int64_new(data->ch_switch.cf1));
|
|
+ ucv_object_add(val, "center_freq2", ucv_int64_new(data->ch_switch.cf2));
|
|
+ }
|
|
+
|
|
+ ucv_put(wpa_ucode_call(4));
|
|
+ ucv_gc(vm);
|
|
+}
|
|
+
|
|
+static const char *obj_stringval(uc_value_t *obj, const char *name)
|
|
+{
|
|
+ uc_value_t *val = ucv_object_get(obj, name, NULL);
|
|
+
|
|
+ return ucv_string_get(val);
|
|
+}
|
|
+
|
|
+static uc_value_t *
|
|
+uc_wpas_add_iface(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ uc_value_t *info = uc_fn_arg(0);
|
|
+ uc_value_t *ifname = ucv_object_get(info, "iface", NULL);
|
|
+ uc_value_t *bridge = ucv_object_get(info, "bridge", NULL);
|
|
+ uc_value_t *config = ucv_object_get(info, "config", NULL);
|
|
+ uc_value_t *ctrl = ucv_object_get(info, "ctrl", NULL);
|
|
+ struct wpa_interface iface;
|
|
+ int ret = -1;
|
|
+
|
|
+ if (ucv_type(info) != UC_OBJECT)
|
|
+ goto out;
|
|
+
|
|
+ iface = (struct wpa_interface){
|
|
+ .driver = "nl80211",
|
|
+ .ifname = ucv_string_get(ifname),
|
|
+ .bridge_ifname = ucv_string_get(bridge),
|
|
+ .confname = ucv_string_get(config),
|
|
+ .ctrl_interface = ucv_string_get(ctrl),
|
|
+ };
|
|
+
|
|
+ if (!iface.ifname || !iface.confname)
|
|
+ goto out;
|
|
+
|
|
+ ret = wpa_supplicant_add_iface(wpa_global, &iface, 0) ? 0 : -1;
|
|
+ wpas_ucode_update_interfaces();
|
|
+
|
|
+out:
|
|
+ return ucv_int64_new(ret);
|
|
+}
|
|
+
|
|
+static uc_value_t *
|
|
+uc_wpas_remove_iface(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ struct wpa_supplicant *wpa_s = NULL;
|
|
+ uc_value_t *ifname_arg = uc_fn_arg(0);
|
|
+ const char *ifname = ucv_string_get(ifname_arg);
|
|
+ int ret = -1;
|
|
+
|
|
+ if (!ifname)
|
|
+ goto out;
|
|
+
|
|
+ for (wpa_s = wpa_global->ifaces; wpa_s; wpa_s = wpa_s->next)
|
|
+ if (!strcmp(wpa_s->ifname, ifname))
|
|
+ break;
|
|
+
|
|
+ if (!wpa_s)
|
|
+ goto out;
|
|
+
|
|
+ ret = wpa_supplicant_remove_iface(wpa_global, wpa_s, 0);
|
|
+ wpas_ucode_update_interfaces();
|
|
+
|
|
+out:
|
|
+ return ucv_int64_new(ret);
|
|
+}
|
|
+
|
|
+static uc_value_t *
|
|
+uc_wpas_iface_status(uc_vm_t *vm, size_t nargs)
|
|
+{
|
|
+ struct wpa_supplicant *wpa_s = uc_fn_thisval("wpas.iface");
|
|
+ struct wpa_bss *bss;
|
|
+ uc_value_t *ret, *val;
|
|
+
|
|
+ if (!wpa_s)
|
|
+ return NULL;
|
|
+
|
|
+ ret = ucv_object_new(vm);
|
|
+
|
|
+ val = ucv_string_new(wpa_supplicant_state_txt(wpa_s->wpa_state));
|
|
+ ucv_object_add(ret, "state", ucv_get(val));
|
|
+
|
|
+ bss = wpa_s->current_bss;
|
|
+ if (bss) {
|
|
+ int sec_chan = 0;
|
|
+ const u8 *ie;
|
|
+
|
|
+ ie = wpa_bss_get_ie(bss, WLAN_EID_HT_OPERATION);
|
|
+ if (ie && ie[1] >= 2) {
|
|
+ const struct ieee80211_ht_operation *ht_oper;
|
|
+
|
|
+ ht_oper = (const void *) (ie + 2);
|
|
+ if (ht_oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE)
|
|
+ sec_chan = 1;
|
|
+ else if (ht_oper->ht_param &
|
|
+ HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW)
|
|
+ sec_chan = -1;
|
|
+ }
|
|
+
|
|
+ ucv_object_add(ret, "sec_chan_offset", ucv_int64_new(sec_chan));
|
|
+ ucv_object_add(ret, "frequency", ucv_int64_new(bss->freq));
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+int wpas_ucode_init(struct wpa_global *gl)
|
|
+{
|
|
+ static const uc_function_list_t global_fns[] = {
|
|
+ { "printf", uc_wpa_printf },
|
|
+ { "getpid", uc_wpa_getpid },
|
|
+ { "add_iface", uc_wpas_add_iface },
|
|
+ { "remove_iface", uc_wpas_remove_iface },
|
|
+ };
|
|
+ static const uc_function_list_t iface_fns[] = {
|
|
+ { "status", uc_wpas_iface_status },
|
|
+ };
|
|
+ uc_value_t *data, *proto;
|
|
+
|
|
+ wpa_global = gl;
|
|
+ vm = wpa_ucode_create_vm();
|
|
+
|
|
+ global_type = uc_type_declare(vm, "wpas.global", global_fns, NULL);
|
|
+ iface_type = uc_type_declare(vm, "wpas.iface", iface_fns, NULL);
|
|
+
|
|
+ iface_registry = ucv_array_new(vm);
|
|
+ uc_vm_registry_set(vm, "wpas.iface_registry", iface_registry);
|
|
+
|
|
+ global = wpa_ucode_global_init("wpas", global_type);
|
|
+
|
|
+ if (wpa_ucode_run(HOSTAPD_UC_PATH "wpa_supplicant.uc"))
|
|
+ goto free_vm;
|
|
+
|
|
+ ucv_gc(vm);
|
|
+ return 0;
|
|
+
|
|
+free_vm:
|
|
+ wpa_ucode_free_vm();
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+void wpas_ucode_free(void)
|
|
+{
|
|
+ if (wpa_ucode_call_prepare("shutdown") == 0)
|
|
+ ucv_put(wpa_ucode_call(0));
|
|
+ wpa_ucode_free_vm();
|
|
+}
|
|
diff --git a/package/network/services/hostapd/src/wpa_supplicant/ucode.h b/package/network/services/hostapd/src/wpa_supplicant/ucode.h
|
|
new file mode 100644
|
|
index 0000000000..a429a0ed87
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/wpa_supplicant/ucode.h
|
|
@@ -0,0 +1,49 @@
|
|
+#ifndef __WPAS_UCODE_H
|
|
+#define __WPAS_UCODE_H
|
|
+
|
|
+#include "utils/ucode.h"
|
|
+
|
|
+struct wpa_global;
|
|
+union wpa_event_data;
|
|
+struct wpa_supplicant;
|
|
+
|
|
+struct wpas_ucode_bss {
|
|
+#ifdef UCODE_SUPPORT
|
|
+ unsigned int idx;
|
|
+#endif
|
|
+};
|
|
+
|
|
+#ifdef UCODE_SUPPORT
|
|
+int wpas_ucode_init(struct wpa_global *gl);
|
|
+void wpas_ucode_free(void);
|
|
+void wpas_ucode_add_bss(struct wpa_supplicant *wpa_s);
|
|
+void wpas_ucode_free_bss(struct wpa_supplicant *wpa_s);
|
|
+void wpas_ucode_update_state(struct wpa_supplicant *wpa_s);
|
|
+void wpas_ucode_event(struct wpa_supplicant *wpa_s, int event, union wpa_event_data *data);
|
|
+#else
|
|
+static inline int wpas_ucode_init(struct wpa_global *gl)
|
|
+{
|
|
+ return -EINVAL;
|
|
+}
|
|
+static inline void wpas_ucode_free(void)
|
|
+{
|
|
+}
|
|
+static inline void wpas_ucode_add_bss(struct wpa_supplicant *wpa_s)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void wpas_ucode_free_bss(struct wpa_supplicant *wpa_s)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void wpas_ucode_update_state(struct wpa_supplicant *wpa_s)
|
|
+{
|
|
+}
|
|
+
|
|
+static inline void wpas_ucode_event(struct wpa_supplicant *wpa_s, int event, union wpa_event_data *data)
|
|
+{
|
|
+}
|
|
+
|
|
+#endif
|
|
+
|
|
+#endif
|
|
--
|
|
2.34.1
|
|
|