mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-30 01:52:51 +00:00
21692 lines
698 KiB
Diff
21692 lines
698 KiB
Diff
From 4f17c6e2ca90130f86783e87927019525af719ba Mon Sep 17 00:00:00 2001
|
|
From: Felix Fietkau <nbd@nbd.name>
|
|
Date: Thu, 6 Jul 2023 08:33:25 +0000
|
|
Subject: [PATCH] backport hostapd ucode / wifi reload support
|
|
|
|
Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
---
|
|
package/kernel/mac80211/Makefile | 2 +-
|
|
.../files/lib/netifd/wireless/mac80211.sh | 703 +-
|
|
package/network/services/hostapd/Config.in | 39 +-
|
|
package/network/services/hostapd/Makefile | 231 +-
|
|
package/network/services/hostapd/README.md | 419 +
|
|
.../network/services/hostapd/files/common.uc | 168 +
|
|
.../hostapd/files/hostapd-basic.config | 2 +-
|
|
.../hostapd/files/hostapd-full.config | 6 +-
|
|
.../network/services/hostapd/files/hostapd.sh | 23 -
|
|
.../network/services/hostapd/files/hostapd.uc | 408 +
|
|
.../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 | 153 +
|
|
.../hostapd/files/wpa_supplicant-basic.config | 4 +-
|
|
.../hostapd/files/wpa_supplicant-full.config | 4 +-
|
|
.../hostapd/files/wpa_supplicant-mini.config | 2 +-
|
|
.../hostapd/files/wpa_supplicant-p2p.config | 4 +-
|
|
.../services/hostapd/files/wpa_supplicant.uc | 161 +
|
|
.../network/services/hostapd/files/wpad.init | 2 +
|
|
.../001-wolfssl-init-RNG-with-ECC-key.patch | 6 +-
|
|
...hannels-to-be-selected-if-dfs-is-ena.patch | 93 +-
|
|
...erministic-channel-on-channel-switch.patch | 10 +-
|
|
...ix-sta-add-after-previous-connection.patch | 4 +-
|
|
...use-of-uninitialized-stack-variables.patch | 2 +-
|
|
...ewrite-neigh-code-to-not-depend-on-l.patch | 14 +-
|
|
...ssing-authentication-frames-in-block.patch | 4 +-
|
|
.../hostapd/patches/050-build_fix.patch | 4 +-
|
|
...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 +
|
|
.../hostapd/patches/200-multicall.patch | 60 +-
|
|
.../services/hostapd/patches/300-noscan.patch | 4 +-
|
|
.../hostapd/patches/301-mesh-noscan.patch | 54 +-
|
|
.../patches/310-rescan_immediately.patch | 2 +-
|
|
.../patches/330-nl80211_fix_set_freq.patch | 6 +-
|
|
.../patches/340-reload_freq_change.patch | 11 +-
|
|
.../341-mesh-ctrl-iface-channel-switch.patch | 2 +-
|
|
.../patches/350-nl80211_del_beacon_bss.patch | 43 +-
|
|
.../patches/360-ctrl_iface_reload.patch | 10 +-
|
|
.../hostapd/patches/370-ap_sta_support.patch | 71 +-
|
|
.../patches/380-disable_ctrl_iface_mib.patch | 86 +-
|
|
.../381-hostapd_cli_UNKNOWN-COMMAND.patch | 2 +-
|
|
.../patches/390-wpa_ie_cap_workaround.patch | 4 +-
|
|
.../400-wps_single_auth_enc_type.patch | 2 +-
|
|
.../patches/410-limit_debug_messages.patch | 22 +-
|
|
.../patches/420-indicate-features.patch | 33 +-
|
|
.../patches/430-hostapd_cli_ifdef.patch | 12 +-
|
|
.../hostapd/patches/432-missing-typedef.patch | 10 -
|
|
.../hostapd/patches/450-scan_wait.patch | 10 +-
|
|
...dd-new-config-params-to-be-used-with.patch | 10 +-
|
|
...-use-new-parameters-during-ibss-join.patch | 59 -
|
|
.../patches/463-add-mcast_rate-to-11s.patch | 8 +-
|
|
.../patches/464-fix-mesh-obss-check.patch | 22 +-
|
|
...tapd-config-support-random-BSS-color.patch | 24 +
|
|
.../patches/470-survey_data_fallback.patch | 15 +-
|
|
.../patches/500-lto-jobserver-support.patch | 6 +-
|
|
.../patches/590-rrm-wnm-statistics.patch | 18 +-
|
|
.../hostapd/patches/600-ubus_support.patch | 477 +-
|
|
.../hostapd/patches/601-ucode_support.patch | 224 +
|
|
.../hostapd/patches/700-wifi-reload.patch | 116 +-
|
|
.../hostapd/patches/710-vlan_no_bridge.patch | 4 +-
|
|
.../patches/711-wds_bridge_force.patch | 8 +-
|
|
.../patches/720-iface_max_num_sta.patch | 14 +-
|
|
.../hostapd/patches/730-ft_iface.patch | 8 +-
|
|
.../hostapd/patches/740-snoop_iface.patch | 20 +-
|
|
...750-qos_map_set_without_interworking.patch | 67 +-
|
|
.../751-qos_map_ignore_when_unsupported.patch | 2 +-
|
|
.../hostapd/patches/760-acs_exclude_dfs.patch | 15 -
|
|
.../hostapd/patches/760-dynamic_own_ip.patch | 109 +
|
|
.../hostapd/patches/761-shared_das_port.patch | 298 +
|
|
.../hostapd/patches/770-radius_server.patch | 154 +
|
|
.../hostapd/patches/780-maxassoc.patch | 8 +-
|
|
.../{750-wispr.patch => 790-wispr.patch} | 36 +-
|
|
.../800-fix-ap-sta-channel-setup-failed.patch | 4 +-
|
|
.../hostapd/patches/900-coa_multi.patch | 35 +-
|
|
.../hostapd/patches/901-cfg-section.patch | 36 +-
|
|
..._AP-functions-dependant-on-CONFIG_AP.patch | 33 +
|
|
.../hostapd/patches/999-probe-request.patch | 26 +-
|
|
...ACL-PSK-check-during-4-way-handshake.patch | 484 -
|
|
...ributes-with-Extended-Types-RFC-6929.patch | 350 -
|
|
...ibutes-for-EAPOL-Key-message-details.patch | 102 -
|
|
.../services/hostapd/src/hostapd/radius.c | 715 ++
|
|
.../services/hostapd/src/src/ap/ubus.c | 427 +-
|
|
.../services/hostapd/src/src/ap/ubus.h | 15 +-
|
|
.../services/hostapd/src/src/ap/ucode.c | 386 +
|
|
.../services/hostapd/src/src/ap/ucode.h | 54 +
|
|
.../hostapd/src/src/utils/build_features.h | 12 +-
|
|
.../services/hostapd/src/src/utils/ucode.c | 237 +
|
|
.../services/hostapd/src/src/utils/ucode.h | 28 +
|
|
.../hostapd/src/wpa_supplicant/ubus.c | 162 +-
|
|
.../hostapd/src/wpa_supplicant/ubus.h | 11 -
|
|
.../hostapd/src/wpa_supplicant/ucode.c | 177 +
|
|
.../hostapd/src/wpa_supplicant/ucode.h | 38 +
|
|
98 files changed, 15512 insertions(+), 2535 deletions(-)
|
|
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/hostapd.uc
|
|
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.uc
|
|
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
|
|
delete mode 100644 package/network/services/hostapd/patches/432-missing-typedef.patch
|
|
delete mode 100644 package/network/services/hostapd/patches/461-driver_nl80211-use-new-parameters-during-ibss-join.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/601-ucode_support.patch
|
|
delete mode 100644 package/network/services/hostapd/patches/760-acs_exclude_dfs.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
|
|
rename package/network/services/hostapd/patches/{750-wispr.patch => 790-wispr.patch} (65%)
|
|
create mode 100644 package/network/services/hostapd/patches/990-ctrl-make-WNM_AP-functions-dependant-on-CONFIG_AP.patch
|
|
delete mode 100644 package/network/services/hostapd/patches/n00-001-RADIUS-ACL-PSK-check-during-4-way-handshake.patch
|
|
delete mode 100644 package/network/services/hostapd/patches/n00-002-RADIUS-Attributes-with-Extended-Types-RFC-6929.patch
|
|
delete mode 100644 package/network/services/hostapd/patches/n00-003-RADIUS-attributes-for-EAPOL-Key-message-details.patch
|
|
create mode 100644 package/network/services/hostapd/src/hostapd/radius.c
|
|
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/ucode.c
|
|
create mode 100644 package/network/services/hostapd/src/src/utils/ucode.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/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile
|
|
index 2f9fd11f10..6d39668bbc 100644
|
|
--- a/package/kernel/mac80211/Makefile
|
|
+++ b/package/kernel/mac80211/Makefile
|
|
@@ -126,7 +126,7 @@ define KernelPackage/mac80211
|
|
$(call KernelPackage/mac80211/Default)
|
|
TITLE:=Linux 802.11 Wireless Networking Stack
|
|
# +kmod-crypto-cmac is a runtime only dependency of net/mac80211/aes_cmac.c
|
|
- DEPENDS+= +kmod-cfg80211 +kmod-crypto-cmac +kmod-crypto-ccm +kmod-crypto-gcm +hostapd-common
|
|
+ DEPENDS+= +kmod-cfg80211 +kmod-crypto-cmac +kmod-crypto-ccm +kmod-crypto-gcm
|
|
KCONFIG:=\
|
|
CONFIG_AVERAGE=y
|
|
FILES:= $(PKG_BUILD_DIR)/net/mac80211/mac80211.ko
|
|
diff --git a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
|
|
index 818d88377e..89a9f6ae1c 100644
|
|
--- a/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
|
|
+++ b/package/kernel/mac80211/files/lib/netifd/wireless/mac80211.sh
|
|
@@ -1,6 +1,7 @@
|
|
#!/bin/sh
|
|
. /lib/netifd/netifd-wireless.sh
|
|
. /lib/netifd/hostapd.sh
|
|
+. /lib/functions/system.sh
|
|
|
|
init_wireless_driver "$@"
|
|
|
|
@@ -14,12 +15,9 @@ MP_CONFIG_INT="mesh_retry_timeout mesh_confirm_timeout mesh_holding_timeout mesh
|
|
MP_CONFIG_BOOL="mesh_auto_open_plinks mesh_fwding"
|
|
MP_CONFIG_STRING="mesh_power_mode"
|
|
|
|
-NEWAPLIST=
|
|
-OLDAPLIST=
|
|
-NEWSPLIST=
|
|
-OLDSPLIST=
|
|
-NEWUMLIST=
|
|
-OLDUMLIST=
|
|
+wdev_tool() {
|
|
+ ucode /usr/share/hostap/wdev.uc "$@"
|
|
+}
|
|
|
|
drv_mac80211_init_device_config() {
|
|
hostapd_common_add_device_config
|
|
@@ -28,9 +26,9 @@ drv_mac80211_init_device_config() {
|
|
config_add_string tx_burst
|
|
config_add_string distance
|
|
config_add_int beacon_int chanbw frag rts
|
|
- config_add_int rxantenna txantenna antenna_gain txpower
|
|
+ config_add_int rxantenna txantenna antenna_gain txpower min_tx_power
|
|
config_add_int num_global_macaddr
|
|
- config_add_boolean noscan ht_coex acs_exclude_dfs
|
|
+ config_add_boolean noscan ht_coex acs_exclude_dfs background_radar
|
|
config_add_array ht_capab
|
|
config_add_array channels
|
|
config_add_array scan_list
|
|
@@ -51,6 +49,8 @@ drv_mac80211_init_device_config() {
|
|
rx_antenna_pattern \
|
|
tx_antenna_pattern \
|
|
he_spr_sr_control \
|
|
+ he_spr_psr_enabled \
|
|
+ he_bss_color_enabled \
|
|
he_twt_required
|
|
config_add_int \
|
|
beamformer_antennas \
|
|
@@ -138,13 +138,15 @@ mac80211_hostapd_setup_base() {
|
|
[ -n "$acs_exclude_dfs" ] && [ "$acs_exclude_dfs" -gt 0 ] &&
|
|
append base_cfg "acs_exclude_dfs=1" "$N"
|
|
|
|
- json_get_vars noscan ht_coex
|
|
- json_get_values ht_capab_list ht_capab tx_burst
|
|
+ json_get_vars noscan ht_coex min_tx_power:0 tx_burst
|
|
+ json_get_values ht_capab_list ht_capab
|
|
json_get_values channel_list channels
|
|
|
|
[ "$auto_channel" = 0 ] && [ -z "$channel_list" ] && \
|
|
channel_list="$channel"
|
|
|
|
+ [ "$min_tx_power" -gt 0 ] && append base_cfg "min_tx_power=$min_tx_power"
|
|
+
|
|
set_default noscan 0
|
|
|
|
[ "$noscan" -gt 0 ] && hostapd_noscan=1
|
|
@@ -274,6 +276,11 @@ mac80211_hostapd_setup_base() {
|
|
vht_center_seg0=$idx
|
|
;;
|
|
esac
|
|
+ [ "$band" = "5g" ] && {
|
|
+ json_get_vars background_radar:0
|
|
+
|
|
+ [ "$background_radar" -eq 1 ] && append base_cfg "enable_background_radar=1" "$N"
|
|
+ }
|
|
[ "$band" = "6g" ] && {
|
|
op_class=
|
|
case "$htmode" in
|
|
@@ -314,7 +321,7 @@ mac80211_hostapd_setup_base() {
|
|
done
|
|
|
|
append base_cfg "vht_oper_chwidth=$vht_oper_chwidth" "$N"
|
|
- [ "$auto_channel" -gt 0 ] || append base_cfg "vht_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
|
|
+ append base_cfg "vht_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
|
|
|
|
cap_rx_stbc=$((($vht_cap >> 8) & 7))
|
|
[ "$rx_stbc" -lt "$cap_rx_stbc" ] && cap_rx_stbc="$rx_stbc"
|
|
@@ -407,33 +414,45 @@ mac80211_hostapd_setup_base() {
|
|
if [ "$enable_ax" != "0" ]; then
|
|
json_get_vars \
|
|
he_su_beamformer:1 \
|
|
- he_su_beamformee:0 \
|
|
+ he_su_beamformee:1 \
|
|
he_mu_beamformer:1 \
|
|
he_twt_required:0 \
|
|
- he_spr_sr_control:0 \
|
|
- he_spr_non_srg_obss_pd_max_offset:1 \
|
|
- he_bss_color
|
|
+ he_spr_sr_control:3 \
|
|
+ he_spr_psr_enabled:0 \
|
|
+ he_spr_non_srg_obss_pd_max_offset:0 \
|
|
+ he_bss_color:128 \
|
|
+ he_bss_color_enabled:1
|
|
|
|
- he_phy_cap=$(iw phy "$phy" info | awk -F "[()]" '/HE PHY Capabilities/ { print $2 }' | head -1)
|
|
+ he_phy_cap=$(iw phy "$phy" info | sed -n '/HE Iftypes: AP/,$p' | awk -F "[()]" '/HE PHY Capabilities/ { print $2 }' | head -1)
|
|
he_phy_cap=${he_phy_cap:2}
|
|
- he_mac_cap=$(iw phy "$phy" info | awk -F "[()]" '/HE MAC Capabilities/ { print $2 }' | head -1)
|
|
+ he_mac_cap=$(iw phy "$phy" info | sed -n '/HE Iftypes: AP/,$p' | awk -F "[()]" '/HE MAC Capabilities/ { print $2 }' | head -1)
|
|
he_mac_cap=${he_mac_cap:2}
|
|
|
|
append base_cfg "ieee80211ax=1" "$N"
|
|
- [ -n "$he_bss_color" ] && append base_cfg "he_bss_color=$he_bss_color" "$N"
|
|
[ "$hwmode" = "a" ] && {
|
|
append base_cfg "he_oper_chwidth=$vht_oper_chwidth" "$N"
|
|
- [ "$auto_channel" -gt 0 ] || append base_cfg "he_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
|
|
+ append base_cfg "he_oper_centr_freq_seg0_idx=$vht_center_seg0" "$N"
|
|
}
|
|
|
|
mac80211_add_he_capabilities \
|
|
he_su_beamformer:${he_phy_cap:6:2}:0x80:$he_su_beamformer \
|
|
he_su_beamformee:${he_phy_cap:8:2}:0x1:$he_su_beamformee \
|
|
he_mu_beamformer:${he_phy_cap:8:2}:0x2:$he_mu_beamformer \
|
|
- he_spr_sr_control:${he_phy_cap:14:2}:0x1:$he_spr_sr_control \
|
|
+ he_spr_psr_enabled:${he_phy_cap:14:2}:0x1:$he_spr_psr_enabled \
|
|
he_twt_required:${he_mac_cap:0:2}:0x6:$he_twt_required
|
|
|
|
- [ "$he_spr_sr_control" -gt 0 ] && append base_cfg "he_spr_non_srg_obss_pd_max_offset=$he_spr_non_srg_obss_pd_max_offset" "$N"
|
|
+ if [ "$he_bss_color_enabled" -gt 0 ]; then
|
|
+ append base_cfg "he_bss_color=$he_bss_color" "$N"
|
|
+ [ "$he_spr_non_srg_obss_pd_max_offset" -gt 0 ] && { \
|
|
+ append base_cfg "he_spr_non_srg_obss_pd_max_offset=$he_spr_non_srg_obss_pd_max_offset" "$N"
|
|
+ he_spr_sr_control=$((he_spr_sr_control | (1 << 2)))
|
|
+ }
|
|
+ [ "$he_spr_psr_enabled" -gt 0 ] || he_spr_sr_control=$((he_spr_sr_control | (1 << 0)))
|
|
+ append base_cfg "he_spr_sr_control=$he_spr_sr_control" "$N"
|
|
+ else
|
|
+ append base_cfg "he_bss_color_disabled=1" "$N"
|
|
+ fi
|
|
+
|
|
|
|
append base_cfg "he_default_pe_duration=4" "$N"
|
|
append base_cfg "he_rts_threshold=1023" "$N"
|
|
@@ -568,15 +587,77 @@ mac80211_generate_mac() {
|
|
$(( (0x$6 + $id) % 0x100 ))
|
|
}
|
|
|
|
+get_board_phy_name() (
|
|
+ local path="$1"
|
|
+ local fallback_phy=""
|
|
+
|
|
+ __check_phy() {
|
|
+ local val="$1"
|
|
+ local key="$2"
|
|
+ local ref_path="$3"
|
|
+
|
|
+ json_select "$key"
|
|
+ json_get_values path
|
|
+ json_select ..
|
|
+
|
|
+ [ "${ref_path%+*}" = "$path" ] && fallback_phy=$key
|
|
+ [ "$ref_path" = "$path" ] || return 0
|
|
+
|
|
+ echo "$key"
|
|
+ exit
|
|
+ }
|
|
+
|
|
+ json_load_file /etc/board.json
|
|
+ json_for_each_item __check_phy wlan "$path"
|
|
+ [ -n "$fallback_phy" ] && echo "${fallback_phy}.${path##*+}"
|
|
+)
|
|
+
|
|
+rename_board_phy_by_path() {
|
|
+ local path="$1"
|
|
+
|
|
+ local new_phy="$(get_board_phy_name "$path")"
|
|
+ [ -z "$new_phy" -o "$new_phy" = "$phy" ] && return
|
|
+
|
|
+ iw "$phy" set name "$new_phy" && phy="$new_phy"
|
|
+}
|
|
+
|
|
+rename_board_phy_by_name() (
|
|
+ local phy="$1"
|
|
+ local suffix="${phy##*.}"
|
|
+ [ "$suffix" = "$phy" ] && suffix=
|
|
+
|
|
+ json_load_file /etc/board.json
|
|
+ json_select wlan
|
|
+ json_select "${phy%.*}" || return 0
|
|
+ json_get_values path
|
|
+
|
|
+ prev_phy="$(iwinfo nl80211 phyname "path=$path${suffix:++$suffix}")"
|
|
+ [ -n "$prev_phy" ] || return 0
|
|
+
|
|
+ [ "$prev_phy" = "$phy" ] && return 0
|
|
+
|
|
+ iw "$prev_phy" set name "$phy"
|
|
+)
|
|
+
|
|
find_phy() {
|
|
- [ -n "$phy" -a -d /sys/class/ieee80211/$phy ] && return 0
|
|
+ [ -n "$phy" ] && {
|
|
+ rename_board_phy_by_name "$phy"
|
|
+ [ -d /sys/class/ieee80211/$phy ] && return 0
|
|
+ }
|
|
[ -n "$path" ] && {
|
|
phy="$(iwinfo nl80211 phyname "path=$path")"
|
|
- [ -n "$phy" ] && return 0
|
|
+ [ -n "$phy" ] && {
|
|
+ rename_board_phy_by_path "$path"
|
|
+ return 0
|
|
+ }
|
|
}
|
|
[ -n "$macaddr" ] && {
|
|
for phy in $(ls /sys/class/ieee80211 2>/dev/null); do
|
|
- grep -i -q "$macaddr" "/sys/class/ieee80211/${phy}/macaddress" && return 0
|
|
+ grep -i -q "$macaddr" "/sys/class/ieee80211/${phy}/macaddress" && {
|
|
+ path="$(iwinfo nl80211 path "$phy")"
|
|
+ rename_board_phy_by_path "$path"
|
|
+ return 0
|
|
+ }
|
|
done
|
|
}
|
|
return 1
|
|
@@ -586,72 +667,10 @@ mac80211_check_ap() {
|
|
has_ap=1
|
|
}
|
|
|
|
-mac80211_iw_interface_add() {
|
|
+mac80211_set_ifname() {
|
|
local phy="$1"
|
|
- local ifname="$2"
|
|
- local type="$3"
|
|
- local wdsflag="$4"
|
|
- local rc
|
|
- local oldifname
|
|
-
|
|
- iw phy "$phy" interface add "$ifname" type "$type" $wdsflag >/dev/null 2>&1
|
|
- rc="$?"
|
|
-
|
|
- [ "$rc" = 233 ] && {
|
|
- # Device might have just been deleted, give the kernel some time to finish cleaning it up
|
|
- sleep 1
|
|
-
|
|
- iw phy "$phy" interface add "$ifname" type "$type" $wdsflag >/dev/null 2>&1
|
|
- rc="$?"
|
|
- }
|
|
-
|
|
- [ "$rc" = 233 ] && {
|
|
- # Keep matching pre-existing interface
|
|
- [ -d "/sys/class/ieee80211/${phy}/device/net/${ifname}" ] && \
|
|
- case "$(iw dev $ifname info | grep "^\ttype" | cut -d' ' -f2- 2>/dev/null)" in
|
|
- "AP")
|
|
- [ "$type" = "__ap" ] && rc=0
|
|
- ;;
|
|
- "IBSS")
|
|
- [ "$type" = "adhoc" ] && rc=0
|
|
- ;;
|
|
- "managed")
|
|
- [ "$type" = "managed" ] && rc=0
|
|
- ;;
|
|
- "mesh point")
|
|
- [ "$type" = "mp" ] && rc=0
|
|
- ;;
|
|
- "monitor")
|
|
- [ "$type" = "monitor" ] && rc=0
|
|
- ;;
|
|
- esac
|
|
- }
|
|
-
|
|
- [ "$rc" = 233 ] && {
|
|
- iw dev "$ifname" del >/dev/null 2>&1
|
|
- [ "$?" = 0 ] && {
|
|
- sleep 1
|
|
-
|
|
- iw phy "$phy" interface add "$ifname" type "$type" $wdsflag >/dev/null 2>&1
|
|
- rc="$?"
|
|
- }
|
|
- }
|
|
-
|
|
- [ "$rc" != 0 ] && {
|
|
- # Device might not support virtual interfaces, so the interface never got deleted in the first place.
|
|
- # Check if the interface already exists, and avoid failing in this case.
|
|
- [ -d "/sys/class/ieee80211/${phy}/device/net/${ifname}" ] && rc=0
|
|
- }
|
|
-
|
|
- [ "$rc" != 0 ] && {
|
|
- # Device doesn't support virtual interfaces and may have existing interface other than ifname.
|
|
- oldifname="$(basename "/sys/class/ieee80211/${phy}/device/net"/* 2>/dev/null)"
|
|
- [ "$oldifname" ] && ip link set "$oldifname" name "$ifname" 1>/dev/null 2>&1
|
|
- rc="$?"
|
|
- }
|
|
-
|
|
- [ "$rc" != 0 ] && echo "Failed to create interface $ifname"
|
|
- return $rc
|
|
+ local prefix="$2"
|
|
+ eval "ifname=\"$phy-$prefix\${idx_$prefix:-0}\"; idx_$prefix=\$((\${idx_$prefix:-0 } + 1))"
|
|
}
|
|
|
|
mac80211_prepare_vif() {
|
|
@@ -660,22 +679,33 @@ mac80211_prepare_vif() {
|
|
|
|
json_get_vars ifname mode ssid wds powersave macaddr enable wpa_psk_file vlan_file
|
|
|
|
- [ -n "$ifname" ] || ifname="wlan${phy#phy}${if_idx:+-$if_idx}"
|
|
- if_idx=$((${if_idx:-0} + 1))
|
|
+ [ -n "$ifname" ] || {
|
|
+ local prefix;
|
|
+
|
|
+ case "$mode" in
|
|
+ ap|sta|mesh) prefix=$mode;;
|
|
+ adhoc) prefix=ibss;;
|
|
+ monitor) prefix=mon;;
|
|
+ esac
|
|
|
|
+ mac80211_set_ifname "$phy" "$prefix"
|
|
+ }
|
|
+
|
|
+ append active_ifnames "$ifname"
|
|
set_default wds 0
|
|
set_default powersave 0
|
|
+ json_add_string _ifname "$ifname"
|
|
|
|
- json_select ..
|
|
-
|
|
- [ -n "$macaddr" ] || {
|
|
+ [ -n "$ap" ] || multiple_bssid=0
|
|
+ if [ -z "$macaddr" ]; then
|
|
macaddr="$(mac80211_generate_mac $phy $multiple_bssid)"
|
|
macidx="$(($macidx + 1))"
|
|
- }
|
|
+ elif [ "$macaddr" = 'random' ]; then
|
|
+ macaddr="$(macaddr_random)"
|
|
+ fi
|
|
+ json_add_string _macaddr "$macaddr"
|
|
+ json_select ..
|
|
|
|
- json_add_object data
|
|
- json_add_string ifname "$ifname"
|
|
- json_close_object
|
|
|
|
[ "$mode" == "ap" ] && {
|
|
[ -z "$wpa_psk_file" ] && hostapd_set_psk "$ifname"
|
|
@@ -686,9 +716,6 @@ mac80211_prepare_vif() {
|
|
|
|
# It is far easier to delete and create the desired interface
|
|
case "$mode" in
|
|
- adhoc)
|
|
- mac80211_iw_interface_add "$phy" "$ifname" adhoc || return
|
|
- ;;
|
|
ap)
|
|
# Hostapd will handle recreating the interface and
|
|
# subsequent virtual APs belonging to the same PHY
|
|
@@ -700,118 +727,20 @@ mac80211_prepare_vif() {
|
|
|
|
mac80211_hostapd_setup_bss "$phy" "$ifname" "$macaddr" "$type" || return
|
|
|
|
- NEWAPLIST="${NEWAPLIST}$ifname "
|
|
[ -n "$hostapd_ctrl" ] || {
|
|
ap_ifname="${ifname}"
|
|
hostapd_ctrl="${hostapd_ctrl:-/var/run/hostapd/$ifname}"
|
|
}
|
|
;;
|
|
- mesh)
|
|
- mac80211_iw_interface_add "$phy" "$ifname" mp || return
|
|
- ;;
|
|
- monitor)
|
|
- mac80211_iw_interface_add "$phy" "$ifname" monitor || return
|
|
- ;;
|
|
- sta)
|
|
- local wdsflag=
|
|
- [ "$enable" = 0 ] || staidx="$(($staidx + 1))"
|
|
- [ "$wds" -gt 0 ] && wdsflag="4addr on"
|
|
- mac80211_iw_interface_add "$phy" "$ifname" managed "$wdsflag" || return
|
|
- if [ "$wds" -gt 0 ]; then
|
|
- iw "$ifname" set 4addr on
|
|
- else
|
|
- iw "$ifname" set 4addr off
|
|
- fi
|
|
- [ "$powersave" -gt 0 ] && powersave="on" || powersave="off"
|
|
- iw "$ifname" set power_save "$powersave"
|
|
- ;;
|
|
esac
|
|
|
|
- case "$mode" in
|
|
- monitor|mesh)
|
|
- [ "$auto_channel" -gt 0 ] || iw dev "$ifname" set channel "$channel" $iw_htmode
|
|
- ;;
|
|
- esac
|
|
-
|
|
- if [ "$mode" != "ap" ]; then
|
|
- # ALL ap functionality will be passed to hostapd
|
|
- # All interfaces must have unique mac addresses
|
|
- # which can either be explicitly set in the device
|
|
- # section, or automatically generated
|
|
- ip link set dev "$ifname" address "$macaddr"
|
|
- fi
|
|
-
|
|
json_select ..
|
|
}
|
|
|
|
-mac80211_setup_supplicant() {
|
|
- local enable=$1
|
|
- local add_sp=0
|
|
- local spobj="$(ubus -S list | grep wpa_supplicant.${ifname})"
|
|
-
|
|
- [ "$enable" = 0 ] && {
|
|
- ubus call wpa_supplicant.${phy} config_remove "{\"iface\":\"$ifname\"}"
|
|
- ip link set dev "$ifname" down
|
|
- iw dev "$ifname" del
|
|
- return 0
|
|
- }
|
|
-
|
|
- wpa_supplicant_prepare_interface "$ifname" nl80211 || {
|
|
- iw dev "$ifname" del
|
|
- return 1
|
|
- }
|
|
- if [ "$mode" = "sta" ]; then
|
|
- wpa_supplicant_add_network "$ifname"
|
|
- else
|
|
- wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan"
|
|
- fi
|
|
-
|
|
- NEWSPLIST="${NEWSPLIST}$ifname "
|
|
-
|
|
- if [ "${NEWAPLIST%% *}" != "${OLDAPLIST%% *}" ]; then
|
|
- [ "$spobj" ] && ubus call wpa_supplicant config_remove "{\"iface\":\"$ifname\"}"
|
|
- add_sp=1
|
|
- fi
|
|
- [ -z "$spobj" ] && add_sp=1
|
|
-
|
|
- NEW_MD5_SP=$(test -e "${_config}" && md5sum ${_config})
|
|
- OLD_MD5_SP=$(uci -q -P /var/state get wireless._${phy}.md5_${ifname})
|
|
- if [ "$add_sp" = "1" ]; then
|
|
- wpa_supplicant_run "$ifname" "$hostapd_ctrl"
|
|
- else
|
|
- [ "${NEW_MD5_SP}" == "${OLD_MD5_SP}" ] || ubus call $spobj reload
|
|
- fi
|
|
- uci -q -P /var/state set wireless._${phy}.md5_${ifname}="${NEW_MD5_SP}"
|
|
- return 0
|
|
-}
|
|
-
|
|
-mac80211_setup_supplicant_noctl() {
|
|
- local enable=$1
|
|
- local spobj="$(ubus -S list | grep wpa_supplicant.${ifname})"
|
|
- wpa_supplicant_prepare_interface "$ifname" nl80211 || {
|
|
- iw dev "$ifname" del
|
|
- return 1
|
|
- }
|
|
-
|
|
- wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan"
|
|
-
|
|
- NEWSPLIST="${NEWSPLIST}$ifname "
|
|
- [ "$enable" = 0 ] && {
|
|
- ubus call wpa_supplicant config_remove "{\"iface\":\"$ifname\"}"
|
|
- ip link set dev "$ifname" down
|
|
- return 0
|
|
- }
|
|
- if [ -z "$spobj" ]; then
|
|
- wpa_supplicant_run "$ifname"
|
|
- else
|
|
- ubus call $spobj reload
|
|
- fi
|
|
-}
|
|
-
|
|
mac80211_prepare_iw_htmode() {
|
|
case "$htmode" in
|
|
- VHT20|HT20) iw_htmode=HT20;;
|
|
- HT40*|VHT40|VHT160)
|
|
+ VHT20|HT20|HE20) iw_htmode=HT20;;
|
|
+ HT40*|VHT40|VHT160|HE40)
|
|
case "$band" in
|
|
2g)
|
|
case "$htmode" in
|
|
@@ -835,7 +764,7 @@ mac80211_prepare_iw_htmode() {
|
|
esac
|
|
[ "$auto_channel" -gt 0 ] && iw_htmode="HT40+"
|
|
;;
|
|
- VHT80)
|
|
+ VHT80|HE80)
|
|
iw_htmode="80MHZ"
|
|
;;
|
|
NONE|NOHT)
|
|
@@ -845,6 +774,13 @@ mac80211_prepare_iw_htmode() {
|
|
esac
|
|
}
|
|
|
|
+mac80211_add_mesh_params() {
|
|
+ for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do
|
|
+ eval "mp_val=\"\$var\""
|
|
+ [ -n "$mp_val" ] && json_add_string "$var" "$mp_val"
|
|
+ done
|
|
+}
|
|
+
|
|
mac80211_setup_adhoc() {
|
|
local enable=$1
|
|
json_get_vars bssid ssid key mcast_rate
|
|
@@ -886,82 +822,216 @@ mac80211_setup_adhoc() {
|
|
mcval=
|
|
[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
|
|
|
|
- iw dev "$ifname" set type ibss
|
|
- iw dev "$ifname" ibss join "$ssid" $freq $iw_htmode fixed-freq $bssid \
|
|
- beacon-interval $beacon_int \
|
|
- ${brstr:+basic-rates $brstr} \
|
|
- ${mcval:+mcast-rate $mcval} \
|
|
- ${keyspec:+keys $keyspec}
|
|
+ local prev
|
|
+ json_set_namespace wdev_uc prev
|
|
+
|
|
+ json_add_object "$ifname"
|
|
+ json_add_string mode adhoc
|
|
+ json_add_string macaddr "$macaddr"
|
|
+ json_add_string ssid "$ssid"
|
|
+ json_add_string freq "$freq"
|
|
+ json_add_string htmode "$iw_htmode"
|
|
+ [ -n "$bssid" ] && json_add_string bssid "$bssid"
|
|
+ json_add_int beacon-interval "$beacon_int"
|
|
+ [ -n "$brstr" ] && json_add_string basic-rates "$brstr"
|
|
+ [ -n "$mcval" ] && json_add_string mcast-rate "$mcval"
|
|
+ [ -n "$keyspec" ] && json_add_string keys "$keyspec"
|
|
+ json_close_object
|
|
+
|
|
+ json_set_namespace "$prev"
|
|
}
|
|
|
|
mac80211_setup_mesh() {
|
|
- local enable=$1
|
|
json_get_vars ssid mesh_id mcast_rate
|
|
|
|
- NEWUMLIST="${NEWUMLIST}$ifname "
|
|
-
|
|
- [ "$enable" = 0 ] && {
|
|
- ip link set dev "$ifname" down
|
|
- return 0
|
|
- }
|
|
-
|
|
mcval=
|
|
[ -n "$mcast_rate" ] && wpa_supplicant_add_rate mcval "$mcast_rate"
|
|
[ -n "$mesh_id" ] && ssid="$mesh_id"
|
|
|
|
- iw dev "$ifname" mesh join "$ssid" freq $freq $iw_htmode \
|
|
- ${mcval:+mcast-rate $mcval} \
|
|
- beacon-interval $beacon_int
|
|
+ local prev
|
|
+ json_set_namespace wdev_uc prev
|
|
+
|
|
+ json_add_object "$ifname"
|
|
+ json_add_string mode mesh
|
|
+ json_add_string macaddr "$macaddr"
|
|
+ json_add_string ssid "$ssid"
|
|
+ json_add_string freq "$freq"
|
|
+ json_add_string htmode "$iw_htmode"
|
|
+ [ -n "$mcval" ] && json_add_string mcast-rate "$mcval"
|
|
+ json_add_int beacon-interval "$beacon_int"
|
|
+ mac80211_add_mesh_params
|
|
+
|
|
+ json_close_object
|
|
+
|
|
+ json_set_namespace "$prev"
|
|
}
|
|
|
|
-mac80211_setup_vif() {
|
|
+mac80211_setup_monitor() {
|
|
+ local prev
|
|
+ json_set_namespace wdev_uc prev
|
|
+
|
|
+ json_add_object "$ifname"
|
|
+ json_add_string mode monitor
|
|
+ [ -n "$freq" ] && json_add_string freq "$freq"
|
|
+ json_add_string htmode "$iw_htmode"
|
|
+ json_close_object
|
|
+
|
|
+ json_set_namespace "$prev"
|
|
+}
|
|
+
|
|
+mac80211_set_vif_txpower() {
|
|
local name="$1"
|
|
- local failed
|
|
- local action=up
|
|
|
|
- json_select data
|
|
- json_get_vars ifname
|
|
+ json_select config
|
|
+ json_get_var ifname _ifname
|
|
+ json_get_vars vif_txpower
|
|
json_select ..
|
|
|
|
- json_select config
|
|
- json_get_vars mode
|
|
- json_get_var vif_txpower
|
|
- json_get_var vif_enable enable 1
|
|
-
|
|
- [ "$vif_enable" = 1 ] || action=down
|
|
- if [ "$mode" != "ap" ] || [ "$ifname" = "$ap_ifname" ]; then
|
|
- ip link set dev "$ifname" "$action" || {
|
|
- wireless_setup_vif_failed IFUP_ERROR
|
|
- json_select ..
|
|
- return
|
|
- }
|
|
- [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00"
|
|
+ [ -z "$vif_txpower" ] || iw dev "$ifname" set txpower fixed "${vif_txpower%%.*}00"
|
|
+}
|
|
+
|
|
+wpa_supplicant_init_config() {
|
|
+ json_set_namespace wpa_supp prev
|
|
+
|
|
+ json_init
|
|
+ json_add_array config
|
|
+
|
|
+ json_set_namespace "$prev"
|
|
+}
|
|
+
|
|
+wpa_supplicant_add_interface() {
|
|
+ local ifname="$1"
|
|
+ local mode="$2"
|
|
+ local hostapd_ctrl="$3"
|
|
+ local prev
|
|
+
|
|
+ _wpa_supplicant_common "$ifname"
|
|
+
|
|
+ json_set_namespace wpa_supp prev
|
|
+
|
|
+ json_add_object
|
|
+ json_add_string ctrl "$_rpath"
|
|
+ json_add_string iface "$ifname"
|
|
+ json_add_string mode "$mode"
|
|
+ json_add_string config "$_config"
|
|
+ json_add_string macaddr "$macaddr"
|
|
+ [ -n "$network_bridge" ] && json_add_string bridge "$network_bridge"
|
|
+ [ -n "$hostapd_ctrl" ] && json_add_string hostapd_ctrl "$hostapd_ctrl"
|
|
+ [ -n "$wds" ] && json_add_boolean 4addr "$wds"
|
|
+ json_add_boolean powersave "$powersave"
|
|
+ [ "$mode" = "mesh" ] && mac80211_add_mesh_params
|
|
+ json_close_object
|
|
+
|
|
+ json_set_namespace "$prev"
|
|
+
|
|
+ wpa_supp_init=1
|
|
+}
|
|
+
|
|
+wpa_supplicant_set_config() {
|
|
+ local phy="$1"
|
|
+ local prev
|
|
+
|
|
+ json_set_namespace wpa_supp prev
|
|
+ json_close_array
|
|
+ json_add_string phy "$phy"
|
|
+ json_add_boolean defer 1
|
|
+ local data="$(json_dump)"
|
|
+
|
|
+ json_cleanup
|
|
+ json_set_namespace "$prev"
|
|
+
|
|
+ ubus -S -t 0 wait_for wpa_supplicant || {
|
|
+ [ -n "$wpa_supp_init" ] || return 0
|
|
+
|
|
+ ubus wait_for wpa_supplicant
|
|
+ }
|
|
+
|
|
+ local supplicant_res="$(ubus call wpa_supplicant config_set "$data")"
|
|
+ ret="$?"
|
|
+ [ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED
|
|
+
|
|
+ wireless_add_process "$(jsonfilter -s "$supplicant_res" -l 1 -e @.pid)" "/usr/sbin/wpa_supplicant" 1 1
|
|
+
|
|
+}
|
|
+
|
|
+hostapd_set_config() {
|
|
+ [ -n "$hostapd_ctrl" ] || {
|
|
+ ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"${hostapd_conf_file}.prev"'" }' > /dev/null
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ ubus wait_for hostapd
|
|
+ local hostapd_res="$(ubus call hostapd config_set "{ \"phy\": \"$phy\", \"config\":\"${hostapd_conf_file}\", \"prev_config\": \"${hostapd_conf_file}.prev\"}")"
|
|
+ ret="$?"
|
|
+ [ "$ret" != 0 -o -z "$hostapd_res" ] && {
|
|
+ wireless_setup_failed HOSTAPD_START_FAILED
|
|
+ return
|
|
+ }
|
|
+ wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1
|
|
+}
|
|
+
|
|
+
|
|
+wpa_supplicant_start() {
|
|
+ local phy="$1"
|
|
+
|
|
+ [ -n "$wpa_supp_init" ] || return 0
|
|
+
|
|
+ ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'" }' > /dev/null
|
|
+}
|
|
+
|
|
+mac80211_setup_supplicant() {
|
|
+ local enable=$1
|
|
+ local add_sp=0
|
|
+
|
|
+ wpa_supplicant_prepare_interface "$ifname" nl80211 || return 1
|
|
+
|
|
+ if [ "$mode" = "sta" ]; then
|
|
+ wpa_supplicant_add_network "$ifname"
|
|
+ else
|
|
+ wpa_supplicant_add_network "$ifname" "$freq" "$htmode" "$noscan"
|
|
fi
|
|
|
|
+ wpa_supplicant_add_interface "$ifname" "$mode" "$hostapd_ctrl"
|
|
+
|
|
+ return 0
|
|
+}
|
|
+
|
|
+mac80211_setup_vif() {
|
|
+ local name="$1"
|
|
+ local failed
|
|
+
|
|
+ json_select config
|
|
+ json_get_var ifname _ifname
|
|
+ json_get_var macaddr _macaddr
|
|
+ json_get_vars mode wds powersave
|
|
+
|
|
+ set_default powersave 0
|
|
+ set_default wds 0
|
|
+
|
|
case "$mode" in
|
|
mesh)
|
|
+ json_get_vars $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING
|
|
wireless_vif_parse_encryption
|
|
[ -z "$htmode" ] && htmode="NOHT";
|
|
- if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ] || chan_is_dfs "$phy" "$channel"; then
|
|
- mac80211_setup_supplicant $vif_enable || failed=1
|
|
+ if wpa_supplicant -vmesh; then
|
|
+ mac80211_setup_supplicant || failed=1
|
|
else
|
|
- mac80211_setup_mesh $vif_enable
|
|
+ mac80211_setup_mesh
|
|
fi
|
|
- for var in $MP_CONFIG_INT $MP_CONFIG_BOOL $MP_CONFIG_STRING; do
|
|
- json_get_var mp_val "$var"
|
|
- [ -n "$mp_val" ] && iw dev "$ifname" set mesh_param "$var" "$mp_val"
|
|
- done
|
|
;;
|
|
adhoc)
|
|
wireless_vif_parse_encryption
|
|
if [ "$wpa" -gt 0 -o "$auto_channel" -gt 0 ]; then
|
|
- mac80211_setup_supplicant_noctl $vif_enable || failed=1
|
|
+ mac80211_setup_supplicant || failed=1
|
|
else
|
|
- mac80211_setup_adhoc $vif_enable
|
|
+ mac80211_setup_adhoc
|
|
fi
|
|
;;
|
|
sta)
|
|
- mac80211_setup_supplicant $vif_enable || failed=1
|
|
+ mac80211_setup_supplicant || failed=1
|
|
+ ;;
|
|
+ monitor)
|
|
+ mac80211_setup_monitor
|
|
;;
|
|
esac
|
|
|
|
@@ -994,7 +1064,6 @@ band_match && $3 == "MHz" && $4 == channel {
|
|
'
|
|
}
|
|
|
|
-
|
|
chan_is_dfs() {
|
|
local phy="$1"
|
|
local chan="$2"
|
|
@@ -1002,27 +1071,6 @@ chan_is_dfs() {
|
|
return $!
|
|
}
|
|
|
|
-mac80211_vap_cleanup() {
|
|
- local service="$1"
|
|
- local vaps="$2"
|
|
-
|
|
- for wdev in $vaps; do
|
|
- [ "$service" != "none" ] && ubus call ${service} config_remove "{\"iface\":\"$wdev\"}"
|
|
- ip link set dev "$wdev" down 2>/dev/null
|
|
- iw dev "$wdev" del
|
|
- done
|
|
-}
|
|
-
|
|
-mac80211_interface_cleanup() {
|
|
- local phy="$1"
|
|
- local primary_ap=$(uci -q -P /var/state get wireless._${phy}.aplist)
|
|
- primary_ap=${primary_ap%% *}
|
|
-
|
|
- mac80211_vap_cleanup hostapd "${primary_ap}"
|
|
- mac80211_vap_cleanup wpa_supplicant "$(uci -q -P /var/state get wireless._${phy}.splist)"
|
|
- mac80211_vap_cleanup none "$(uci -q -P /var/state get wireless._${phy}.umlist)"
|
|
-}
|
|
-
|
|
mac80211_set_noscan() {
|
|
hostapd_noscan=1
|
|
}
|
|
@@ -1031,6 +1079,15 @@ drv_mac80211_cleanup() {
|
|
hostapd_common_cleanup
|
|
}
|
|
|
|
+mac80211_reset_config() {
|
|
+ local phy="$1"
|
|
+
|
|
+ hostapd_conf_file="/var/run/hostapd-$phy.conf"
|
|
+ ubus call hostapd config_set '{ "phy": "'"$phy"'", "config": "", "prev_config": "'"$hostapd_conf_file"'" }' > /dev/null
|
|
+ ubus call wpa_supplicant config_set '{ "phy": "'"$phy"'", "config": [] }' > /dev/null
|
|
+ wdev_tool "$phy" '{}'
|
|
+}
|
|
+
|
|
drv_mac80211_setup() {
|
|
json_select config
|
|
json_get_vars \
|
|
@@ -1052,30 +1109,11 @@ drv_mac80211_setup() {
|
|
}
|
|
|
|
wireless_set_data phy="$phy"
|
|
- [ -z "$(uci -q -P /var/state show wireless._${phy})" ] && uci -q -P /var/state set wireless._${phy}=phy
|
|
-
|
|
- OLDAPLIST=$(uci -q -P /var/state get wireless._${phy}.aplist)
|
|
- OLDSPLIST=$(uci -q -P /var/state get wireless._${phy}.splist)
|
|
- OLDUMLIST=$(uci -q -P /var/state get wireless._${phy}.umlist)
|
|
|
|
local wdev
|
|
local cwdev
|
|
local found
|
|
|
|
- for wdev in $(list_phy_interfaces "$phy"); do
|
|
- found=0
|
|
- for cwdev in $OLDAPLIST $OLDSPLIST $OLDUMLIST; do
|
|
- if [ "$wdev" = "$cwdev" ]; then
|
|
- found=1
|
|
- break
|
|
- fi
|
|
- done
|
|
- if [ "$found" = "0" ]; then
|
|
- ip link set dev "$wdev" down
|
|
- iw dev "$wdev" del
|
|
- fi
|
|
- done
|
|
-
|
|
# convert channel to frequency
|
|
[ "$auto_channel" -gt 0 ] || freq="$(get_freq "$phy" "$channel" "$band")"
|
|
|
|
@@ -1088,7 +1126,6 @@ drv_mac80211_setup() {
|
|
|
|
hostapd_conf_file="/var/run/hostapd-$phy.conf"
|
|
|
|
- no_ap=1
|
|
macidx=0
|
|
staidx=0
|
|
|
|
@@ -1124,78 +1161,36 @@ drv_mac80211_setup() {
|
|
hostapd_ctrl=
|
|
ap_ifname=
|
|
hostapd_noscan=
|
|
+ wpa_supp_init=
|
|
for_each_interface "ap" mac80211_check_ap
|
|
|
|
- rm -f "$hostapd_conf_file"
|
|
+ [ -f "$hostapd_conf_file" ] && mv "$hostapd_conf_file" "$hostapd_conf_file.prev"
|
|
|
|
for_each_interface "sta adhoc mesh" mac80211_set_noscan
|
|
[ -n "$has_ap" ] && mac80211_hostapd_setup_base "$phy"
|
|
|
|
- mac80211_prepare_iw_htmode
|
|
- for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif
|
|
- NEWAPLIST=
|
|
- for_each_interface "ap" mac80211_prepare_vif ${multiple_bssid}
|
|
- NEW_MD5=$(test -e "${hostapd_conf_file}" && md5sum ${hostapd_conf_file})
|
|
- OLD_MD5=$(uci -q -P /var/state get wireless._${phy}.md5)
|
|
- if [ "${NEWAPLIST}" != "${OLDAPLIST}" ]; then
|
|
- mac80211_vap_cleanup hostapd "${OLDAPLIST}"
|
|
- fi
|
|
- [ -n "${NEWAPLIST}" ] && mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap
|
|
- local add_ap=0
|
|
- local primary_ap=${NEWAPLIST%% *}
|
|
- [ -n "$hostapd_ctrl" ] && {
|
|
- local no_reload=1
|
|
- if [ -n "$(ubus list | grep hostapd.$primary_ap)" ]; then
|
|
- no_reload=0
|
|
- [ "${NEW_MD5}" = "${OLD_MD5}" ] || {
|
|
- ubus call hostapd.$primary_ap reload
|
|
- no_reload=$?
|
|
- if [ "$no_reload" != "0" ]; then
|
|
- mac80211_vap_cleanup hostapd "${OLDAPLIST}"
|
|
- mac80211_vap_cleanup wpa_supplicant "$(uci -q -P /var/state get wireless._${phy}.splist)"
|
|
- mac80211_vap_cleanup none "$(uci -q -P /var/state get wireless._${phy}.umlist)"
|
|
- sleep 2
|
|
- mac80211_iw_interface_add "$phy" "${NEWAPLIST%% *}" __ap
|
|
- for_each_interface "sta adhoc mesh monitor" mac80211_prepare_vif
|
|
- fi
|
|
- }
|
|
- fi
|
|
- if [ "$no_reload" != "0" ]; then
|
|
- add_ap=1
|
|
- ubus wait_for hostapd
|
|
- local hostapd_res="$(ubus call hostapd config_add "{\"iface\":\"$primary_ap\", \"config\":\"${hostapd_conf_file}\"}")"
|
|
- ret="$?"
|
|
- [ "$ret" != 0 -o -z "$hostapd_res" ] && {
|
|
- wireless_setup_failed HOSTAPD_START_FAILED
|
|
- return
|
|
- }
|
|
- wireless_add_process "$(jsonfilter -s "$hostapd_res" -l 1 -e @.pid)" "/usr/sbin/hostapd" 1 1
|
|
- fi
|
|
- }
|
|
- uci -q -P /var/state set wireless._${phy}.aplist="${NEWAPLIST}"
|
|
- uci -q -P /var/state set wireless._${phy}.md5="${NEW_MD5}"
|
|
+ local prev
|
|
+ json_set_namespace wdev_uc prev
|
|
+ json_init
|
|
+ json_set_namespace "$prev"
|
|
+
|
|
+ wpa_supplicant_init_config
|
|
|
|
- [ "${add_ap}" = 1 ] && sleep 1
|
|
- for_each_interface "ap" mac80211_setup_vif
|
|
+ mac80211_prepare_iw_htmode
|
|
+ active_ifnames=
|
|
+ for_each_interface "ap sta adhoc mesh monitor" mac80211_prepare_vif
|
|
+ for_each_interface "ap sta adhoc mesh monitor" mac80211_setup_vif
|
|
|
|
- NEWSPLIST=
|
|
- NEWUMLIST=
|
|
+ [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_set_config "$phy"
|
|
+ [ -x /usr/sbin/hostapd ] && hostapd_set_config "$phy"
|
|
|
|
- for_each_interface "sta adhoc mesh monitor" mac80211_setup_vif
|
|
+ [ -x /usr/sbin/wpa_supplicant ] && wpa_supplicant_start "$phy"
|
|
|
|
- uci -q -P /var/state set wireless._${phy}.splist="${NEWSPLIST}"
|
|
- uci -q -P /var/state set wireless._${phy}.umlist="${NEWUMLIST}"
|
|
+ json_set_namespace wdev_uc prev
|
|
+ wdev_tool "$phy" "$(json_dump)" $active_ifnames
|
|
+ json_set_namespace "$prev"
|
|
|
|
- local foundvap
|
|
- local dropvap=""
|
|
- for oldvap in $OLDSPLIST; do
|
|
- foundvap=0
|
|
- for newvap in $NEWSPLIST; do
|
|
- [ "$oldvap" = "$newvap" ] && foundvap=1
|
|
- done
|
|
- [ "$foundvap" = "0" ] && dropvap="$dropvap $oldvap"
|
|
- done
|
|
- [ -n "$dropvap" ] && mac80211_vap_cleanup wpa_supplicant "$dropvap"
|
|
+ for_each_interface "ap sta adhoc mesh monitor" mac80211_set_vif_txpower
|
|
wireless_set_up
|
|
}
|
|
|
|
@@ -1226,8 +1221,12 @@ drv_mac80211_teardown() {
|
|
return 1
|
|
}
|
|
|
|
- mac80211_interface_cleanup "$phy"
|
|
- uci -q -P /var/state revert wireless._${phy}
|
|
+ mac80211_reset_config "$phy"
|
|
+
|
|
+ for wdev in $(list_phy_interfaces "$phy"); do
|
|
+ ip link set dev "$wdev" down
|
|
+ iw dev "$wdev" del
|
|
+ done
|
|
}
|
|
|
|
add_driver mac80211
|
|
diff --git a/package/network/services/hostapd/Config.in b/package/network/services/hostapd/Config.in
|
|
index 5c00f3e24e..87ad7e093e 100644
|
|
--- a/package/network/services/hostapd/Config.in
|
|
+++ b/package/network/services/hostapd/Config.in
|
|
@@ -4,20 +4,25 @@ config WPA_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-wolfssl || \
|
|
+ PACKAGE_wpad-mesh-mbedtls
|
|
default n
|
|
|
|
config WPA_MSG_MIN_PRIORITY
|
|
@@ -25,20 +30,25 @@ config WPA_MSG_MIN_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-wolfssl || \
|
|
+ PACKAGE_wpad-mesh-mbedtls
|
|
default 3
|
|
help
|
|
Useful values are:
|
|
@@ -63,14 +73,6 @@ config WPA_WOLFSSL
|
|
select WOLFSSL_HAS_SESSION_TICKET
|
|
select WOLFSSL_HAS_WPAS
|
|
|
|
-config DRIVER_WEXT_SUPPORT
|
|
- bool
|
|
- default n
|
|
-
|
|
-config DRIVER_11N_SUPPORT
|
|
- bool
|
|
- default n
|
|
-
|
|
config DRIVER_11AC_SUPPORT
|
|
bool
|
|
default n
|
|
@@ -78,6 +80,7 @@ config DRIVER_11AC_SUPPORT
|
|
config DRIVER_11AX_SUPPORT
|
|
bool
|
|
default n
|
|
+ select WPA_MBO_SUPPORT
|
|
|
|
config WPA_ENABLE_WEP
|
|
bool "Enable support for unsecure and obsolete WEP"
|
|
@@ -87,3 +90,19 @@ config WPA_ENABLE_WEP
|
|
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
|
|
index 243c43551e..24077ebe87 100644
|
|
--- a/package/network/services/hostapd/Makefile
|
|
+++ b/package/network/services/hostapd/Makefile
|
|
@@ -5,13 +5,13 @@
|
|
include $(TOPDIR)/rules.mk
|
|
|
|
PKG_NAME:=hostapd
|
|
-PKG_RELEASE:=$(AUTORELEASE)
|
|
+PKG_RELEASE:=1.2
|
|
|
|
PKG_SOURCE_URL:=http://w1.fi/hostap.git
|
|
PKG_SOURCE_PROTO:=git
|
|
-PKG_SOURCE_DATE:=2022-01-16
|
|
-PKG_SOURCE_VERSION:=cff80b4f7d3c0a47c052e8187d671710f48939e4
|
|
-PKG_MIRROR_HASH:=712965bfa11a2e601d3e1c9a51a2cf3cffc6db89abafb3df3eb0cfd83c64705b
|
|
+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
|
|
@@ -27,12 +27,12 @@ PKG_CONFIG_DEPENDS:= \
|
|
CONFIG_PACKAGE_hostapd-basic \
|
|
CONFIG_PACKAGE_hostapd-mini \
|
|
CONFIG_WPA_RFKILL_SUPPORT \
|
|
- CONFIG_DRIVER_WEXT_SUPPORT \
|
|
- CONFIG_DRIVER_11N_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:=
|
|
@@ -53,14 +53,16 @@ LOCAL_AND_LIB_VARIANT=$(patsubst hostapd-%,%,\
|
|
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)
|
|
@@ -71,11 +73,6 @@ include $(INCLUDE_DIR)/package.mk
|
|
|
|
STAMP_CONFIGURED:=$(STAMP_CONFIGURED)_$(CONFIG_WPA_MSG_MIN_PRIORITY)
|
|
|
|
-
|
|
-ifneq ($(CONFIG_DRIVER_11N_SUPPORT),)
|
|
- HOSTAPD_IEEE80211N:=y
|
|
-endif
|
|
-
|
|
ifneq ($(CONFIG_DRIVER_11AC_SUPPORT),)
|
|
HOSTAPD_IEEE80211AC:=y
|
|
endif
|
|
@@ -84,13 +81,15 @@ ifneq ($(CONFIG_DRIVER_11AX_SUPPORT),)
|
|
HOSTAPD_IEEE80211AX:=y
|
|
endif
|
|
|
|
+CORE_DEPENDS = +libubus +libucode +ucode-mod-fs +ucode-mod-nl80211 +ucode-mod-ubus +ucode-mod-uloop +libblobmsg-json
|
|
+
|
|
DRIVER_MAKEOPTS= \
|
|
CONFIG_ACS=$(CONFIG_PACKAGE_kmod-cfg80211) \
|
|
CONFIG_DRIVER_NL80211=$(CONFIG_PACKAGE_kmod-cfg80211) \
|
|
- CONFIG_IEEE80211N=$(HOSTAPD_IEEE80211N) \
|
|
CONFIG_IEEE80211AC=$(HOSTAPD_IEEE80211AC) \
|
|
CONFIG_IEEE80211AX=$(HOSTAPD_IEEE80211AX) \
|
|
- CONFIG_DRIVER_WEXT=$(CONFIG_DRIVER_WEXT_SUPPORT) \
|
|
+ CONFIG_MBO=$(CONFIG_WPA_MBO_SUPPORT) \
|
|
+ CONFIG_UCODE=y
|
|
|
|
ifeq ($(SSL_VARIANT),openssl)
|
|
DRIVER_MAKEOPTS += CONFIG_TLS=openssl CONFIG_SAE=y
|
|
@@ -122,17 +121,27 @@ ifeq ($(SSL_VARIANT),wolfssl)
|
|
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
|
|
|
|
-ifdef CONFIG_USE_GLIBC
|
|
- TARGET_LDFLAGS += -lrt
|
|
- TARGET_LDFLAGS_C += -lrt
|
|
-endif
|
|
-
|
|
DRV_DEPENDS:=+PACKAGE_kmod-cfg80211:libnl-tiny
|
|
|
|
|
|
@@ -142,7 +151,7 @@ define Package/hostapd/Default
|
|
SUBMENU:=WirelessAPD
|
|
TITLE:=IEEE 802.1x Authenticator
|
|
URL:=http://hostap.epitest.fi/
|
|
- DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus
|
|
+ DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS)
|
|
EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE))
|
|
USERID:=network=101:network=101
|
|
PROVIDES:=hostapd
|
|
@@ -165,7 +174,7 @@ define Package/hostapd-openssl
|
|
$(call Package/hostapd/Default,$(1))
|
|
TITLE+= (OpenSSL full)
|
|
VARIANT:=full-openssl
|
|
- DEPENDS+=+libopenssl
|
|
+ DEPENDS+=+PACKAGE_hostapd-openssl:libopenssl
|
|
endef
|
|
|
|
Package/hostapd-openssl/description = $(Package/hostapd/description)
|
|
@@ -174,11 +183,20 @@ define Package/hostapd-wolfssl
|
|
$(call Package/hostapd/Default,$(1))
|
|
TITLE+= (wolfSSL full)
|
|
VARIANT:=full-wolfssl
|
|
- DEPENDS+=+libwolfssl
|
|
+ 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)
|
|
@@ -193,7 +211,7 @@ define Package/hostapd-basic-openssl
|
|
$(call Package/hostapd/Default,$(1))
|
|
TITLE+= (WPA-PSK, 11r and 11w)
|
|
VARIANT:=basic-openssl
|
|
- DEPENDS+=+libopenssl
|
|
+ DEPENDS+=+PACKAGE_hostapd-basic-openssl:libopenssl
|
|
endef
|
|
|
|
define Package/hostapd-basic-openssl/description
|
|
@@ -204,13 +222,24 @@ define Package/hostapd-basic-wolfssl
|
|
$(call Package/hostapd/Default,$(1))
|
|
TITLE+= (WPA-PSK, 11r and 11w)
|
|
VARIANT:=basic-wolfssl
|
|
- DEPENDS+=+libwolfssl
|
|
+ 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)
|
|
@@ -227,7 +256,7 @@ define Package/wpad/Default
|
|
CATEGORY:=Network
|
|
SUBMENU:=WirelessAPD
|
|
TITLE:=IEEE 802.1x Auth/Supplicant
|
|
- DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus
|
|
+ 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/
|
|
@@ -252,7 +281,7 @@ define Package/wpad-openssl
|
|
$(call Package/wpad/Default,$(1))
|
|
TITLE+= (OpenSSL full)
|
|
VARIANT:=wpad-full-openssl
|
|
- DEPENDS+=+libopenssl
|
|
+ DEPENDS+=+PACKAGE_wpad-openssl:libopenssl
|
|
endef
|
|
|
|
Package/wpad-openssl/description = $(Package/wpad/description)
|
|
@@ -261,11 +290,20 @@ define Package/wpad-wolfssl
|
|
$(call Package/wpad/Default,$(1))
|
|
TITLE+= (wolfSSL full)
|
|
VARIANT:=wpad-full-wolfssl
|
|
- DEPENDS+=+libwolfssl
|
|
+ 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)
|
|
@@ -280,7 +318,7 @@ define Package/wpad-basic-openssl
|
|
$(call Package/wpad/Default,$(1))
|
|
TITLE+= (OpenSSL, 11r, 11w)
|
|
VARIANT:=wpad-basic-openssl
|
|
- DEPENDS+=+libopenssl
|
|
+ DEPENDS+=+PACKAGE_wpad-basic-openssl:libopenssl
|
|
endef
|
|
|
|
define Package/wpad-basic-openssl/description
|
|
@@ -291,13 +329,24 @@ define Package/wpad-basic-wolfssl
|
|
$(call Package/wpad/Default,$(1))
|
|
TITLE+= (wolfSSL, 11r, 11w)
|
|
VARIANT:=wpad-basic-wolfssl
|
|
- DEPENDS+=+libwolfssl
|
|
+ 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)
|
|
@@ -321,7 +370,7 @@ endef
|
|
define Package/wpad-mesh-openssl
|
|
$(call Package/wpad-mesh,$(1))
|
|
TITLE+= (OpenSSL, 11s, SAE)
|
|
- DEPENDS+=+libopenssl
|
|
+ DEPENDS+=+PACKAGE_wpad-mesh-openssl:libopenssl
|
|
VARIANT:=wpad-mesh-openssl
|
|
endef
|
|
|
|
@@ -330,12 +379,21 @@ Package/wpad-mesh-openssl/description = $(Package/wpad-mesh/description)
|
|
define Package/wpad-mesh-wolfssl
|
|
$(call Package/wpad-mesh,$(1))
|
|
TITLE+= (wolfSSL, 11s, SAE)
|
|
- DEPENDS+=+libwolfssl
|
|
+ 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
|
|
@@ -343,7 +401,7 @@ define Package/wpa-supplicant/Default
|
|
SUBMENU:=WirelessAPD
|
|
TITLE:=WPA Supplicant
|
|
URL:=http://hostap.epitest.fi/wpa_supplicant/
|
|
- DEPENDS:=$(DRV_DEPENDS) +hostapd-common +libubus
|
|
+ DEPENDS:=$(DRV_DEPENDS) +hostapd-common $(CORE_DEPENDS)
|
|
EXTRA_DEPENDS:=hostapd-common (=$(PKG_VERSION)-$(PKG_RELEASE))
|
|
USERID:=network=101:network=101
|
|
PROVIDES:=wpa-supplicant
|
|
@@ -361,14 +419,21 @@ define Package/wpa-supplicant-openssl
|
|
$(call Package/wpa-supplicant/Default,$(1))
|
|
TITLE+= (OpenSSL full)
|
|
VARIANT:=supplicant-full-openssl
|
|
- DEPENDS+=+libopenssl
|
|
+ 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+=+libwolfssl
|
|
+ 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
|
|
@@ -392,14 +457,21 @@ define Package/wpa-supplicant-mesh-openssl
|
|
$(call Package/wpa-supplicant-mesh/Default,$(1))
|
|
TITLE+= (OpenSSL, 11s, SAE)
|
|
VARIANT:=supplicant-mesh-openssl
|
|
- DEPENDS+=+libopenssl
|
|
+ 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+=+libwolfssl
|
|
+ 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
|
|
@@ -451,7 +523,7 @@ define Package/eapol-test/Default
|
|
SECTION:=net
|
|
SUBMENU:=WirelessAPD
|
|
CATEGORY:=Network
|
|
- DEPENDS:=$(DRV_DEPENDS) +libubus
|
|
+ DEPENDS:=$(DRV_DEPENDS) $(CORE_DEPENDS)
|
|
endef
|
|
|
|
define Package/eapol-test
|
|
@@ -465,7 +537,7 @@ define Package/eapol-test-openssl
|
|
TITLE+= (OpenSSL full)
|
|
VARIANT:=supplicant-full-openssl
|
|
CONFLICTS:=$(filter-out eapol-test-openssl ,$(EAPOL_TEST_PROVIDERS))
|
|
- DEPENDS+=+libopenssl
|
|
+ DEPENDS+=+PACKAGE_eapol-test-openssl:libopenssl
|
|
PROVIDES:=eapol-test
|
|
endef
|
|
|
|
@@ -474,7 +546,16 @@ define Package/eapol-test-wolfssl
|
|
TITLE+= (wolfSSL full)
|
|
VARIANT:=supplicant-full-wolfssl
|
|
CONFLICTS:=$(filter-out eapol-test-openssl ,$(filter-out eapol-test-wolfssl ,$(EAPOL_TEST_PROVIDERS)))
|
|
- DEPENDS+=+libwolfssl
|
|
+ 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
|
|
|
|
@@ -507,8 +588,7 @@ TARGET_CPPFLAGS := \
|
|
-D_GNU_SOURCE \
|
|
$(if $(CONFIG_WPA_MSG_MIN_PRIORITY),-DCONFIG_MSG_MIN_PRIORITY=$(CONFIG_WPA_MSG_MIN_PRIORITY))
|
|
|
|
-TARGET_CFLAGS += -ffunction-sections -fdata-sections -flto
|
|
-TARGET_LDFLAGS += -Wl,--gc-sections -flto=jobserver -fuse-linker-plugin -lubox -lubus
|
|
+TARGET_LDFLAGS += -lubox -lubus -lblobmsg_json -lucode
|
|
|
|
ifdef CONFIG_PACKAGE_kmod-cfg80211
|
|
TARGET_LDFLAGS += -lm -lnl-tiny
|
|
@@ -586,27 +666,66 @@ define Build/Compile/supplicant-full-wolfssl
|
|
)
|
|
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
|
|
+ $(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
|
|
+ $(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
|
|
+ $(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
|
|
@@ -616,9 +735,11 @@ 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)
|
|
|
|
define Package/hostapd-utils/install
|
|
abc
|
|
@@ -637,11 +758,14 @@ 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))
|
|
@@ -652,8 +776,10 @@ 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
|
|
@@ -683,6 +809,13 @@ ifeq ($(BUILD_VARIANT),supplicant-full-wolfssl)
|
|
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))
|
|
@@ -690,28 +823,36 @@ $(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..2002572cf1
|
|
--- /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;
|
|
+
|
|
+ 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/hostapd-basic.config b/package/network/services/hostapd/files/hostapd-basic.config
|
|
index 1f52546d57..3d19d8f902 100644
|
|
--- a/package/network/services/hostapd/files/hostapd-basic.config
|
|
+++ b/package/network/services/hostapd/files/hostapd-basic.config
|
|
@@ -54,7 +54,7 @@ CONFIG_RSN_PREAUTH=y
|
|
#CONFIG_IEEE80211W=y
|
|
|
|
# Support Operating Channel Validation
|
|
-#CONFIG_OCV=y
|
|
+CONFIG_OCV=y
|
|
|
|
# Integrated EAP server
|
|
#CONFIG_EAP=y
|
|
diff --git a/package/network/services/hostapd/files/hostapd-full.config b/package/network/services/hostapd/files/hostapd-full.config
|
|
index 38a29143d5..2ac2a312d1 100644
|
|
--- a/package/network/services/hostapd/files/hostapd-full.config
|
|
+++ b/package/network/services/hostapd/files/hostapd-full.config
|
|
@@ -54,7 +54,7 @@ CONFIG_RSN_PREAUTH=y
|
|
#CONFIG_IEEE80211W=y
|
|
|
|
# Support Operating Channel Validation
|
|
-#CONFIG_OCV=y
|
|
+CONFIG_OCV=y
|
|
|
|
# Integrated EAP server
|
|
CONFIG_EAP=y
|
|
@@ -142,7 +142,7 @@ CONFIG_PKCS12=y
|
|
|
|
# RADIUS authentication server. This provides access to the integrated EAP
|
|
# server from external hosts using RADIUS.
|
|
-#CONFIG_RADIUS_SERVER=y
|
|
+CONFIG_RADIUS_SERVER=y
|
|
|
|
# Build IPv6 support for RADIUS operations
|
|
CONFIG_IPV6=y
|
|
@@ -316,7 +316,7 @@ CONFIG_INTERNAL_LIBTOMMATH=y
|
|
CONFIG_INTERWORKING=y
|
|
|
|
# Hotspot 2.0
|
|
-#CONFIG_HS20=y
|
|
+CONFIG_HS20=y
|
|
|
|
# Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file
|
|
#CONFIG_SQLITE=y
|
|
diff --git a/package/network/services/hostapd/files/hostapd.sh b/package/network/services/hostapd/files/hostapd.sh
|
|
index 68dbd374ff..62703dc2f4 100644
|
|
--- a/package/network/services/hostapd/files/hostapd.sh
|
|
+++ b/package/network/services/hostapd/files/hostapd.sh
|
|
@@ -1625,29 +1625,6 @@ EOF
|
|
return 0
|
|
}
|
|
|
|
-wpa_supplicant_run() {
|
|
- local ifname="$1"
|
|
- local hostapd_ctrl="$2"
|
|
-
|
|
- _wpa_supplicant_common "$ifname"
|
|
-
|
|
- ubus wait_for wpa_supplicant
|
|
- local supplicant_res="$(ubus call wpa_supplicant config_add "{ \
|
|
- \"driver\": \"${_w_driver:-wext}\", \"ctrl\": \"$_rpath\", \
|
|
- \"iface\": \"$ifname\", \"config\": \"$_config\" \
|
|
- ${network_bridge:+, \"bridge\": \"$network_bridge\"} \
|
|
- ${hostapd_ctrl:+, \"hostapd_ctrl\": \"$hostapd_ctrl\"} \
|
|
- }")"
|
|
-
|
|
- ret="$?"
|
|
-
|
|
- [ "$ret" != 0 -o -z "$supplicant_res" ] && wireless_setup_vif_failed WPA_SUPPLICANT_FAILED
|
|
-
|
|
- wireless_add_process "$(jsonfilter -s "$supplicant_res" -l 1 -e @.pid)" "/usr/sbin/wpa_supplicant" 1 1
|
|
-
|
|
- return $ret
|
|
-}
|
|
-
|
|
hostapd_common_cleanup() {
|
|
killall meshd-nl80211
|
|
}
|
|
diff --git a/package/network/services/hostapd/files/hostapd.uc b/package/network/services/hostapd/files/hostapd.uc
|
|
new file mode 100644
|
|
index 0000000000..386ff72f7b
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/hostapd.uc
|
|
@@ -0,0 +1,408 @@
|
|
+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 write_lines(f, data)
|
|
+{
|
|
+ for (let line in data) {
|
|
+ f.write(line);
|
|
+ f.write("\n");
|
|
+ }
|
|
+}
|
|
+
|
|
+function iface_write_config(phy, config)
|
|
+{
|
|
+ config.file = `/var/run/ap-${phy}.conf`;
|
|
+
|
|
+ let f = open(config.file, "w");
|
|
+ if (!f) {
|
|
+ hostapd.printf(`Failed to open file ${config.file}`);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ write_lines(f, config.radio.data);
|
|
+ f.write(`channel=${config.radio.channel}\n`);
|
|
+
|
|
+ for (let i = 0; i < length(config.bss); i++) {
|
|
+ let bss = config.bss[i];
|
|
+ let type = i > 0 ? "bss" : "interface";
|
|
+
|
|
+ f.write(`${type}=${bss.ifname}\n`);
|
|
+ write_lines(f, bss.data);
|
|
+ }
|
|
+ f.close();
|
|
+}
|
|
+
|
|
+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}`);
|
|
+ if (hostapd.add_iface(`bss_config=${bss.ifname}:${config.file}`) < 0) {
|
|
+ hostapd.printf(`hostapd.add_iface failed for phy ${phy} ifname=${bss.ifname}`);
|
|
+ return;
|
|
+ }
|
|
+}
|
|
+
|
|
+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 (config.bss[0].ifname != old_config.bss[0].ifname)
|
|
+ return false;
|
|
+
|
|
+ let iface = hostapd.interfaces[config.bss[0].ifname];
|
|
+ if (!iface)
|
|
+ return false;
|
|
+
|
|
+ bss_reload_psk(iface.bss[0], config.bss[0], old_config.bss[0]);
|
|
+ if (!is_equal(config.bss[0], old_config.bss[0])) {
|
|
+ if (phy_is_fullmac(phy))
|
|
+ return false;
|
|
+
|
|
+ hostapd.printf(`Reload config for bss '${config.bss[0].ifname}' on phy '${phy}'`);
|
|
+ if (iface.bss[0].set_config(config.file, 0) < 0) {
|
|
+ hostapd.printf(`Failed to set config`);
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ let bss_list = array_to_obj(iface.bss, "name", 1);
|
|
+ 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 = bss_list[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();
|
|
+ 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.file, 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.file, 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);
|
|
+
|
|
+ iface_write_config(phy, 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] == "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;
|
|
+ }
|
|
+ },
|
|
+ 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/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..9701af125a
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/wdev.uc
|
|
@@ -0,0 +1,153 @@
|
|
+#!/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, 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", 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 (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
|
|
index c550b37b21..944b4d9287 100644
|
|
--- a/package/network/services/hostapd/files/wpa_supplicant-basic.config
|
|
+++ b/package/network/services/hostapd/files/wpa_supplicant-basic.config
|
|
@@ -26,7 +26,7 @@
|
|
# 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
|
|
+#CONFIG_DRIVER_WEXT=y
|
|
|
|
# Driver interface for Linux drivers using the nl80211 kernel interface
|
|
CONFIG_DRIVER_NL80211=y
|
|
@@ -315,7 +315,7 @@ CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
|
|
#CONFIG_IEEE80211W=y
|
|
|
|
# Support Operating Channel Validation
|
|
-#CONFIG_OCV=y
|
|
+CONFIG_OCV=y
|
|
|
|
# Select TLS implementation
|
|
# openssl = OpenSSL (default)
|
|
diff --git a/package/network/services/hostapd/files/wpa_supplicant-full.config b/package/network/services/hostapd/files/wpa_supplicant-full.config
|
|
index de3302c875..b39dabca06 100644
|
|
--- a/package/network/services/hostapd/files/wpa_supplicant-full.config
|
|
+++ b/package/network/services/hostapd/files/wpa_supplicant-full.config
|
|
@@ -26,7 +26,7 @@
|
|
# 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
|
|
+#CONFIG_DRIVER_WEXT=y
|
|
|
|
# Driver interface for Linux drivers using the nl80211 kernel interface
|
|
CONFIG_DRIVER_NL80211=y
|
|
@@ -315,7 +315,7 @@ CONFIG_NO_LINUX_PACKET_SOCKET_WAR=y
|
|
#CONFIG_IEEE80211W=y
|
|
|
|
# Support Operating Channel Validation
|
|
-#CONFIG_OCV=y
|
|
+CONFIG_OCV=y
|
|
|
|
# Select TLS implementation
|
|
# openssl = OpenSSL (default)
|
|
diff --git a/package/network/services/hostapd/files/wpa_supplicant-mini.config b/package/network/services/hostapd/files/wpa_supplicant-mini.config
|
|
index 9eb1111e52..2a3f8fb69d 100644
|
|
--- a/package/network/services/hostapd/files/wpa_supplicant-mini.config
|
|
+++ b/package/network/services/hostapd/files/wpa_supplicant-mini.config
|
|
@@ -26,7 +26,7 @@
|
|
# 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
|
|
+#CONFIG_DRIVER_WEXT=y
|
|
|
|
# Driver interface for Linux drivers using the nl80211 kernel interface
|
|
CONFIG_DRIVER_NL80211=y
|
|
diff --git a/package/network/services/hostapd/files/wpa_supplicant-p2p.config b/package/network/services/hostapd/files/wpa_supplicant-p2p.config
|
|
index 48302bb4c3..7f5140622c 100644
|
|
--- a/package/network/services/hostapd/files/wpa_supplicant-p2p.config
|
|
+++ b/package/network/services/hostapd/files/wpa_supplicant-p2p.config
|
|
@@ -26,7 +26,7 @@
|
|
# 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
|
|
+#CONFIG_DRIVER_WEXT=y
|
|
|
|
# Driver interface for Linux drivers using the nl80211 kernel interface
|
|
CONFIG_DRIVER_NL80211=y
|
|
@@ -622,4 +622,4 @@ 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
|
|
+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..22cb130e73
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/files/wpa_supplicant.uc
|
|
@@ -0,0 +1,161 @@
|
|
+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 = {};
|
|
+
|
|
+function iface_stop(iface)
|
|
+{
|
|
+ let ifname = iface.config.iface;
|
|
+
|
|
+ wpas.remove_iface(ifname);
|
|
+ wdev_remove(ifname);
|
|
+ iface.running = false;
|
|
+}
|
|
+
|
|
+function iface_start(phy, iface)
|
|
+{
|
|
+ if (iface.running)
|
|
+ return;
|
|
+
|
|
+ let ifname = iface.config.iface;
|
|
+
|
|
+ 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 && old_if.running)
|
|
+ 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 = {
|
|
+ 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: {} });
|
|
+}
|
|
+
|
|
+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);
|
|
+ }
|
|
+};
|
|
diff --git a/package/network/services/hostapd/files/wpad.init b/package/network/services/hostapd/files/wpad.init
|
|
index 79c5bf1075..65d46df982 100644
|
|
--- a/package/network/services/hostapd/files/wpad.init
|
|
+++ b/package/network/services/hostapd/files/wpad.init
|
|
@@ -13,6 +13,7 @@ start_service() {
|
|
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
|
|
@@ -29,6 +30,7 @@ start_service() {
|
|
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
|
|
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
|
|
index 994aa30626..269dcaac75 100644
|
|
--- 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
|
|
@@ -16,7 +16,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
|
|
|
--- a/src/crypto/crypto_wolfssl.c
|
|
+++ b/src/crypto/crypto_wolfssl.c
|
|
-@@ -1307,6 +1307,7 @@ int ecc_projective_add_point(ecc_point *
|
|
+@@ -1340,6 +1340,7 @@ int ecc_projective_add_point(ecc_point *
|
|
|
|
struct crypto_ec {
|
|
ecc_key key;
|
|
@@ -24,7 +24,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
|
mp_int a;
|
|
mp_int prime;
|
|
mp_int order;
|
|
-@@ -1361,6 +1362,8 @@ struct crypto_ec * crypto_ec_init(int gr
|
|
+@@ -1394,6 +1395,8 @@ struct crypto_ec * crypto_ec_init(int gr
|
|
return NULL;
|
|
|
|
if (wc_ecc_init(&e->key) != 0 ||
|
|
@@ -33,7 +33,7 @@ Signed-off-by: David Bauer <mail@david-bauer.net>
|
|
wc_ecc_set_curve(&e->key, 0, curve_id) != 0 ||
|
|
mp_init(&e->a) != MP_OKAY ||
|
|
mp_init(&e->prime) != MP_OKAY ||
|
|
-@@ -1392,6 +1395,7 @@ void crypto_ec_deinit(struct crypto_ec*
|
|
+@@ -1425,6 +1428,7 @@ void crypto_ec_deinit(struct crypto_ec*
|
|
mp_clear(&e->order);
|
|
mp_clear(&e->prime);
|
|
mp_clear(&e->a);
|
|
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
|
|
index 16d24d1000..0a51c84d21 100644
|
|
--- 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
|
|
@@ -14,7 +14,7 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
|
|
|
|
--- a/wpa_supplicant/wpa_supplicant.c
|
|
+++ b/wpa_supplicant/wpa_supplicant.c
|
|
-@@ -2409,7 +2409,7 @@ static int drv_supports_vht(struct wpa_s
|
|
+@@ -2638,7 +2638,7 @@ static int drv_supports_vht(struct wpa_s
|
|
}
|
|
|
|
|
|
@@ -23,7 +23,7 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
|
|
{
|
|
int i;
|
|
|
|
-@@ -2418,7 +2418,10 @@ static bool ibss_mesh_is_80mhz_avail(int
|
|
+@@ -2647,7 +2647,10 @@ static bool ibss_mesh_is_80mhz_avail(int
|
|
|
|
chan = hw_get_channel_chan(mode, i, NULL);
|
|
if (!chan ||
|
|
@@ -35,16 +35,16 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
|
|
return false;
|
|
}
|
|
|
|
-@@ -2447,6 +2450,8 @@ void ibss_mesh_setup_freq(struct wpa_sup
|
|
- int chwidth, seg0, seg1;
|
|
- u32 vht_caps = 0;
|
|
- bool is_24ghz, is_6ghz;
|
|
-+ bool dfs_enabled = wpa_s->conf->country[0] &&
|
|
-+ (wpa_s->drv_flags & WPA_DRIVER_FLAGS_RADAR);
|
|
-
|
|
- freq->freq = ssid->frequency;
|
|
-
|
|
-@@ -2543,8 +2548,11 @@ void ibss_mesh_setup_freq(struct wpa_sup
|
|
+@@ -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 */
|
|
@@ -55,9 +55,9 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
|
|
+ if (!dfs_enabled)
|
|
+ return;
|
|
|
|
- freq->channel = pri_chan->chan;
|
|
-
|
|
-@@ -2577,8 +2585,11 @@ void ibss_mesh_setup_freq(struct wpa_sup
|
|
+ #ifdef CONFIG_HT_OVERRIDES
|
|
+ if (ssid->disable_ht40)
|
|
+@@ -2825,8 +2831,11 @@ static void ibss_mesh_select_40mhz(struc
|
|
return;
|
|
|
|
/* Check secondary channel flags */
|
|
@@ -70,25 +70,34 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
|
|
|
|
if (ht40 == -1) {
|
|
if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS))
|
|
-@@ -2667,7 +2678,7 @@ skip_to_6ghz:
|
|
- return;
|
|
-
|
|
- /* Back to HT configuration if channel not usable */
|
|
+@@ -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))
|
|
- return;
|
|
-
|
|
- chwidth = CHANWIDTH_80MHZ;
|
|
-@@ -2681,7 +2692,7 @@ skip_to_6ghz:
|
|
- * above; check the remaining four 20 MHz channels for the total
|
|
- * of 160 MHz bandwidth.
|
|
- */
|
|
-- if (!ibss_mesh_is_80mhz_avail(channel + 16, mode))
|
|
-+ if (!ibss_mesh_is_80mhz_avail(channel + 16, mode, dfs_enabled))
|
|
- return;
|
|
-
|
|
+ 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++) {
|
|
-@@ -2711,10 +2722,12 @@ skip_to_6ghz:
|
|
+ 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;
|
|
|
|
@@ -103,4 +112,24 @@ Signed-off-by: Peter Oh <peter.oh@bowerswilkins.com>
|
|
+ continue;
|
|
|
|
/* Found a suitable second segment for 80+80 */
|
|
- chwidth = CHANWIDTH_80P80MHZ;
|
|
+ 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
|
|
index 1faeacf766..9b11f0e803 100644
|
|
--- 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
|
|
@@ -28,8 +28,8 @@ Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
|
|
+#include "crypto/crypto.h"
|
|
|
|
|
|
- static int dfs_get_used_n_chans(struct hostapd_iface *iface, int *seg1)
|
|
-@@ -483,9 +484,14 @@ dfs_get_valid_channel(struct hostapd_ifa
|
|
+ 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;
|
|
@@ -44,7 +44,7 @@ Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
|
|
wpa_printf(MSG_DEBUG, "DFS: Selecting random channel");
|
|
*secondary_channel = 0;
|
|
*oper_centr_freq_seg0_idx = 0;
|
|
-@@ -505,8 +511,20 @@ dfs_get_valid_channel(struct hostapd_ifa
|
|
+@@ -543,8 +549,20 @@ dfs_get_valid_channel(struct hostapd_ifa
|
|
if (num_available_chandefs == 0)
|
|
return NULL;
|
|
|
|
@@ -64,11 +64,11 @@ Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
|
|
return NULL;
|
|
+
|
|
chan_idx = _rand % num_available_chandefs;
|
|
- dfs_find_channel(iface, &chan, chan_idx, skip_radar);
|
|
+ dfs_find_channel(iface, &chan, chan_idx, type);
|
|
if (!chan) {
|
|
--- a/src/drivers/driver_nl80211.c
|
|
+++ b/src/drivers/driver_nl80211.c
|
|
-@@ -9895,6 +9895,10 @@ static int nl80211_switch_channel(void *
|
|
+@@ -10977,6 +10977,10 @@ static int nl80211_switch_channel(void *
|
|
if (ret)
|
|
goto error;
|
|
|
|
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
|
|
index ac02ec5ab7..4ee43b5186 100644
|
|
--- 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
|
|
@@ -1,6 +1,6 @@
|
|
--- a/src/ap/ieee802_11.c
|
|
+++ b/src/ap/ieee802_11.c
|
|
-@@ -4944,6 +4944,13 @@ static int add_associated_sta(struct hos
|
|
+@@ -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.
|
|
@@ -14,7 +14,7 @@
|
|
*/
|
|
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)",
|
|
-@@ -4957,7 +4964,8 @@ static int add_associated_sta(struct hos
|
|
+@@ -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) &&
|
|
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
|
|
index c7da33f029..8dec325c98 100644
|
|
--- 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
|
|
@@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
|
|
--- a/src/ap/hostapd.c
|
|
+++ b/src/ap/hostapd.c
|
|
-@@ -3431,7 +3431,7 @@ static int hostapd_change_config_freq(st
|
|
+@@ -3764,7 +3764,7 @@ static int hostapd_change_config_freq(st
|
|
struct hostapd_freq_params *old_params)
|
|
{
|
|
int channel;
|
|
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
|
|
index ade0b11311..19248e80d8 100644
|
|
--- 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
|
|
@@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
#include <linux/rtnetlink.h>
|
|
#include <netpacket/packet.h>
|
|
#include <linux/errqueue.h>
|
|
-@@ -5300,26 +5297,29 @@ fail:
|
|
+@@ -5783,26 +5780,29 @@ fail:
|
|
|
|
static void rtnl_neigh_delete_fdb_entry(struct i802_bss *bss, const u8 *addr)
|
|
{
|
|
@@ -64,7 +64,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
if (err < 0) {
|
|
wpa_printf(MSG_DEBUG, "nl80211: bridge FDB entry delete for "
|
|
MACSTR " ifindex=%d failed: %s", MAC2STR(addr),
|
|
-@@ -5329,9 +5329,8 @@ static void rtnl_neigh_delete_fdb_entry(
|
|
+@@ -5812,9 +5812,8 @@ static void rtnl_neigh_delete_fdb_entry(
|
|
MACSTR, MAC2STR(addr));
|
|
}
|
|
|
|
@@ -76,7 +76,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
}
|
|
|
|
|
|
-@@ -7714,7 +7713,6 @@ static void *i802_init(struct hostapd_da
|
|
+@@ -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);
|
|
|
|
@@ -84,7 +84,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
if (bss->added_if_into_bridge || bss->already_in_bridge) {
|
|
int err;
|
|
|
|
-@@ -7731,7 +7729,6 @@ static void *i802_init(struct hostapd_da
|
|
+@@ -8509,7 +8507,6 @@ static void *i802_init(struct hostapd_da
|
|
goto failed;
|
|
}
|
|
}
|
|
@@ -92,7 +92,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
|
|
if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) {
|
|
wpa_printf(MSG_DEBUG,
|
|
-@@ -10678,13 +10675,14 @@ static int wpa_driver_br_add_ip_neigh(vo
|
|
+@@ -11843,13 +11840,14 @@ static int wpa_driver_br_add_ip_neigh(vo
|
|
const u8 *ipaddr, int prefixlen,
|
|
const u8 *addr)
|
|
{
|
|
@@ -112,7 +112,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
int res;
|
|
|
|
if (!ipaddr || prefixlen == 0 || !addr)
|
|
-@@ -10703,85 +10701,66 @@ static int wpa_driver_br_add_ip_neigh(vo
|
|
+@@ -11868,85 +11866,66 @@ static int wpa_driver_br_add_ip_neigh(vo
|
|
}
|
|
|
|
if (version == 4) {
|
|
@@ -220,7 +220,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
addrsize = 16;
|
|
} else {
|
|
return -EINVAL;
|
|
-@@ -10799,41 +10778,30 @@ static int wpa_driver_br_delete_ip_neigh
|
|
+@@ -11964,41 +11943,30 @@ static int wpa_driver_br_delete_ip_neigh
|
|
return -1;
|
|
}
|
|
|
|
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
|
|
index 6d9fd81acf..f98d3806dc 100644
|
|
--- 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
|
|
@@ -16,7 +16,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
|
|
--- a/src/ap/ieee802_11.c
|
|
+++ b/src/ap/ieee802_11.c
|
|
-@@ -3761,15 +3761,6 @@ static void handle_auth(struct hostapd_d
|
|
+@@ -3012,15 +3012,6 @@ static void handle_auth(struct hostapd_d
|
|
seq_ctrl);
|
|
return;
|
|
}
|
|
@@ -25,7 +25,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
|
- sta->plink_state == PLINK_BLOCKED) {
|
|
- wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR
|
|
- " is blocked - drop Authentication frame",
|
|
-- MAC2STR(mgmt->sa));
|
|
+- MAC2STR(sa));
|
|
- return;
|
|
- }
|
|
-#endif /* CONFIG_MESH */
|
|
diff --git a/package/network/services/hostapd/patches/050-build_fix.patch b/package/network/services/hostapd/patches/050-build_fix.patch
|
|
index 2652a83316..8680b07c66 100644
|
|
--- a/package/network/services/hostapd/patches/050-build_fix.patch
|
|
+++ b/package/network/services/hostapd/patches/050-build_fix.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/hostapd/Makefile
|
|
+++ b/hostapd/Makefile
|
|
-@@ -323,6 +323,7 @@ ifdef CONFIG_FILS
|
|
+@@ -324,6 +324,7 @@ ifdef CONFIG_FILS
|
|
CFLAGS += -DCONFIG_FILS
|
|
OBJS += ../src/ap/fils_hlp.o
|
|
NEED_SHA384=y
|
|
@@ -10,7 +10,7 @@
|
|
CFLAGS += -DCONFIG_FILS_SK_PFS
|
|
--- a/wpa_supplicant/Makefile
|
|
+++ b/wpa_supplicant/Makefile
|
|
-@@ -312,6 +312,7 @@ endif
|
|
+@@ -331,6 +331,7 @@ endif
|
|
ifdef CONFIG_FILS
|
|
CFLAGS += -DCONFIG_FILS
|
|
NEED_SHA384=y
|
|
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/200-multicall.patch b/package/network/services/hostapd/patches/200-multicall.patch
|
|
index ad82e020f6..f7e797a9c8 100644
|
|
--- a/package/network/services/hostapd/patches/200-multicall.patch
|
|
+++ b/package/network/services/hostapd/patches/200-multicall.patch
|
|
@@ -18,7 +18,7 @@
|
|
OBJS += ../src/ap/vlan_init.o
|
|
OBJS += ../src/ap/vlan_ifconfig.o
|
|
OBJS += ../src/ap/vlan.o
|
|
-@@ -350,10 +352,14 @@ CFLAGS += -DCONFIG_MBO
|
|
+@@ -357,10 +359,14 @@ CFLAGS += -DCONFIG_MBO
|
|
OBJS += ../src/ap/mbo_ap.o
|
|
endif
|
|
|
|
@@ -36,7 +36,7 @@
|
|
LIBS += $(DRV_AP_LIBS)
|
|
|
|
ifdef CONFIG_L2_PACKET
|
|
-@@ -1281,6 +1287,12 @@ install: $(addprefix $(DESTDIR)$(BINDIR)
|
|
+@@ -1380,6 +1386,12 @@ install: $(addprefix $(DESTDIR)$(BINDIR)
|
|
_OBJS_VAR := OBJS
|
|
include ../src/objs.mk
|
|
|
|
@@ -49,7 +49,7 @@
|
|
hostapd: $(OBJS)
|
|
$(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS)
|
|
@$(E) " LD " $@
|
|
-@@ -1355,6 +1367,12 @@ include ../src/objs.mk
|
|
+@@ -1460,6 +1472,12 @@ include ../src/objs.mk
|
|
_OBJS_VAR := SOBJS
|
|
include ../src/objs.mk
|
|
|
|
@@ -64,15 +64,15 @@
|
|
@$(E) " LD " $@
|
|
--- a/wpa_supplicant/Makefile
|
|
+++ b/wpa_supplicant/Makefile
|
|
-@@ -17,6 +17,7 @@ endif
|
|
+@@ -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 LIBS
|
|
-@@ -363,7 +364,9 @@ endif
|
|
+ ifdef CONFIG_BUILD_PASN_SO
|
|
+@@ -382,7 +383,9 @@ endif
|
|
ifdef CONFIG_IBSS_RSN
|
|
NEED_RSN_AUTHENTICATOR=y
|
|
CFLAGS += -DCONFIG_IBSS_RSN
|
|
@@ -82,7 +82,7 @@
|
|
OBJS += ibss_rsn.o
|
|
endif
|
|
|
|
-@@ -900,6 +903,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS
|
|
+@@ -924,6 +927,10 @@ ifdef CONFIG_DYNAMIC_EAP_METHODS
|
|
CFLAGS += -DCONFIG_DYNAMIC_EAP_METHODS
|
|
LIBS += -ldl -rdynamic
|
|
endif
|
|
@@ -93,7 +93,7 @@
|
|
endif
|
|
|
|
ifdef CONFIG_AP
|
|
-@@ -907,9 +914,11 @@ NEED_EAP_COMMON=y
|
|
+@@ -931,9 +938,11 @@ NEED_EAP_COMMON=y
|
|
NEED_RSN_AUTHENTICATOR=y
|
|
CFLAGS += -DCONFIG_AP
|
|
OBJS += ap.o
|
|
@@ -105,7 +105,7 @@
|
|
OBJS += ../src/ap/hostapd.o
|
|
OBJS += ../src/ap/wpa_auth_glue.o
|
|
OBJS += ../src/ap/utils.o
|
|
-@@ -989,6 +998,12 @@ endif
|
|
+@@ -1022,6 +1031,12 @@ endif
|
|
ifdef CONFIG_HS20
|
|
OBJS += ../src/ap/hs20.o
|
|
endif
|
|
@@ -118,7 +118,7 @@
|
|
endif
|
|
|
|
ifdef CONFIG_MBO
|
|
-@@ -997,7 +1012,9 @@ CFLAGS += -DCONFIG_MBO
|
|
+@@ -1030,7 +1045,9 @@ CFLAGS += -DCONFIG_MBO
|
|
endif
|
|
|
|
ifdef NEED_RSN_AUTHENTICATOR
|
|
@@ -128,7 +128,7 @@
|
|
NEED_AES_WRAP=y
|
|
OBJS += ../src/ap/wpa_auth.o
|
|
OBJS += ../src/ap/wpa_auth_ie.o
|
|
-@@ -1891,6 +1908,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv)
|
|
+@@ -2010,6 +2027,12 @@ wpa_priv: $(BCHECK) $(OBJS_priv)
|
|
|
|
_OBJS_VAR := OBJS
|
|
include ../src/objs.mk
|
|
@@ -141,7 +141,7 @@
|
|
wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)
|
|
$(Q)$(LDO) $(LDFLAGS) -o wpa_supplicant $(OBJS) $(LIBS) $(EXTRALIBS)
|
|
@$(E) " LD " $@
|
|
-@@ -2023,6 +2046,12 @@ eap_gpsk.so: $(SRC_EAP_GPSK)
|
|
+@@ -2142,6 +2165,12 @@ eap_gpsk.so: $(SRC_EAP_GPSK)
|
|
$(Q)sed -e 's|\@BINDIR\@|$(BINDIR)|g' $< >$@
|
|
@$(E) " sed" $<
|
|
|
|
@@ -156,7 +156,7 @@
|
|
wpa_cli.exe: wpa_cli
|
|
--- a/src/drivers/driver.h
|
|
+++ b/src/drivers/driver.h
|
|
-@@ -6033,8 +6033,8 @@ union wpa_event_data {
|
|
+@@ -6651,8 +6651,8 @@ union wpa_event_data {
|
|
* Driver wrapper code should call this function whenever an event is received
|
|
* from the driver.
|
|
*/
|
|
@@ -167,7 +167,7 @@
|
|
|
|
/**
|
|
* wpa_supplicant_event_global - Report a driver event for wpa_supplicant
|
|
-@@ -6046,7 +6046,7 @@ void wpa_supplicant_event(void *ctx, enu
|
|
+@@ -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.
|
|
*/
|
|
@@ -178,7 +178,7 @@
|
|
/*
|
|
--- a/src/ap/drv_callbacks.c
|
|
+++ b/src/ap/drv_callbacks.c
|
|
-@@ -1842,8 +1842,8 @@ err:
|
|
+@@ -1994,8 +1994,8 @@ err:
|
|
#endif /* CONFIG_OWE */
|
|
|
|
|
|
@@ -189,7 +189,7 @@
|
|
{
|
|
struct hostapd_data *hapd = ctx;
|
|
#ifndef CONFIG_NO_STDOUT_DEBUG
|
|
-@@ -2088,7 +2088,7 @@ void wpa_supplicant_event(void *ctx, enu
|
|
+@@ -2271,7 +2271,7 @@ void wpa_supplicant_event(void *ctx, enu
|
|
}
|
|
|
|
|
|
@@ -200,7 +200,7 @@
|
|
struct hapd_interfaces *interfaces = ctx;
|
|
--- a/wpa_supplicant/wpa_priv.c
|
|
+++ b/wpa_supplicant/wpa_priv.c
|
|
-@@ -1038,8 +1038,8 @@ static void wpa_priv_send_ft_response(st
|
|
+@@ -1039,8 +1039,8 @@ static void wpa_priv_send_ft_response(st
|
|
}
|
|
|
|
|
|
@@ -211,7 +211,7 @@
|
|
{
|
|
struct wpa_priv_interface *iface = ctx;
|
|
|
|
-@@ -1102,7 +1102,7 @@ void wpa_supplicant_event(void *ctx, enu
|
|
+@@ -1103,7 +1103,7 @@ void wpa_supplicant_event(void *ctx, enu
|
|
}
|
|
|
|
|
|
@@ -220,7 +220,7 @@
|
|
union wpa_event_data *data)
|
|
{
|
|
struct wpa_priv_global *global = ctx;
|
|
-@@ -1215,6 +1215,8 @@ int main(int argc, char *argv[])
|
|
+@@ -1217,6 +1217,8 @@ int main(int argc, char *argv[])
|
|
if (os_program_init())
|
|
return -1;
|
|
|
|
@@ -231,7 +231,7 @@
|
|
os_memset(&global, 0, sizeof(global));
|
|
--- a/wpa_supplicant/events.c
|
|
+++ b/wpa_supplicant/events.c
|
|
-@@ -4891,8 +4891,8 @@ static void wpas_event_unprot_beacon(str
|
|
+@@ -5345,8 +5345,8 @@ static void wpas_link_reconfig(struct wp
|
|
}
|
|
|
|
|
|
@@ -242,7 +242,7 @@
|
|
{
|
|
struct wpa_supplicant *wpa_s = ctx;
|
|
int resched;
|
|
-@@ -5745,7 +5745,7 @@ void wpa_supplicant_event(void *ctx, enu
|
|
+@@ -6264,7 +6264,7 @@ void wpa_supplicant_event(void *ctx, enu
|
|
}
|
|
|
|
|
|
@@ -253,7 +253,7 @@
|
|
struct wpa_supplicant *wpa_s;
|
|
--- a/wpa_supplicant/wpa_supplicant.c
|
|
+++ b/wpa_supplicant/wpa_supplicant.c
|
|
-@@ -7043,7 +7043,6 @@ struct wpa_interface * wpa_supplicant_ma
|
|
+@@ -7435,7 +7435,6 @@ struct wpa_interface * wpa_supplicant_ma
|
|
return NULL;
|
|
}
|
|
|
|
@@ -261,7 +261,7 @@
|
|
/**
|
|
* wpa_supplicant_match_existing - Match existing interfaces
|
|
* @global: Pointer to global data from wpa_supplicant_init()
|
|
-@@ -7078,6 +7077,11 @@ static int wpa_supplicant_match_existing
|
|
+@@ -7470,6 +7469,11 @@ static int wpa_supplicant_match_existing
|
|
|
|
#endif /* CONFIG_MATCH_IFACE */
|
|
|
|
@@ -273,7 +273,7 @@
|
|
|
|
/**
|
|
* wpa_supplicant_add_iface - Add a new network interface
|
|
-@@ -7334,6 +7338,8 @@ struct wpa_global * wpa_supplicant_init(
|
|
+@@ -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 */
|
|
@@ -284,7 +284,7 @@
|
|
wpa_debug_open_file(params->wpa_debug_file_path);
|
|
--- a/hostapd/main.c
|
|
+++ b/hostapd/main.c
|
|
-@@ -590,6 +590,11 @@ fail:
|
|
+@@ -685,6 +685,11 @@ fail:
|
|
return -1;
|
|
}
|
|
|
|
@@ -296,14 +296,14 @@
|
|
|
|
#ifdef CONFIG_WPS
|
|
static int gen_uuid(const char *txt_addr)
|
|
-@@ -683,6 +688,8 @@ int main(int argc, char *argv[])
|
|
+@@ -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:");
|
|
+ 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
|
|
@@ -320,7 +320,7 @@
|
|
{
|
|
--- a/wpa_supplicant/eapol_test.c
|
|
+++ b/wpa_supplicant/eapol_test.c
|
|
-@@ -30,7 +30,12 @@
|
|
+@@ -31,7 +31,12 @@
|
|
#include "ctrl_iface.h"
|
|
#include "pcsc_funcs.h"
|
|
#include "wpas_glue.h"
|
|
@@ -333,7 +333,7 @@
|
|
|
|
const struct wpa_driver_ops *const wpa_drivers[] = { NULL };
|
|
|
|
-@@ -1291,6 +1296,10 @@ static void usage(void)
|
|
+@@ -1303,6 +1308,10 @@ static void usage(void)
|
|
"option several times.\n");
|
|
}
|
|
|
|
@@ -344,7 +344,7 @@
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
-@@ -1311,6 +1320,8 @@ int main(int argc, char *argv[])
|
|
+@@ -1323,6 +1332,8 @@ int main(int argc, char *argv[])
|
|
if (os_program_init())
|
|
return -1;
|
|
|
|
diff --git a/package/network/services/hostapd/patches/300-noscan.patch b/package/network/services/hostapd/patches/300-noscan.patch
|
|
index 01a33d0d03..c6f9eba9d5 100644
|
|
--- a/package/network/services/hostapd/patches/300-noscan.patch
|
|
+++ b/package/network/services/hostapd/patches/300-noscan.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/hostapd/config_file.c
|
|
+++ b/hostapd/config_file.c
|
|
-@@ -3474,6 +3474,10 @@ static int hostapd_config_fill(struct ho
|
|
+@@ -3446,6 +3446,10 @@ static int hostapd_config_fill(struct ho
|
|
if (bss->ocv && !bss->ieee80211w)
|
|
bss->ieee80211w = 1;
|
|
#endif /* CONFIG_OCV */
|
|
@@ -13,7 +13,7 @@
|
|
} else if (os_strcmp(buf, "ht_capab") == 0) {
|
|
--- a/src/ap/ap_config.h
|
|
+++ b/src/ap/ap_config.h
|
|
-@@ -1014,6 +1014,8 @@ struct hostapd_config {
|
|
+@@ -1072,6 +1072,8 @@ struct hostapd_config {
|
|
|
|
int ht_op_mode_fixed;
|
|
u16 ht_capab;
|
|
diff --git a/package/network/services/hostapd/patches/301-mesh-noscan.patch b/package/network/services/hostapd/patches/301-mesh-noscan.patch
|
|
index e682efb543..6b5416f0ea 100644
|
|
--- a/package/network/services/hostapd/patches/301-mesh-noscan.patch
|
|
+++ b/package/network/services/hostapd/patches/301-mesh-noscan.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/wpa_supplicant/config.c
|
|
+++ b/wpa_supplicant/config.c
|
|
-@@ -2532,6 +2532,7 @@ static const struct parse_data ssid_fiel
|
|
+@@ -2600,6 +2600,7 @@ static const struct parse_data ssid_fiel
|
|
#else /* CONFIG_MESH */
|
|
{ INT_RANGE(mode, 0, 4) },
|
|
#endif /* CONFIG_MESH */
|
|
@@ -10,7 +10,7 @@
|
|
{ STR(id_str) },
|
|
--- a/wpa_supplicant/config_file.c
|
|
+++ b/wpa_supplicant/config_file.c
|
|
-@@ -769,6 +769,7 @@ static void wpa_config_write_network(FIL
|
|
+@@ -775,6 +775,7 @@ static void wpa_config_write_network(FIL
|
|
#endif /* IEEE8021X_EAPOL */
|
|
INT(mode);
|
|
INT(no_auto_peer);
|
|
@@ -20,7 +20,7 @@
|
|
INT(enable_edmg);
|
|
--- a/wpa_supplicant/mesh.c
|
|
+++ b/wpa_supplicant/mesh.c
|
|
-@@ -505,6 +505,8 @@ static int wpa_supplicant_mesh_init(stru
|
|
+@@ -506,6 +506,8 @@ static int wpa_supplicant_mesh_init(stru
|
|
frequency);
|
|
goto out_free;
|
|
}
|
|
@@ -31,36 +31,36 @@
|
|
/*
|
|
--- a/wpa_supplicant/wpa_supplicant.c
|
|
+++ b/wpa_supplicant/wpa_supplicant.c
|
|
-@@ -2436,7 +2436,7 @@ void ibss_mesh_setup_freq(struct wpa_sup
|
|
+@@ -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 ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
|
|
-+ int ht40plus[] = { 1, 2, 3, 4, 5, 6, 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
|
|
- 184, 192 };
|
|
- int bw80[] = { 5180, 5260, 5500, 5580, 5660, 5745, 5955,
|
|
- 6035, 6115, 6195, 6275, 6355, 6435, 6515,
|
|
-@@ -2444,7 +2444,7 @@ void ibss_mesh_setup_freq(struct wpa_sup
|
|
- int bw160[] = { 5955, 6115, 6275, 6435, 6595, 6755, 6915 };
|
|
- struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL;
|
|
+- int i, obss_scan = 1;
|
|
++ int i, obss_scan = !(ssid->noscan);
|
|
u8 channel;
|
|
-- int i, chan_idx, ht40 = -1, res, obss_scan = 1;
|
|
-+ int i, chan_idx, ht40 = -1, res, obss_scan = !(ssid->noscan);
|
|
- unsigned int j, k;
|
|
- struct hostapd_freq_params vht_freq;
|
|
- int chwidth, seg0, seg1;
|
|
-@@ -2535,7 +2535,7 @@ void ibss_mesh_setup_freq(struct wpa_sup
|
|
- #endif /* CONFIG_HE_OVERRIDES */
|
|
-
|
|
- /* Setup higher BW only for 5 GHz */
|
|
-- if (mode->mode != HOSTAPD_MODE_IEEE80211A)
|
|
-+ if (mode->mode != HOSTAPD_MODE_IEEE80211A && !(ssid->noscan))
|
|
- return;
|
|
-
|
|
- for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) {
|
|
+ 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
|
|
-@@ -974,6 +974,8 @@ struct wpa_ssid {
|
|
+@@ -1035,6 +1035,8 @@ struct wpa_ssid {
|
|
*/
|
|
int no_auto_peer;
|
|
|
|
diff --git a/package/network/services/hostapd/patches/310-rescan_immediately.patch b/package/network/services/hostapd/patches/310-rescan_immediately.patch
|
|
index b0c1cb8354..a47546d38f 100644
|
|
--- a/package/network/services/hostapd/patches/310-rescan_immediately.patch
|
|
+++ b/package/network/services/hostapd/patches/310-rescan_immediately.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/wpa_supplicant/wpa_supplicant.c
|
|
+++ b/wpa_supplicant/wpa_supplicant.c
|
|
-@@ -5377,7 +5377,7 @@ wpa_supplicant_alloc(struct wpa_supplica
|
|
+@@ -5740,7 +5740,7 @@ wpa_supplicant_alloc(struct wpa_supplica
|
|
if (wpa_s == NULL)
|
|
return NULL;
|
|
wpa_s->scan_req = INITIAL_SCAN_REQ;
|
|
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
|
|
index 37033c3035..c11c957216 100644
|
|
--- a/package/network/services/hostapd/patches/330-nl80211_fix_set_freq.patch
|
|
+++ b/package/network/services/hostapd/patches/330-nl80211_fix_set_freq.patch
|
|
@@ -1,8 +1,8 @@
|
|
--- a/src/drivers/driver_nl80211.c
|
|
+++ b/src/drivers/driver_nl80211.c
|
|
-@@ -4986,7 +4986,7 @@ static int nl80211_set_channel(struct i8
|
|
- freq->freq, freq->ht_enabled, freq->vht_enabled, freq->he_enabled,
|
|
- freq->bandwidth, freq->center_freq1, freq->center_freq2);
|
|
+@@ -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 :
|
|
diff --git a/package/network/services/hostapd/patches/340-reload_freq_change.patch b/package/network/services/hostapd/patches/340-reload_freq_change.patch
|
|
index 3d51a47a1e..ae6cd81ea4 100644
|
|
--- a/package/network/services/hostapd/patches/340-reload_freq_change.patch
|
|
+++ b/package/network/services/hostapd/patches/340-reload_freq_change.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/src/ap/hostapd.c
|
|
+++ b/src/ap/hostapd.c
|
|
-@@ -115,6 +115,28 @@ static void hostapd_reload_bss(struct ho
|
|
+@@ -143,6 +143,29 @@ static void hostapd_reload_bss(struct ho
|
|
#endif /* CONFIG_NO_RADIUS */
|
|
|
|
ssid = &hapd->conf->ssid;
|
|
@@ -12,6 +12,7 @@
|
|
+ hapd->iconf->ieee80211n,
|
|
+ hapd->iconf->ieee80211ac,
|
|
+ hapd->iconf->ieee80211ax,
|
|
++ hapd->iconf->ieee80211be,
|
|
+ hapd->iconf->secondary_channel,
|
|
+ hostapd_get_oper_chwidth(hapd->iconf),
|
|
+ hostapd_get_oper_centr_freq_seg0_idx(hapd->iconf),
|
|
@@ -29,7 +30,7 @@
|
|
if (!ssid->wpa_psk_set && ssid->wpa_psk && !ssid->wpa_psk->next &&
|
|
ssid->wpa_passphrase_set && ssid->wpa_passphrase) {
|
|
/*
|
|
-@@ -216,6 +238,7 @@ int hostapd_reload_config(struct hostapd
|
|
+@@ -251,6 +274,7 @@ int hostapd_reload_config(struct hostapd
|
|
struct hostapd_data *hapd = iface->bss[0];
|
|
struct hostapd_config *newconf, *oldconf;
|
|
size_t j;
|
|
@@ -37,7 +38,7 @@
|
|
|
|
if (iface->config_fname == NULL) {
|
|
/* Only in-memory config in use - assume it has been updated */
|
|
-@@ -266,24 +289,20 @@ int hostapd_reload_config(struct hostapd
|
|
+@@ -301,6 +325,17 @@ int hostapd_reload_config(struct hostapd
|
|
}
|
|
iface->conf = newconf;
|
|
|
|
@@ -54,6 +55,10 @@
|
|
+
|
|
for (j = 0; j < iface->num_bss; j++) {
|
|
hapd = iface->bss[j];
|
|
+ if (!hapd->conf->config_id || !newconf->bss[j]->config_id ||
|
|
+@@ -308,21 +343,6 @@ int hostapd_reload_config(struct hostapd
|
|
+ newconf->bss[j]->config_id) != 0)
|
|
+ hostapd_clear_old_bss(hapd);
|
|
hapd->iconf = newconf;
|
|
- hapd->iconf->channel = oldconf->channel;
|
|
- hapd->iconf->acs = oldconf->acs;
|
|
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
|
|
index b13dcb0673..8784452876 100644
|
|
--- 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
|
|
@@ -1,6 +1,6 @@
|
|
--- a/wpa_supplicant/ap.c
|
|
+++ b/wpa_supplicant/ap.c
|
|
-@@ -1611,15 +1611,35 @@ int ap_switch_channel(struct wpa_supplic
|
|
+@@ -1825,15 +1825,35 @@ int ap_switch_channel(struct wpa_supplic
|
|
|
|
|
|
#ifdef 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
|
|
index 35567838f5..647ca2cbf9 100644
|
|
--- a/package/network/services/hostapd/patches/350-nl80211_del_beacon_bss.patch
|
|
+++ b/package/network/services/hostapd/patches/350-nl80211_del_beacon_bss.patch
|
|
@@ -1,54 +1,35 @@
|
|
--- a/src/drivers/driver_nl80211.c
|
|
+++ b/src/drivers/driver_nl80211.c
|
|
-@@ -2931,10 +2931,15 @@ static int wpa_driver_nl80211_del_beacon
|
|
- struct nl_msg *msg;
|
|
- struct wpa_driver_nl80211_data *drv = bss->drv;
|
|
+@@ -3008,12 +3008,12 @@ static int wpa_driver_nl80211_del_beacon
|
|
+ return 0;
|
|
|
|
-+ if (!bss->beacon_set)
|
|
-+ return 0;
|
|
-+
|
|
-+ bss->beacon_set = 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);
|
|
- return send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL);
|
|
- }
|
|
+ if (!msg)
|
|
+ return -ENOBUFS;
|
|
|
|
-@@ -5617,7 +5622,7 @@ static void nl80211_teardown_ap(struct i
|
|
+@@ -6100,7 +6100,7 @@ static void nl80211_teardown_ap(struct i
|
|
nl80211_mgmt_unsubscribe(bss, "AP teardown");
|
|
|
|
nl80211_put_wiphy_data_ap(bss);
|
|
-- bss->beacon_set = 0;
|
|
-+ wpa_driver_nl80211_del_beacon(bss);
|
|
+- bss->flink->beacon_set = 0;
|
|
++ wpa_driver_nl80211_del_beacon_all(bss);
|
|
}
|
|
|
|
|
|
-@@ -8071,8 +8076,6 @@ static int wpa_driver_nl80211_if_remove(
|
|
+@@ -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(bss);
|
|
+- wpa_driver_nl80211_del_beacon_all(bss);
|
|
nl80211_destroy_bss(bss);
|
|
if (!bss->added_if)
|
|
i802_set_iface_flags(bss, 0);
|
|
-@@ -8469,7 +8472,6 @@ static int wpa_driver_nl80211_deinit_ap(
|
|
- if (!is_ap_interface(drv->nlmode))
|
|
- return -1;
|
|
- wpa_driver_nl80211_del_beacon(bss);
|
|
-- bss->beacon_set = 0;
|
|
-
|
|
- /*
|
|
- * If the P2P GO interface was dynamically added, then it is
|
|
-@@ -8489,7 +8491,6 @@ static int wpa_driver_nl80211_stop_ap(vo
|
|
- if (!is_ap_interface(drv->nlmode))
|
|
- return -1;
|
|
- wpa_driver_nl80211_del_beacon(bss);
|
|
-- bss->beacon_set = 0;
|
|
- return 0;
|
|
- }
|
|
-
|
|
diff --git a/package/network/services/hostapd/patches/360-ctrl_iface_reload.patch b/package/network/services/hostapd/patches/360-ctrl_iface_reload.patch
|
|
index 7f3aa91889..4d85ea11f9 100644
|
|
--- a/package/network/services/hostapd/patches/360-ctrl_iface_reload.patch
|
|
+++ b/package/network/services/hostapd/patches/360-ctrl_iface_reload.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/hostapd/ctrl_iface.c
|
|
+++ b/hostapd/ctrl_iface.c
|
|
-@@ -67,6 +67,7 @@
|
|
+@@ -68,6 +68,7 @@
|
|
#include "fst/fst_ctrl_iface.h"
|
|
#include "config_file.h"
|
|
#include "ctrl_iface.h"
|
|
@@ -8,7 +8,7 @@
|
|
|
|
|
|
#define HOSTAPD_CLI_DUP_VALUE_MAX_LEN 256
|
|
-@@ -82,6 +83,7 @@ static void hostapd_ctrl_iface_send(stru
|
|
+@@ -83,6 +84,7 @@ static void hostapd_ctrl_iface_send(stru
|
|
enum wpa_msg_type type,
|
|
const char *buf, size_t len);
|
|
|
|
@@ -16,7 +16,7 @@
|
|
|
|
static int hostapd_ctrl_iface_attach(struct hostapd_data *hapd,
|
|
struct sockaddr_storage *from,
|
|
-@@ -133,6 +135,61 @@ static int hostapd_ctrl_iface_new_sta(st
|
|
+@@ -134,6 +136,61 @@ static int hostapd_ctrl_iface_new_sta(st
|
|
return 0;
|
|
}
|
|
|
|
@@ -78,7 +78,7 @@
|
|
|
|
#ifdef NEED_AP_MLME
|
|
static int hostapd_ctrl_iface_sa_query(struct hostapd_data *hapd,
|
|
-@@ -3771,6 +3828,8 @@ static int hostapd_ctrl_iface_receive_pr
|
|
+@@ -3564,6 +3621,8 @@ static int hostapd_ctrl_iface_receive_pr
|
|
} else if (os_strncmp(buf, "VENDOR ", 7) == 0) {
|
|
reply_len = hostapd_ctrl_iface_vendor(hapd, buf + 7, reply,
|
|
reply_size);
|
|
@@ -89,7 +89,7 @@
|
|
#ifdef RADIUS_SERVER
|
|
--- a/src/ap/ctrl_iface_ap.c
|
|
+++ b/src/ap/ctrl_iface_ap.c
|
|
-@@ -927,7 +927,13 @@ int hostapd_parse_csa_settings(const cha
|
|
+@@ -1023,7 +1023,13 @@ int hostapd_parse_csa_settings(const cha
|
|
|
|
int hostapd_ctrl_iface_stop_ap(struct hostapd_data *hapd)
|
|
{
|
|
diff --git a/package/network/services/hostapd/patches/370-ap_sta_support.patch b/package/network/services/hostapd/patches/370-ap_sta_support.patch
|
|
index c81c841a43..3baad2a52e 100644
|
|
--- a/package/network/services/hostapd/patches/370-ap_sta_support.patch
|
|
+++ b/package/network/services/hostapd/patches/370-ap_sta_support.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/wpa_supplicant/Makefile
|
|
+++ b/wpa_supplicant/Makefile
|
|
-@@ -108,6 +108,8 @@ OBJS_c += ../src/utils/common.o
|
|
+@@ -126,6 +126,8 @@ OBJS_c += ../src/utils/common.o
|
|
OBJS_c += ../src/common/cli.o
|
|
OBJS += wmm_ac.o
|
|
|
|
@@ -19,7 +19,7 @@
|
|
#include "drivers/driver.h"
|
|
#include "eap_peer/eap.h"
|
|
#include "wpa_supplicant_i.h"
|
|
-@@ -282,6 +283,10 @@ void calculate_update_time(const struct
|
|
+@@ -283,6 +284,10 @@ void calculate_update_time(const struct
|
|
static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src,
|
|
struct os_reltime *fetch_time)
|
|
{
|
|
@@ -30,7 +30,7 @@
|
|
dst->flags = src->flags;
|
|
os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
|
|
dst->freq = src->freq;
|
|
-@@ -294,6 +299,15 @@ static void wpa_bss_copy_res(struct wpa_
|
|
+@@ -296,6 +301,15 @@ static void wpa_bss_copy_res(struct wpa_
|
|
dst->est_throughput = src->est_throughput;
|
|
dst->snr = src->snr;
|
|
|
|
@@ -61,7 +61,7 @@
|
|
/** Beacon interval in TUs (host byte order) */
|
|
--- a/wpa_supplicant/main.c
|
|
+++ b/wpa_supplicant/main.c
|
|
-@@ -34,7 +34,7 @@ static void usage(void)
|
|
+@@ -35,7 +35,7 @@ static void usage(void)
|
|
"vW] [-P<pid file>] "
|
|
"[-g<global ctrl>] \\\n"
|
|
" [-G<group>] \\\n"
|
|
@@ -70,7 +70,7 @@
|
|
"[-p<driver_param>] \\\n"
|
|
" [-b<br_ifname>] [-e<entropy file>]"
|
|
#ifdef CONFIG_DEBUG_FILE
|
|
-@@ -74,6 +74,7 @@ static void usage(void)
|
|
+@@ -75,6 +75,7 @@ static void usage(void)
|
|
" -g = global ctrl_interface\n"
|
|
" -G = global ctrl_interface group\n"
|
|
" -h = show this help text\n"
|
|
@@ -78,7 +78,7 @@
|
|
" -i = interface name\n"
|
|
" -I = additional configuration file\n"
|
|
" -K = include keys (passwords, etc.) in debug output\n"
|
|
-@@ -201,7 +202,7 @@ int main(int argc, char *argv[])
|
|
+@@ -202,7 +203,7 @@ int main(int argc, char *argv[])
|
|
|
|
for (;;) {
|
|
c = getopt(argc, argv,
|
|
@@ -87,7 +87,7 @@
|
|
if (c < 0)
|
|
break;
|
|
switch (c) {
|
|
-@@ -248,6 +249,9 @@ int main(int argc, char *argv[])
|
|
+@@ -249,6 +250,9 @@ int main(int argc, char *argv[])
|
|
usage();
|
|
exitcode = 0;
|
|
goto out;
|
|
@@ -99,7 +99,7 @@
|
|
break;
|
|
--- a/wpa_supplicant/wpa_supplicant.c
|
|
+++ b/wpa_supplicant/wpa_supplicant.c
|
|
-@@ -130,6 +130,54 @@ static void wpas_update_fils_connect_par
|
|
+@@ -131,6 +131,54 @@ static void wpas_update_fils_connect_par
|
|
static void wpas_update_owe_connect_params(struct wpa_supplicant *wpa_s);
|
|
#endif /* CONFIG_OWE */
|
|
|
|
@@ -154,7 +154,7 @@
|
|
|
|
#ifdef CONFIG_WEP
|
|
/* Configure default/group WEP keys for static WEP */
|
|
-@@ -1015,6 +1063,8 @@ void wpa_supplicant_set_state(struct wpa
|
|
+@@ -1026,6 +1074,8 @@ void wpa_supplicant_set_state(struct wpa
|
|
|
|
sme_sched_obss_scan(wpa_s, 1);
|
|
|
|
@@ -163,7 +163,7 @@
|
|
#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
|
|
if (!fils_hlp_sent && ssid && ssid->eap.erp)
|
|
update_fils_connect_params = true;
|
|
-@@ -1025,6 +1075,8 @@ void wpa_supplicant_set_state(struct wpa
|
|
+@@ -1036,6 +1086,8 @@ void wpa_supplicant_set_state(struct wpa
|
|
#endif /* CONFIG_OWE */
|
|
} else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
|
|
state == WPA_ASSOCIATED) {
|
|
@@ -172,7 +172,7 @@
|
|
wpa_s->new_connection = 1;
|
|
wpa_drv_set_operstate(wpa_s, 0);
|
|
#ifndef IEEE8021X_EAPOL
|
|
-@@ -2308,6 +2360,8 @@ void wpa_supplicant_associate(struct wpa
|
|
+@@ -2537,6 +2589,8 @@ void wpa_supplicant_associate(struct wpa
|
|
return;
|
|
}
|
|
wpa_s->current_bss = bss;
|
|
@@ -181,7 +181,7 @@
|
|
#else /* CONFIG_MESH */
|
|
wpa_msg(wpa_s, MSG_ERROR,
|
|
"mesh mode support not included in the build");
|
|
-@@ -6650,6 +6704,16 @@ static int wpa_supplicant_init_iface(str
|
|
+@@ -7037,6 +7091,16 @@ static int wpa_supplicant_init_iface(str
|
|
sizeof(wpa_s->bridge_ifname));
|
|
}
|
|
|
|
@@ -198,7 +198,7 @@
|
|
/* RSNA Supplicant Key Management - INITIALIZE */
|
|
eapol_sm_notify_portEnabled(wpa_s->eapol, false);
|
|
eapol_sm_notify_portValid(wpa_s->eapol, false);
|
|
-@@ -6987,6 +7051,11 @@ static void wpa_supplicant_deinit_iface(
|
|
+@@ -7379,6 +7443,11 @@ static void wpa_supplicant_deinit_iface(
|
|
if (terminate)
|
|
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING);
|
|
|
|
@@ -212,7 +212,7 @@
|
|
|
|
--- a/wpa_supplicant/wpa_supplicant_i.h
|
|
+++ b/wpa_supplicant/wpa_supplicant_i.h
|
|
-@@ -104,6 +104,11 @@ struct wpa_interface {
|
|
+@@ -106,6 +106,11 @@ struct wpa_interface {
|
|
const char *ifname;
|
|
|
|
/**
|
|
@@ -224,7 +224,7 @@
|
|
* bridge_ifname - Optional bridge interface name
|
|
*
|
|
* If the driver interface (ifname) is included in a Linux bridge
|
|
-@@ -718,6 +723,8 @@ struct wpa_supplicant {
|
|
+@@ -665,6 +670,8 @@ struct wpa_supplicant {
|
|
#endif /* CONFIG_CTRL_IFACE_BINDER */
|
|
char bridge_ifname[16];
|
|
|
|
@@ -235,7 +235,7 @@
|
|
|
|
--- a/hostapd/ctrl_iface.c
|
|
+++ b/hostapd/ctrl_iface.c
|
|
-@@ -2889,6 +2889,12 @@ static int hostapd_ctrl_iface_chan_switc
|
|
+@@ -2751,6 +2751,12 @@ static int hostapd_ctrl_iface_chan_switc
|
|
return 0;
|
|
}
|
|
|
|
@@ -247,10 +247,10 @@
|
|
+
|
|
for (i = 0; i < iface->num_bss; i++) {
|
|
|
|
- /* Save CHAN_SWITCH VHT and HE config */
|
|
+ /* Save CHAN_SWITCH VHT, HE, and EHT config */
|
|
--- a/src/ap/beacon.c
|
|
+++ b/src/ap/beacon.c
|
|
-@@ -1791,11 +1791,6 @@ static int __ieee802_11_set_beacon(struc
|
|
+@@ -2108,11 +2108,6 @@ static int __ieee802_11_set_beacon(struc
|
|
return -1;
|
|
}
|
|
|
|
@@ -264,7 +264,7 @@
|
|
if (ieee802_11_build_ap_params(hapd, ¶ms) < 0)
|
|
--- a/wpa_supplicant/events.c
|
|
+++ b/wpa_supplicant/events.c
|
|
-@@ -4891,6 +4891,60 @@ static void wpas_event_unprot_beacon(str
|
|
+@@ -5345,6 +5345,60 @@ static void wpas_link_reconfig(struct wp
|
|
}
|
|
|
|
|
|
@@ -325,7 +325,7 @@
|
|
void supplicant_event(void *ctx, enum wpa_event_type event,
|
|
union wpa_event_data *data)
|
|
{
|
|
-@@ -5206,8 +5260,10 @@ void supplicant_event(void *ctx, enum wp
|
|
+@@ -5697,8 +5751,10 @@ void supplicant_event(void *ctx, enum wp
|
|
channel_width_to_string(data->ch_switch.ch_width),
|
|
data->ch_switch.cf1,
|
|
data->ch_switch.cf2);
|
|
@@ -339,7 +339,7 @@
|
|
wpa_s->current_ssid->frequency = data->ch_switch.freq;
|
|
--- a/src/drivers/driver.h
|
|
+++ b/src/drivers/driver.h
|
|
-@@ -5837,6 +5837,7 @@ union wpa_event_data {
|
|
+@@ -6421,6 +6421,7 @@ union wpa_event_data {
|
|
|
|
/**
|
|
* struct ch_switch
|
|
@@ -347,8 +347,8 @@
|
|
* @freq: Frequency of new channel in MHz
|
|
* @ht_enabled: Whether this is an HT channel
|
|
* @ch_offset: Secondary channel offset
|
|
-@@ -5845,6 +5846,7 @@ union wpa_event_data {
|
|
- * @cf2: Center frequency 2
|
|
+@@ -6431,6 +6432,7 @@ union wpa_event_data {
|
|
+ * @punct_bitmap: Puncturing bitmap
|
|
*/
|
|
struct ch_switch {
|
|
+ int count;
|
|
@@ -357,16 +357,15 @@
|
|
int ch_offset;
|
|
--- a/src/drivers/driver_nl80211_event.c
|
|
+++ b/src/drivers/driver_nl80211_event.c
|
|
-@@ -684,7 +684,7 @@ static void mlme_event_ch_switch(struct
|
|
- struct nlattr *ifindex, struct nlattr *freq,
|
|
- struct nlattr *type, struct nlattr *bw,
|
|
- struct nlattr *cf1, struct nlattr *cf2,
|
|
-- int finished)
|
|
-+ struct nlattr *count, int finished)
|
|
+@@ -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;
|
|
- union wpa_event_data data;
|
|
-@@ -745,6 +745,8 @@ static void mlme_event_ch_switch(struct
|
|
+@@ -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);
|
|
@@ -374,19 +373,19 @@
|
|
+ data.ch_switch.count = nla_get_u32(count);
|
|
|
|
if (finished)
|
|
- bss->freq = data.ch_switch.freq;
|
|
-@@ -3003,6 +3005,7 @@ static void do_process_drv_event(struct
|
|
- tb[NL80211_ATTR_CHANNEL_WIDTH],
|
|
+ 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:
|
|
-@@ -3013,6 +3016,7 @@ static void do_process_drv_event(struct
|
|
- tb[NL80211_ATTR_CHANNEL_WIDTH],
|
|
+@@ -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;
|
|
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
|
|
index 92b52a6d37..456599db09 100644
|
|
--- a/package/network/services/hostapd/patches/380-disable_ctrl_iface_mib.patch
|
|
+++ b/package/network/services/hostapd/patches/380-disable_ctrl_iface_mib.patch
|
|
@@ -12,7 +12,7 @@
|
|
else
|
|
--- a/hostapd/ctrl_iface.c
|
|
+++ b/hostapd/ctrl_iface.c
|
|
-@@ -3587,6 +3587,7 @@ static int hostapd_ctrl_iface_receive_pr
|
|
+@@ -3377,6 +3377,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);
|
|
@@ -20,7 +20,7 @@
|
|
} else if (os_strcmp(buf, "MIB") == 0) {
|
|
reply_len = ieee802_11_get_mib(hapd, reply, reply_size);
|
|
if (reply_len >= 0) {
|
|
-@@ -3628,6 +3629,7 @@ static int hostapd_ctrl_iface_receive_pr
|
|
+@@ -3418,6 +3419,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);
|
|
@@ -30,7 +30,7 @@
|
|
reply_len = -1;
|
|
--- a/wpa_supplicant/Makefile
|
|
+++ b/wpa_supplicant/Makefile
|
|
-@@ -958,6 +958,9 @@ ifdef CONFIG_FILS
|
|
+@@ -985,6 +985,9 @@ ifdef CONFIG_FILS
|
|
OBJS += ../src/ap/fils_hlp.o
|
|
endif
|
|
ifdef CONFIG_CTRL_IFACE
|
|
@@ -42,7 +42,7 @@
|
|
|
|
--- a/wpa_supplicant/ctrl_iface.c
|
|
+++ b/wpa_supplicant/ctrl_iface.c
|
|
-@@ -2314,7 +2314,7 @@ static int wpa_supplicant_ctrl_iface_sta
|
|
+@@ -2326,7 +2326,7 @@ static int wpa_supplicant_ctrl_iface_sta
|
|
pos += ret;
|
|
}
|
|
|
|
@@ -51,7 +51,7 @@
|
|
if (wpa_s->ap_iface) {
|
|
pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
|
|
end - pos,
|
|
-@@ -11494,6 +11494,7 @@ char * wpa_supplicant_ctrl_iface_process
|
|
+@@ -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);
|
|
@@ -59,7 +59,7 @@
|
|
} else if (os_strcmp(buf, "MIB") == 0) {
|
|
reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
|
|
if (reply_len >= 0) {
|
|
-@@ -11506,6 +11507,7 @@ char * wpa_supplicant_ctrl_iface_process
|
|
+@@ -11976,6 +11977,7 @@ char * wpa_supplicant_ctrl_iface_process
|
|
reply_size - reply_len);
|
|
#endif /* CONFIG_MACSEC */
|
|
}
|
|
@@ -67,7 +67,7 @@
|
|
} else if (os_strncmp(buf, "STATUS", 6) == 0) {
|
|
reply_len = wpa_supplicant_ctrl_iface_status(
|
|
wpa_s, buf + 6, reply, reply_size);
|
|
-@@ -11994,6 +11996,7 @@ char * wpa_supplicant_ctrl_iface_process
|
|
+@@ -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
|
|
@@ -75,7 +75,7 @@
|
|
} 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) {
|
|
-@@ -12002,12 +12005,15 @@ char * wpa_supplicant_ctrl_iface_process
|
|
+@@ -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);
|
|
@@ -93,15 +93,61 @@
|
|
reply_len = -1;
|
|
--- a/src/ap/ctrl_iface_ap.c
|
|
+++ b/src/ap/ctrl_iface_ap.c
|
|
-@@ -25,6 +25,7 @@
|
|
- #include "mbo_ap.h"
|
|
+@@ -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)
|
|
-@@ -459,6 +460,7 @@ int hostapd_ctrl_iface_sta_next(struct h
|
|
+@@ -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);
|
|
}
|
|
|
|
@@ -109,7 +155,7 @@
|
|
|
|
#ifdef CONFIG_P2P_MANAGER
|
|
static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype,
|
|
-@@ -815,12 +817,12 @@ int hostapd_ctrl_iface_status(struct hos
|
|
+@@ -884,12 +885,12 @@ int hostapd_ctrl_iface_status(struct hos
|
|
return len;
|
|
len += ret;
|
|
}
|
|
@@ -126,7 +172,7 @@
|
|
if (os_snprintf_error(buflen - len, ret))
|
|
--- a/src/ap/ieee802_1x.c
|
|
+++ b/src/ap/ieee802_1x.c
|
|
-@@ -2712,6 +2712,7 @@ static const char * bool_txt(bool val)
|
|
+@@ -2834,6 +2834,7 @@ static const char * bool_txt(bool val)
|
|
return val ? "TRUE" : "FALSE";
|
|
}
|
|
|
|
@@ -134,7 +180,7 @@
|
|
|
|
int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen)
|
|
{
|
|
-@@ -2898,6 +2899,7 @@ int ieee802_1x_get_mib_sta(struct hostap
|
|
+@@ -3020,6 +3021,7 @@ int ieee802_1x_get_mib_sta(struct hostap
|
|
return len;
|
|
}
|
|
|
|
@@ -144,7 +190,7 @@
|
|
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
|
|
-@@ -4519,6 +4519,7 @@ static const char * wpa_bool_txt(int val
|
|
+@@ -5328,6 +5328,7 @@ static const char * wpa_bool_txt(int val
|
|
return val ? "TRUE" : "FALSE";
|
|
}
|
|
|
|
@@ -152,7 +198,7 @@
|
|
|
|
#define RSN_SUITE "%02x-%02x-%02x-%d"
|
|
#define RSN_SUITE_ARG(s) \
|
|
-@@ -4669,7 +4670,7 @@ int wpa_get_mib_sta(struct wpa_state_mac
|
|
+@@ -5480,7 +5481,7 @@ int wpa_get_mib_sta(struct wpa_state_mac
|
|
|
|
return len;
|
|
}
|
|
@@ -163,7 +209,7 @@
|
|
{
|
|
--- a/src/rsn_supp/wpa.c
|
|
+++ b/src/rsn_supp/wpa.c
|
|
-@@ -2777,6 +2777,8 @@ static u32 wpa_key_mgmt_suite(struct wpa
|
|
+@@ -3834,6 +3834,8 @@ static u32 wpa_key_mgmt_suite(struct wpa
|
|
}
|
|
|
|
|
|
@@ -172,7 +218,7 @@
|
|
#define RSN_SUITE "%02x-%02x-%02x-%d"
|
|
#define RSN_SUITE_ARG(s) \
|
|
((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff
|
|
-@@ -2858,6 +2860,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch
|
|
+@@ -3915,6 +3917,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch
|
|
|
|
return (int) len;
|
|
}
|
|
@@ -182,7 +228,7 @@
|
|
|
|
--- a/wpa_supplicant/ap.c
|
|
+++ b/wpa_supplicant/ap.c
|
|
-@@ -1462,7 +1462,7 @@ int wpas_ap_wps_nfc_report_handover(stru
|
|
+@@ -1499,7 +1499,7 @@ int wpas_ap_wps_nfc_report_handover(stru
|
|
#endif /* CONFIG_WPS */
|
|
|
|
|
|
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
|
|
index d2414faf01..e9083f6ecc 100644
|
|
--- a/package/network/services/hostapd/patches/381-hostapd_cli_UNKNOWN-COMMAND.patch
|
|
+++ b/package/network/services/hostapd/patches/381-hostapd_cli_UNKNOWN-COMMAND.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/hostapd/hostapd_cli.c
|
|
+++ b/hostapd/hostapd_cli.c
|
|
-@@ -744,7 +744,7 @@ static int wpa_ctrl_command_sta(struct w
|
|
+@@ -757,7 +757,7 @@ static int wpa_ctrl_command_sta(struct w
|
|
}
|
|
|
|
buf[len] = '\0';
|
|
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
|
|
index 65a8b07e65..40c39ff29c 100644
|
|
--- a/package/network/services/hostapd/patches/390-wpa_ie_cap_workaround.patch
|
|
+++ b/package/network/services/hostapd/patches/390-wpa_ie_cap_workaround.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/src/common/wpa_common.c
|
|
+++ b/src/common/wpa_common.c
|
|
-@@ -2444,6 +2444,31 @@ u32 wpa_akm_to_suite(int akm)
|
|
+@@ -2719,6 +2719,31 @@ u32 wpa_akm_to_suite(int akm)
|
|
}
|
|
|
|
|
|
@@ -32,7 +32,7 @@
|
|
int wpa_compare_rsn_ie(int ft_initial_assoc,
|
|
const u8 *ie1, size_t ie1len,
|
|
const u8 *ie2, size_t ie2len)
|
|
-@@ -2451,8 +2476,19 @@ int wpa_compare_rsn_ie(int ft_initial_as
|
|
+@@ -2726,8 +2751,19 @@ int wpa_compare_rsn_ie(int ft_initial_as
|
|
if (ie1 == NULL || ie2 == NULL)
|
|
return -1;
|
|
|
|
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
|
|
index f708bf39ba..edcd985257 100644
|
|
--- 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
|
|
@@ -11,7 +11,7 @@
|
|
bss->wpa_pairwise |= WPA_CIPHER_TKIP;
|
|
#endif /* CONFIG_NO_TKIP */
|
|
bss->rsn_pairwise = bss->wpa_pairwise;
|
|
-@@ -1180,8 +1179,7 @@ int hostapd_init_wps(struct hostapd_data
|
|
+@@ -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;
|
|
diff --git a/package/network/services/hostapd/patches/410-limit_debug_messages.patch b/package/network/services/hostapd/patches/410-limit_debug_messages.patch
|
|
index d2713fc29b..48a5589200 100644
|
|
--- a/package/network/services/hostapd/patches/410-limit_debug_messages.patch
|
|
+++ b/package/network/services/hostapd/patches/410-limit_debug_messages.patch
|
|
@@ -60,7 +60,7 @@
|
|
#ifdef CONFIG_DEBUG_FILE
|
|
static char *last_path = NULL;
|
|
#endif /* CONFIG_DEBUG_FILE */
|
|
-@@ -636,7 +610,7 @@ void wpa_msg_register_ifname_cb(wpa_msg_
|
|
+@@ -644,7 +618,7 @@ void wpa_msg_register_ifname_cb(wpa_msg_
|
|
}
|
|
|
|
|
|
@@ -69,7 +69,7 @@
|
|
{
|
|
va_list ap;
|
|
char *buf;
|
|
-@@ -674,7 +648,7 @@ void wpa_msg(void *ctx, int level, const
|
|
+@@ -682,7 +656,7 @@ void wpa_msg(void *ctx, int level, const
|
|
}
|
|
|
|
|
|
@@ -80,9 +80,9 @@
|
|
char *buf;
|
|
--- a/src/utils/wpa_debug.h
|
|
+++ b/src/utils/wpa_debug.h
|
|
-@@ -50,6 +50,17 @@ int wpa_debug_reopen_file(void);
|
|
- void wpa_debug_close_file(void);
|
|
+@@ -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,
|
|
@@ -98,7 +98,7 @@
|
|
/**
|
|
* wpa_debug_printf_timestamp - Print timestamp for debug output
|
|
*
|
|
-@@ -70,9 +81,15 @@ void wpa_debug_print_timestamp(void);
|
|
+@@ -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.
|
|
*/
|
|
@@ -115,7 +115,7 @@
|
|
/**
|
|
* wpa_hexdump - conditional hex dump
|
|
* @level: priority level (MSG_*) of the message
|
|
-@@ -84,7 +101,13 @@ PRINTF_FORMAT(2, 3);
|
|
+@@ -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.
|
|
*/
|
|
@@ -130,7 +130,7 @@
|
|
|
|
static inline void wpa_hexdump_buf(int level, const char *title,
|
|
const struct wpabuf *buf)
|
|
-@@ -106,7 +129,13 @@ static inline void wpa_hexdump_buf(int l
|
|
+@@ -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.
|
|
*/
|
|
@@ -145,7 +145,7 @@
|
|
|
|
static inline void wpa_hexdump_buf_key(int level, const char *title,
|
|
const struct wpabuf *buf)
|
|
-@@ -128,8 +157,14 @@ static inline void wpa_hexdump_buf_key(i
|
|
+@@ -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.
|
|
*/
|
|
@@ -162,7 +162,7 @@
|
|
|
|
/**
|
|
* wpa_hexdump_ascii_key - conditional hex dump, hide keys
|
|
-@@ -145,8 +180,14 @@ void wpa_hexdump_ascii(int level, const
|
|
+@@ -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.
|
|
*/
|
|
@@ -179,7 +179,7 @@
|
|
|
|
/*
|
|
* wpa_dbg() behaves like wpa_msg(), but it can be removed from build to reduce
|
|
-@@ -183,7 +224,12 @@ void wpa_hexdump_ascii_key(int level, co
|
|
+@@ -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.
|
|
*/
|
|
@@ -193,7 +193,7 @@
|
|
|
|
/**
|
|
* wpa_msg_ctrl - Conditional printf for ctrl_iface monitors
|
|
-@@ -197,8 +243,13 @@ void wpa_msg(void *ctx, int level, const
|
|
+@@ -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.
|
|
*/
|
|
diff --git a/package/network/services/hostapd/patches/420-indicate-features.patch b/package/network/services/hostapd/patches/420-indicate-features.patch
|
|
index f9dff66073..786b83d315 100644
|
|
--- a/package/network/services/hostapd/patches/420-indicate-features.patch
|
|
+++ b/package/network/services/hostapd/patches/420-indicate-features.patch
|
|
@@ -1,23 +1,24 @@
|
|
--- a/hostapd/main.c
|
|
+++ b/hostapd/main.c
|
|
-@@ -15,6 +15,7 @@
|
|
- #include "utils/common.h"
|
|
- #include "utils/eloop.h"
|
|
- #include "utils/uuid.h"
|
|
-+#include "utils/build_features.h"
|
|
- #include "crypto/random.h"
|
|
- #include "crypto/tls.h"
|
|
- #include "common/version.h"
|
|
-@@ -691,7 +692,7 @@ int main(int argc, char *argv[])
|
|
+@@ -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:");
|
|
-+ c = getopt(argc, argv, "b:Bde:f:hi:KP:sSTtu:g:G:v::");
|
|
+- 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) {
|
|
-@@ -728,6 +729,8 @@ int main(int argc, char *argv[])
|
|
+@@ -823,6 +823,8 @@ int main(int argc, char *argv[])
|
|
break;
|
|
#endif /* CONFIG_DEBUG_LINUX_TRACING */
|
|
case 'v':
|
|
@@ -25,7 +26,7 @@
|
|
+ exit(!has_feature(optarg));
|
|
show_version();
|
|
exit(1);
|
|
- break;
|
|
+ case 'g':
|
|
--- a/wpa_supplicant/main.c
|
|
+++ b/wpa_supplicant/main.c
|
|
@@ -12,6 +12,7 @@
|
|
@@ -33,10 +34,10 @@
|
|
|
|
#include "common.h"
|
|
+#include "build_features.h"
|
|
+ #include "crypto/crypto.h"
|
|
#include "fst/fst.h"
|
|
#include "wpa_supplicant_i.h"
|
|
- #include "driver_i.h"
|
|
-@@ -202,7 +203,7 @@ int main(int argc, char *argv[])
|
|
+@@ -203,7 +204,7 @@ int main(int argc, char *argv[])
|
|
|
|
for (;;) {
|
|
c = getopt(argc, argv,
|
|
@@ -45,7 +46,7 @@
|
|
if (c < 0)
|
|
break;
|
|
switch (c) {
|
|
-@@ -305,8 +306,12 @@ int main(int argc, char *argv[])
|
|
+@@ -306,8 +307,12 @@ int main(int argc, char *argv[])
|
|
break;
|
|
#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
|
|
case 'v':
|
|
diff --git a/package/network/services/hostapd/patches/430-hostapd_cli_ifdef.patch b/package/network/services/hostapd/patches/430-hostapd_cli_ifdef.patch
|
|
index dc1fa3d29d..a21f0bf7ce 100644
|
|
--- a/package/network/services/hostapd/patches/430-hostapd_cli_ifdef.patch
|
|
+++ b/package/network/services/hostapd/patches/430-hostapd_cli_ifdef.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/hostapd/hostapd_cli.c
|
|
+++ b/hostapd/hostapd_cli.c
|
|
-@@ -388,7 +388,6 @@ static int hostapd_cli_cmd_disassociate(
|
|
+@@ -401,7 +401,6 @@ static int hostapd_cli_cmd_disassociate(
|
|
}
|
|
|
|
|
|
@@ -8,7 +8,7 @@
|
|
static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc,
|
|
char *argv[])
|
|
{
|
|
-@@ -401,7 +400,6 @@ static int hostapd_cli_cmd_signature(str
|
|
+@@ -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);
|
|
}
|
|
@@ -16,7 +16,7 @@
|
|
|
|
|
|
static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
|
|
-@@ -418,7 +416,6 @@ static int hostapd_cli_cmd_sa_query(stru
|
|
+@@ -431,7 +429,6 @@ static int hostapd_cli_cmd_sa_query(stru
|
|
}
|
|
|
|
|
|
@@ -24,7 +24,7 @@
|
|
static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
|
|
char *argv[])
|
|
{
|
|
-@@ -644,7 +641,6 @@ static int hostapd_cli_cmd_wps_config(st
|
|
+@@ -657,7 +654,6 @@ static int hostapd_cli_cmd_wps_config(st
|
|
ssid_hex, argv[1]);
|
|
return wpa_ctrl_command(ctrl, buf);
|
|
}
|
|
@@ -32,7 +32,7 @@
|
|
|
|
|
|
static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
|
|
-@@ -1579,13 +1575,10 @@ static const struct hostapd_cli_cmd host
|
|
+@@ -1610,13 +1606,10 @@ static const struct hostapd_cli_cmd host
|
|
{ "disassociate", hostapd_cli_cmd_disassociate,
|
|
hostapd_complete_stations,
|
|
"<addr> = disassociate a station" },
|
|
@@ -46,7 +46,7 @@
|
|
{ "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,
|
|
-@@ -1610,7 +1603,6 @@ static const struct hostapd_cli_cmd host
|
|
+@@ -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" },
|
|
diff --git a/package/network/services/hostapd/patches/432-missing-typedef.patch b/package/network/services/hostapd/patches/432-missing-typedef.patch
|
|
deleted file mode 100644
|
|
index 7a100f1a0d..0000000000
|
|
--- a/package/network/services/hostapd/patches/432-missing-typedef.patch
|
|
+++ /dev/null
|
|
@@ -1,10 +0,0 @@
|
|
---- a/src/drivers/linux_wext.h
|
|
-+++ b/src/drivers/linux_wext.h
|
|
-@@ -26,6 +26,7 @@ typedef int32_t __s32;
|
|
- typedef uint16_t __u16;
|
|
- typedef int16_t __s16;
|
|
- typedef uint8_t __u8;
|
|
-+typedef int8_t __s8;
|
|
- #ifndef __user
|
|
- #define __user
|
|
- #endif /* __user */
|
|
diff --git a/package/network/services/hostapd/patches/450-scan_wait.patch b/package/network/services/hostapd/patches/450-scan_wait.patch
|
|
index ac874ad66a..45886896ee 100644
|
|
--- a/package/network/services/hostapd/patches/450-scan_wait.patch
|
|
+++ b/package/network/services/hostapd/patches/450-scan_wait.patch
|
|
@@ -24,16 +24,16 @@
|
|
|
|
/**
|
|
* hostapd_driver_init - Preparate driver interface
|
|
-@@ -164,6 +174,8 @@ static int hostapd_driver_init(struct ho
|
|
- return -1;
|
|
+@@ -217,6 +227,8 @@ static int hostapd_driver_init(struct ho
|
|
}
|
|
+ #endif /* CONFIG_IEEE80211BE */
|
|
|
|
+ hapd->setup_complete_cb = hostapd_setup_complete_cb;
|
|
+
|
|
/* Initialize the driver interface */
|
|
if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5]))
|
|
b = NULL;
|
|
-@@ -404,8 +416,6 @@ static void hostapd_global_deinit(const
|
|
+@@ -497,8 +509,6 @@ static void hostapd_global_deinit(const
|
|
#endif /* CONFIG_NATIVE_WINDOWS */
|
|
|
|
eap_server_unregister_methods();
|
|
@@ -42,7 +42,7 @@
|
|
}
|
|
|
|
|
|
-@@ -431,18 +441,6 @@ static int hostapd_global_run(struct hap
|
|
+@@ -524,18 +534,6 @@ static int hostapd_global_run(struct hap
|
|
}
|
|
#endif /* EAP_SERVER_TNC */
|
|
|
|
@@ -61,7 +61,7 @@
|
|
eloop_run();
|
|
|
|
return 0;
|
|
-@@ -645,8 +643,7 @@ int main(int argc, char *argv[])
|
|
+@@ -739,8 +737,7 @@ int main(int argc, char *argv[])
|
|
struct hapd_interfaces interfaces;
|
|
int ret = 1;
|
|
size_t i, j;
|
|
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
|
|
index 28f07c7dc2..4c72868139 100644
|
|
--- 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
|
|
@@ -22,7 +22,7 @@ Signed-hostap: Antonio Quartulli <ordex@autistici.org>
|
|
#include "common/defs.h"
|
|
#include "common/ieee802_11_defs.h"
|
|
#include "common/wpa_common.h"
|
|
-@@ -857,6 +858,9 @@ struct wpa_driver_associate_params {
|
|
+@@ -953,6 +954,9 @@ struct wpa_driver_associate_params {
|
|
* responsible for selecting with which BSS to associate. */
|
|
const u8 *bssid;
|
|
|
|
@@ -42,7 +42,7 @@ Signed-hostap: Antonio Quartulli <ordex@autistici.org>
|
|
#include "config.h"
|
|
|
|
|
|
-@@ -2321,6 +2322,97 @@ static char * wpa_config_write_peerkey(c
|
|
+@@ -2389,6 +2390,97 @@ static char * wpa_config_write_mac_value
|
|
#endif /* NO_CONFIG_WRITE */
|
|
|
|
|
|
@@ -140,7 +140,7 @@ Signed-hostap: Antonio Quartulli <ordex@autistici.org>
|
|
/* Helper macros for network block parser */
|
|
|
|
#ifdef OFFSET
|
|
-@@ -2606,6 +2698,8 @@ static const struct parse_data ssid_fiel
|
|
+@@ -2674,6 +2766,8 @@ static const struct parse_data ssid_fiel
|
|
{ INT(ap_max_inactivity) },
|
|
{ INT(dtim_period) },
|
|
{ INT(beacon_int) },
|
|
@@ -162,7 +162,7 @@ Signed-hostap: Antonio Quartulli <ordex@autistici.org>
|
|
|
|
|
|
#define DEFAULT_EAP_WORKAROUND ((unsigned int) -1)
|
|
-@@ -846,6 +848,9 @@ struct wpa_ssid {
|
|
+@@ -879,6 +881,9 @@ struct wpa_ssid {
|
|
*/
|
|
void *parent_cred;
|
|
|
|
@@ -174,7 +174,7 @@ Signed-hostap: Antonio Quartulli <ordex@autistici.org>
|
|
* macsec_policy - Determines the policy for MACsec secure session
|
|
--- a/wpa_supplicant/wpa_supplicant.c
|
|
+++ b/wpa_supplicant/wpa_supplicant.c
|
|
-@@ -3865,6 +3865,12 @@ static void wpas_start_assoc_cb(struct w
|
|
+@@ -4203,6 +4203,12 @@ static void wpas_start_assoc_cb(struct w
|
|
params.beacon_int = ssid->beacon_int;
|
|
else
|
|
params.beacon_int = wpa_s->conf->beacon_int;
|
|
diff --git a/package/network/services/hostapd/patches/461-driver_nl80211-use-new-parameters-during-ibss-join.patch b/package/network/services/hostapd/patches/461-driver_nl80211-use-new-parameters-during-ibss-join.patch
|
|
deleted file mode 100644
|
|
index 0be77f9845..0000000000
|
|
--- a/package/network/services/hostapd/patches/461-driver_nl80211-use-new-parameters-during-ibss-join.patch
|
|
+++ /dev/null
|
|
@@ -1,59 +0,0 @@
|
|
-From ffc4445958a3ed4064f2e1bf73fa478a61c5cf7b Mon Sep 17 00:00:00 2001
|
|
-From: Antonio Quartulli <ordex@autistici.org>
|
|
-Date: Sun, 3 Jun 2012 18:42:25 +0200
|
|
-Subject: [PATCHv2 602/602] driver_nl80211: use new parameters during ibss join
|
|
-
|
|
-Signed-hostap: Antonio Quartulli <ordex@autistici.org>
|
|
----
|
|
- src/drivers/driver_nl80211.c | 33 ++++++++++++++++++++++++++++++++-
|
|
- 1 file changed, 32 insertions(+), 1 deletion(-)
|
|
-
|
|
---- a/src/drivers/driver_nl80211.c
|
|
-+++ b/src/drivers/driver_nl80211.c
|
|
-@@ -5966,7 +5966,7 @@ static int wpa_driver_nl80211_ibss(struc
|
|
- struct wpa_driver_associate_params *params)
|
|
- {
|
|
- struct nl_msg *msg;
|
|
-- int ret = -1;
|
|
-+ int ret = -1, i;
|
|
- int count = 0;
|
|
-
|
|
- wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex);
|
|
-@@ -5993,6 +5993,37 @@ retry:
|
|
- nl80211_put_beacon_int(msg, params->beacon_int))
|
|
- goto fail;
|
|
-
|
|
-+ if (params->fixed_freq) {
|
|
-+ wpa_printf(MSG_DEBUG, " * fixed_freq");
|
|
-+ nla_put_flag(msg, NL80211_ATTR_FREQ_FIXED);
|
|
-+ }
|
|
-+
|
|
-+ if (params->beacon_int > 0) {
|
|
-+ wpa_printf(MSG_DEBUG, " * beacon_int=%d",
|
|
-+ params->beacon_int);
|
|
-+ nla_put_u32(msg, NL80211_ATTR_BEACON_INTERVAL,
|
|
-+ params->beacon_int);
|
|
-+ }
|
|
-+
|
|
-+ if (params->rates[0] > 0) {
|
|
-+ wpa_printf(MSG_DEBUG, " * basic_rates:");
|
|
-+ i = 0;
|
|
-+ while (i < NL80211_MAX_SUPP_RATES &&
|
|
-+ params->rates[i] > 0) {
|
|
-+ wpa_printf(MSG_DEBUG, " %.1f",
|
|
-+ (double)params->rates[i] / 2);
|
|
-+ i++;
|
|
-+ }
|
|
-+ nla_put(msg, NL80211_ATTR_BSS_BASIC_RATES, i,
|
|
-+ params->rates);
|
|
-+ }
|
|
-+
|
|
-+ if (params->mcast_rate > 0) {
|
|
-+ wpa_printf(MSG_DEBUG, " * mcast_rate=%.1f",
|
|
-+ (double)params->mcast_rate / 10);
|
|
-+ nla_put_u32(msg, NL80211_ATTR_MCAST_RATE, params->mcast_rate);
|
|
-+ }
|
|
-+
|
|
- ret = nl80211_set_conn_keys(params, msg);
|
|
- if (ret)
|
|
- goto fail;
|
|
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
|
|
index bd1d4d7565..be9e0507d6 100644
|
|
--- 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
|
|
@@ -19,7 +19,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich@openmesh.com>
|
|
|
|
--- a/src/drivers/driver.h
|
|
+++ b/src/drivers/driver.h
|
|
-@@ -1624,6 +1624,7 @@ struct wpa_driver_mesh_join_params {
|
|
+@@ -1827,6 +1827,7 @@ struct wpa_driver_mesh_join_params {
|
|
#define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008
|
|
unsigned int flags;
|
|
bool handle_dfs;
|
|
@@ -29,7 +29,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich@openmesh.com>
|
|
struct wpa_driver_set_key_params {
|
|
--- a/src/drivers/driver_nl80211.c
|
|
+++ b/src/drivers/driver_nl80211.c
|
|
-@@ -10496,6 +10496,18 @@ static int nl80211_put_mesh_id(struct nl
|
|
+@@ -11626,6 +11626,18 @@ static int nl80211_put_mesh_id(struct nl
|
|
}
|
|
|
|
|
|
@@ -48,7 +48,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich@openmesh.com>
|
|
static int nl80211_put_mesh_config(struct nl_msg *msg,
|
|
struct wpa_driver_mesh_bss_params *params)
|
|
{
|
|
-@@ -10557,6 +10569,7 @@ static int nl80211_join_mesh(struct i802
|
|
+@@ -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) ||
|
|
@@ -58,7 +58,7 @@ Tested-by: Simon Wunderlich <simon.wunderlich@openmesh.com>
|
|
|
|
--- a/wpa_supplicant/mesh.c
|
|
+++ b/wpa_supplicant/mesh.c
|
|
-@@ -631,6 +631,7 @@ int wpa_supplicant_join_mesh(struct wpa_
|
|
+@@ -632,6 +632,7 @@ int wpa_supplicant_join_mesh(struct wpa_
|
|
|
|
params->meshid = ssid->ssid;
|
|
params->meshid_len = ssid->ssid_len;
|
|
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
|
|
index 4807727e0e..c7e8cf25ce 100644
|
|
--- a/package/network/services/hostapd/patches/464-fix-mesh-obss-check.patch
|
|
+++ b/package/network/services/hostapd/patches/464-fix-mesh-obss-check.patch
|
|
@@ -1,19 +1,13 @@
|
|
--- a/wpa_supplicant/wpa_supplicant.c
|
|
+++ b/wpa_supplicant/wpa_supplicant.c
|
|
-@@ -2512,11 +2512,13 @@ void ibss_mesh_setup_freq(struct wpa_sup
|
|
- for (j = 0; j < wpa_s->last_scan_res_used; j++) {
|
|
- struct wpa_bss *bss = wpa_s->last_scan_res[j];
|
|
+@@ -3094,6 +3094,10 @@ void ibss_mesh_setup_freq(struct wpa_sup
|
|
|
|
-- if (ssid->mode != WPAS_MODE_IBSS)
|
|
-+ /* Don't adjust control freq in case of fixed_freq */
|
|
-+ if (ssid->fixed_freq) {
|
|
-+ obss_scan = 0;
|
|
- break;
|
|
-+ }
|
|
+ freq->freq = ssid->frequency;
|
|
|
|
-- /* Don't adjust control freq in case of fixed_freq */
|
|
-- if (ssid->fixed_freq)
|
|
-+ if (ssid->mode != WPAS_MODE_IBSS)
|
|
- break;
|
|
++ 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);
|
|
|
|
- if (!bss_is_ibss(bss))
|
|
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..ada77853fe
|
|
--- /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
|
|
+@@ -3498,6 +3498,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
|
|
index 359b5f3ef8..79ab48c5c2 100644
|
|
--- a/package/network/services/hostapd/patches/470-survey_data_fallback.patch
|
|
+++ b/package/network/services/hostapd/patches/470-survey_data_fallback.patch
|
|
@@ -1,24 +1,29 @@
|
|
--- a/src/ap/acs.c
|
|
+++ b/src/ap/acs.c
|
|
-@@ -420,20 +420,19 @@ static int acs_usable_bw160_chan(const s
|
|
+@@ -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 is missing noise floor");
|
|
+ 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 is missing channel time");
|
|
+ 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) &&
|
|
- !(survey->filled & SURVEY_HAS_CHAN_TIME_RX)) {
|
|
+@@ -473,7 +473,6 @@ static int acs_survey_is_sufficient(stru
|
|
wpa_printf(MSG_INFO,
|
|
- "ACS: Survey is missing RX and busy time (at least one is required)");
|
|
+ "ACS: Survey for freq %d is missing RX and busy time (at least one is required)",
|
|
+ survey->freq);
|
|
- return 0;
|
|
}
|
|
|
|
diff --git a/package/network/services/hostapd/patches/500-lto-jobserver-support.patch b/package/network/services/hostapd/patches/500-lto-jobserver-support.patch
|
|
index c51db01fec..046da42ab8 100644
|
|
--- a/package/network/services/hostapd/patches/500-lto-jobserver-support.patch
|
|
+++ b/package/network/services/hostapd/patches/500-lto-jobserver-support.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/hostapd/Makefile
|
|
+++ b/hostapd/Makefile
|
|
-@@ -1297,7 +1297,7 @@ hostapd_multi.a: $(BCHECK) $(OBJS)
|
|
+@@ -1396,7 +1396,7 @@ hostapd_multi.a: $(BCHECK) $(OBJS)
|
|
@$(AR) cr $@ hostapd_multi.o $(OBJS)
|
|
|
|
hostapd: $(OBJS)
|
|
@@ -9,7 +9,7 @@
|
|
@$(E) " LD " $@
|
|
|
|
ifdef CONFIG_WPA_TRACE
|
|
-@@ -1308,7 +1308,7 @@ _OBJS_VAR := OBJS_c
|
|
+@@ -1407,7 +1407,7 @@ _OBJS_VAR := OBJS_c
|
|
include ../src/objs.mk
|
|
|
|
hostapd_cli: $(OBJS_c)
|
|
@@ -20,7 +20,7 @@
|
|
NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS)
|
|
--- a/wpa_supplicant/Makefile
|
|
+++ b/wpa_supplicant/Makefile
|
|
-@@ -1920,31 +1920,31 @@ wpa_supplicant_multi.a: .config $(BCHECK
|
|
+@@ -2039,31 +2039,31 @@ wpa_supplicant_multi.a: .config $(BCHECK
|
|
@$(AR) cr $@ wpa_supplicant_multi.o $(OBJS)
|
|
|
|
wpa_supplicant: $(BCHECK) $(OBJS) $(EXTRA_progs)
|
|
diff --git a/package/network/services/hostapd/patches/590-rrm-wnm-statistics.patch b/package/network/services/hostapd/patches/590-rrm-wnm-statistics.patch
|
|
index ee3ab7938a..0efa6db908 100644
|
|
--- a/package/network/services/hostapd/patches/590-rrm-wnm-statistics.patch
|
|
+++ b/package/network/services/hostapd/patches/590-rrm-wnm-statistics.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/src/ap/hostapd.h
|
|
+++ b/src/ap/hostapd.h
|
|
-@@ -150,6 +150,21 @@ struct hostapd_sae_commit_queue {
|
|
+@@ -163,6 +163,21 @@ struct hostapd_sae_commit_queue {
|
|
};
|
|
|
|
/**
|
|
@@ -22,9 +22,9 @@
|
|
* struct hostapd_data - hostapd per-BSS data structure
|
|
*/
|
|
struct hostapd_data {
|
|
-@@ -163,6 +178,9 @@ struct hostapd_data {
|
|
+@@ -182,6 +197,9 @@ struct hostapd_data {
|
|
|
|
- u8 own_addr[ETH_ALEN];
|
|
+ struct hostapd_data *mld_first_bss;
|
|
|
|
+ /* OpenWrt specific statistics */
|
|
+ struct hostapd_openwrt_stats openwrt_stats;
|
|
@@ -42,9 +42,9 @@
|
|
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",
|
|
-@@ -646,10 +647,12 @@ int ieee802_11_rx_wnm_action_ap(struct h
|
|
-
|
|
- switch (action) {
|
|
+@@ -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,
|
|
@@ -55,7 +55,7 @@
|
|
ieee802_11_rx_bss_trans_mgmt_resp(hapd, mgmt->sa, payload,
|
|
plen);
|
|
return 0;
|
|
-@@ -696,6 +699,7 @@ int wnm_send_disassoc_imminent(struct ho
|
|
+@@ -840,6 +843,7 @@ int wnm_send_disassoc_imminent(struct ho
|
|
|
|
pos = mgmt->u.action.u.bss_tm_req.variable;
|
|
|
|
@@ -63,7 +63,7 @@
|
|
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) {
|
|
-@@ -777,6 +781,7 @@ int wnm_send_ess_disassoc_imminent(struc
|
|
+@@ -921,6 +925,7 @@ int wnm_send_ess_disassoc_imminent(struc
|
|
return -1;
|
|
}
|
|
|
|
@@ -71,7 +71,7 @@
|
|
if (disassoc_timer) {
|
|
/* send disassociation frame after time-out */
|
|
set_disassoc_timer(hapd, sta, disassoc_timer);
|
|
-@@ -857,6 +862,7 @@ int wnm_send_bss_tm_req(struct hostapd_d
|
|
+@@ -1001,6 +1006,7 @@ int wnm_send_bss_tm_req(struct hostapd_d
|
|
}
|
|
os_free(buf);
|
|
|
|
diff --git a/package/network/services/hostapd/patches/600-ubus_support.patch b/package/network/services/hostapd/patches/600-ubus_support.patch
|
|
index 89e1e72acd..f420c18644 100644
|
|
--- a/package/network/services/hostapd/patches/600-ubus_support.patch
|
|
+++ b/package/network/services/hostapd/patches/600-ubus_support.patch
|
|
@@ -1,24 +1,21 @@
|
|
-Index: hostapd-2022-01-16-cff80b4f/hostapd/Makefile
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/hostapd/Makefile
|
|
-+++ hostapd-2022-01-16-cff80b4f/hostapd/Makefile
|
|
-@@ -166,6 +166,11 @@ OBJS += ../src/common/hw_features_common
|
|
+--- 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
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/hostapd.h
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/hostapd.h
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/hostapd.h
|
|
-@@ -17,6 +17,7 @@
|
|
+--- 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"
|
|
@@ -26,16 +23,7 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/hostapd.h
|
|
|
|
#define OCE_STA_CFON_ENABLED(hapd) \
|
|
((hapd->conf->oce & OCE_STA_CFON) && \
|
|
-@@ -80,7 +81,7 @@ struct hapd_interfaces {
|
|
- #ifdef CONFIG_CTRL_IFACE_UDP
|
|
- unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN];
|
|
- #endif /* CONFIG_CTRL_IFACE_UDP */
|
|
--
|
|
-+ struct ubus_object ubus;
|
|
- };
|
|
-
|
|
- enum hostapd_chan_status {
|
|
-@@ -171,6 +172,7 @@ struct hostapd_data {
|
|
+@@ -184,6 +185,7 @@ struct hostapd_data {
|
|
struct hostapd_iface *iface;
|
|
struct hostapd_config *iconf;
|
|
struct hostapd_bss_config *conf;
|
|
@@ -43,7 +31,7 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/hostapd.h
|
|
int interface_added; /* virtual interface added for this BSS */
|
|
unsigned int started:1;
|
|
unsigned int disabled:1;
|
|
-@@ -630,6 +632,7 @@ hostapd_alloc_bss_data(struct hostapd_if
|
|
+@@ -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);
|
|
@@ -51,11 +39,9 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/hostapd.h
|
|
void hostapd_interface_deinit(struct hostapd_iface *iface);
|
|
void hostapd_interface_free(struct hostapd_iface *iface);
|
|
struct hostapd_iface * hostapd_alloc_iface(void);
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/hostapd.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/hostapd.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/hostapd.c
|
|
-@@ -396,6 +396,7 @@ void hostapd_free_hapd_data(struct hosta
|
|
+--- a/src/ap/hostapd.c
|
|
++++ b/src/ap/hostapd.c
|
|
+@@ -455,6 +455,7 @@ void hostapd_free_hapd_data(struct hosta
|
|
hapd->beacon_set_done = 0;
|
|
|
|
wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
|
|
@@ -63,7 +49,7 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/hostapd.c
|
|
accounting_deinit(hapd);
|
|
hostapd_deinit_wpa(hapd);
|
|
vlan_deinit(hapd);
|
|
-@@ -1422,6 +1423,8 @@ static int hostapd_setup_bss(struct host
|
|
+@@ -1207,6 +1208,8 @@ static int hostapd_start_beacon(struct h
|
|
if (hapd->driver && hapd->driver->set_operstate)
|
|
hapd->driver->set_operstate(hapd->drv_priv, 1);
|
|
|
|
@@ -72,7 +58,7 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/hostapd.c
|
|
return 0;
|
|
}
|
|
|
|
-@@ -2028,6 +2031,7 @@ static int hostapd_setup_interface_compl
|
|
+@@ -2295,6 +2298,7 @@ static int hostapd_setup_interface_compl
|
|
if (err)
|
|
goto fail;
|
|
|
|
@@ -80,15 +66,15 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/hostapd.c
|
|
wpa_printf(MSG_DEBUG, "Completing interface initialization");
|
|
if (iface->freq) {
|
|
#ifdef NEED_AP_MLME
|
|
-@@ -2225,6 +2229,7 @@ dfs_offload:
|
|
+@@ -2514,6 +2518,7 @@ dfs_offload:
|
|
|
|
fail:
|
|
wpa_printf(MSG_ERROR, "Interface initialization failed");
|
|
+ hostapd_ubus_free_iface(iface);
|
|
- hostapd_set_state(iface, HAPD_IFACE_DISABLED);
|
|
- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
|
|
- #ifdef CONFIG_FST
|
|
-@@ -2700,6 +2705,7 @@ void hostapd_interface_deinit_free(struc
|
|
+
|
|
+ if (iface->is_no_ir) {
|
|
+ hostapd_set_state(iface, HAPD_IFACE_NO_IR);
|
|
+@@ -3004,6 +3009,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;
|
|
@@ -96,11 +82,9 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/hostapd.c
|
|
hostapd_interface_deinit(iface);
|
|
wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit",
|
|
__func__, driver, drv_priv);
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/ieee802_11.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.c
|
|
-@@ -3553,13 +3553,18 @@ static void handle_auth(struct hostapd_d
|
|
+--- 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;
|
|
@@ -109,9 +93,10 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.c
|
|
u16 fc;
|
|
const u8 *challenge = NULL;
|
|
u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN];
|
|
- size_t resp_ies_len = 0;
|
|
- u16 seq_ctrl;
|
|
+@@ -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,
|
|
@@ -120,12 +105,12 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.c
|
|
|
|
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) {
|
|
wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)",
|
|
-@@ -3727,6 +3732,13 @@ static void handle_auth(struct hostapd_d
|
|
+@@ -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 (0 && ubus_resp) {
|
|
++ 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;
|
|
@@ -134,7 +119,7 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.c
|
|
if (res == HOSTAPD_ACL_PENDING)
|
|
return;
|
|
|
|
-@@ -5447,7 +5459,7 @@ static void handle_assoc(struct hostapd_
|
|
+@@ -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;
|
|
@@ -143,7 +128,7 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.c
|
|
struct sta_info *sta;
|
|
u8 *tmp = NULL;
|
|
#ifdef CONFIG_FILS
|
|
-@@ -5660,6 +5672,11 @@ static void handle_assoc(struct hostapd_
|
|
+@@ -5354,6 +5366,11 @@ static void handle_assoc(struct hostapd_
|
|
left = res;
|
|
}
|
|
#endif /* CONFIG_FILS */
|
|
@@ -155,12 +140,12 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.c
|
|
|
|
/* followed by SSID and Supported rates; and HT capabilities if 802.11n
|
|
* is used */
|
|
-@@ -5758,6 +5775,13 @@ static void handle_assoc(struct hostapd_
|
|
+@@ -5452,6 +5469,13 @@ static void handle_assoc(struct hostapd_
|
|
}
|
|
#endif /* CONFIG_FILS */
|
|
|
|
+ ubus_resp = hostapd_ubus_handle_event(hapd, &req);
|
|
-+ if (0 && ubus_resp) {
|
|
++ 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;
|
|
@@ -169,28 +154,26 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.c
|
|
fail:
|
|
|
|
/*
|
|
-@@ -5851,6 +5875,7 @@ static void handle_disassoc(struct hosta
|
|
- wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d",
|
|
- MAC2STR(mgmt->sa),
|
|
- le_to_host16(mgmt->u.disassoc.reason_code));
|
|
+@@ -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 == NULL) {
|
|
-@@ -5920,6 +5945,8 @@ static void handle_deauth(struct hostapd
|
|
+ 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 == NULL) {
|
|
- wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying "
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/beacon.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/beacon.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/beacon.c
|
|
-@@ -852,6 +852,12 @@ void handle_probe_req(struct hostapd_dat
|
|
+ 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;
|
|
@@ -203,7 +186,7 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/beacon.c
|
|
|
|
if (hapd->iconf->rssi_ignore_probe_request && ssi_signal &&
|
|
ssi_signal < hapd->iconf->rssi_ignore_probe_request)
|
|
-@@ -1038,6 +1044,12 @@ void handle_probe_req(struct hostapd_dat
|
|
+@@ -1222,6 +1228,12 @@ void handle_probe_req(struct hostapd_dat
|
|
}
|
|
#endif /* CONFIG_P2P */
|
|
|
|
@@ -216,10 +199,8 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/beacon.c
|
|
/* TODO: verify that supp_rates contains at least one matching rate
|
|
* with AP configuration */
|
|
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/drv_callbacks.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/drv_callbacks.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/drv_callbacks.c
|
|
+--- 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;
|
|
@@ -244,11 +225,9 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/drv_callbacks.c
|
|
#ifdef CONFIG_P2P
|
|
if (elems.p2p) {
|
|
wpabuf_free(sta->p2p_ie);
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/sta_info.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/sta_info.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/sta_info.c
|
|
-@@ -458,6 +458,7 @@ void ap_handle_timer(void *eloop_ctx, vo
|
|
+--- 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");
|
|
@@ -256,7 +235,7 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/sta_info.c
|
|
ap_free_sta(hapd, sta);
|
|
return;
|
|
}
|
|
-@@ -613,6 +614,7 @@ skip_poll:
|
|
+@@ -626,6 +627,7 @@ skip_poll:
|
|
mlme_deauthenticate_indication(
|
|
hapd, sta,
|
|
WLAN_REASON_PREV_AUTH_NOT_VALID);
|
|
@@ -264,27 +243,76 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/sta_info.c
|
|
ap_free_sta(hapd, sta);
|
|
break;
|
|
}
|
|
-@@ -1319,6 +1321,7 @@ void ap_sta_set_authorized(struct hostap
|
|
- " keyid=%s", keyid);
|
|
+@@ -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);
|
|
}
|
|
|
|
-+ hostapd_ubus_notify_authorized(hapd, sta);
|
|
- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s",
|
|
- buf, ip_addr, keyid_buf);
|
|
+- 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);
|
|
|
|
-@@ -1329,6 +1332,7 @@ void ap_sta_set_authorized(struct hostap
|
|
- buf, ip_addr, keyid_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)
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth_glue.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/wpa_auth_glue.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth_glue.c
|
|
-@@ -265,6 +265,7 @@ static void hostapd_wpa_auth_psk_failure
|
|
+--- 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));
|
|
@@ -292,24 +320,23 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth_glue.c
|
|
}
|
|
|
|
|
|
-Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/Makefile
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/wpa_supplicant/Makefile
|
|
-+++ hostapd-2022-01-16-cff80b4f/wpa_supplicant/Makefile
|
|
-@@ -176,6 +176,12 @@ ifdef CONFIG_EAPOL_TEST
|
|
+--- a/wpa_supplicant/Makefile
|
|
++++ b/wpa_supplicant/Makefile
|
|
+@@ -194,6 +194,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
|
|
-@@ -962,6 +968,9 @@ ifdef CONFIG_CTRL_IFACE_MIB
|
|
+@@ -989,6 +996,9 @@ ifdef CONFIG_CTRL_IFACE_MIB
|
|
CFLAGS += -DCONFIG_CTRL_IFACE_MIB
|
|
endif
|
|
OBJS += ../src/ap/ctrl_iface_ap.o
|
|
@@ -319,11 +346,9 @@ Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/Makefile
|
|
endif
|
|
|
|
CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
|
|
-Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/wpa_supplicant.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/wpa_supplicant/wpa_supplicant.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/wpa_supplicant/wpa_supplicant.c
|
|
-@@ -7241,6 +7241,8 @@ struct wpa_supplicant * wpa_supplicant_a
|
|
+--- a/wpa_supplicant/wpa_supplicant.c
|
|
++++ b/wpa_supplicant/wpa_supplicant.c
|
|
+@@ -7635,6 +7635,8 @@ struct wpa_supplicant * wpa_supplicant_a
|
|
}
|
|
#endif /* CONFIG_P2P */
|
|
|
|
@@ -332,7 +357,7 @@ Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/wpa_supplicant.c
|
|
return wpa_s;
|
|
}
|
|
|
|
-@@ -7267,6 +7269,8 @@ int wpa_supplicant_remove_iface(struct w
|
|
+@@ -7661,6 +7663,8 @@ int wpa_supplicant_remove_iface(struct w
|
|
struct wpa_supplicant *parent = wpa_s->parent;
|
|
#endif /* CONFIG_MESH */
|
|
|
|
@@ -341,7 +366,7 @@ Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/wpa_supplicant.c
|
|
/* Remove interface from the global list of interfaces */
|
|
prev = global->ifaces;
|
|
if (prev == wpa_s) {
|
|
-@@ -7570,8 +7574,12 @@ int wpa_supplicant_run(struct wpa_global
|
|
+@@ -8007,8 +8011,12 @@ int wpa_supplicant_run(struct wpa_global
|
|
eloop_register_signal_terminate(wpa_supplicant_terminate, global);
|
|
eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
|
|
|
|
@@ -354,19 +379,17 @@ Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/wpa_supplicant.c
|
|
return 0;
|
|
}
|
|
|
|
-Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/wpa_supplicant_i.h
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/wpa_supplicant/wpa_supplicant_i.h
|
|
-+++ hostapd-2022-01-16-cff80b4f/wpa_supplicant/wpa_supplicant_i.h
|
|
-@@ -19,6 +19,7 @@
|
|
- #include "wps/wps_defs.h"
|
|
+--- 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;
|
|
-@@ -322,6 +323,8 @@ struct wpa_global {
|
|
+@@ -324,6 +325,8 @@ struct wpa_global {
|
|
#endif /* CONFIG_WIFI_DISPLAY */
|
|
|
|
struct psk_list_entry *add_psk; /* From group formation */
|
|
@@ -375,7 +398,7 @@ Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/wpa_supplicant_i.h
|
|
};
|
|
|
|
|
|
-@@ -708,6 +711,7 @@ struct wpa_supplicant {
|
|
+@@ -655,6 +658,7 @@ struct wpa_supplicant {
|
|
unsigned char own_addr[ETH_ALEN];
|
|
unsigned char perm_addr[ETH_ALEN];
|
|
char ifname[100];
|
|
@@ -383,10 +406,8 @@ Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/wpa_supplicant_i.h
|
|
#ifdef CONFIG_MATCH_IFACE
|
|
int matched;
|
|
#endif /* CONFIG_MATCH_IFACE */
|
|
-Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/wps_supplicant.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/wpa_supplicant/wps_supplicant.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/wpa_supplicant/wps_supplicant.c
|
|
+--- a/wpa_supplicant/wps_supplicant.c
|
|
++++ b/wpa_supplicant/wps_supplicant.c
|
|
@@ -33,6 +33,7 @@
|
|
#include "p2p/p2p.h"
|
|
#include "p2p_supplicant.h"
|
|
@@ -395,7 +416,7 @@ Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/wps_supplicant.c
|
|
|
|
|
|
#ifndef WPS_PIN_SCAN_IGNORE_SEL_REG
|
|
-@@ -393,6 +394,8 @@ static int wpa_supplicant_wps_cred(void
|
|
+@@ -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);
|
|
|
|
@@ -404,31 +425,9 @@ Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/wps_supplicant.c
|
|
if (wpa_s->conf->wps_cred_processing == 1)
|
|
return 0;
|
|
|
|
-Index: hostapd-2022-01-16-cff80b4f/hostapd/main.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/hostapd/main.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/hostapd/main.c
|
|
-@@ -895,6 +895,7 @@ int main(int argc, char *argv[])
|
|
- }
|
|
-
|
|
- hostapd_global_ctrl_iface_init(&interfaces);
|
|
-+ hostapd_ubus_add(&interfaces);
|
|
-
|
|
- if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
|
|
- wpa_printf(MSG_ERROR, "Failed to start eloop");
|
|
-@@ -904,6 +905,7 @@ int main(int argc, char *argv[])
|
|
- ret = 0;
|
|
-
|
|
- out:
|
|
-+ hostapd_ubus_free(&interfaces);
|
|
- hostapd_global_ctrl_iface_deinit(&interfaces);
|
|
- /* Deinitialize all interfaces */
|
|
- for (i = 0; i < interfaces.count; i++) {
|
|
-Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/main.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/wpa_supplicant/main.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/wpa_supplicant/main.c
|
|
-@@ -203,7 +203,7 @@ int main(int argc, char *argv[])
|
|
+--- a/wpa_supplicant/main.c
|
|
++++ b/wpa_supplicant/main.c
|
|
+@@ -204,7 +204,7 @@ int main(int argc, char *argv[])
|
|
|
|
for (;;) {
|
|
c = getopt(argc, argv,
|
|
@@ -437,7 +436,7 @@ Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/main.c
|
|
if (c < 0)
|
|
break;
|
|
switch (c) {
|
|
-@@ -271,6 +271,9 @@ int main(int argc, char *argv[])
|
|
+@@ -272,6 +272,9 @@ int main(int argc, char *argv[])
|
|
params.conf_p2p_dev = optarg;
|
|
break;
|
|
#endif /* CONFIG_P2P */
|
|
@@ -447,10 +446,8 @@ Index: hostapd-2022-01-16-cff80b4f/wpa_supplicant/main.c
|
|
case 'o':
|
|
params.override_driver = optarg;
|
|
break;
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/rrm.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/rrm.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/rrm.c
|
|
+--- 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",
|
|
@@ -461,10 +458,18 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/rrm.c
|
|
}
|
|
|
|
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/vlan_init.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/vlan_init.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/vlan_init.c
|
|
+@@ -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)
|
|
@@ -501,11 +506,9 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/vlan_init.c
|
|
return hostapd_vlan_if_remove(hapd, vlan->ifname);
|
|
}
|
|
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/dfs.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/dfs.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/dfs.c
|
|
-@@ -1196,6 +1196,8 @@ int hostapd_dfs_radar_detected(struct ho
|
|
+--- 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);
|
|
|
|
@@ -514,10 +517,8 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/dfs.c
|
|
/* Proceed only if DFS is not offloaded to the driver */
|
|
if (iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
|
|
return 0;
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/airtime_policy.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/airtime_policy.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/airtime_policy.c
|
|
+--- 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;
|
|
@@ -547,11 +548,9 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/airtime_policy.c
|
|
if (weight)
|
|
return sta_set_airtime_weight(hapd, sta, weight);
|
|
}
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/sta_info.h
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/sta_info.h
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/sta_info.h
|
|
-@@ -324,6 +324,7 @@ struct sta_info {
|
|
+--- 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;
|
|
@@ -559,13 +558,11 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/sta_info.h
|
|
struct os_reltime backlogged_until;
|
|
#endif /* CONFIG_AIRTIME_POLICY */
|
|
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/wnm_ap.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/wnm_ap.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/wnm_ap.c
|
|
-@@ -442,7 +442,8 @@ static void ieee802_11_rx_bss_trans_mgmt
|
|
- wpa_hexdump(MSG_DEBUG, "WNM: BSS Transition Candidate List Entries",
|
|
- pos, end - pos);
|
|
+--- 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))
|
|
@@ -573,7 +570,7 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/wnm_ap.c
|
|
}
|
|
|
|
|
|
-@@ -464,7 +465,7 @@ static void ieee802_11_rx_bss_trans_mgmt
|
|
+@@ -477,7 +478,7 @@ static void ieee802_11_rx_bss_trans_mgmt
|
|
size_t len)
|
|
{
|
|
u8 dialog_token, status_code, bss_termination_delay;
|
|
@@ -582,7 +579,7 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/wnm_ap.c
|
|
int enabled = hapd->conf->bss_transition;
|
|
struct sta_info *sta;
|
|
|
|
-@@ -511,6 +512,7 @@ static void ieee802_11_rx_bss_trans_mgmt
|
|
+@@ -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;
|
|
}
|
|
@@ -590,7 +587,7 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/wnm_ap.c
|
|
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,
|
|
-@@ -530,6 +532,10 @@ static void ieee802_11_rx_bss_trans_mgmt
|
|
+@@ -543,6 +545,10 @@ static void ieee802_11_rx_bss_trans_mgmt
|
|
MAC2STR(addr), status_code, bss_termination_delay);
|
|
}
|
|
|
|
@@ -601,3 +598,151 @@ Index: hostapd-2022-01-16-cff80b4f/src/ap/wnm_ap.c
|
|
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..6cfc9b7d8d
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/patches/601-ucode_support.patch
|
|
@@ -0,0 +1,224 @@
|
|
+--- 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
|
|
+@@ -991,6 +991,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");
|
|
+@@ -1000,6 +1001,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;
|
|
+--- a/src/ap/hostapd.c
|
|
++++ b/src/ap/hostapd.c
|
|
+@@ -276,6 +276,8 @@ int hostapd_reload_config(struct hostapd
|
|
+ size_t j;
|
|
+ int i;
|
|
+
|
|
++ hostapd_ucode_reload_bss(hapd, reconf);
|
|
++
|
|
+ if (iface->config_fname == NULL) {
|
|
+ /* Only in-memory config in use - assume it has been updated */
|
|
+ hostapd_clear_old(iface);
|
|
+@@ -455,6 +457,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);
|
|
+@@ -619,6 +622,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);
|
|
+@@ -1209,6 +1213,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;
|
|
+ }
|
|
+--- a/wpa_supplicant/Makefile
|
|
++++ b/wpa_supplicant/Makefile
|
|
+@@ -197,8 +197,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
|
|
+--- a/wpa_supplicant/wpa_supplicant.c
|
|
++++ b/wpa_supplicant/wpa_supplicant.c
|
|
+@@ -7636,6 +7636,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;
|
|
+ }
|
|
+@@ -7663,6 +7664,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 */
|
|
+@@ -7973,6 +7975,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;
|
|
+ }
|
|
+@@ -8011,12 +8014,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;
|
|
+ }
|
|
+
|
|
+@@ -8049,6 +8048,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;
|
|
+@@ -659,6 +660,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
|
|
+@@ -4921,6 +4921,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;
|
|
+@@ -5022,6 +5023,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);
|
|
+
|
|
diff --git a/package/network/services/hostapd/patches/700-wifi-reload.patch b/package/network/services/hostapd/patches/700-wifi-reload.patch
|
|
index e6d7c2f673..7e082ed80b 100644
|
|
--- a/package/network/services/hostapd/patches/700-wifi-reload.patch
|
|
+++ b/package/network/services/hostapd/patches/700-wifi-reload.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/hostapd/config_file.c
|
|
+++ b/hostapd/config_file.c
|
|
-@@ -2458,6 +2458,8 @@ static int hostapd_config_fill(struct ho
|
|
+@@ -2418,6 +2418,8 @@ static int hostapd_config_fill(struct ho
|
|
bss->isolate = atoi(pos);
|
|
} else if (os_strcmp(buf, "ap_max_inactivity") == 0) {
|
|
bss->ap_max_inactivity = atoi(pos);
|
|
@@ -8,8 +8,8 @@
|
|
+ bss->config_id = os_strdup(pos);
|
|
} else if (os_strcmp(buf, "skip_inactivity_poll") == 0) {
|
|
bss->skip_inactivity_poll = atoi(pos);
|
|
- } else if (os_strcmp(buf, "country_code") == 0) {
|
|
-@@ -3158,6 +3160,8 @@ static int hostapd_config_fill(struct ho
|
|
+ } else if (os_strcmp(buf, "config_id") == 0) {
|
|
+@@ -3128,6 +3130,8 @@ static int hostapd_config_fill(struct ho
|
|
}
|
|
} else if (os_strcmp(buf, "acs_exclude_dfs") == 0) {
|
|
conf->acs_exclude_dfs = atoi(pos);
|
|
@@ -20,15 +20,7 @@
|
|
} else if (os_strcmp(buf, "channel") == 0) {
|
|
--- a/src/ap/ap_config.c
|
|
+++ b/src/ap/ap_config.c
|
|
-@@ -792,6 +792,7 @@ void hostapd_config_free_bss(struct host
|
|
- os_free(conf->radius_req_attr_sqlite);
|
|
- os_free(conf->rsn_preauth_interfaces);
|
|
- os_free(conf->ctrl_interface);
|
|
-+ os_free(conf->config_id);
|
|
- os_free(conf->ca_cert);
|
|
- os_free(conf->server_cert);
|
|
- os_free(conf->server_cert2);
|
|
-@@ -988,6 +989,7 @@ void hostapd_config_free(struct hostapd_
|
|
+@@ -998,6 +998,7 @@ void hostapd_config_free(struct hostapd_
|
|
|
|
for (i = 0; i < conf->num_bss; i++)
|
|
hostapd_config_free_bss(conf->bss[i]);
|
|
@@ -38,16 +30,7 @@
|
|
os_free(conf->basic_rates);
|
|
--- a/src/ap/ap_config.h
|
|
+++ b/src/ap/ap_config.h
|
|
-@@ -279,6 +279,8 @@ struct hostapd_bss_config {
|
|
- char vlan_bridge[IFNAMSIZ + 1];
|
|
- char wds_bridge[IFNAMSIZ + 1];
|
|
-
|
|
-+ char *config_id;
|
|
-+
|
|
- enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
|
|
-
|
|
- unsigned int logger_syslog; /* module bitfield */
|
|
-@@ -942,6 +944,7 @@ struct spatial_reuse {
|
|
+@@ -998,6 +998,7 @@ struct eht_phy_capabilities_info {
|
|
struct hostapd_config {
|
|
struct hostapd_bss_config **bss, *last_bss;
|
|
size_t num_bss;
|
|
@@ -57,7 +40,16 @@
|
|
int rts_threshold;
|
|
--- a/src/ap/hostapd.c
|
|
+++ b/src/ap/hostapd.c
|
|
-@@ -219,6 +219,10 @@ static int hostapd_iface_conf_changed(st
|
|
+@@ -127,7 +127,7 @@ void hostapd_reconfig_encryption(struct
|
|
+ }
|
|
+
|
|
+
|
|
+-static void hostapd_reload_bss(struct hostapd_data *hapd)
|
|
++void hostapd_reload_bss(struct hostapd_data *hapd)
|
|
+ {
|
|
+ struct hostapd_ssid *ssid;
|
|
+
|
|
+@@ -255,6 +255,10 @@ static int hostapd_iface_conf_changed(st
|
|
{
|
|
size_t i;
|
|
|
|
@@ -68,7 +60,7 @@
|
|
if (newconf->num_bss != oldconf->num_bss)
|
|
return 1;
|
|
|
|
-@@ -232,7 +236,7 @@ static int hostapd_iface_conf_changed(st
|
|
+@@ -268,7 +272,7 @@ static int hostapd_iface_conf_changed(st
|
|
}
|
|
|
|
|
|
@@ -77,26 +69,17 @@
|
|
{
|
|
struct hapd_interfaces *interfaces = iface->interfaces;
|
|
struct hostapd_data *hapd = iface->bss[0];
|
|
-@@ -255,13 +259,16 @@ int hostapd_reload_config(struct hostapd
|
|
- if (newconf == NULL)
|
|
- return -1;
|
|
-
|
|
-- hostapd_clear_old(iface);
|
|
--
|
|
- oldconf = hapd->iconf;
|
|
- if (hostapd_iface_conf_changed(newconf, oldconf)) {
|
|
+@@ -298,6 +302,9 @@ int hostapd_reload_config(struct hostapd
|
|
char *fname;
|
|
int res;
|
|
|
|
+ if (reconf)
|
|
+ return -1;
|
|
+
|
|
-+ hostapd_clear_old(iface);
|
|
-+
|
|
+ hostapd_clear_old(iface);
|
|
+
|
|
wpa_printf(MSG_DEBUG,
|
|
- "Configuration changes include interface/BSS modification - force full disable+enable sequence");
|
|
- fname = os_strdup(iface->config_fname);
|
|
-@@ -286,6 +293,24 @@ int hostapd_reload_config(struct hostapd
|
|
+@@ -324,6 +331,24 @@ int hostapd_reload_config(struct hostapd
|
|
wpa_printf(MSG_ERROR,
|
|
"Failed to enable interface on config reload");
|
|
return res;
|
|
@@ -121,7 +104,7 @@
|
|
}
|
|
iface->conf = newconf;
|
|
|
|
-@@ -302,6 +327,12 @@ int hostapd_reload_config(struct hostapd
|
|
+@@ -340,6 +365,12 @@ int hostapd_reload_config(struct hostapd
|
|
|
|
for (j = 0; j < iface->num_bss; j++) {
|
|
hapd = iface->bss[j];
|
|
@@ -131,10 +114,20 @@
|
|
+ }
|
|
+ if (newconf->bss[j]->config_id)
|
|
+ hapd->config_id = strdup(newconf->bss[j]->config_id);
|
|
- hapd->iconf = newconf;
|
|
- hapd->conf = newconf->bss[j];
|
|
- hostapd_reload_bss(hapd);
|
|
-@@ -2397,6 +2428,10 @@ hostapd_alloc_bss_data(struct hostapd_if
|
|
+ if (!hapd->conf->config_id || !newconf->bss[j]->config_id ||
|
|
+ os_strcmp(hapd->conf->config_id,
|
|
+ newconf->bss[j]->config_id) != 0)
|
|
+@@ -1236,8 +1267,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];
|
|
+@@ -2705,6 +2735,10 @@ hostapd_alloc_bss_data(struct hostapd_if
|
|
hapd->iconf = conf;
|
|
hapd->conf = bss;
|
|
hapd->iface = hapd_iface;
|
|
@@ -145,9 +138,18 @@
|
|
if (conf)
|
|
hapd->driver = conf->driver;
|
|
hapd->ctrl_sock = -1;
|
|
+@@ -2723,7 +2757,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/src/ap/hostapd.h
|
|
+++ b/src/ap/hostapd.h
|
|
-@@ -46,7 +46,7 @@ struct mesh_conf;
|
|
+@@ -48,7 +48,7 @@ struct mesh_conf;
|
|
struct hostapd_iface;
|
|
|
|
struct hapd_interfaces {
|
|
@@ -156,38 +158,48 @@
|
|
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);
|
|
-@@ -173,6 +173,7 @@ struct hostapd_data {
|
|
- struct hostapd_config *iconf;
|
|
+@@ -192,6 +192,7 @@ struct hostapd_data {
|
|
struct hostapd_bss_config *conf;
|
|
struct hostapd_ubus_bss ubus;
|
|
+ struct hostapd_ucode_bss ucode;
|
|
+ char *config_id;
|
|
int interface_added; /* virtual interface added for this BSS */
|
|
unsigned int started:1;
|
|
unsigned int disabled:1;
|
|
-@@ -624,7 +625,7 @@ struct hostapd_iface {
|
|
+@@ -696,7 +697,9 @@ struct hostapd_iface {
|
|
int hostapd_for_each_interface(struct hapd_interfaces *interfaces,
|
|
int (*cb)(struct hostapd_iface *iface,
|
|
void *ctx), void *ctx);
|
|
-int hostapd_reload_config(struct hostapd_iface *iface);
|
|
+int hostapd_reload_config(struct hostapd_iface *iface, int reconf);
|
|
++void hostapd_reload_bss(struct hostapd_data *hapd);
|
|
++void hostapd_bss_deinit(struct hostapd_data *hapd);
|
|
void hostapd_reconfig_encryption(struct hostapd_data *hapd);
|
|
struct hostapd_data *
|
|
hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface,
|
|
+@@ -713,6 +716,7 @@ 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_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
|
|
+ int reassoc);
|
|
+ void hostapd_interface_deinit_free(struct hostapd_iface *iface);
|
|
--- a/src/drivers/driver_nl80211.c
|
|
+++ b/src/drivers/driver_nl80211.c
|
|
-@@ -4833,6 +4833,9 @@ static int wpa_driver_nl80211_set_ap(voi
|
|
+@@ -5322,6 +5322,9 @@ static int wpa_driver_nl80211_set_ap(voi
|
|
if (ret) {
|
|
wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
|
|
ret, strerror(-ret));
|
|
-+ if (!bss->beacon_set)
|
|
++ if (!bss->flink->beacon_set)
|
|
+ ret = 0;
|
|
-+ bss->beacon_set = 0;
|
|
++ bss->flink->beacon_set = 0;
|
|
} else {
|
|
- bss->beacon_set = 1;
|
|
+ link->beacon_set = 1;
|
|
nl80211_set_bss(bss, params->cts_protect, params->preamble,
|
|
--- a/hostapd/ctrl_iface.c
|
|
+++ b/hostapd/ctrl_iface.c
|
|
-@@ -186,7 +186,7 @@ static int hostapd_ctrl_iface_update(str
|
|
+@@ -187,7 +187,7 @@ static int hostapd_ctrl_iface_update(str
|
|
iface->interfaces->config_read_cb = hostapd_ctrl_iface_config_read;
|
|
reload_opts = txt;
|
|
|
|
@@ -198,7 +210,7 @@
|
|
}
|
|
--- a/hostapd/main.c
|
|
+++ b/hostapd/main.c
|
|
-@@ -317,7 +317,7 @@ static void handle_term(int sig, void *s
|
|
+@@ -410,7 +410,7 @@ static void handle_term(int sig, void *s
|
|
|
|
static int handle_reload_iface(struct hostapd_iface *iface, void *ctx)
|
|
{
|
|
diff --git a/package/network/services/hostapd/patches/710-vlan_no_bridge.patch b/package/network/services/hostapd/patches/710-vlan_no_bridge.patch
|
|
index 856dc8ba88..f625f4bda4 100644
|
|
--- a/package/network/services/hostapd/patches/710-vlan_no_bridge.patch
|
|
+++ b/package/network/services/hostapd/patches/710-vlan_no_bridge.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/src/ap/ap_config.h
|
|
+++ b/src/ap/ap_config.h
|
|
-@@ -115,6 +115,7 @@ struct hostapd_ssid {
|
|
+@@ -121,6 +121,7 @@ struct hostapd_ssid {
|
|
#define DYNAMIC_VLAN_OPTIONAL 1
|
|
#define DYNAMIC_VLAN_REQUIRED 2
|
|
int dynamic_vlan;
|
|
@@ -30,7 +30,7 @@
|
|
|
|
--- a/hostapd/config_file.c
|
|
+++ b/hostapd/config_file.c
|
|
-@@ -3381,6 +3381,8 @@ static int hostapd_config_fill(struct ho
|
|
+@@ -3353,6 +3353,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);
|
|
diff --git a/package/network/services/hostapd/patches/711-wds_bridge_force.patch b/package/network/services/hostapd/patches/711-wds_bridge_force.patch
|
|
index a22580c357..e04ae62538 100644
|
|
--- a/package/network/services/hostapd/patches/711-wds_bridge_force.patch
|
|
+++ b/package/network/services/hostapd/patches/711-wds_bridge_force.patch
|
|
@@ -1,17 +1,17 @@
|
|
--- a/hostapd/config_file.c
|
|
+++ b/hostapd/config_file.c
|
|
-@@ -2358,6 +2358,8 @@ static int hostapd_config_fill(struct ho
|
|
+@@ -2316,6 +2316,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) {
|
|
- os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
|
|
- } else if (os_strcmp(buf, "wds_bridge") == 0) {
|
|
--- a/src/ap/ap_drv_ops.c
|
|
+++ b/src/ap/ap_drv_ops.c
|
|
-@@ -340,8 +340,6 @@ int hostapd_set_wds_sta(struct hostapd_d
|
|
+@@ -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;
|
|
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
|
|
index 106f9d7407..b2ae53b63c 100644
|
|
--- a/package/network/services/hostapd/patches/720-iface_max_num_sta.patch
|
|
+++ b/package/network/services/hostapd/patches/720-iface_max_num_sta.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/hostapd/config_file.c
|
|
+++ b/hostapd/config_file.c
|
|
-@@ -2880,6 +2880,14 @@ static int hostapd_config_fill(struct ho
|
|
+@@ -2848,6 +2848,14 @@ static int hostapd_config_fill(struct ho
|
|
line, bss->max_num_sta, MAX_STA_COUNT);
|
|
return 1;
|
|
}
|
|
@@ -17,17 +17,17 @@
|
|
} else if (os_strcmp(buf, "extended_key_id") == 0) {
|
|
--- a/src/ap/hostapd.h
|
|
+++ b/src/ap/hostapd.h
|
|
-@@ -668,6 +668,7 @@ void hostapd_cleanup_cs_params(struct ho
|
|
+@@ -744,6 +744,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);
|
|
|
|
- /* utils.c */
|
|
- int hostapd_register_probereq_cb(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
|
|
-@@ -236,6 +236,30 @@ static int hostapd_iface_conf_changed(st
|
|
+@@ -272,6 +272,30 @@ static int hostapd_iface_conf_changed(st
|
|
}
|
|
|
|
|
|
@@ -60,7 +60,7 @@
|
|
struct hapd_interfaces *interfaces = iface->interfaces;
|
|
--- a/src/ap/beacon.c
|
|
+++ b/src/ap/beacon.c
|
|
-@@ -1068,7 +1068,7 @@ void handle_probe_req(struct hostapd_dat
|
|
+@@ -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) &&
|
|
@@ -71,7 +71,7 @@
|
|
" since no room for additional STA",
|
|
--- a/src/ap/ap_config.h
|
|
+++ b/src/ap/ap_config.h
|
|
-@@ -981,6 +981,8 @@ struct hostapd_config {
|
|
+@@ -1037,6 +1037,8 @@ struct hostapd_config {
|
|
unsigned int track_sta_max_num;
|
|
unsigned int track_sta_max_age;
|
|
|
|
diff --git a/package/network/services/hostapd/patches/730-ft_iface.patch b/package/network/services/hostapd/patches/730-ft_iface.patch
|
|
index b5809222d7..0795ed15a1 100644
|
|
--- a/package/network/services/hostapd/patches/730-ft_iface.patch
|
|
+++ b/package/network/services/hostapd/patches/730-ft_iface.patch
|
|
@@ -1,6 +1,6 @@
|
|
--- a/hostapd/config_file.c
|
|
+++ b/hostapd/config_file.c
|
|
-@@ -3038,6 +3038,8 @@ static int hostapd_config_fill(struct ho
|
|
+@@ -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
|
|
@@ -11,17 +11,17 @@
|
|
hexstr2bin(pos, bss->mobility_domain,
|
|
--- a/src/ap/ap_config.h
|
|
+++ b/src/ap/ap_config.h
|
|
-@@ -277,6 +277,7 @@ struct airtime_sta_weight {
|
|
+@@ -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
|
|
-@@ -1566,8 +1566,12 @@ int hostapd_setup_wpa(struct hostapd_dat
|
|
+@@ -1727,8 +1727,12 @@ int hostapd_setup_wpa(struct hostapd_dat
|
|
wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt)) {
|
|
const char *ft_iface;
|
|
|
|
diff --git a/package/network/services/hostapd/patches/740-snoop_iface.patch b/package/network/services/hostapd/patches/740-snoop_iface.patch
|
|
index 2ed73750ca..a116644736 100644
|
|
--- a/package/network/services/hostapd/patches/740-snoop_iface.patch
|
|
+++ b/package/network/services/hostapd/patches/740-snoop_iface.patch
|
|
@@ -1,18 +1,18 @@
|
|
--- a/src/ap/ap_config.h
|
|
+++ b/src/ap/ap_config.h
|
|
-@@ -278,6 +278,7 @@ struct hostapd_bss_config {
|
|
+@@ -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
|
|
-@@ -31,14 +31,16 @@ int x_snoop_init(struct hostapd_data *ha
|
|
- return -1;
|
|
- }
|
|
+@@ -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] &&
|
|
@@ -29,7 +29,7 @@
|
|
wpa_printf(MSG_DEBUG,
|
|
"x_snoop: Failed to enable proxyarp on the bridge port");
|
|
return -1;
|
|
-@@ -52,7 +54,8 @@ int x_snoop_init(struct hostapd_data *ha
|
|
+@@ -54,7 +56,8 @@ int x_snoop_init(struct hostapd_data *ha
|
|
}
|
|
|
|
#ifdef CONFIG_IPV6
|
|
@@ -39,7 +39,7 @@
|
|
wpa_printf(MSG_DEBUG,
|
|
"x_snoop: Failed to enable multicast snooping on the bridge");
|
|
return -1;
|
|
-@@ -71,8 +74,12 @@ x_snoop_get_l2_packet(struct hostapd_dat
|
|
+@@ -73,8 +76,12 @@ x_snoop_get_l2_packet(struct hostapd_dat
|
|
{
|
|
struct hostapd_bss_config *conf = hapd->conf;
|
|
struct l2_packet_data *l2;
|
|
@@ -55,10 +55,10 @@
|
|
"x_snoop: Failed to initialize L2 packet processing %s",
|
|
--- a/hostapd/config_file.c
|
|
+++ b/hostapd/config_file.c
|
|
-@@ -2360,6 +2360,8 @@ static int hostapd_config_fill(struct ho
|
|
- os_strlcpy(bss->bridge, pos, sizeof(bss->bridge));
|
|
- if (!bss->wds_bridge[0])
|
|
+@@ -2320,6 +2320,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) {
|
|
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
|
|
index 43a4ea73b3..8cd4e502be 100644
|
|
--- 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
|
|
@@ -1,6 +1,6 @@
|
|
--- a/hostapd/config_file.c
|
|
+++ b/hostapd/config_file.c
|
|
-@@ -1644,6 +1644,8 @@ static int parse_anqp_elem(struct hostap
|
|
+@@ -1602,6 +1602,8 @@ static int parse_anqp_elem(struct hostap
|
|
return 0;
|
|
}
|
|
|
|
@@ -9,7 +9,7 @@
|
|
|
|
static int parse_qos_map_set(struct hostapd_bss_config *bss,
|
|
char *buf, int line)
|
|
-@@ -1685,8 +1687,6 @@ static int parse_qos_map_set(struct host
|
|
+@@ -1643,8 +1645,6 @@ static int parse_qos_map_set(struct host
|
|
return 0;
|
|
}
|
|
|
|
@@ -18,7 +18,7 @@
|
|
|
|
#ifdef CONFIG_HS20
|
|
static int hs20_parse_conn_capab(struct hostapd_bss_config *bss, char *buf,
|
|
-@@ -4077,10 +4077,10 @@ static int hostapd_config_fill(struct ho
|
|
+@@ -4064,10 +4064,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);
|
|
@@ -32,7 +32,7 @@
|
|
os_free(bss->dump_msk_file);
|
|
--- a/src/ap/hostapd.c
|
|
+++ b/src/ap/hostapd.c
|
|
-@@ -1415,6 +1415,7 @@ static int hostapd_setup_bss(struct host
|
|
+@@ -1538,6 +1538,7 @@ int hostapd_setup_bss(struct hostapd_dat
|
|
wpa_printf(MSG_ERROR, "GAS server initialization failed");
|
|
return -1;
|
|
}
|
|
@@ -40,7 +40,7 @@
|
|
|
|
if (conf->qos_map_set_len &&
|
|
hostapd_drv_set_qos_map(hapd, conf->qos_map_set,
|
|
-@@ -1422,7 +1423,6 @@ static int hostapd_setup_bss(struct host
|
|
+@@ -1545,7 +1546,6 @@ int hostapd_setup_bss(struct hostapd_dat
|
|
wpa_printf(MSG_ERROR, "Failed to initialize QoS Map");
|
|
return -1;
|
|
}
|
|
@@ -48,40 +48,9 @@
|
|
|
|
if (conf->bss_load_update_period && bss_load_update_init(hapd)) {
|
|
wpa_printf(MSG_ERROR, "BSS Load initialization failed");
|
|
---- a/src/ap/drv_callbacks.c
|
|
-+++ b/src/ap/drv_callbacks.c
|
|
-@@ -271,12 +271,10 @@ int hostapd_notif_assoc(struct hostapd_d
|
|
- }
|
|
- #endif /* NEED_AP_MLME */
|
|
-
|
|
--#ifdef CONFIG_INTERWORKING
|
|
- if (elems.ext_capab && elems.ext_capab_len > 4) {
|
|
- if (elems.ext_capab[4] & 0x01)
|
|
- sta->qos_map_enabled = 1;
|
|
- }
|
|
--#endif /* CONFIG_INTERWORKING */
|
|
-
|
|
- #ifdef CONFIG_HS20
|
|
- wpabuf_free(sta->hs20_ie);
|
|
---- a/src/ap/ieee802_11.c
|
|
-+++ b/src/ap/ieee802_11.c
|
|
-@@ -4129,13 +4129,11 @@ static u16 copy_supp_rates(struct hostap
|
|
- static 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));
|
|
--- a/wpa_supplicant/events.c
|
|
+++ b/wpa_supplicant/events.c
|
|
-@@ -2540,8 +2540,6 @@ void wnm_bss_keep_alive_deinit(struct wp
|
|
+@@ -2683,8 +2683,6 @@ void wnm_bss_keep_alive_deinit(struct wp
|
|
}
|
|
|
|
|
|
@@ -90,16 +59,16 @@
|
|
static int wpas_qos_map_set(struct wpa_supplicant *wpa_s, const u8 *qos_map,
|
|
size_t len)
|
|
{
|
|
-@@ -2574,8 +2572,6 @@ static void interworking_process_assoc_r
|
|
+@@ -2717,8 +2715,6 @@ static void interworking_process_assoc_r
|
|
}
|
|
}
|
|
|
|
-#endif /* CONFIG_INTERWORKING */
|
|
-
|
|
|
|
- static void multi_ap_process_assoc_resp(struct wpa_supplicant *wpa_s,
|
|
- const u8 *ies, size_t ies_len)
|
|
-@@ -2908,10 +2904,8 @@ static int wpa_supplicant_event_associnf
|
|
+ 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 */
|
|
@@ -110,3 +79,19 @@
|
|
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
|
|
index 8af5a0a046..f5ebab70d1 100644
|
|
--- 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
|
|
@@ -1,6 +1,6 @@
|
|
--- a/src/ap/ap_drv_ops.c
|
|
+++ b/src/ap/ap_drv_ops.c
|
|
-@@ -850,7 +850,8 @@ int hostapd_start_dfs_cac(struct hostapd
|
|
+@@ -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)
|
|
{
|
|
diff --git a/package/network/services/hostapd/patches/760-acs_exclude_dfs.patch b/package/network/services/hostapd/patches/760-acs_exclude_dfs.patch
|
|
deleted file mode 100644
|
|
index 52d63c5ff9..0000000000
|
|
--- a/package/network/services/hostapd/patches/760-acs_exclude_dfs.patch
|
|
+++ /dev/null
|
|
@@ -1,15 +0,0 @@
|
|
-Index: hostapd-2021-02-20-59e9794c/src/ap/acs.c
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/ap/acs.c
|
|
-+++ hostapd-2021-02-20-59e9794c/src/ap/acs.c
|
|
-@@ -672,6 +672,10 @@ acs_find_ideal_chan_mode(struct hostapd_
|
|
- continue;
|
|
- }
|
|
-
|
|
-+ if (iface->conf->acs_exclude_dfs &&
|
|
-+ (chan->flag & HOSTAPD_CHAN_RADAR))
|
|
-+ continue;
|
|
-+
|
|
- /* HT40 on 5 GHz has a limited set of primary channels as per
|
|
- * 11n Annex J */
|
|
- if (mode->mode == HOSTAPD_MODE_IEEE80211A &&
|
|
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..d60764ac59
|
|
--- /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
|
|
+@@ -1475,6 +1475,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..6fca86d881
|
|
--- /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
|
|
+@@ -42,6 +42,7 @@ static struct hapd_global global;
|
|
+ static int daemonize = 0;
|
|
+ static char *pid_file = NULL;
|
|
+
|
|
++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,
|
|
+@@ -755,6 +756,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/780-maxassoc.patch b/package/network/services/hostapd/patches/780-maxassoc.patch
|
|
index 98840f382a..458d4ce2d6 100644
|
|
--- a/package/network/services/hostapd/patches/780-maxassoc.patch
|
|
+++ b/package/network/services/hostapd/patches/780-maxassoc.patch
|
|
@@ -1,8 +1,6 @@
|
|
-Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.c
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.c
|
|
-+++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.c
|
|
-@@ -717,7 +717,7 @@ struct sta_info * ap_sta_add(struct host
|
|
+--- a/src/ap/sta_info.c
|
|
++++ b/src/ap/sta_info.c
|
|
+@@ -730,7 +730,7 @@ struct sta_info * ap_sta_add(struct host
|
|
return sta;
|
|
|
|
wpa_printf(MSG_DEBUG, " New STA");
|
|
diff --git a/package/network/services/hostapd/patches/750-wispr.patch b/package/network/services/hostapd/patches/790-wispr.patch
|
|
similarity index 65%
|
|
rename from package/network/services/hostapd/patches/750-wispr.patch
|
|
rename to package/network/services/hostapd/patches/790-wispr.patch
|
|
index 59537cedeb..3df2f48d87 100644
|
|
--- a/package/network/services/hostapd/patches/750-wispr.patch
|
|
+++ b/package/network/services/hostapd/patches/790-wispr.patch
|
|
@@ -1,8 +1,6 @@
|
|
-Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_1x.c
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/ap/ieee802_1x.c
|
|
-+++ hostapd-2021-02-20-59e9794c/src/ap/ieee802_1x.c
|
|
-@@ -1904,6 +1904,25 @@ static int ieee802_1x_update_vlan(struct
|
|
+--- a/src/ap/ieee802_1x.c
|
|
++++ b/src/ap/ieee802_1x.c
|
|
+@@ -2009,6 +2009,25 @@ static int ieee802_1x_update_vlan(struct
|
|
}
|
|
#endif /* CONFIG_NO_VLAN */
|
|
|
|
@@ -28,7 +26,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_1x.c
|
|
|
|
/**
|
|
* ieee802_1x_receive_auth - Process RADIUS frames from Authentication Server
|
|
-@@ -2029,6 +2048,7 @@ ieee802_1x_receive_auth(struct radius_ms
|
|
+@@ -2134,6 +2153,7 @@ ieee802_1x_receive_auth(struct radius_ms
|
|
ieee802_1x_check_hs20(hapd, sta, msg,
|
|
session_timeout_set ?
|
|
(int) session_timeout : -1);
|
|
@@ -36,11 +34,9 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ieee802_1x.c
|
|
break;
|
|
case RADIUS_CODE_ACCESS_REJECT:
|
|
sm->eap_if->aaaFail = true;
|
|
-Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.h
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/ap/sta_info.h
|
|
-+++ hostapd-2021-02-20-59e9794c/src/ap/sta_info.h
|
|
-@@ -117,6 +117,7 @@ struct sta_info {
|
|
+--- a/src/ap/sta_info.h
|
|
++++ b/src/ap/sta_info.h
|
|
+@@ -112,6 +112,7 @@ struct sta_info {
|
|
u8 supported_rates[WLAN_SUPP_RATES_MAX];
|
|
int supported_rates_len;
|
|
u8 qosinfo; /* Valid when WLAN_STA_WMM is set */
|
|
@@ -48,11 +44,9 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/sta_info.h
|
|
|
|
#ifdef CONFIG_MESH
|
|
enum mesh_plink_state plink_state;
|
|
-Index: hostapd-2021-02-20-59e9794c/src/radius/radius.c
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/radius/radius.c
|
|
-+++ hostapd-2021-02-20-59e9794c/src/radius/radius.c
|
|
-@@ -1182,6 +1182,35 @@ radius_msg_get_cisco_keys(struct radius_
|
|
+--- a/src/radius/radius.c
|
|
++++ b/src/radius/radius.c
|
|
+@@ -1304,6 +1304,35 @@ radius_msg_get_cisco_keys(struct radius_
|
|
return keys;
|
|
}
|
|
|
|
@@ -88,11 +82,9 @@ Index: hostapd-2021-02-20-59e9794c/src/radius/radius.c
|
|
|
|
int radius_msg_add_mppe_keys(struct radius_msg *msg,
|
|
const u8 *req_authenticator,
|
|
-Index: hostapd-2021-02-20-59e9794c/src/radius/radius.h
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/radius/radius.h
|
|
-+++ hostapd-2021-02-20-59e9794c/src/radius/radius.h
|
|
-@@ -205,6 +205,10 @@ enum {
|
|
+--- a/src/radius/radius.h
|
|
++++ b/src/radius/radius.h
|
|
+@@ -233,6 +233,10 @@ enum {
|
|
RADIUS_VENDOR_ATTR_WFA_HS20_T_C_URL = 10,
|
|
};
|
|
|
|
@@ -103,7 +95,7 @@ Index: hostapd-2021-02-20-59e9794c/src/radius/radius.h
|
|
#ifdef _MSC_VER
|
|
#pragma pack(pop)
|
|
#endif /* _MSC_VER */
|
|
-@@ -277,6 +281,7 @@ radius_msg_get_ms_keys(struct radius_msg
|
|
+@@ -305,6 +309,7 @@ radius_msg_get_ms_keys(struct radius_msg
|
|
struct radius_ms_mppe_keys *
|
|
radius_msg_get_cisco_keys(struct radius_msg *msg, struct radius_msg *sent_msg,
|
|
const u8 *secret, size_t secret_len);
|
|
diff --git a/package/network/services/hostapd/patches/800-fix-ap-sta-channel-setup-failed.patch b/package/network/services/hostapd/patches/800-fix-ap-sta-channel-setup-failed.patch
|
|
index de7a611587..2bff78be27 100644
|
|
--- a/package/network/services/hostapd/patches/800-fix-ap-sta-channel-setup-failed.patch
|
|
+++ b/package/network/services/hostapd/patches/800-fix-ap-sta-channel-setup-failed.patch
|
|
@@ -1,8 +1,6 @@
|
|
-diff --git a/src/common/hw_features_common.c b/src/common/hw_features_common.c
|
|
-index ad2aebf..355b4a8 100644
|
|
--- a/src/common/hw_features_common.c
|
|
+++ b/src/common/hw_features_common.c
|
|
-@@ -615,9 +615,21 @@ int hostapd_set_freq_params(struct hostapd_freq_params *data,
|
|
+@@ -640,9 +640,21 @@ int hostapd_set_freq_params(struct hosta
|
|
center_segment0 == channel - 6)
|
|
data->center_freq1 = 5000 + center_segment0 * 5;
|
|
else {
|
|
diff --git a/package/network/services/hostapd/patches/900-coa_multi.patch b/package/network/services/hostapd/patches/900-coa_multi.patch
|
|
index 2b0131de0d..1652eb1049 100644
|
|
--- a/package/network/services/hostapd/patches/900-coa_multi.patch
|
|
+++ b/package/network/services/hostapd/patches/900-coa_multi.patch
|
|
@@ -1,8 +1,6 @@
|
|
-Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/ap/hostapd.c
|
|
-+++ hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
|
|
-@@ -862,7 +862,6 @@ static int hostapd_das_nas_mismatch(stru
|
|
+--- a/src/ap/hostapd.c
|
|
++++ b/src/ap/hostapd.c
|
|
+@@ -934,7 +934,6 @@ static int hostapd_das_nas_mismatch(stru
|
|
return 0;
|
|
}
|
|
|
|
@@ -10,7 +8,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
|
|
static struct sta_info * hostapd_das_find_sta(struct hostapd_data *hapd,
|
|
struct radius_das_attrs *attr,
|
|
int *multi)
|
|
-@@ -1050,6 +1049,24 @@ static int hostapd_das_disconnect_pmksa(
|
|
+@@ -1122,6 +1121,24 @@ static int hostapd_das_disconnect_pmksa(
|
|
}
|
|
|
|
|
|
@@ -35,7 +33,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
|
|
static enum radius_das_res
|
|
hostapd_das_disconnect(void *ctx, struct radius_das_attrs *attr)
|
|
{
|
|
-@@ -1057,6 +1074,10 @@ hostapd_das_disconnect(void *ctx, struct
|
|
+@@ -1129,6 +1146,10 @@ hostapd_das_disconnect(void *ctx, struct
|
|
struct sta_info *sta;
|
|
int multi;
|
|
|
|
@@ -46,7 +44,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
|
|
if (hostapd_das_nas_mismatch(hapd, attr))
|
|
return RADIUS_DAS_NAS_MISMATCH;
|
|
|
|
-@@ -1096,6 +1117,10 @@ hostapd_das_coa(void *ctx, struct radius
|
|
+@@ -1168,6 +1189,10 @@ hostapd_das_coa(void *ctx, struct radius
|
|
struct sta_info *sta;
|
|
int multi;
|
|
|
|
@@ -57,20 +55,17 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/hostapd.c
|
|
if (hostapd_das_nas_mismatch(hapd, attr))
|
|
return RADIUS_DAS_NAS_MISMATCH;
|
|
|
|
-Index: hostapd-2021-02-20-59e9794c/src/radius/radius_das.c
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/radius/radius_das.c
|
|
-+++ hostapd-2021-02-20-59e9794c/src/radius/radius_das.c
|
|
-@@ -568,10 +568,9 @@ radius_das_init(struct radius_das_conf *
|
|
-
|
|
- das->sock = radius_das_open_socket(conf->port);
|
|
- if (das->sock < 0) {
|
|
-- wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS "
|
|
-+ wpa_printf(MSG_ERROR, "Failed to open UDP socket for RADIUS - reusing existing port "
|
|
- "DAS");
|
|
+--- a/src/radius/radius_das.c
|
|
++++ b/src/radius/radius_das.c
|
|
+@@ -652,9 +652,8 @@ radius_das_init(struct radius_das_conf *
|
|
+ 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;
|
|
++ "DAS - reusing existing port");
|
|
+ return das;
|
|
}
|
|
|
|
- if (eloop_register_read_sock(das->sock, radius_das_receive, das, NULL))
|
|
+ dl_list_add(&das->port->das_data, &das->list);
|
|
diff --git a/package/network/services/hostapd/patches/901-cfg-section.patch b/package/network/services/hostapd/patches/901-cfg-section.patch
|
|
index dcfdd658fe..32b4885ba3 100644
|
|
--- a/package/network/services/hostapd/patches/901-cfg-section.patch
|
|
+++ b/package/network/services/hostapd/patches/901-cfg-section.patch
|
|
@@ -1,8 +1,6 @@
|
|
-Index: hostapd-2021-02-20-59e9794c/hostapd/config_file.c
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/hostapd/config_file.c
|
|
-+++ hostapd-2021-02-20-59e9794c/hostapd/config_file.c
|
|
-@@ -2366,6 +2366,8 @@ static int hostapd_config_fill(struct ho
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -2343,6 +2343,8 @@ static int hostapd_config_fill(struct ho
|
|
return 1;
|
|
}
|
|
conf->driver = driver;
|
|
@@ -11,23 +9,19 @@ Index: hostapd-2021-02-20-59e9794c/hostapd/config_file.c
|
|
} else if (os_strcmp(buf, "driver_params") == 0) {
|
|
os_free(conf->driver_params);
|
|
conf->driver_params = os_strdup(pos);
|
|
-Index: hostapd-2021-02-20-59e9794c/src/ap/ap_config.h
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/ap/ap_config.h
|
|
-+++ hostapd-2021-02-20-59e9794c/src/ap/ap_config.h
|
|
-@@ -279,6 +279,7 @@ struct hostapd_bss_config {
|
|
+--- a/src/ap/ap_config.h
|
|
++++ b/src/ap/ap_config.h
|
|
+@@ -287,6 +287,7 @@ struct hostapd_bss_config {
|
|
char snoop_iface[IFNAMSIZ + 1];
|
|
char vlan_bridge[IFNAMSIZ + 1];
|
|
char wds_bridge[IFNAMSIZ + 1];
|
|
+ char *uci_section;
|
|
+ int bridge_hairpin; /* hairpin_mode on bridge members */
|
|
|
|
- char *config_id;
|
|
-
|
|
-Index: hostapd-2021-02-20-59e9794c/src/ap/ubus.c
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/ap/ubus.c
|
|
-+++ hostapd-2021-02-20-59e9794c/src/ap/ubus.c
|
|
-@@ -467,6 +467,9 @@ hostapd_bss_get_status(struct ubus_conte
|
|
+ enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
|
|
+--- a/src/ap/ubus.c
|
|
++++ b/src/ap/ubus.c
|
|
+@@ -418,6 +418,9 @@ hostapd_bss_get_status(struct ubus_conte
|
|
hapd->iface->cac_started ? hapd->iface->dfs_cac_ms / 1000 - now.sec : 0);
|
|
blobmsg_close_table(&b, dfs_table);
|
|
|
|
@@ -37,11 +31,9 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ubus.c
|
|
ubus_send_reply(ctx, req, b.head);
|
|
|
|
return 0;
|
|
-Index: hostapd-2021-02-20-59e9794c/src/ap/ap_config.c
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/ap/ap_config.c
|
|
-+++ hostapd-2021-02-20-59e9794c/src/ap/ap_config.c
|
|
-@@ -785,6 +785,7 @@ void hostapd_config_free_bss(struct host
|
|
+--- a/src/ap/ap_config.c
|
|
++++ b/src/ap/ap_config.c
|
|
+@@ -798,6 +798,7 @@ void hostapd_config_free_bss(struct host
|
|
os_free(conf->radius_req_attr_sqlite);
|
|
os_free(conf->rsn_preauth_interfaces);
|
|
os_free(conf->ctrl_interface);
|
|
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/patches/999-probe-request.patch b/package/network/services/hostapd/patches/999-probe-request.patch
|
|
index 3b79338c2f..bb5f259e0e 100644
|
|
--- a/package/network/services/hostapd/patches/999-probe-request.patch
|
|
+++ b/package/network/services/hostapd/patches/999-probe-request.patch
|
|
@@ -1,8 +1,6 @@
|
|
-Index: hostapd-2021-02-20-59e9794c/hostapd/config_file.c
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/hostapd/config_file.c
|
|
-+++ hostapd-2021-02-20-59e9794c/hostapd/config_file.c
|
|
-@@ -3339,6 +3339,8 @@ static int hostapd_config_fill(struct ho
|
|
+--- a/hostapd/config_file.c
|
|
++++ b/hostapd/config_file.c
|
|
+@@ -3348,6 +3348,8 @@ static int hostapd_config_fill(struct ho
|
|
bss->ignore_broadcast_ssid = atoi(pos);
|
|
} else if (os_strcmp(buf, "no_probe_resp_if_max_sta") == 0) {
|
|
bss->no_probe_resp_if_max_sta = atoi(pos);
|
|
@@ -11,11 +9,9 @@ Index: hostapd-2021-02-20-59e9794c/hostapd/config_file.c
|
|
#ifdef CONFIG_WEP
|
|
} else if (os_strcmp(buf, "wep_default_key") == 0) {
|
|
bss->ssid.wep.idx = atoi(pos);
|
|
-Index: hostapd-2021-02-20-59e9794c/src/ap/ap_config.h
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/ap/ap_config.h
|
|
-+++ hostapd-2021-02-20-59e9794c/src/ap/ap_config.h
|
|
-@@ -460,6 +460,7 @@ struct hostapd_bss_config {
|
|
+--- a/src/ap/ap_config.h
|
|
++++ b/src/ap/ap_config.h
|
|
+@@ -470,6 +470,7 @@ struct hostapd_bss_config {
|
|
int ap_max_inactivity;
|
|
int ignore_broadcast_ssid;
|
|
int no_probe_resp_if_max_sta;
|
|
@@ -23,11 +19,9 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/ap_config.h
|
|
|
|
int wmm_enabled;
|
|
int wmm_uapsd;
|
|
-Index: hostapd-2021-02-20-59e9794c/src/ap/beacon.c
|
|
-===================================================================
|
|
---- hostapd-2021-02-20-59e9794c.orig/src/ap/beacon.c
|
|
-+++ hostapd-2021-02-20-59e9794c/src/ap/beacon.c
|
|
-@@ -920,7 +920,8 @@ void handle_probe_req(struct hostapd_dat
|
|
+--- a/src/ap/beacon.c
|
|
++++ b/src/ap/beacon.c
|
|
+@@ -1133,7 +1133,8 @@ void handle_probe_req(struct hostapd_dat
|
|
}
|
|
#endif /* CONFIG_P2P */
|
|
|
|
@@ -37,7 +31,7 @@ Index: hostapd-2021-02-20-59e9794c/src/ap/beacon.c
|
|
elems.ssid_list_len == 0 && elems.short_ssid_list_len == 0) {
|
|
wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
|
|
"broadcast SSID ignored", MAC2STR(mgmt->sa));
|
|
-@@ -967,7 +968,8 @@ void handle_probe_req(struct hostapd_dat
|
|
+@@ -1180,7 +1181,8 @@ void handle_probe_req(struct hostapd_dat
|
|
return;
|
|
}
|
|
|
|
diff --git a/package/network/services/hostapd/patches/n00-001-RADIUS-ACL-PSK-check-during-4-way-handshake.patch b/package/network/services/hostapd/patches/n00-001-RADIUS-ACL-PSK-check-during-4-way-handshake.patch
|
|
deleted file mode 100644
|
|
index 7a265ecc6b..0000000000
|
|
--- a/package/network/services/hostapd/patches/n00-001-RADIUS-ACL-PSK-check-during-4-way-handshake.patch
|
|
+++ /dev/null
|
|
@@ -1,484 +0,0 @@
|
|
-From 1c3438fec4bad13a676617915ff56af54e7b4542 Mon Sep 17 00:00:00 2001
|
|
-From: Jouni Malinen <j@w1.fi>
|
|
-Date: Sat, 2 Apr 2022 13:12:43 +0300
|
|
-Subject: [PATCH] RADIUS ACL/PSK check during 4-way handshake
|
|
-
|
|
-Add an alternative sequence for performing the RADIUS ACL check and PSK
|
|
-fetch. The previously used (macaddr_acl=2, wpa_psk_radius=2) combination
|
|
-does this during IEEE 802.11 Authentication frame exchange while the new
|
|
-option (wpa_psk_radius=3) does this during the 4-way handshake. This
|
|
-allows some more information to be provided to the RADIUS authentication
|
|
-server.
|
|
-
|
|
-Signed-off-by: Jouni Malinen <j@w1.fi>
|
|
----
|
|
- hostapd/config_file.c | 3 +-
|
|
- hostapd/hostapd.conf | 5 ++-
|
|
- src/ap/ap_config.c | 4 ++-
|
|
- src/ap/ap_config.h | 5 +--
|
|
- src/ap/ieee802_11.c | 5 ++-
|
|
- src/ap/ieee802_11.h | 2 ++
|
|
- src/ap/ieee802_11_auth.c | 76 ++++++++++++++++++++++++++++++++++++----
|
|
- src/ap/ieee802_11_auth.h | 5 ++-
|
|
- src/ap/wpa_auth.c | 51 ++++++++++++++++++++++++++-
|
|
- src/ap/wpa_auth.h | 9 ++++-
|
|
- src/ap/wpa_auth_glue.c | 25 ++++++++++++-
|
|
- src/ap/wpa_auth_i.h | 1 +
|
|
- 12 files changed, 172 insertions(+), 19 deletions(-)
|
|
-
|
|
-Index: hostapd-2022-01-16-cff80b4f/hostapd/config_file.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/hostapd/config_file.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/hostapd/config_file.c
|
|
-@@ -2989,7 +2989,8 @@ static int hostapd_config_fill(struct ho
|
|
- bss->wpa_psk_radius = atoi(pos);
|
|
- if (bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
|
|
- bss->wpa_psk_radius != PSK_RADIUS_ACCEPTED &&
|
|
-- bss->wpa_psk_radius != PSK_RADIUS_REQUIRED) {
|
|
-+ bss->wpa_psk_radius != PSK_RADIUS_REQUIRED &&
|
|
-+ bss->wpa_psk_radius != PSK_RADIUS_DURING_4WAY_HS) {
|
|
- wpa_printf(MSG_ERROR,
|
|
- "Line %d: unknown wpa_psk_radius %d",
|
|
- line, bss->wpa_psk_radius);
|
|
-Index: hostapd-2022-01-16-cff80b4f/hostapd/hostapd.conf
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/hostapd/hostapd.conf
|
|
-+++ hostapd-2022-01-16-cff80b4f/hostapd/hostapd.conf
|
|
-@@ -1651,12 +1651,15 @@ own_ip_addr=127.0.0.1
|
|
- #wpa_psk_file=/etc/hostapd.wpa_psk
|
|
-
|
|
- # Optionally, WPA passphrase can be received from RADIUS authentication server
|
|
--# This requires macaddr_acl to be set to 2 (RADIUS)
|
|
-+# This requires macaddr_acl to be set to 2 (RADIUS) for wpa_psk_radius values
|
|
-+# 1 and 2.
|
|
- # 0 = disabled (default)
|
|
- # 1 = optional; use default passphrase/psk if RADIUS server does not include
|
|
- # Tunnel-Password
|
|
- # 2 = required; reject authentication if RADIUS server does not include
|
|
- # Tunnel-Password
|
|
-+# 3 = ask RADIUS server during 4-way handshake if there is no locally
|
|
-+# configured PSK/passphrase for the STA
|
|
- #wpa_psk_radius=0
|
|
-
|
|
- # Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/ap_config.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/ap_config.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/ap_config.c
|
|
-@@ -1,6 +1,6 @@
|
|
- /*
|
|
- * hostapd / Configuration helper functions
|
|
-- * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
|
|
-+ * Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
|
|
- *
|
|
- * This software may be distributed under the terms of the BSD license.
|
|
- * See README for more details.
|
|
-@@ -1245,6 +1245,7 @@ static int hostapd_config_check_bss(stru
|
|
-
|
|
- if (full_config && bss->wpa &&
|
|
- bss->wpa_psk_radius != PSK_RADIUS_IGNORED &&
|
|
-+ bss->wpa_psk_radius != PSK_RADIUS_DURING_4WAY_HS &&
|
|
- bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) {
|
|
- wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no "
|
|
- "RADIUS checking (macaddr_acl=2) enabled.");
|
|
-@@ -1254,6 +1255,7 @@ static int hostapd_config_check_bss(stru
|
|
- if (full_config && bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) &&
|
|
- bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL &&
|
|
- bss->ssid.wpa_psk_file == NULL &&
|
|
-+ bss->wpa_psk_radius != PSK_RADIUS_DURING_4WAY_HS &&
|
|
- (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED ||
|
|
- bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) {
|
|
- wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase "
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/ap_config.h
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/ap_config.h
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/ap_config.h
|
|
-@@ -1,6 +1,6 @@
|
|
- /*
|
|
- * hostapd / Configuration definitions and helpers functions
|
|
-- * Copyright (c) 2003-2015, Jouni Malinen <j@w1.fi>
|
|
-+ * Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
|
|
- *
|
|
- * This software may be distributed under the terms of the BSD license.
|
|
- * See README for more details.
|
|
-@@ -369,7 +369,8 @@ struct hostapd_bss_config {
|
|
- enum {
|
|
- PSK_RADIUS_IGNORED = 0,
|
|
- PSK_RADIUS_ACCEPTED = 1,
|
|
-- PSK_RADIUS_REQUIRED = 2
|
|
-+ PSK_RADIUS_REQUIRED = 2,
|
|
-+ PSK_RADIUS_DURING_4WAY_HS = 3,
|
|
- } wpa_psk_radius;
|
|
- int wpa_pairwise;
|
|
- int group_cipher; /* wpa_group value override from configuation */
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/ieee802_11.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.c
|
|
-@@ -2315,9 +2315,8 @@ static int ieee802_11_allowed_address(st
|
|
- }
|
|
-
|
|
-
|
|
--static int
|
|
--ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
|
|
-- int res, struct radius_sta *info)
|
|
-+int ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
|
|
-+ int res, struct radius_sta *info)
|
|
- {
|
|
- u32 session_timeout = info->session_timeout;
|
|
- u32 acct_interim_interval = info->acct_interim_interval;
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.h
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/ieee802_11.h
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11.h
|
|
-@@ -196,5 +196,7 @@ void auth_sae_process_commit(void *eloop
|
|
- u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len);
|
|
- size_t hostapd_eid_rnr_len(struct hostapd_data *hapd, u32 type);
|
|
- u8 * hostapd_eid_rnr(struct hostapd_data *hapd, u8 *eid, u32 type);
|
|
-+int ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
|
|
-+ int res, struct radius_sta *info);
|
|
-
|
|
- #endif /* IEEE802_11_H */
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11_auth.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/ieee802_11_auth.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11_auth.c
|
|
-@@ -1,6 +1,6 @@
|
|
- /*
|
|
- * hostapd / IEEE 802.11 authentication (ACL)
|
|
-- * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
|
|
-+ * Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
|
|
- *
|
|
- * This software may be distributed under the terms of the BSD license.
|
|
- * See README for more details.
|
|
-@@ -20,6 +20,8 @@
|
|
- #include "hostapd.h"
|
|
- #include "ap_config.h"
|
|
- #include "ap_drv_ops.h"
|
|
-+#include "sta_info.h"
|
|
-+#include "wpa_auth.h"
|
|
- #include "ieee802_11.h"
|
|
- #include "ieee802_1x.h"
|
|
- #include "ieee802_11_auth.h"
|
|
-@@ -43,6 +45,8 @@ struct hostapd_acl_query_data {
|
|
- u8 *auth_msg; /* IEEE 802.11 authentication frame from station */
|
|
- size_t auth_msg_len;
|
|
- struct hostapd_acl_query_data *next;
|
|
-+ bool radius_psk;
|
|
-+ int akm;
|
|
- };
|
|
-
|
|
-
|
|
-@@ -153,6 +157,13 @@ static int hostapd_radius_acl_query(stru
|
|
- goto fail;
|
|
- }
|
|
-
|
|
-+ if (query->akm &&
|
|
-+ !radius_msg_add_attr_int32(msg, RADIUS_ATTR_WLAN_AKM_SUITE,
|
|
-+ wpa_akm_to_suite(query->akm))) {
|
|
-+ wpa_printf(MSG_DEBUG, "Could not add WLAN-AKM-Suite");
|
|
-+ goto fail;
|
|
-+ }
|
|
-+
|
|
- if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0)
|
|
- goto fail;
|
|
- return 0;
|
|
-@@ -557,17 +568,40 @@ hostapd_acl_recv_radius(struct radius_ms
|
|
- cache->next = hapd->acl_cache;
|
|
- hapd->acl_cache = cache;
|
|
-
|
|
-+ if (query->radius_psk) {
|
|
-+ struct sta_info *sta;
|
|
-+ bool success = cache->accepted == HOSTAPD_ACL_ACCEPT;
|
|
-+
|
|
-+ sta = ap_get_sta(hapd, query->addr);
|
|
-+ if (!sta || !sta->wpa_sm) {
|
|
-+ wpa_printf(MSG_DEBUG,
|
|
-+ "No STA/SM entry found for the RADIUS PSK response");
|
|
-+ goto done;
|
|
-+ }
|
|
-+#ifdef NEED_AP_MLME
|
|
-+ if (success &&
|
|
-+ (ieee802_11_set_radius_info(hapd, sta, cache->accepted,
|
|
-+ info) < 0 ||
|
|
-+ ap_sta_bind_vlan(hapd, sta) < 0))
|
|
-+ success = false;
|
|
-+#endif /* NEED_AP_MLME */
|
|
-+ wpa_auth_sta_radius_psk_resp(sta->wpa_sm, success);
|
|
-+ } else {
|
|
- #ifdef CONFIG_DRIVER_RADIUS_ACL
|
|
-- hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted,
|
|
-- info->session_timeout);
|
|
-+ hostapd_drv_set_radius_acl_auth(hapd, query->addr,
|
|
-+ cache->accepted,
|
|
-+ info->session_timeout);
|
|
- #else /* CONFIG_DRIVER_RADIUS_ACL */
|
|
- #ifdef NEED_AP_MLME
|
|
-- /* Re-send original authentication frame for 802.11 processing */
|
|
-- wpa_printf(MSG_DEBUG, "Re-sending authentication frame after "
|
|
-- "successful RADIUS ACL query");
|
|
-- ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL);
|
|
-+ /* Re-send original authentication frame for 802.11 processing
|
|
-+ */
|
|
-+ wpa_printf(MSG_DEBUG,
|
|
-+ "Re-sending authentication frame after successful RADIUS ACL query");
|
|
-+ ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len,
|
|
-+ NULL);
|
|
- #endif /* NEED_AP_MLME */
|
|
- #endif /* CONFIG_DRIVER_RADIUS_ACL */
|
|
-+ }
|
|
-
|
|
- done:
|
|
- if (prev == NULL)
|
|
-@@ -649,3 +683,31 @@ void hostapd_free_psk_list(struct hostap
|
|
- os_free(prev);
|
|
- }
|
|
- }
|
|
-+
|
|
-+
|
|
-+#ifndef CONFIG_NO_RADIUS
|
|
-+void hostapd_acl_req_radius_psk(struct hostapd_data *hapd, const u8 *addr,
|
|
-+ int key_mgmt, const u8 *anonce,
|
|
-+ const u8 *eapol, size_t eapol_len)
|
|
-+{
|
|
-+ struct hostapd_acl_query_data *query;
|
|
-+
|
|
-+ query = os_zalloc(sizeof(*query));
|
|
-+ if (!query)
|
|
-+ return;
|
|
-+
|
|
-+ query->radius_psk = true;
|
|
-+ query->akm = key_mgmt;
|
|
-+ os_get_reltime(&query->timestamp);
|
|
-+ os_memcpy(query->addr, addr, ETH_ALEN);
|
|
-+ if (hostapd_radius_acl_query(hapd, addr, query)) {
|
|
-+ wpa_printf(MSG_DEBUG,
|
|
-+ "Failed to send Access-Request for RADIUS PSK/ACL query");
|
|
-+ hostapd_acl_query_free(query);
|
|
-+ return;
|
|
-+ }
|
|
-+
|
|
-+ query->next = hapd->acl_queries;
|
|
-+ hapd->acl_queries = query;
|
|
-+}
|
|
-+#endif /* CONFIG_NO_RADIUS */
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11_auth.h
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/ieee802_11_auth.h
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/ieee802_11_auth.h
|
|
-@@ -1,6 +1,6 @@
|
|
- /*
|
|
- * hostapd / IEEE 802.11 authentication (ACL)
|
|
-- * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
|
-+ * Copyright (c) 2003-2022, Jouni Malinen <j@w1.fi>
|
|
- *
|
|
- * This software may be distributed under the terms of the BSD license.
|
|
- * See README for more details.
|
|
-@@ -36,5 +36,8 @@ void hostapd_free_psk_list(struct hostap
|
|
- void hostapd_acl_expire(struct hostapd_data *hapd);
|
|
- void hostapd_copy_psk_list(struct hostapd_sta_wpa_psk_short **psk,
|
|
- struct hostapd_sta_wpa_psk_short *src);
|
|
-+void hostapd_acl_req_radius_psk(struct hostapd_data *hapd, const u8 *addr,
|
|
-+ int key_mgmt, const u8 *anonce,
|
|
-+ const u8 *eapol, size_t eapol_len);
|
|
-
|
|
- #endif /* IEEE802_11_AUTH_H */
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/wpa_auth.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth.c
|
|
-@@ -1,6 +1,6 @@
|
|
- /*
|
|
- * IEEE 802.11 RSN / WPA Authenticator
|
|
-- * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
|
|
-+ * Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi>
|
|
- *
|
|
- * This software may be distributed under the terms of the BSD license.
|
|
- * See README for more details.
|
|
-@@ -1481,6 +1481,12 @@ static void wpa_send_eapol_timeout(void
|
|
- struct wpa_authenticator *wpa_auth = eloop_ctx;
|
|
- struct wpa_state_machine *sm = timeout_ctx;
|
|
-
|
|
-+ if (sm->waiting_radius_psk) {
|
|
-+ wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG,
|
|
-+ "Ignore EAPOL-Key timeout while waiting for RADIUS PSK");
|
|
-+ return;
|
|
-+ }
|
|
-+
|
|
- sm->pending_1_of_4_timeout = 0;
|
|
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout");
|
|
- sm->TimeoutEvt = true;
|
|
-@@ -3017,6 +3023,19 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
|
|
- break;
|
|
- }
|
|
-
|
|
-+ if (!ok && wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
|
|
-+ wpa_auth->conf.radius_psk && wpa_auth->cb->request_radius_psk &&
|
|
-+ !sm->waiting_radius_psk) {
|
|
-+ wpa_printf(MSG_DEBUG, "No PSK available - ask RADIUS server");
|
|
-+ wpa_auth->cb->request_radius_psk(wpa_auth->cb_ctx, sm->addr,
|
|
-+ sm->wpa_key_mgmt,
|
|
-+ sm->ANonce,
|
|
-+ sm->last_rx_eapol_key,
|
|
-+ sm->last_rx_eapol_key_len);
|
|
-+ sm->waiting_radius_psk = 1;
|
|
-+ return;
|
|
-+ }
|
|
-+
|
|
- if (!ok) {
|
|
- wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
|
|
- "invalid MIC in msg 2/4 of 4-Way Handshake");
|
|
-@@ -3774,6 +3793,11 @@ SM_STEP(WPA_PTK)
|
|
- } else if (wpa_auth_uses_sae(sm) && sm->pmksa) {
|
|
- SM_ENTER(WPA_PTK, PTKSTART);
|
|
- #endif /* CONFIG_SAE */
|
|
-+ } else if (wpa_key_mgmt_wpa_psk_no_sae(sm->wpa_key_mgmt) &&
|
|
-+ wpa_auth->conf.radius_psk) {
|
|
-+ wpa_printf(MSG_DEBUG,
|
|
-+ "INITPSK: No PSK yet available for STA - use RADIUS later");
|
|
-+ SM_ENTER(WPA_PTK, PTKSTART);
|
|
- } else {
|
|
- wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO,
|
|
- "no PSK configured for the STA");
|
|
-@@ -5688,3 +5712,28 @@ void wpa_auth_set_ocv_override_freq(stru
|
|
- }
|
|
-
|
|
- #endif /* CONFIG_TESTING_OPTIONS */
|
|
-+
|
|
-+
|
|
-+void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success)
|
|
-+{
|
|
-+ if (!sm->waiting_radius_psk) {
|
|
-+ wpa_printf(MSG_DEBUG,
|
|
-+ "Ignore RADIUS PSK response for " MACSTR
|
|
-+ " that did not wait one",
|
|
-+ MAC2STR(sm->addr));
|
|
-+ return;
|
|
-+ }
|
|
-+
|
|
-+ wpa_printf(MSG_DEBUG, "RADIUS PSK response for " MACSTR " (%s)",
|
|
-+ MAC2STR(sm->addr), success ? "success" : "fail");
|
|
-+ sm->waiting_radius_psk = 0;
|
|
-+
|
|
-+ if (success) {
|
|
-+ /* Try to process the EAPOL-Key msg 2/4 again */
|
|
-+ sm->EAPOLKeyReceived = true;
|
|
-+ } else {
|
|
-+ sm->Disconnect = true;
|
|
-+ }
|
|
-+
|
|
-+ eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL);
|
|
-+}
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth.h
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/wpa_auth.h
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth.h
|
|
-@@ -1,6 +1,6 @@
|
|
- /*
|
|
- * hostapd - IEEE 802.11i-2004 / WPA Authenticator
|
|
-- * Copyright (c) 2004-2017, Jouni Malinen <j@w1.fi>
|
|
-+ * Copyright (c) 2004-2022, Jouni Malinen <j@w1.fi>
|
|
- *
|
|
- * This software may be distributed under the terms of the BSD license.
|
|
- * See README for more details.
|
|
-@@ -273,6 +273,8 @@ struct wpa_auth_config {
|
|
- * PTK derivation regardless of advertised capabilities.
|
|
- */
|
|
- bool force_kdk_derivation;
|
|
-+
|
|
-+ bool radius_psk;
|
|
- };
|
|
-
|
|
- typedef enum {
|
|
-@@ -320,6 +322,9 @@ struct wpa_auth_callbacks {
|
|
- void (*store_ptksa)(void *ctx, const u8 *addr, int cipher,
|
|
- u32 life_time, const struct wpa_ptk *ptk);
|
|
- void (*clear_ptksa)(void *ctx, const u8 *addr, int cipher);
|
|
-+ void (*request_radius_psk)(void *ctx, const u8 *addr, int key_mgmt,
|
|
-+ const u8 *anonce,
|
|
-+ const u8 *eapol, size_t eapol_len);
|
|
- #ifdef CONFIG_IEEE80211R_AP
|
|
- struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr);
|
|
- int (*add_sta_ft)(void *ctx, const u8 *sta_addr);
|
|
-@@ -572,4 +577,6 @@ void wpa_auth_set_ocv_override_freq(stru
|
|
- enum wpa_auth_ocv_override_frame frame,
|
|
- unsigned int freq);
|
|
-
|
|
-+void wpa_auth_sta_radius_psk_resp(struct wpa_state_machine *sm, bool success);
|
|
-+
|
|
- #endif /* WPA_AUTH_H */
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth_glue.c
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/wpa_auth_glue.c
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth_glue.c
|
|
-@@ -1,6 +1,6 @@
|
|
- /*
|
|
- * hostapd / WPA authenticator glue code
|
|
-- * Copyright (c) 2002-2012, Jouni Malinen <j@w1.fi>
|
|
-+ * Copyright (c) 2002-2022, Jouni Malinen <j@w1.fi>
|
|
- *
|
|
- * This software may be distributed under the terms of the BSD license.
|
|
- * See README for more details.
|
|
-@@ -29,6 +29,7 @@
|
|
- #include "ap_drv_ops.h"
|
|
- #include "ap_config.h"
|
|
- #include "ieee802_11.h"
|
|
-+#include "ieee802_11_auth.h"
|
|
- #include "pmksa_cache_auth.h"
|
|
- #include "wpa_auth.h"
|
|
- #include "wpa_auth_glue.h"
|
|
-@@ -214,6 +215,8 @@ static void hostapd_wpa_auth_conf(struct
|
|
- wconf->force_kdk_derivation = conf->force_kdk_derivation;
|
|
- #endif /* CONFIG_TESTING_OPTIONS */
|
|
- #endif /* CONFIG_PASN */
|
|
-+
|
|
-+ wconf->radius_psk = conf->wpa_psk_radius == PSK_RADIUS_DURING_4WAY_HS;
|
|
- }
|
|
-
|
|
-
|
|
-@@ -1444,6 +1447,23 @@ static void hostapd_wpa_unregister_ft_ou
|
|
- #endif /* CONFIG_IEEE80211R_AP */
|
|
-
|
|
-
|
|
-+#ifndef CONFIG_NO_RADIUS
|
|
-+static void hostapd_request_radius_psk(void *ctx, const u8 *addr, int key_mgmt,
|
|
-+ const u8 *anonce,
|
|
-+ const u8 *eapol, size_t eapol_len)
|
|
-+{
|
|
-+ struct hostapd_data *hapd = ctx;
|
|
-+
|
|
-+ wpa_printf(MSG_DEBUG, "RADIUS PSK request for " MACSTR " key_mgmt=0x%x",
|
|
-+ MAC2STR(addr), key_mgmt);
|
|
-+ wpa_hexdump(MSG_DEBUG, "ANonce", anonce, WPA_NONCE_LEN);
|
|
-+ wpa_hexdump(MSG_DEBUG, "EAPOL", eapol, eapol_len);
|
|
-+ hostapd_acl_req_radius_psk(hapd, addr, key_mgmt, anonce, eapol,
|
|
-+ eapol_len);
|
|
-+}
|
|
-+#endif /* CONFIG_NO_RADIUS */
|
|
-+
|
|
-+
|
|
- int hostapd_setup_wpa(struct hostapd_data *hapd)
|
|
- {
|
|
- struct wpa_auth_config _conf;
|
|
-@@ -1487,6 +1507,9 @@ int hostapd_setup_wpa(struct hostapd_dat
|
|
- .set_session_timeout = hostapd_wpa_auth_set_session_timeout,
|
|
- .get_session_timeout = hostapd_wpa_auth_get_session_timeout,
|
|
- #endif /* CONFIG_IEEE80211R_AP */
|
|
-+#ifndef CONFIG_NO_RADIUS
|
|
-+ .request_radius_psk = hostapd_request_radius_psk,
|
|
-+#endif /* CONFIG_NO_RADIUS */
|
|
- };
|
|
- const u8 *wpa_ie;
|
|
- size_t wpa_ie_len;
|
|
-Index: hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth_i.h
|
|
-===================================================================
|
|
---- hostapd-2022-01-16-cff80b4f.orig/src/ap/wpa_auth_i.h
|
|
-+++ hostapd-2022-01-16-cff80b4f/src/ap/wpa_auth_i.h
|
|
-@@ -89,6 +89,7 @@ struct wpa_state_machine {
|
|
- unsigned int rx_eapol_key_secure:1;
|
|
- unsigned int update_snonce:1;
|
|
- unsigned int alt_snonce_valid:1;
|
|
-+ unsigned int waiting_radius_psk:1;
|
|
- #ifdef CONFIG_IEEE80211R_AP
|
|
- unsigned int ft_completed:1;
|
|
- unsigned int pmk_r1_name_valid:1;
|
|
diff --git a/package/network/services/hostapd/patches/n00-002-RADIUS-Attributes-with-Extended-Types-RFC-6929.patch b/package/network/services/hostapd/patches/n00-002-RADIUS-Attributes-with-Extended-Types-RFC-6929.patch
|
|
deleted file mode 100644
|
|
index eef9117176..0000000000
|
|
--- a/package/network/services/hostapd/patches/n00-002-RADIUS-Attributes-with-Extended-Types-RFC-6929.patch
|
|
+++ /dev/null
|
|
@@ -1,350 +0,0 @@
|
|
-From 24763e3cd0a564eb71f3c501bbb4fbb0d7070762 Mon Sep 17 00:00:00 2001
|
|
-From: Jouni Malinen <j@w1.fi>
|
|
-Date: Fri, 15 Apr 2022 17:31:48 +0300
|
|
-Subject: [PATCH] RADIUS: Attributes with Extended Types (RFC 6929)
|
|
-
|
|
-Supported extended types for RADIUS attributes for the cases defined in
|
|
-RFC 6929.
|
|
-
|
|
-Signed-off-by: Jouni Malinen <j@w1.fi>
|
|
----
|
|
- src/radius/radius.c | 195 ++++++++++++++++++++++++++++++++++++++------
|
|
- src/radius/radius.h | 26 +++++-
|
|
- 2 files changed, 193 insertions(+), 28 deletions(-)
|
|
-
|
|
-diff --git a/src/radius/radius.c b/src/radius/radius.c
|
|
-index be16e27b9..a64228067 100644
|
|
---- a/src/radius/radius.c
|
|
-+++ b/src/radius/radius.c
|
|
-@@ -1,6 +1,6 @@
|
|
- /*
|
|
- * RADIUS message processing
|
|
-- * Copyright (c) 2002-2009, 2011-2015, Jouni Malinen <j@w1.fi>
|
|
-+ * Copyright (c) 2002-2009, 2011-2022, Jouni Malinen <j@w1.fi>
|
|
- *
|
|
- * This software may be distributed under the terms of the BSD license.
|
|
- * See README for more details.
|
|
-@@ -159,7 +159,8 @@ static const char *radius_code_string(u8 code)
|
|
-
|
|
-
|
|
- struct radius_attr_type {
|
|
-- u8 type;
|
|
-+ u16 type; /* 0..255 for basic types;
|
|
-+ * (241 << 8) | <ext-type> for extended types */
|
|
- char *name;
|
|
- enum {
|
|
- RADIUS_ATTR_UNDIST, RADIUS_ATTR_TEXT, RADIUS_ATTR_IP,
|
|
-@@ -260,11 +261,31 @@ static const struct radius_attr_type radius_attrs[] =
|
|
- RADIUS_ATTR_HEXDUMP },
|
|
- { RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER, "WLAN-Group-Mgmt-Pairwise-Cipher",
|
|
- RADIUS_ATTR_HEXDUMP },
|
|
-+ { RADIUS_ATTR_EXT_TYPE_1, "Extended-Type-1", RADIUS_ATTR_UNDIST },
|
|
-+ { RADIUS_ATTR_EXT_TYPE_2, "Extended-Type-2", RADIUS_ATTR_UNDIST },
|
|
-+ { RADIUS_ATTR_EXT_TYPE_3, "Extended-Type-3", RADIUS_ATTR_UNDIST },
|
|
-+ { RADIUS_ATTR_EXT_TYPE_4, "Extended-Type-4", RADIUS_ATTR_UNDIST },
|
|
-+ { RADIUS_ATTR_LONG_EXT_TYPE_1, "Long-Extended-Type-1",
|
|
-+ RADIUS_ATTR_UNDIST },
|
|
-+ { RADIUS_ATTR_LONG_EXT_TYPE_2, "Long-Extended-Type-2",
|
|
-+ RADIUS_ATTR_UNDIST },
|
|
-+ { RADIUS_ATTR_EXT_VENDOR_SPECIFIC_1, "Extended-Vendor-Specific-1",
|
|
-+ RADIUS_ATTR_UNDIST },
|
|
-+ { RADIUS_ATTR_EXT_VENDOR_SPECIFIC_2, "Extended-Vendor-Specific-2",
|
|
-+ RADIUS_ATTR_UNDIST },
|
|
-+ { RADIUS_ATTR_EXT_VENDOR_SPECIFIC_3, "Extended-Vendor-Specific-3",
|
|
-+ RADIUS_ATTR_UNDIST },
|
|
-+ { RADIUS_ATTR_EXT_VENDOR_SPECIFIC_4, "Extended-Vendor-Specific-4",
|
|
-+ RADIUS_ATTR_UNDIST },
|
|
-+ { RADIUS_ATTR_EXT_VENDOR_SPECIFIC_5, "Extended-Vendor-Specific-5",
|
|
-+ RADIUS_ATTR_UNDIST },
|
|
-+ { RADIUS_ATTR_EXT_VENDOR_SPECIFIC_6, "Extended-Vendor-Specific-6",
|
|
-+ RADIUS_ATTR_UNDIST },
|
|
- };
|
|
- #define RADIUS_ATTRS ARRAY_SIZE(radius_attrs)
|
|
-
|
|
-
|
|
--static const struct radius_attr_type *radius_get_attr_type(u8 type)
|
|
-+static const struct radius_attr_type * radius_get_attr_type(u16 type)
|
|
- {
|
|
- size_t i;
|
|
-
|
|
-@@ -277,23 +298,60 @@ static const struct radius_attr_type *radius_get_attr_type(u8 type)
|
|
- }
|
|
-
|
|
-
|
|
-+static bool radius_is_long_ext_type(u8 type)
|
|
-+{
|
|
-+ return type == RADIUS_ATTR_LONG_EXT_TYPE_1 ||
|
|
-+ type == RADIUS_ATTR_LONG_EXT_TYPE_2;
|
|
-+}
|
|
-+
|
|
-+
|
|
-+static bool radius_is_ext_type(u8 type)
|
|
-+{
|
|
-+ return type >= RADIUS_ATTR_EXT_TYPE_1 &&
|
|
-+ type <= RADIUS_ATTR_LONG_EXT_TYPE_2;
|
|
-+}
|
|
-+
|
|
-+
|
|
- static void radius_msg_dump_attr(struct radius_attr_hdr *hdr)
|
|
- {
|
|
-+ struct radius_attr_hdr_ext *ext = NULL;
|
|
- const struct radius_attr_type *attr;
|
|
- int len;
|
|
- unsigned char *pos;
|
|
- char buf[1000];
|
|
-
|
|
-- attr = radius_get_attr_type(hdr->type);
|
|
-+ if (hdr->length < sizeof(struct radius_attr_hdr))
|
|
-+ return;
|
|
-
|
|
-- wpa_printf(MSG_INFO, " Attribute %d (%s) length=%d",
|
|
-- hdr->type, attr ? attr->name : "?Unknown?", hdr->length);
|
|
-+ if (radius_is_ext_type(hdr->type)) {
|
|
-+ if (hdr->length < 4) {
|
|
-+ wpa_printf(MSG_INFO,
|
|
-+ " Invalid attribute %d (too short for extended type)",
|
|
-+ hdr->type);
|
|
-+ return;
|
|
-+ }
|
|
-
|
|
-- if (attr == NULL || hdr->length < sizeof(struct radius_attr_hdr))
|
|
-- return;
|
|
-+ ext = (struct radius_attr_hdr_ext *) hdr;
|
|
-+ }
|
|
-+
|
|
-+ if (ext) {
|
|
-+ attr = radius_get_attr_type((ext->type << 8) | ext->ext_type);
|
|
-+ wpa_printf(MSG_INFO, " Attribute %d.%d (%s) length=%d",
|
|
-+ ext->type, ext->ext_type,
|
|
-+ attr ? attr->name : "?Unknown?", ext->length);
|
|
-+ pos = (unsigned char *) (ext + 1);
|
|
-+ len = ext->length - sizeof(struct radius_attr_hdr_ext);
|
|
-+ } else {
|
|
-+ attr = radius_get_attr_type(hdr->type);
|
|
-+ wpa_printf(MSG_INFO, " Attribute %d (%s) length=%d",
|
|
-+ hdr->type, attr ? attr->name : "?Unknown?",
|
|
-+ hdr->length);
|
|
-+ pos = (unsigned char *) (hdr + 1);
|
|
-+ len = hdr->length - sizeof(struct radius_attr_hdr);
|
|
-+ }
|
|
-
|
|
-- len = hdr->length - sizeof(struct radius_attr_hdr);
|
|
-- pos = (unsigned char *) (hdr + 1);
|
|
-+ if (!attr)
|
|
-+ return;
|
|
-
|
|
- switch (attr->data_type) {
|
|
- case RADIUS_ATTR_TEXT:
|
|
-@@ -627,22 +685,54 @@ static int radius_msg_add_attr_to_array(struct radius_msg *msg,
|
|
- }
|
|
-
|
|
-
|
|
--struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type,
|
|
-- const u8 *data, size_t data_len)
|
|
-+struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u16 type,
|
|
-+ const u8 *data, size_t data_len)
|
|
- {
|
|
-- size_t buf_needed;
|
|
-- struct radius_attr_hdr *attr;
|
|
-+ size_t buf_needed, max_len;
|
|
-+ struct radius_attr_hdr *attr = NULL;
|
|
-+ struct radius_attr_hdr_ext *ext;
|
|
-+ u8 ext_type = 0;
|
|
-
|
|
- if (TEST_FAIL())
|
|
- return NULL;
|
|
-
|
|
-- if (data_len > RADIUS_MAX_ATTR_LEN) {
|
|
-- wpa_printf(MSG_ERROR, "radius_msg_add_attr: too long attribute (%lu bytes)",
|
|
-- (unsigned long) data_len);
|
|
-- return NULL;
|
|
-+ if (type > 255) {
|
|
-+ if (!radius_is_ext_type(type >> 8)) {
|
|
-+ wpa_printf(MSG_ERROR,
|
|
-+ "%s: Undefined extended type %d.%d",
|
|
-+ __func__, type >> 8, type & 0xff);
|
|
-+ return NULL;
|
|
-+ }
|
|
-+ ext_type = type & 0xff;
|
|
-+ type >>= 8;
|
|
-+ } else if (radius_is_ext_type(type)) {
|
|
-+ wpa_printf(MSG_ERROR, "%s: Unexpected extended type use for %d",
|
|
-+ __func__, type);
|
|
- }
|
|
-
|
|
-- buf_needed = sizeof(*attr) + data_len;
|
|
-+ if (radius_is_long_ext_type(type)) {
|
|
-+ size_t hdr_len = sizeof(struct radius_attr_hdr_ext) + 1;
|
|
-+ size_t plen = 255 - hdr_len;
|
|
-+ size_t num;
|
|
-+
|
|
-+ max_len = 4096;
|
|
-+ num = (data_len + plen - 1) / plen;
|
|
-+ if (num == 0)
|
|
-+ num = 1;
|
|
-+ buf_needed = num * hdr_len + data_len;
|
|
-+ } else if (radius_is_ext_type(type)) {
|
|
-+ max_len = RADIUS_MAX_EXT_ATTR_LEN;
|
|
-+ buf_needed = sizeof(struct radius_attr_hdr_ext) + data_len;
|
|
-+ } else {
|
|
-+ max_len = RADIUS_MAX_ATTR_LEN;
|
|
-+ buf_needed = sizeof(*attr) + data_len;
|
|
-+ }
|
|
-+ if (data_len > max_len) {
|
|
-+ wpa_printf(MSG_ERROR,
|
|
-+ "%s: too long attribute (%zu > %zu bytes)",
|
|
-+ __func__, data_len, max_len);
|
|
-+ return NULL;
|
|
-+ }
|
|
-
|
|
- if (wpabuf_tailroom(msg->buf) < buf_needed) {
|
|
- /* allocate more space for message buffer */
|
|
-@@ -651,13 +741,44 @@ struct radius_attr_hdr *radius_msg_add_attr(struct radius_msg *msg, u8 type,
|
|
- msg->hdr = wpabuf_mhead(msg->buf);
|
|
- }
|
|
-
|
|
-- attr = wpabuf_put(msg->buf, sizeof(struct radius_attr_hdr));
|
|
-- attr->type = type;
|
|
-- attr->length = sizeof(*attr) + data_len;
|
|
-- wpabuf_put_data(msg->buf, data, data_len);
|
|
--
|
|
-- if (radius_msg_add_attr_to_array(msg, attr))
|
|
-- return NULL;
|
|
-+ if (radius_is_long_ext_type(type)) {
|
|
-+ size_t plen = 255 - sizeof(struct radius_attr_hdr_ext) - 1;
|
|
-+ size_t alen;
|
|
-+
|
|
-+ do {
|
|
-+ alen = data_len > plen ? plen : data_len;
|
|
-+ ext = wpabuf_put(msg->buf,
|
|
-+ sizeof(struct radius_attr_hdr_ext));
|
|
-+ if (!attr)
|
|
-+ attr = (struct radius_attr_hdr *) ext;
|
|
-+ ext->type = type;
|
|
-+ ext->length = sizeof(*ext) + 1 + alen;
|
|
-+ ext->ext_type = ext_type;
|
|
-+ wpabuf_put_u8(msg->buf, data_len > alen ? 0x80 : 0);
|
|
-+ wpabuf_put_data(msg->buf, data, data_len);
|
|
-+ data += alen;
|
|
-+ data_len -= alen;
|
|
-+ if (radius_msg_add_attr_to_array(
|
|
-+ msg, (struct radius_attr_hdr *) ext))
|
|
-+ return NULL;
|
|
-+ } while (data_len > 0);
|
|
-+ } else if (radius_is_ext_type(type)) {
|
|
-+ ext = wpabuf_put(msg->buf, sizeof(struct radius_attr_hdr_ext));
|
|
-+ attr = (struct radius_attr_hdr *) ext;
|
|
-+ ext->type = type;
|
|
-+ ext->length = sizeof(*ext) + data_len;
|
|
-+ ext->ext_type = ext_type;
|
|
-+ wpabuf_put_data(msg->buf, data, data_len);
|
|
-+ if (radius_msg_add_attr_to_array(msg, attr))
|
|
-+ return NULL;
|
|
-+ } else {
|
|
-+ attr = wpabuf_put(msg->buf, sizeof(struct radius_attr_hdr));
|
|
-+ attr->type = type;
|
|
-+ attr->length = sizeof(*attr) + data_len;
|
|
-+ wpabuf_put_data(msg->buf, data, data_len);
|
|
-+ if (radius_msg_add_attr_to_array(msg, attr))
|
|
-+ return NULL;
|
|
-+ }
|
|
-
|
|
- return attr;
|
|
- }
|
|
-@@ -1285,6 +1406,28 @@ int radius_msg_add_wfa(struct radius_msg *msg, u8 subtype, const u8 *data,
|
|
- }
|
|
-
|
|
-
|
|
-+int radius_msg_add_ext_vs(struct radius_msg *msg, u16 type, u32 vendor_id,
|
|
-+ u8 vendor_type, const u8 *data, size_t len)
|
|
-+{
|
|
-+ struct radius_attr_hdr *attr;
|
|
-+ u8 *buf, *pos;
|
|
-+ size_t alen;
|
|
-+
|
|
-+ alen = 4 + 1 + len;
|
|
-+ buf = os_malloc(alen);
|
|
-+ if (!buf)
|
|
-+ return 0;
|
|
-+ pos = buf;
|
|
-+ WPA_PUT_BE32(pos, vendor_id);
|
|
-+ pos += 4;
|
|
-+ *pos++ = vendor_type;
|
|
-+ os_memcpy(pos, data, len);
|
|
-+ attr = radius_msg_add_attr(msg, type, buf, alen);
|
|
-+ os_free(buf);
|
|
-+ return attr != NULL;
|
|
-+}
|
|
-+
|
|
-+
|
|
- int radius_user_password_hide(struct radius_msg *msg,
|
|
- const u8 *data, size_t data_len,
|
|
- const u8 *secret, size_t secret_len,
|
|
-diff --git a/src/radius/radius.h b/src/radius/radius.h
|
|
-index fb8148180..490c8d1f6 100644
|
|
---- a/src/radius/radius.h
|
|
-+++ b/src/radius/radius.h
|
|
-@@ -1,6 +1,6 @@
|
|
- /*
|
|
- * RADIUS message processing
|
|
-- * Copyright (c) 2002-2009, 2012, 2014-2015, Jouni Malinen <j@w1.fi>
|
|
-+ * Copyright (c) 2002-2009, 2012, 2014-2022, Jouni Malinen <j@w1.fi>
|
|
- *
|
|
- * This software may be distributed under the terms of the BSD license.
|
|
- * See README for more details.
|
|
-@@ -46,7 +46,15 @@ struct radius_attr_hdr {
|
|
- /* followed by length-2 octets of attribute value */
|
|
- } STRUCT_PACKED;
|
|
-
|
|
-+struct radius_attr_hdr_ext {
|
|
-+ u8 type;
|
|
-+ u8 length; /* including this header */
|
|
-+ u8 ext_type;
|
|
-+ /* followed by length-3 octets of attribute value */
|
|
-+} STRUCT_PACKED;
|
|
-+
|
|
- #define RADIUS_MAX_ATTR_LEN (255 - sizeof(struct radius_attr_hdr))
|
|
-+#define RADIUS_MAX_EXT_ATTR_LEN (255 - sizeof(struct radius_attr_hdr_ext))
|
|
-
|
|
- enum { RADIUS_ATTR_USER_NAME = 1,
|
|
- RADIUS_ATTR_USER_PASSWORD = 2,
|
|
-@@ -113,6 +121,18 @@ enum { RADIUS_ATTR_USER_NAME = 1,
|
|
- RADIUS_ATTR_WLAN_GROUP_CIPHER = 187,
|
|
- RADIUS_ATTR_WLAN_AKM_SUITE = 188,
|
|
- RADIUS_ATTR_WLAN_GROUP_MGMT_CIPHER = 189,
|
|
-+ RADIUS_ATTR_EXT_TYPE_1 = 241,
|
|
-+ RADIUS_ATTR_EXT_TYPE_2 = 242,
|
|
-+ RADIUS_ATTR_EXT_TYPE_3 = 243,
|
|
-+ RADIUS_ATTR_EXT_TYPE_4 = 244,
|
|
-+ RADIUS_ATTR_LONG_EXT_TYPE_1 = 245,
|
|
-+ RADIUS_ATTR_LONG_EXT_TYPE_2 = 246,
|
|
-+ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_1 = (241 << 8) | 26,
|
|
-+ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_2 = (242 << 8) | 26,
|
|
-+ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_3 = (243 << 8) | 26,
|
|
-+ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_4 = (244 << 8) | 26,
|
|
-+ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_5 = (245 << 8) | 26,
|
|
-+ RADIUS_ATTR_EXT_VENDOR_SPECIFIC_6 = (246 << 8) | 26,
|
|
- };
|
|
-
|
|
-
|
|
-@@ -257,7 +277,7 @@ int radius_msg_verify_acct_req(struct radius_msg *msg, const u8 *secret,
|
|
- int radius_msg_verify_das_req(struct radius_msg *msg, const u8 *secret,
|
|
- size_t secret_len,
|
|
- int require_message_authenticator);
|
|
--struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u8 type,
|
|
-+struct radius_attr_hdr * radius_msg_add_attr(struct radius_msg *msg, u16 type,
|
|
- const u8 *data, size_t data_len);
|
|
- struct radius_msg * radius_msg_parse(const u8 *data, size_t len);
|
|
- int radius_msg_add_eap(struct radius_msg *msg, const u8 *data,
|
|
-@@ -284,6 +304,8 @@ int radius_msg_add_mppe_keys(struct radius_msg *msg,
|
|
- const u8 *recv_key, size_t recv_key_len);
|
|
- int radius_msg_add_wfa(struct radius_msg *msg, u8 subtype, const u8 *data,
|
|
- size_t len);
|
|
-+int radius_msg_add_ext_vs(struct radius_msg *msg, u16 type, u32 vendor_id,
|
|
-+ u8 vendor_type, const u8 *data, size_t len);
|
|
- int radius_user_password_hide(struct radius_msg *msg,
|
|
- const u8 *data, size_t data_len,
|
|
- const u8 *secret, size_t secret_len,
|
|
---
|
|
-2.25.1
|
|
-
|
|
diff --git a/package/network/services/hostapd/patches/n00-003-RADIUS-attributes-for-EAPOL-Key-message-details.patch b/package/network/services/hostapd/patches/n00-003-RADIUS-attributes-for-EAPOL-Key-message-details.patch
|
|
deleted file mode 100644
|
|
index df8baa7856..0000000000
|
|
--- a/package/network/services/hostapd/patches/n00-003-RADIUS-attributes-for-EAPOL-Key-message-details.patch
|
|
+++ /dev/null
|
|
@@ -1,102 +0,0 @@
|
|
-From b94371af8402f60218716552e571ca72cff4e3c0 Mon Sep 17 00:00:00 2001
|
|
-From: Jouni Malinen <j@w1.fi>
|
|
-Date: Fri, 15 Apr 2022 17:36:25 +0300
|
|
-Subject: [PATCH] RADIUS attributes for EAPOL-Key message details
|
|
-
|
|
-Use vendor specific RADIUS attributes for sending ANonce and EAPOL-Key
|
|
-msg 2/4 for the wpa_psk_radius=3 case. The vendor specific attributes
|
|
-for this are defined in FreeRADIUS as follows:
|
|
-
|
|
-BEGIN-VENDOR FreeRADIUS format=Extended-Vendor-Specific-5
|
|
-ATTRIBUTE FreeRADIUS-802.1X-Anonce 1 octets[32]
|
|
-ATTRIBUTE FreeRADIUS-802.1X-EAPoL-Key-Msg 2 octets
|
|
-END-VENDOR FreeRADIUS
|
|
-
|
|
-Signed-off-by: Jouni Malinen <j@w1.fi>
|
|
----
|
|
- src/ap/ieee802_11_auth.c | 29 +++++++++++++++++++++++++++++
|
|
- src/radius/radius.h | 7 +++++++
|
|
- 2 files changed, 36 insertions(+)
|
|
-
|
|
-diff --git a/src/ap/ieee802_11_auth.c b/src/ap/ieee802_11_auth.c
|
|
-index a54d7616e..4277d82cb 100644
|
|
---- a/src/ap/ieee802_11_auth.c
|
|
-+++ b/src/ap/ieee802_11_auth.c
|
|
-@@ -47,6 +47,9 @@ struct hostapd_acl_query_data {
|
|
- struct hostapd_acl_query_data *next;
|
|
- bool radius_psk;
|
|
- int akm;
|
|
-+ u8 *anonce;
|
|
-+ u8 *eapol;
|
|
-+ size_t eapol_len;
|
|
- };
|
|
-
|
|
-
|
|
-@@ -102,6 +105,8 @@ static void hostapd_acl_query_free(struct hostapd_acl_query_data *query)
|
|
- if (!query)
|
|
- return;
|
|
- os_free(query->auth_msg);
|
|
-+ os_free(query->anonce);
|
|
-+ os_free(query->eapol);
|
|
- os_free(query);
|
|
- }
|
|
-
|
|
-@@ -164,6 +169,24 @@ static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr,
|
|
- goto fail;
|
|
- }
|
|
-
|
|
-+ if (query->anonce &&
|
|
-+ !radius_msg_add_ext_vs(msg, RADIUS_ATTR_EXT_VENDOR_SPECIFIC_5,
|
|
-+ RADIUS_VENDOR_ID_FREERADIUS,
|
|
-+ RADIUS_VENDOR_ATTR_FREERADIUS_802_1X_ANONCE,
|
|
-+ query->anonce, WPA_NONCE_LEN)) {
|
|
-+ wpa_printf(MSG_DEBUG, "Could not add FreeRADIUS-802.1X-Anonce");
|
|
-+ goto fail;
|
|
-+ }
|
|
-+
|
|
-+ if (query->eapol &&
|
|
-+ !radius_msg_add_ext_vs(msg, RADIUS_ATTR_EXT_VENDOR_SPECIFIC_5,
|
|
-+ RADIUS_VENDOR_ID_FREERADIUS,
|
|
-+ RADIUS_VENDOR_ATTR_FREERADIUS_802_1X_EAPOL_KEY_MSG,
|
|
-+ query->eapol, query->eapol_len)) {
|
|
-+ wpa_printf(MSG_DEBUG, "Could not add FreeRADIUS-802.1X-EAPoL-Key-Msg");
|
|
-+ goto fail;
|
|
-+ }
|
|
-+
|
|
- if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0)
|
|
- goto fail;
|
|
- return 0;
|
|
-@@ -703,6 +726,12 @@ void hostapd_acl_req_radius_psk(struct hostapd_data *hapd, const u8 *addr,
|
|
- query->akm = key_mgmt;
|
|
- os_get_reltime(&query->timestamp);
|
|
- os_memcpy(query->addr, addr, ETH_ALEN);
|
|
-+ if (anonce)
|
|
-+ query->anonce = os_memdup(anonce, WPA_NONCE_LEN);
|
|
-+ if (eapol) {
|
|
-+ query->eapol = os_memdup(eapol, eapol_len);
|
|
-+ query->eapol_len = eapol_len;
|
|
-+ }
|
|
- if (hostapd_radius_acl_query(hapd, addr, query)) {
|
|
- wpa_printf(MSG_DEBUG,
|
|
- "Failed to send Access-Request for RADIUS PSK/ACL query");
|
|
-diff --git a/src/radius/radius.h b/src/radius/radius.h
|
|
-index 490c8d1f6..177c64a66 100644
|
|
---- a/src/radius/radius.h
|
|
-+++ b/src/radius/radius.h
|
|
-@@ -208,6 +208,13 @@ enum { RADIUS_VENDOR_ATTR_MS_MPPE_SEND_KEY = 16,
|
|
- RADIUS_VENDOR_ATTR_MS_MPPE_RECV_KEY = 17
|
|
- };
|
|
-
|
|
-+/* FreeRADIUS vendor-specific attributes */
|
|
-+#define RADIUS_VENDOR_ID_FREERADIUS 11344
|
|
-+/* Extended-Vendor-Specific-5 (245.26; long extended header) */
|
|
-+enum {
|
|
-+ RADIUS_VENDOR_ATTR_FREERADIUS_802_1X_ANONCE = 1,
|
|
-+ RADIUS_VENDOR_ATTR_FREERADIUS_802_1X_EAPOL_KEY_MSG = 2,
|
|
-+};
|
|
-
|
|
- /* Hotspot 2.0 - WFA Vendor-specific RADIUS Attributes */
|
|
- #define RADIUS_VENDOR_ID_WFA 40808
|
|
---
|
|
-2.25.1
|
|
-
|
|
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
|
|
index 441f23226c..dd93acc73b 100644
|
|
--- a/package/network/services/hostapd/src/src/ap/ubus.c
|
|
+++ b/package/network/services/hostapd/src/src/ap/ubus.c
|
|
@@ -29,11 +29,6 @@ static struct ubus_context *ctx;
|
|
static struct blob_buf b;
|
|
static int ctx_ref;
|
|
|
|
-static inline struct hapd_interfaces *get_hapd_interfaces_from_object(struct ubus_object *obj)
|
|
-{
|
|
- return container_of(obj, struct hapd_interfaces, ubus);
|
|
-}
|
|
-
|
|
static inline struct hostapd_data *get_hapd_from_object(struct ubus_object *obj)
|
|
{
|
|
return container_of(obj, struct hostapd_data, ubus.obj);
|
|
@@ -44,12 +39,6 @@ struct ubus_banned_client {
|
|
u8 addr[ETH_ALEN];
|
|
};
|
|
|
|
-static void ubus_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
|
-{
|
|
- struct ubus_context *ctx = eloop_ctx;
|
|
- ubus_handle_event(ctx);
|
|
-}
|
|
-
|
|
static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx)
|
|
{
|
|
if (ubus_reconnect(ctx, NULL)) {
|
|
@@ -57,12 +46,12 @@ static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx)
|
|
return;
|
|
}
|
|
|
|
- eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL);
|
|
+ ubus_add_uloop(ctx);
|
|
}
|
|
|
|
static void hostapd_ubus_connection_lost(struct ubus_context *ctx)
|
|
{
|
|
- eloop_unregister_read_sock(ctx->sock.fd);
|
|
+ uloop_fd_delete(&ctx->sock);
|
|
eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL);
|
|
}
|
|
|
|
@@ -71,12 +60,14 @@ 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;
|
|
- eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL);
|
|
+ ubus_add_uloop(ctx);
|
|
+
|
|
return true;
|
|
}
|
|
|
|
@@ -94,7 +85,7 @@ static void hostapd_ubus_ref_dec(void)
|
|
if (ctx_ref)
|
|
return;
|
|
|
|
- eloop_unregister_read_sock(ctx->sock.fd);
|
|
+ uloop_fd_delete(&ctx->sock);
|
|
ubus_free(ctx);
|
|
ctx = NULL;
|
|
}
|
|
@@ -127,38 +118,6 @@ static void hostapd_notify_ubus(struct ubus_object *obj, char *bssname, char *ev
|
|
free(event_type);
|
|
}
|
|
|
|
-static void hostapd_send_procd_event(char *bssname, char *event)
|
|
-{
|
|
- char *name, *s;
|
|
- uint32_t id;
|
|
- void *v;
|
|
-
|
|
- if (!ctx || ubus_lookup_id(ctx, "service", &id))
|
|
- return;
|
|
-
|
|
- if (asprintf(&name, "hostapd.%s.%s", bssname, event) < 0)
|
|
- return;
|
|
-
|
|
- blob_buf_init(&b, 0);
|
|
-
|
|
- s = blobmsg_alloc_string_buffer(&b, "type", strlen(name) + 1);
|
|
- sprintf(s, "%s", name);
|
|
- blobmsg_add_string_buffer(&b);
|
|
-
|
|
- v = blobmsg_open_table(&b, "data");
|
|
- blobmsg_close_table(&b, v);
|
|
-
|
|
- ubus_invoke(ctx, id, "event", b.head, NULL, NULL, 1000);
|
|
-
|
|
- free(name);
|
|
-}
|
|
-
|
|
-static void hostapd_send_shared_event(struct ubus_object *obj, char *bssname, char *event)
|
|
-{
|
|
- hostapd_send_procd_event(bssname, event);
|
|
- hostapd_notify_ubus(obj, bssname, event);
|
|
-}
|
|
-
|
|
static void
|
|
hostapd_bss_del_ban(void *eloop_data, void *user_ctx)
|
|
{
|
|
@@ -203,10 +162,8 @@ hostapd_bss_reload(struct ubus_context *ctx, struct ubus_object *obj,
|
|
struct blob_attr *msg)
|
|
{
|
|
struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj);
|
|
- int ret = hostapd_reload_config(hapd->iface, 1);
|
|
|
|
- hostapd_send_shared_event(&hapd->iface->interfaces->ubus, hapd->conf->iface, "reload");
|
|
- return ret;
|
|
+ return hostapd_reload_config(hapd->iface, 1);
|
|
}
|
|
|
|
|
|
@@ -318,10 +275,24 @@ hostapd_bss_get_clients(struct ubus_context *ctx, struct ubus_object *obj,
|
|
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);
|
|
@@ -376,32 +347,6 @@ hostapd_bss_get_features(struct ubus_context *ctx, struct ubus_object *obj,
|
|
return 0;
|
|
}
|
|
|
|
-/* Imported from iw/util.c
|
|
- * https://git.kernel.org/pub/scm/linux/kernel/git/jberg/iw.git/tree/util.c?id=4b25ae3537af48dbf9d0abf94132e5ba01b32c18#n200
|
|
- */
|
|
-int ieee80211_frequency_to_channel(int freq)
|
|
-{
|
|
- /* see 802.11-2007 17.3.8.3.2 and Annex J */
|
|
- if (freq == 2484)
|
|
- return 14;
|
|
- /* see 802.11ax D6.1 27.3.23.2 and Annex E */
|
|
- else if (freq == 5935)
|
|
- return 2;
|
|
- else if (freq < 2484)
|
|
- return (freq - 2407) / 5;
|
|
- else if (freq >= 4910 && freq <= 4980)
|
|
- return (freq - 4000) / 5;
|
|
- else if (freq < 5950)
|
|
- return (freq - 5000) / 5;
|
|
- else if (freq <= 45000) /* DMG band lower limit */
|
|
- /* see 802.11ax D6.1 27.3.23.2 */
|
|
- return (freq - 5950) / 5;
|
|
- else if (freq >= 58320 && freq <= 70200)
|
|
- return (freq - 56160) / 2160;
|
|
- else
|
|
- return 0;
|
|
-}
|
|
-
|
|
static int
|
|
hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj,
|
|
struct ubus_request_data *req, const char *method,
|
|
@@ -435,6 +380,12 @@ hostapd_bss_get_status(struct ubus_context *ctx, struct ubus_object *obj,
|
|
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);
|
|
@@ -693,68 +644,6 @@ enum {
|
|
__CONFIG_MAX
|
|
};
|
|
|
|
-static const struct blobmsg_policy config_add_policy[__CONFIG_MAX] = {
|
|
- [CONFIG_IFACE] = { "iface", BLOBMSG_TYPE_STRING },
|
|
- [CONFIG_FILE] = { "config", BLOBMSG_TYPE_STRING },
|
|
-};
|
|
-
|
|
-static int
|
|
-hostapd_config_add(struct ubus_context *ctx, struct ubus_object *obj,
|
|
- struct ubus_request_data *req, const char *method,
|
|
- struct blob_attr *msg)
|
|
-{
|
|
- struct blob_attr *tb[__CONFIG_MAX];
|
|
- struct hapd_interfaces *interfaces = get_hapd_interfaces_from_object(obj);
|
|
- char buf[128];
|
|
-
|
|
- blobmsg_parse(config_add_policy, __CONFIG_MAX, tb, blob_data(msg), blob_len(msg));
|
|
-
|
|
- if (!tb[CONFIG_FILE] || !tb[CONFIG_IFACE])
|
|
- return UBUS_STATUS_INVALID_ARGUMENT;
|
|
-
|
|
- snprintf(buf, sizeof(buf), "bss_config=%s:%s",
|
|
- blobmsg_get_string(tb[CONFIG_IFACE]),
|
|
- blobmsg_get_string(tb[CONFIG_FILE]));
|
|
-
|
|
- if (hostapd_add_iface(interfaces, buf))
|
|
- return UBUS_STATUS_INVALID_ARGUMENT;
|
|
-
|
|
- blob_buf_init(&b, 0);
|
|
- blobmsg_add_u32(&b, "pid", getpid());
|
|
- ubus_send_reply(ctx, req, b.head);
|
|
-
|
|
- return UBUS_STATUS_OK;
|
|
-}
|
|
-
|
|
-enum {
|
|
- CONFIG_REM_IFACE,
|
|
- __CONFIG_REM_MAX
|
|
-};
|
|
-
|
|
-static const struct blobmsg_policy config_remove_policy[__CONFIG_REM_MAX] = {
|
|
- [CONFIG_REM_IFACE] = { "iface", BLOBMSG_TYPE_STRING },
|
|
-};
|
|
-
|
|
-static int
|
|
-hostapd_config_remove(struct ubus_context *ctx, struct ubus_object *obj,
|
|
- struct ubus_request_data *req, const char *method,
|
|
- struct blob_attr *msg)
|
|
-{
|
|
- struct blob_attr *tb[__CONFIG_REM_MAX];
|
|
- struct hapd_interfaces *interfaces = get_hapd_interfaces_from_object(obj);
|
|
- char buf[128];
|
|
-
|
|
- blobmsg_parse(config_remove_policy, __CONFIG_REM_MAX, tb, blob_data(msg), blob_len(msg));
|
|
-
|
|
- if (!tb[CONFIG_REM_IFACE])
|
|
- return UBUS_STATUS_INVALID_ARGUMENT;
|
|
-
|
|
- if (hostapd_remove_iface(interfaces, blobmsg_get_string(tb[CONFIG_REM_IFACE])))
|
|
- return UBUS_STATUS_INVALID_ARGUMENT;
|
|
-
|
|
- return UBUS_STATUS_OK;
|
|
-}
|
|
-
|
|
enum {
|
|
CSA_FREQ,
|
|
CSA_BCN_COUNT,
|
|
@@ -878,10 +767,13 @@ hostapd_switch_chan(struct ubus_context *ctx, struct ubus_object *obj,
|
|
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++) {
|
|
@@ -985,6 +877,7 @@ hostapd_rrm_print_nr(struct hostapd_neighbor_entry *nr)
|
|
enum {
|
|
BSS_MGMT_EN_NEIGHBOR,
|
|
BSS_MGMT_EN_BEACON,
|
|
+ BSS_MGMT_EN_LINK_MEASUREMENT,
|
|
#ifdef CONFIG_WNM_AP
|
|
BSS_MGMT_EN_BSS_TRANSITION,
|
|
#endif
|
|
@@ -1012,6 +905,14 @@ __hostapd_bss_mgmt_enable_f(struct hostapd_data *hapd, int flag)
|
|
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;
|
|
|
|
@@ -1049,6 +950,7 @@ __hostapd_bss_mgmt_enable(struct hostapd_data *hapd, uint32_t flags)
|
|
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
|
|
@@ -1077,6 +979,8 @@ hostapd_bss_mgmt_enable(struct ubus_context *ctx, struct ubus_object *obj,
|
|
}
|
|
|
|
__hostapd_bss_mgmt_enable(hapd, flags);
|
|
+
|
|
+ return 0;
|
|
}
|
|
|
|
|
|
@@ -1327,13 +1231,105 @@ hostapd_rrm_beacon_req(struct ubus_context *ctx, struct ubus_object *obj,
|
|
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)
|
|
+ struct blob_attr *neighbors, u8 mbo_reason, u8 cell_pref, u8 reassoc_delay)
|
|
{
|
|
struct blob_attr *cur;
|
|
struct sta_info *sta;
|
|
@@ -1341,6 +1337,8 @@ hostapd_bss_tr_send(struct hostapd_data *hapd, u8 *addr, bool disassoc_imminent,
|
|
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)
|
|
@@ -1392,8 +1390,37 @@ hostapd_bss_tr_send(struct hostapd_data *hapd, u8 *addr, bool disassoc_imminent,
|
|
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, NULL, 0))
|
|
+ dialog_token, NULL, nr, nr_len, mbo_len ? mbo : NULL, mbo_len))
|
|
return UBUS_STATUS_UNKNOWN_ERROR;
|
|
|
|
return 0;
|
|
@@ -1407,6 +1434,11 @@ enum {
|
|
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
|
|
};
|
|
|
|
@@ -1418,6 +1450,11 @@ static const struct blobmsg_policy bss_tr_policy[__BSS_TR_DISASSOC_MAX] = {
|
|
[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
|
|
@@ -1434,6 +1471,9 @@ hostapd_bss_transition_request(struct ubus_context *ctx, struct ubus_object *obj
|
|
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));
|
|
|
|
@@ -1455,52 +1495,19 @@ hostapd_bss_transition_request(struct ubus_context *ctx, struct ubus_object *obj
|
|
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]));
|
|
|
|
- return hostapd_bss_tr_send(hapd, addr, da_imminent, abridged, da_timer, valid_period,
|
|
- dialog_token, tb[BSS_TR_NEIGHBORS]);
|
|
-}
|
|
-
|
|
-enum {
|
|
- WNM_DISASSOC_ADDR,
|
|
- WNM_DISASSOC_DURATION,
|
|
- WNM_DISASSOC_NEIGHBORS,
|
|
- WNM_DISASSOC_ABRIDGED,
|
|
- __WNM_DISASSOC_MAX,
|
|
-};
|
|
-
|
|
-static const struct blobmsg_policy wnm_disassoc_policy[__WNM_DISASSOC_MAX] = {
|
|
- [WNM_DISASSOC_ADDR] = { "addr", BLOBMSG_TYPE_STRING },
|
|
- [WNM_DISASSOC_DURATION] { "duration", BLOBMSG_TYPE_INT32 },
|
|
- [WNM_DISASSOC_NEIGHBORS] { "neighbors", BLOBMSG_TYPE_ARRAY },
|
|
- [WNM_DISASSOC_ABRIDGED] { "abridged", BLOBMSG_TYPE_BOOL },
|
|
-};
|
|
-
|
|
-static int
|
|
-hostapd_wnm_disassoc_imminent(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[__WNM_DISASSOC_MAX];
|
|
- struct sta_info *sta;
|
|
- int duration = 10;
|
|
- u8 addr[ETH_ALEN];
|
|
- bool abridged;
|
|
-
|
|
- blobmsg_parse(wnm_disassoc_policy, __WNM_DISASSOC_MAX, tb, blob_data(msg), blob_len(msg));
|
|
-
|
|
- if (!tb[WNM_DISASSOC_ADDR])
|
|
- return UBUS_STATUS_INVALID_ARGUMENT;
|
|
-
|
|
- if (hwaddr_aton(blobmsg_data(tb[WNM_DISASSOC_ADDR]), addr))
|
|
- return UBUS_STATUS_INVALID_ARGUMENT;
|
|
+#ifdef CONFIG_MBO
|
|
+ if (tb[BSS_TR_MBO_REASON])
|
|
+ mbo_reason = blobmsg_get_u32(tb[BSS_TR_MBO_REASON]);
|
|
|
|
- if (tb[WNM_DISASSOC_DURATION])
|
|
- duration = blobmsg_get_u32(tb[WNM_DISASSOC_DURATION]);
|
|
+ if (tb[BSS_TR_CELL_PREF])
|
|
+ cell_pref = blobmsg_get_u32(tb[BSS_TR_CELL_PREF]);
|
|
|
|
- abridged = !!(tb[WNM_DISASSOC_ABRIDGED] && blobmsg_get_bool(tb[WNM_DISASSOC_ABRIDGED]));
|
|
+ if (tb[BSS_TR_REASSOC_DELAY])
|
|
+ reassoc_delay = blobmsg_get_u32(tb[BSS_TR_REASSOC_DELAY]);
|
|
+#endif
|
|
|
|
- return hostapd_bss_tr_send(hapd, addr, true, abridged, duration, duration,
|
|
- 1, tb[WNM_DISASSOC_NEIGHBORS]);
|
|
+ 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
|
|
|
|
@@ -1584,8 +1591,8 @@ static const struct ubus_method bss_methods[] = {
|
|
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("wnm_disassoc_imminent", hostapd_wnm_disassoc_imminent, wnm_disassoc_policy),
|
|
UBUS_METHOD("bss_transition_request", hostapd_bss_transition_request, bss_tr_policy),
|
|
#endif
|
|
};
|
|
@@ -1622,8 +1629,6 @@ void hostapd_ubus_add_bss(struct hostapd_data *hapd)
|
|
obj->n_methods = bss_object_type.n_methods;
|
|
ret = ubus_add_object(ctx, obj);
|
|
hostapd_ubus_ref_inc();
|
|
-
|
|
- hostapd_send_shared_event(&hapd->iface->interfaces->ubus, hapd->conf->iface, "add");
|
|
}
|
|
|
|
void hostapd_ubus_free_bss(struct hostapd_data *hapd)
|
|
@@ -1639,8 +1644,6 @@ void hostapd_ubus_free_bss(struct hostapd_data *hapd)
|
|
if (!ctx)
|
|
return;
|
|
|
|
- hostapd_send_shared_event(&hapd->iface->interfaces->ubus, hapd->conf->iface, "remove");
|
|
-
|
|
if (obj->id) {
|
|
ubus_remove_object(ctx, obj);
|
|
hostapd_ubus_ref_dec();
|
|
@@ -1686,47 +1689,6 @@ void hostapd_ubus_remove_vlan(struct hostapd_data *hapd, struct hostapd_vlan *vl
|
|
hostapd_ubus_vlan_action(hapd, vlan, "vlan_remove");
|
|
}
|
|
|
|
-static const struct ubus_method daemon_methods[] = {
|
|
- UBUS_METHOD("config_add", hostapd_config_add, config_add_policy),
|
|
- UBUS_METHOD("config_remove", hostapd_config_remove, config_remove_policy),
|
|
-};
|
|
-
|
|
-static struct ubus_object_type daemon_object_type =
|
|
- UBUS_OBJECT_TYPE("hostapd", daemon_methods);
|
|
-
|
|
-void hostapd_ubus_add(struct hapd_interfaces *interfaces)
|
|
-{
|
|
- struct ubus_object *obj = &interfaces->ubus;
|
|
- int ret;
|
|
-
|
|
- if (!hostapd_ubus_init())
|
|
- return;
|
|
-
|
|
- obj->name = strdup("hostapd");
|
|
-
|
|
- obj->type = &daemon_object_type;
|
|
- obj->methods = daemon_object_type.methods;
|
|
- obj->n_methods = daemon_object_type.n_methods;
|
|
- ret = ubus_add_object(ctx, obj);
|
|
- hostapd_ubus_ref_inc();
|
|
-}
|
|
-
|
|
-void hostapd_ubus_free(struct hapd_interfaces *interfaces)
|
|
-{
|
|
- struct ubus_object *obj = &interfaces->ubus;
|
|
- char *name = (char *) obj->name;
|
|
-
|
|
- if (!ctx)
|
|
- return;
|
|
-
|
|
- if (obj->id) {
|
|
- ubus_remove_object(ctx, obj);
|
|
- hostapd_ubus_ref_dec();
|
|
- }
|
|
-
|
|
- free(name);
|
|
-}
|
|
-
|
|
struct ubus_event_req {
|
|
struct ubus_notify_request nreq;
|
|
int resp;
|
|
@@ -1848,14 +1810,16 @@ void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *
|
|
ubus_notify(ctx, &hapd->ubus.obj, type, b.head, -1);
|
|
}
|
|
|
|
-void hostapd_ubus_notify_authorized(struct hostapd_data *hapd, struct sta_info *sta)
|
|
+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);
|
|
- blobmsg_add_string(&b, "ifname", hapd->conf->iface);
|
|
+ if (auth_alg)
|
|
+ blobmsg_add_string(&b, "auth-alg", auth_alg);
|
|
if (sta->bandwidth[0] || sta->bandwidth[1]) {
|
|
void *r = blobmsg_open_array(&b, "rate-limit");
|
|
|
|
@@ -1889,6 +1853,7 @@ void hostapd_ubus_notify_beacon_report(
|
|
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);
|
|
}
|
|
diff --git a/package/network/services/hostapd/src/src/ap/ubus.h b/package/network/services/hostapd/src/src/ap/ubus.h
|
|
index b3d6e93844..b0f7c44ab5 100644
|
|
--- a/package/network/services/hostapd/src/src/ap/ubus.h
|
|
+++ b/package/network/services/hostapd/src/src/ap/ubus.h
|
|
@@ -47,6 +47,7 @@ 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,
|
|
@@ -54,7 +55,6 @@ void hostapd_ubus_notify_beacon_report(struct hostapd_data *hapd,
|
|
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_authorized(struct hostapd_data *hapd, struct sta_info *sta);
|
|
|
|
void hostapd_ubus_notify_bss_transition_response(
|
|
struct hostapd_data *hapd, const u8 *addr, u8 dialog_token, u8 status_code,
|
|
@@ -65,6 +65,8 @@ 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
|
|
|
|
@@ -99,6 +101,10 @@ static inline int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct ho
|
|
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)
|
|
{
|
|
}
|
|
@@ -136,6 +142,13 @@ static inline int hostapd_ubus_notify_bss_transition_query(
|
|
{
|
|
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..4dcb4363a2
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/src/ap/ucode.c
|
|
@@ -0,0 +1,386 @@
|
|
+#include <sys/un.h>
|
|
+
|
|
+#include "utils/includes.h"
|
|
+#include "utils/common.h"
|
|
+#include "utils/ucode.h"
|
|
+#include "hostapd.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);
|
|
+ wpa_ucode_registry_add(bss_registry, val, &hapd->ucode.idx);
|
|
+
|
|
+ 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);
|
|
+ wpa_ucode_registry_add(iface_registry, val, &hapd->ucode.idx);
|
|
+
|
|
+ return val;
|
|
+}
|
|
+
|
|
+static void
|
|
+hostapd_ucode_update_bss_list(struct hostapd_iface *iface)
|
|
+{
|
|
+ uc_value_t *ifval, *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);
|
|
+ uc_value_t *proto = ucv_prototype_get(val);
|
|
+
|
|
+ ucv_object_add(proto, "name", ucv_get(ucv_string_new(hapd->conf->iface)));
|
|
+ ucv_object_add(proto, "index", ucv_int64_new(i));
|
|
+ ucv_array_set(list, i, ucv_get(val));
|
|
+ }
|
|
+
|
|
+ ifval = hostapd_ucode_iface_get_uval(iface);
|
|
+ ucv_object_add(ucv_prototype_get(ifval), "bss", ucv_get(list));
|
|
+}
|
|
+
|
|
+static void
|
|
+hostapd_ucode_update_interfaces(void)
|
|
+{
|
|
+ uc_value_t *ifs = 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);
|
|
+ }
|
|
+
|
|
+ ucv_object_add(ucv_prototype_get(global), "interfaces", ucv_get(ifs));
|
|
+ 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_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_config_free_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] = NULL;
|
|
+ hostapd_config_free(conf);
|
|
+
|
|
+ hostapd_reload_bss(hapd);
|
|
+ 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_bss_deinit(hapd);
|
|
+ hostapd_remove_iface_bss_conf(iface->conf, hapd->conf);
|
|
+ hostapd_config_free_bss(hapd->conf);
|
|
+ os_free(hapd);
|
|
+
|
|
+ hostapd_ucode_update_bss_list(iface);
|
|
+ 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_bss_list(iface);
|
|
+ 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);
|
|
+}
|
|
+
|
|
+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 },
|
|
+ { "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 }
|
|
+ };
|
|
+ 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, int reconf)
|
|
+{
|
|
+ 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));
|
|
+ uc_value_push(ucv_int64_new(reconf));
|
|
+ ucv_put(wpa_ucode_call(3));
|
|
+ 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..dbc49e6eac
|
|
--- /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, int reconf);
|
|
+
|
|
+#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, int reconf)
|
|
+{
|
|
+}
|
|
+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
|
|
index cb7cb72731..553769eceb 100644
|
|
--- a/package/network/services/hostapd/src/src/utils/build_features.h
|
|
+++ b/package/network/services/hostapd/src/src/utils/build_features.h
|
|
@@ -7,10 +7,6 @@ static inline int has_feature(const char *feat)
|
|
if (!strcmp(feat, "eap"))
|
|
return 1;
|
|
#endif
|
|
-#ifdef CONFIG_IEEE80211N
|
|
- if (!strcmp(feat, "11n"))
|
|
- return 1;
|
|
-#endif
|
|
#ifdef CONFIG_IEEE80211AC
|
|
if (!strcmp(feat, "11ac"))
|
|
return 1;
|
|
@@ -54,6 +50,14 @@ static inline int has_feature(const char *feat)
|
|
#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;
|
|
}
|
|
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..fabf58a5e8
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/src/utils/ucode.c
|
|
@@ -0,0 +1,237 @@
|
|
+#include <unistd.h>
|
|
+#include "ucode.h"
|
|
+#include "utils/eloop.h"
|
|
+#include "crypto/crypto.h"
|
|
+#include "crypto/sha1.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_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;
|
|
+}
|
|
+
|
|
+void wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val, int *idx)
|
|
+{
|
|
+ uc_value_t *data;
|
|
+ int i = 0;
|
|
+
|
|
+ while (ucv_array_get(reg, i))
|
|
+ i++;
|
|
+
|
|
+ ucv_array_set(reg, i, ucv_get(val));
|
|
+
|
|
+ data = ucv_object_new(&vm);
|
|
+ ucv_object_add(ucv_prototype_get(val), "data", ucv_get(data));
|
|
+
|
|
+ *idx = 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..4caf8ada5a
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/src/utils/ucode.h
|
|
@@ -0,0 +1,28 @@
|
|
+#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);
|
|
+
|
|
+void wpa_ucode_registry_add(uc_value_t *reg, uc_value_t *val, int *idx);
|
|
+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);
|
|
+
|
|
+#endif
|
|
diff --git a/package/network/services/hostapd/src/wpa_supplicant/ubus.c b/package/network/services/hostapd/src/wpa_supplicant/ubus.c
|
|
index 16a68c5073..1c477f0c0c 100644
|
|
--- a/package/network/services/hostapd/src/wpa_supplicant/ubus.c
|
|
+++ b/package/network/services/hostapd/src/wpa_supplicant/ubus.c
|
|
@@ -30,12 +30,6 @@ static inline struct wpa_supplicant *get_wpas_from_object(struct ubus_object *ob
|
|
return container_of(obj, struct wpa_supplicant, ubus.obj);
|
|
}
|
|
|
|
-static void ubus_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
|
-{
|
|
- struct ubus_context *ctx = eloop_ctx;
|
|
- ubus_handle_event(ctx);
|
|
-}
|
|
-
|
|
static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx)
|
|
{
|
|
if (ubus_reconnect(ctx, NULL)) {
|
|
@@ -43,12 +37,12 @@ static void ubus_reconnect_timeout(void *eloop_data, void *user_ctx)
|
|
return;
|
|
}
|
|
|
|
- eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL);
|
|
+ ubus_add_uloop(ctx);
|
|
}
|
|
|
|
static void wpas_ubus_connection_lost(struct ubus_context *ctx)
|
|
{
|
|
- eloop_unregister_read_sock(ctx->sock.fd);
|
|
+ uloop_fd_delete(&ctx->sock);
|
|
eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL);
|
|
}
|
|
|
|
@@ -57,12 +51,14 @@ 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;
|
|
- eloop_register_read_sock(ctx->sock.fd, ubus_receive, ctx, NULL);
|
|
+ ubus_add_uloop(ctx);
|
|
+
|
|
return true;
|
|
}
|
|
|
|
@@ -80,7 +76,7 @@ static void wpas_ubus_ref_dec(void)
|
|
if (ctx_ref)
|
|
return;
|
|
|
|
- eloop_unregister_read_sock(ctx->sock.fd);
|
|
+ uloop_fd_delete(&ctx->sock);
|
|
ubus_free(ctx);
|
|
ctx = NULL;
|
|
}
|
|
@@ -211,152 +207,6 @@ void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s)
|
|
free(name);
|
|
}
|
|
|
|
-enum {
|
|
- WPAS_CONFIG_DRIVER,
|
|
- WPAS_CONFIG_IFACE,
|
|
- WPAS_CONFIG_BRIDGE,
|
|
- WPAS_CONFIG_HOSTAPD_CTRL,
|
|
- WPAS_CONFIG_CTRL,
|
|
- WPAS_CONFIG_FILE,
|
|
- __WPAS_CONFIG_MAX
|
|
-};
|
|
-
|
|
-static const struct blobmsg_policy wpas_config_add_policy[__WPAS_CONFIG_MAX] = {
|
|
- [WPAS_CONFIG_DRIVER] = { "driver", BLOBMSG_TYPE_STRING },
|
|
- [WPAS_CONFIG_IFACE] = { "iface", BLOBMSG_TYPE_STRING },
|
|
- [WPAS_CONFIG_BRIDGE] = { "bridge", BLOBMSG_TYPE_STRING },
|
|
- [WPAS_CONFIG_HOSTAPD_CTRL] = { "hostapd_ctrl", BLOBMSG_TYPE_STRING },
|
|
- [WPAS_CONFIG_CTRL] = { "ctrl", BLOBMSG_TYPE_STRING },
|
|
- [WPAS_CONFIG_FILE] = { "config", BLOBMSG_TYPE_STRING },
|
|
-};
|
|
-
|
|
-static int
|
|
-wpas_config_add(struct ubus_context *ctx, struct ubus_object *obj,
|
|
- struct ubus_request_data *req, const char *method,
|
|
- struct blob_attr *msg)
|
|
-{
|
|
- struct blob_attr *tb[__WPAS_CONFIG_MAX];
|
|
- struct wpa_global *global = get_wpa_global_from_object(obj);
|
|
- struct wpa_interface *iface;
|
|
-
|
|
- blobmsg_parse(wpas_config_add_policy, __WPAS_CONFIG_MAX, tb, blob_data(msg), blob_len(msg));
|
|
-
|
|
- if (!tb[WPAS_CONFIG_FILE] || !tb[WPAS_CONFIG_IFACE] || !tb[WPAS_CONFIG_DRIVER])
|
|
- return UBUS_STATUS_INVALID_ARGUMENT;
|
|
-
|
|
- iface = os_zalloc(sizeof(struct wpa_interface));
|
|
- if (iface == NULL)
|
|
- return UBUS_STATUS_UNKNOWN_ERROR;
|
|
-
|
|
- iface->driver = blobmsg_get_string(tb[WPAS_CONFIG_DRIVER]);
|
|
- iface->ifname = blobmsg_get_string(tb[WPAS_CONFIG_IFACE]);
|
|
- iface->confname = blobmsg_get_string(tb[WPAS_CONFIG_FILE]);
|
|
-
|
|
- if (tb[WPAS_CONFIG_BRIDGE])
|
|
- iface->bridge_ifname = blobmsg_get_string(tb[WPAS_CONFIG_BRIDGE]);
|
|
-
|
|
- if (tb[WPAS_CONFIG_CTRL])
|
|
- iface->ctrl_interface = blobmsg_get_string(tb[WPAS_CONFIG_CTRL]);
|
|
-
|
|
- if (tb[WPAS_CONFIG_HOSTAPD_CTRL])
|
|
- iface->hostapd_ctrl = blobmsg_get_string(tb[WPAS_CONFIG_HOSTAPD_CTRL]);
|
|
-
|
|
- if (!wpa_supplicant_add_iface(global, iface, NULL))
|
|
- return UBUS_STATUS_INVALID_ARGUMENT;
|
|
-
|
|
- blob_buf_init(&b, 0);
|
|
- blobmsg_add_u32(&b, "pid", getpid());
|
|
- ubus_send_reply(ctx, req, b.head);
|
|
-
|
|
- return UBUS_STATUS_OK;
|
|
-}
|
|
-
|
|
-enum {
|
|
- WPAS_CONFIG_REM_IFACE,
|
|
- __WPAS_CONFIG_REM_MAX
|
|
-};
|
|
-
|
|
-static const struct blobmsg_policy wpas_config_remove_policy[__WPAS_CONFIG_REM_MAX] = {
|
|
- [WPAS_CONFIG_REM_IFACE] = { "iface", BLOBMSG_TYPE_STRING },
|
|
-};
|
|
-
|
|
-static int
|
|
-wpas_config_remove(struct ubus_context *ctx, struct ubus_object *obj,
|
|
- struct ubus_request_data *req, const char *method,
|
|
- struct blob_attr *msg)
|
|
-{
|
|
- struct blob_attr *tb[__WPAS_CONFIG_REM_MAX];
|
|
- struct wpa_global *global = get_wpa_global_from_object(obj);
|
|
- struct wpa_supplicant *wpa_s = NULL;
|
|
- unsigned int found = 0;
|
|
-
|
|
- blobmsg_parse(wpas_config_remove_policy, __WPAS_CONFIG_REM_MAX, tb, blob_data(msg), blob_len(msg));
|
|
-
|
|
- if (!tb[WPAS_CONFIG_REM_IFACE])
|
|
- return UBUS_STATUS_INVALID_ARGUMENT;
|
|
-
|
|
- /* find wpa_s object for to-be-removed interface */
|
|
- for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) {
|
|
- if (!strncmp(wpa_s->ifname,
|
|
- blobmsg_get_string(tb[WPAS_CONFIG_REM_IFACE]),
|
|
- sizeof(wpa_s->ifname)))
|
|
- {
|
|
- found = 1;
|
|
- break;
|
|
- }
|
|
- }
|
|
-
|
|
- if (!found)
|
|
- return UBUS_STATUS_INVALID_ARGUMENT;
|
|
-
|
|
- if (wpa_supplicant_remove_iface(global, wpa_s, 0))
|
|
- return UBUS_STATUS_INVALID_ARGUMENT;
|
|
-
|
|
- return UBUS_STATUS_OK;
|
|
-}
|
|
-
|
|
-static const struct ubus_method wpas_daemon_methods[] = {
|
|
- UBUS_METHOD("config_add", wpas_config_add, wpas_config_add_policy),
|
|
- UBUS_METHOD("config_remove", wpas_config_remove, wpas_config_remove_policy),
|
|
-};
|
|
-
|
|
-static struct ubus_object_type wpas_daemon_object_type =
|
|
- UBUS_OBJECT_TYPE("wpa_supplicant", wpas_daemon_methods);
|
|
-
|
|
-void wpas_ubus_add(struct wpa_global *global)
|
|
-{
|
|
- struct ubus_object *obj = &global->ubus_global;
|
|
- int ret;
|
|
-
|
|
- if (!wpas_ubus_init())
|
|
- return;
|
|
-
|
|
- obj->name = strdup("wpa_supplicant");
|
|
-
|
|
- obj->type = &wpas_daemon_object_type;
|
|
- obj->methods = wpas_daemon_object_type.methods;
|
|
- obj->n_methods = wpas_daemon_object_type.n_methods;
|
|
- ret = ubus_add_object(ctx, obj);
|
|
- wpas_ubus_ref_inc();
|
|
-}
|
|
-
|
|
-void wpas_ubus_free(struct wpa_global *global)
|
|
-{
|
|
- struct ubus_object *obj = &global->ubus_global;
|
|
- 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)
|
|
{
|
|
diff --git a/package/network/services/hostapd/src/wpa_supplicant/ubus.h b/package/network/services/hostapd/src/wpa_supplicant/ubus.h
|
|
index bf92b98c01..f6681cb26d 100644
|
|
--- a/package/network/services/hostapd/src/wpa_supplicant/ubus.h
|
|
+++ b/package/network/services/hostapd/src/wpa_supplicant/ubus.h
|
|
@@ -24,9 +24,6 @@ struct wpas_ubus_bss {
|
|
void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s);
|
|
void wpas_ubus_free_bss(struct wpa_supplicant *wpa_s);
|
|
|
|
-void wpas_ubus_add(struct wpa_global *global);
|
|
-void wpas_ubus_free(struct wpa_global *global);
|
|
-
|
|
#ifdef CONFIG_WPS
|
|
void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential *cred);
|
|
#endif
|
|
@@ -34,14 +31,6 @@ void wpas_ubus_notify(struct wpa_supplicant *wpa_s, const struct wps_credential
|
|
#else
|
|
struct wpas_ubus_bss {};
|
|
|
|
-static inline void wpas_ubus_add_iface(struct wpa_supplicant *wpa_s)
|
|
-{
|
|
-}
|
|
-
|
|
-static inline void wpas_ubus_free_iface(struct wpa_supplicant *wpa_s)
|
|
-{
|
|
-}
|
|
-
|
|
static inline void wpas_ubus_add_bss(struct wpa_supplicant *wpa_s)
|
|
{
|
|
}
|
|
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..660357a43d
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/wpa_supplicant/ucode.c
|
|
@@ -0,0 +1,177 @@
|
|
+#include "utils/includes.h"
|
|
+#include "utils/common.h"
|
|
+#include "utils/ucode.h"
|
|
+#include "wpa_supplicant_i.h"
|
|
+#include "wps_supplicant.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_ucode_registry_add(iface_registry, val, &wpa_s->ucode.idx);
|
|
+
|
|
+ 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_string_new(wpa_s->ifname));
|
|
+ uc_value_push(ucv_get(val));
|
|
+ ucv_put(wpa_ucode_call(2));
|
|
+ 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);
|
|
+ uc_value_t *hapd_ctrl = ucv_object_get(info, "hostapd_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),
|
|
+ .hostapd_ctrl = ucv_string_get(hapd_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);
|
|
+}
|
|
+
|
|
+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[] = {
|
|
+ };
|
|
+ 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, "hostapd.iface", iface_fns, NULL);
|
|
+
|
|
+ iface_registry = ucv_array_new(vm);
|
|
+ uc_vm_registry_set(vm, "hostap.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..fcd231357b
|
|
--- /dev/null
|
|
+++ b/package/network/services/hostapd/src/wpa_supplicant/ucode.h
|
|
@@ -0,0 +1,38 @@
|
|
+#ifndef __WPAS_UCODE_H
|
|
+#define __WPAS_UCODE_H
|
|
+
|
|
+#include "utils/ucode.h"
|
|
+
|
|
+struct wpa_global;
|
|
+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);
|
|
+#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)
|
|
+{
|
|
+}
|
|
+
|
|
+#endif
|
|
+
|
|
+#endif
|
|
--
|
|
2.34.1
|
|
|