diff --git a/package/libs/openssl/Makefile b/package/libs/openssl/Makefile index b05ddf817..d35dad657 100644 --- a/package/libs/openssl/Makefile +++ b/package/libs/openssl/Makefile @@ -11,7 +11,7 @@ PKG_NAME:=openssl PKG_BASE:=1.1.1 PKG_BUGFIX:=t PKG_VERSION:=$(PKG_BASE)$(PKG_BUGFIX) -PKG_RELEASE:=1 +PKG_RELEASE:=2 PKG_USE_MIPS16:=0 PKG_BUILD_PARALLEL:=1 @@ -130,8 +130,8 @@ endef define Package/libopenssl-conf/conffiles /etc/ssl/openssl.cnf -$(if CONFIG_OPENSSL_ENGINE_BUILTIN_DEVCRYPTO,/etc/ssl/engines.cnf.d/devcrypto.cnf) -$(if CONFIG_OPENSSL_ENGINE_BUILTIN_PADLOCK,/etc/ssl/engines.cnf.d/padlock.cnf) +$(if $(CONFIG_OPENSSL_ENGINE_BUILTIN_DEVCRYPTO),/etc/ssl/engines.cnf.d/devcrypto.cnf) +$(if $(CONFIG_OPENSSL_ENGINE_BUILTIN_PADLOCK),/etc/ssl/engines.cnf.d/padlock.cnf) endef define Package/libopenssl-conf/description diff --git a/package/libs/openssl/patches/200-x509-excessive-resource-use-verifying-policy-constra.patch b/package/libs/openssl/patches/200-x509-excessive-resource-use-verifying-policy-constra.patch new file mode 100644 index 000000000..a3a4de600 --- /dev/null +++ b/package/libs/openssl/patches/200-x509-excessive-resource-use-verifying-policy-constra.patch @@ -0,0 +1,214 @@ +From 879f7080d7e141f415c79eaa3a8ac4a3dad0348b Mon Sep 17 00:00:00 2001 +From: Pauli +Date: Wed, 8 Mar 2023 15:28:20 +1100 +Subject: [PATCH] x509: excessive resource use verifying policy constraints + +A security vulnerability has been identified in all supported versions +of OpenSSL related to the verification of X.509 certificate chains +that include policy constraints. Attackers may be able to exploit this +vulnerability by creating a malicious certificate chain that triggers +exponential use of computational resources, leading to a denial-of-service +(DoS) attack on affected systems. + +Fixes CVE-2023-0464 + +Reviewed-by: Tomas Mraz +Reviewed-by: Shane Lontis +(Merged from https://github.com/openssl/openssl/pull/20569) + +diff --git a/crypto/x509v3/pcy_local.h b/crypto/x509v3/pcy_local.h +index 5daf78de45..344aa06765 100644 +--- a/crypto/x509v3/pcy_local.h ++++ b/crypto/x509v3/pcy_local.h +@@ -111,6 +111,11 @@ struct X509_POLICY_LEVEL_st { + }; + + struct X509_POLICY_TREE_st { ++ /* The number of nodes in the tree */ ++ size_t node_count; ++ /* The maximum number of nodes in the tree */ ++ size_t node_maximum; ++ + /* This is the tree 'level' data */ + X509_POLICY_LEVEL *levels; + int nlevel; +@@ -159,7 +164,8 @@ X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk, + X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + X509_POLICY_DATA *data, + X509_POLICY_NODE *parent, +- X509_POLICY_TREE *tree); ++ X509_POLICY_TREE *tree, ++ int extra_data); + void policy_node_free(X509_POLICY_NODE *node); + int policy_node_match(const X509_POLICY_LEVEL *lvl, + const X509_POLICY_NODE *node, const ASN1_OBJECT *oid); +diff --git a/crypto/x509v3/pcy_node.c b/crypto/x509v3/pcy_node.c +index e2d7b15322..d574fb9d66 100644 +--- a/crypto/x509v3/pcy_node.c ++++ b/crypto/x509v3/pcy_node.c +@@ -59,10 +59,15 @@ X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level, + X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + X509_POLICY_DATA *data, + X509_POLICY_NODE *parent, +- X509_POLICY_TREE *tree) ++ X509_POLICY_TREE *tree, ++ int extra_data) + { + X509_POLICY_NODE *node; + ++ /* Verify that the tree isn't too large. This mitigates CVE-2023-0464 */ ++ if (tree->node_maximum > 0 && tree->node_count >= tree->node_maximum) ++ return NULL; ++ + node = OPENSSL_zalloc(sizeof(*node)); + if (node == NULL) { + X509V3err(X509V3_F_LEVEL_ADD_NODE, ERR_R_MALLOC_FAILURE); +@@ -70,7 +75,7 @@ X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + } + node->data = data; + node->parent = parent; +- if (level) { ++ if (level != NULL) { + if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) { + if (level->anyPolicy) + goto node_error; +@@ -90,7 +95,7 @@ X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + } + } + +- if (tree) { ++ if (extra_data) { + if (tree->extra_data == NULL) + tree->extra_data = sk_X509_POLICY_DATA_new_null(); + if (tree->extra_data == NULL){ +@@ -103,6 +108,7 @@ X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level, + } + } + ++ tree->node_count++; + if (parent) + parent->nchild++; + +diff --git a/crypto/x509v3/pcy_tree.c b/crypto/x509v3/pcy_tree.c +index 6e8322cbc5..6c7fd35405 100644 +--- a/crypto/x509v3/pcy_tree.c ++++ b/crypto/x509v3/pcy_tree.c +@@ -13,6 +13,18 @@ + + #include "pcy_local.h" + ++/* ++ * If the maximum number of nodes in the policy tree isn't defined, set it to ++ * a generous default of 1000 nodes. ++ * ++ * Defining this to be zero means unlimited policy tree growth which opens the ++ * door on CVE-2023-0464. ++ */ ++ ++#ifndef OPENSSL_POLICY_TREE_NODES_MAX ++# define OPENSSL_POLICY_TREE_NODES_MAX 1000 ++#endif ++ + /* + * Enable this to print out the complete policy tree at various point during + * evaluation. +@@ -168,6 +180,9 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, + return X509_PCY_TREE_INTERNAL; + } + ++ /* Limit the growth of the tree to mitigate CVE-2023-0464 */ ++ tree->node_maximum = OPENSSL_POLICY_TREE_NODES_MAX; ++ + /* + * http://tools.ietf.org/html/rfc5280#section-6.1.2, figure 3. + * +@@ -184,7 +199,7 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, + level = tree->levels; + if ((data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0)) == NULL) + goto bad_tree; +- if (level_add_node(level, data, NULL, tree) == NULL) { ++ if (level_add_node(level, data, NULL, tree, 1) == NULL) { + policy_data_free(data); + goto bad_tree; + } +@@ -243,7 +258,8 @@ static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs, + * Return value: 1 on success, 0 otherwise + */ + static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, +- X509_POLICY_DATA *data) ++ X509_POLICY_DATA *data, ++ X509_POLICY_TREE *tree) + { + X509_POLICY_LEVEL *last = curr - 1; + int i, matched = 0; +@@ -253,13 +269,13 @@ static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, + X509_POLICY_NODE *node = sk_X509_POLICY_NODE_value(last->nodes, i); + + if (policy_node_match(last, node, data->valid_policy)) { +- if (level_add_node(curr, data, node, NULL) == NULL) ++ if (level_add_node(curr, data, node, tree, 0) == NULL) + return 0; + matched = 1; + } + } + if (!matched && last->anyPolicy) { +- if (level_add_node(curr, data, last->anyPolicy, NULL) == NULL) ++ if (level_add_node(curr, data, last->anyPolicy, tree, 0) == NULL) + return 0; + } + return 1; +@@ -272,7 +288,8 @@ static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr, + * Return value: 1 on success, 0 otherwise. + */ + static int tree_link_nodes(X509_POLICY_LEVEL *curr, +- const X509_POLICY_CACHE *cache) ++ const X509_POLICY_CACHE *cache, ++ X509_POLICY_TREE *tree) + { + int i; + +@@ -280,7 +297,7 @@ static int tree_link_nodes(X509_POLICY_LEVEL *curr, + X509_POLICY_DATA *data = sk_X509_POLICY_DATA_value(cache->data, i); + + /* Look for matching nodes in previous level */ +- if (!tree_link_matching_nodes(curr, data)) ++ if (!tree_link_matching_nodes(curr, data, tree)) + return 0; + } + return 1; +@@ -311,7 +328,7 @@ static int tree_add_unmatched(X509_POLICY_LEVEL *curr, + /* Curr may not have anyPolicy */ + data->qualifier_set = cache->anyPolicy->qualifier_set; + data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS; +- if (level_add_node(curr, data, node, tree) == NULL) { ++ if (level_add_node(curr, data, node, tree, 1) == NULL) { + policy_data_free(data); + return 0; + } +@@ -373,7 +390,7 @@ static int tree_link_any(X509_POLICY_LEVEL *curr, + } + /* Finally add link to anyPolicy */ + if (last->anyPolicy && +- level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL) == NULL) ++ level_add_node(curr, cache->anyPolicy, last->anyPolicy, tree, 0) == NULL) + return 0; + return 1; + } +@@ -555,7 +572,7 @@ static int tree_calculate_user_set(X509_POLICY_TREE *tree, + extra->qualifier_set = anyPolicy->data->qualifier_set; + extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS + | POLICY_DATA_FLAG_EXTRA_NODE; +- node = level_add_node(NULL, extra, anyPolicy->parent, tree); ++ node = level_add_node(NULL, extra, anyPolicy->parent, tree, 1); + } + if (!tree->user_policies) { + tree->user_policies = sk_X509_POLICY_NODE_new_null(); +@@ -582,7 +599,7 @@ static int tree_evaluate(X509_POLICY_TREE *tree) + + for (i = 1; i < tree->nlevel; i++, curr++) { + cache = policy_cache_set(curr->cert); +- if (!tree_link_nodes(curr, cache)) ++ if (!tree_link_nodes(curr, cache, tree)) + return X509_PCY_TREE_INTERNAL; + + if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY) diff --git a/package/libs/openssl/patches/210-Ensure-that-EXFLAG_INVALID_POLICY-is-checked-even-in.patch b/package/libs/openssl/patches/210-Ensure-that-EXFLAG_INVALID_POLICY-is-checked-even-in.patch new file mode 100644 index 000000000..ffb7317d7 --- /dev/null +++ b/package/libs/openssl/patches/210-Ensure-that-EXFLAG_INVALID_POLICY-is-checked-even-in.patch @@ -0,0 +1,48 @@ +From b013765abfa80036dc779dd0e50602c57bb3bf95 Mon Sep 17 00:00:00 2001 +From: Matt Caswell +Date: Tue, 7 Mar 2023 16:52:55 +0000 +Subject: [PATCH] Ensure that EXFLAG_INVALID_POLICY is checked even in leaf + certs + +Even though we check the leaf cert to confirm it is valid, we +later ignored the invalid flag and did not notice that the leaf +cert was bad. + +Fixes: CVE-2023-0465 + +Reviewed-by: Hugo Landau +Reviewed-by: Tomas Mraz +(Merged from https://github.com/openssl/openssl/pull/20588) + +diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c +index 925fbb5412..1dfe4f9f31 100644 +--- a/crypto/x509/x509_vfy.c ++++ b/crypto/x509/x509_vfy.c +@@ -1649,18 +1649,25 @@ static int check_policy(X509_STORE_CTX *ctx) + } + /* Invalid or inconsistent extensions */ + if (ret == X509_PCY_TREE_INVALID) { +- int i; ++ int i, cbcalled = 0; + + /* Locate certificates with bad extensions and notify callback. */ +- for (i = 1; i < sk_X509_num(ctx->chain); i++) { ++ for (i = 0; i < sk_X509_num(ctx->chain); i++) { + X509 *x = sk_X509_value(ctx->chain, i); + + if (!(x->ex_flags & EXFLAG_INVALID_POLICY)) + continue; ++ cbcalled = 1; + if (!verify_cb_cert(ctx, x, i, + X509_V_ERR_INVALID_POLICY_EXTENSION)) + return 0; + } ++ if (!cbcalled) { ++ /* Should not be able to get here */ ++ X509err(X509_F_CHECK_POLICY, ERR_R_INTERNAL_ERROR); ++ return 0; ++ } ++ /* The callback ignored the error so we return success */ + return 1; + } + if (ret == X509_PCY_TREE_FAILURE) { diff --git a/package/network/services/hostapd/Config.in b/package/network/services/hostapd/Config.in index 5c00f3e24..8f28eb2bd 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: @@ -65,10 +75,7 @@ config WPA_WOLFSSL config DRIVER_WEXT_SUPPORT bool - default n - -config DRIVER_11N_SUPPORT - bool + select KERNEL_WIRELESS_EXT default n config DRIVER_11AC_SUPPORT @@ -78,6 +85,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 +95,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 916912b11..fcf853ba7 100644 --- a/package/network/services/hostapd/Makefile +++ b/package/network/services/hostapd/Makefile @@ -9,9 +9,9 @@ PKG_RELEASE:=$(AUTORELEASE) 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:=2022-07-29 +PKG_SOURCE_VERSION:=b704dc72ef824dfdd96674b90179b274d1d38105 +PKG_MIRROR_HASH:=6c9dd359ef5a4595b6576e07928566d6864957c4af6466d641d6c3f7717f4689 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=BSD-3-Clause @@ -28,11 +28,12 @@ PKG_CONFIG_DEPENDS:= \ 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 +54,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 +74,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 @@ -87,10 +85,10 @@ endif 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) ifeq ($(SSL_VARIANT),openssl) DRIVER_MAKEOPTS += CONFIG_TLS=openssl CONFIG_SAE=y @@ -122,6 +120,21 @@ 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 @@ -160,7 +173,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) @@ -169,11 +182,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) @@ -188,7 +210,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 @@ -199,13 +221,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) @@ -247,7 +280,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) @@ -256,11 +289,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) @@ -275,7 +317,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 @@ -286,13 +328,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) @@ -316,7 +369,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 @@ -325,12 +378,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 @@ -356,14 +418,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 @@ -387,14 +456,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 @@ -460,7 +536,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 @@ -469,7 +545,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 @@ -502,8 +587,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 ifdef CONFIG_PACKAGE_kmod-cfg80211 TARGET_LDFLAGS += -lm -lnl-tiny @@ -581,6 +665,12 @@ 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)) @@ -611,9 +701,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) ifneq ($(LOCAL_TYPE),supplicant) define Package/hostapd-utils/install @@ -632,11 +724,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)) @@ -647,8 +742,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 @@ -678,6 +775,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)) @@ -685,28 +789,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/files/hostapd-basic.config b/package/network/services/hostapd/files/hostapd-basic.config index 1f52546d5..3d19d8f90 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 dbc202255..9076ebc44 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 e861323e4..a714356e0 100644 --- a/package/network/services/hostapd/files/hostapd.sh +++ b/package/network/services/hostapd/files/hostapd.sh @@ -24,12 +24,12 @@ hostapd_append_wep_key() { [1234]) for idx in 1 2 3 4; do local zidx - zidx=$(($idx - 1)) + zidx="$(($idx - 1))" json_get_var ckey "key${idx}" [ -n "$ckey" ] && \ append $var "wep_key${zidx}=$(prepare_key_wep "$ckey")" "$N$T" done - wep_keyidx=$((key - 1)) + wep_keyidx="$((key - 1))" ;; *) append $var "wep_key0=$(prepare_key_wep "$key")" "$N$T" @@ -132,9 +132,10 @@ hostapd_prepare_device_config() { local base_cfg= - json_get_vars country country3 country_ie beacon_int:100 dtim_period:2 doth require_mode legacy_rates \ + json_get_vars country country3 country_ie beacon_int:100 doth require_mode legacy_rates \ acs_chan_bias local_pwr_constraint spectrum_mgmt_required airtime_mode cell_density \ - rts_threshold beacon_rate rssi_reject_assoc_rssi rssi_ignore_probe_request maxassoc vendor_vht + rts_threshold beacon_rate rssi_reject_assoc_rssi rssi_ignore_probe_request maxassoc \ + vendor_vht hostapd_set_log_options base_cfg @@ -234,7 +235,6 @@ hostapd_prepare_device_config() { [ -n "$brlist" ] && append base_cfg "basic_rates=$brlist" "$N" append base_cfg "beacon_int=$beacon_int" "$N" [ -n "$rts_threshold" ] && append base_cfg "rts_threshold=$rts_threshold" "$N" - append base_cfg "dtim_period=$dtim_period" "$N" [ "$airtime_mode" -gt 0 ] && append base_cfg "airtime_mode=$airtime_mode" "$N" [ -n "$maxassoc" ] && append base_cfg "iface_max_num_sta=$maxassoc" "$N" @@ -251,7 +251,7 @@ EOF hostapd_common_add_bss_config() { config_add_string 'bssid:macaddr' 'ssid:string' - config_add_boolean wds wmm uapsd hidden utf8_ssid + config_add_boolean wds wmm uapsd hidden utf8_ssid ppsk config_add_int maxassoc max_inactivity config_add_boolean disassoc_low_ack isolate short_preamble skip_inactivity_poll @@ -268,11 +268,11 @@ hostapd_common_add_bss_config() { config_add_int ieee80211w config_add_int eapol_version - config_add_string 'auth_server:host' 'server:host' + config_add_array auth_server acct_server + config_add_string 'server:host' config_add_string auth_secret key config_add_int 'auth_port:port' 'port:port' - config_add_string acct_server config_add_string acct_secret config_add_int acct_port config_add_int acct_interval @@ -309,7 +309,7 @@ hostapd_common_add_bss_config() { config_add_string wps_device_type wps_device_name wps_manufacturer wps_pin config_add_string multi_ap_backhaul_ssid multi_ap_backhaul_key - config_add_boolean wnm_sleep_mode wnm_sleep_mode_no_keys bss_transition + config_add_boolean wnm_sleep_mode wnm_sleep_mode_no_keys bss_transition mbo config_add_int time_advertisement config_add_string time_zone config_add_string vendor_elements @@ -340,6 +340,7 @@ hostapd_common_add_bss_config() { config_add_int sae_pwe config_add_string 'owe_transition_bssid:macaddr' 'owe_transition_ssid:string' + config_add_string owe_transition_ifname config_add_boolean iw_enabled iw_internet iw_asra iw_esr iw_uesa config_add_int iw_access_network_type iw_venue_group iw_venue_type @@ -362,7 +363,7 @@ hostapd_common_add_bss_config() { config_add_array airtime_sta_weight config_add_int airtime_bss_weight airtime_bss_limit - config_add_boolean multicast_to_unicast proxy_arp per_sta_vif + config_add_boolean multicast_to_unicast multicast_to_unicast_all proxy_arp per_sta_vif config_add_array hostapd_bss_options config_add_boolean default_disabled @@ -376,6 +377,8 @@ hostapd_common_add_bss_config() { config_add_boolean fils config_add_string fils_dhcp + + config_add_int ocv } hostapd_set_vlan_file() { @@ -524,6 +527,20 @@ append_airtime_sta_weight() { [ -n "$1" ] && append bss_conf "airtime_sta_weight=$1" "$N" } +append_auth_server() { + [ -n "$1" ] || return + append bss_conf "auth_server_addr=$1" "$N" + append bss_conf "auth_server_port=$auth_port" "$N" + [ -n "$auth_secret" ] && append bss_conf "auth_server_shared_secret=$auth_secret" "$N" +} + +append_acct_server() { + [ -n "$1" ] || return + append bss_conf "acct_server_addr=$1" "$N" + append bss_conf "acct_server_port=$acct_port" "$N" + [ -n "$acct_secret" ] && append bss_conf "acct_server_shared_secret=$acct_secret" "$N" +} + hostapd_set_bss_options() { local var="$1" local phy="$2" @@ -542,13 +559,13 @@ hostapd_set_bss_options() { wps_independent wps_device_type wps_device_name wps_manufacturer wps_pin \ macfilter ssid utf8_ssid wmm uapsd hidden short_preamble rsn_preauth \ iapp_interface eapol_version dynamic_vlan ieee80211w nasid \ - acct_server acct_secret acct_port acct_interval \ + acct_secret acct_port acct_interval \ bss_load_update_period chan_util_avg_period sae_require_mfp sae_pwe \ multi_ap multi_ap_backhaul_ssid multi_ap_backhaul_key skip_inactivity_poll \ - airtime_bss_weight airtime_bss_limit airtime_sta_weight \ - multicast_to_unicast proxy_arp per_sta_vif \ + ppsk airtime_bss_weight airtime_bss_limit airtime_sta_weight \ + multicast_to_unicast_all proxy_arp per_sta_vif \ eap_server eap_user_file ca_cert server_cert private_key private_key_passwd server_id \ - vendor_elements fils + vendor_elements fils ocv set_default fils 0 set_default isolate 0 @@ -568,6 +585,7 @@ hostapd_set_bss_options() { set_default chan_util_avg_period 600 set_default utf8_ssid 1 set_default multi_ap 0 + set_default ppsk 0 set_default airtime_bss_weight 0 set_default airtime_bss_limit 0 set_default eap_server 0 @@ -610,16 +628,15 @@ hostapd_set_bss_options() { [ -n "$wpa_strict_rekey" ] && append bss_conf "wpa_strict_rekey=$wpa_strict_rekey" "$N" } - [ -n "$nasid" ] && append bss_conf "nas_identifier=$nasid" "$N" - [ -n "$acct_server" ] && { - append bss_conf "acct_server_addr=$acct_server" "$N" - append bss_conf "acct_server_port=$acct_port" "$N" - [ -n "$acct_secret" ] && \ - append bss_conf "acct_server_shared_secret=$acct_secret" "$N" - [ -n "$acct_interval" ] && \ - append bss_conf "radius_acct_interim_interval=$acct_interval" "$N" - json_for_each_item append_radius_acct_req_attr radius_acct_req_attr - } + set_default nasid "${macaddr//\:}" + append bss_conf "nas_identifier=$nasid" "$N" + + [ -n "$acct_interval" ] && \ + append bss_conf "radius_acct_interim_interval=$acct_interval" "$N" + json_for_each_item append_acct_server acct_server + json_for_each_item append_radius_acct_req_attr radius_acct_req_attr + + [ -n "$ocv" ] && append bss_conf "ocv=$ocv" "$N" case "$auth_type" in sae|owe|eap192|eap-eap192) @@ -640,10 +657,11 @@ hostapd_set_bss_options() { case "$auth_type" in none|owe) - json_get_vars owe_transition_bssid owe_transition_ssid + json_get_vars owe_transition_bssid owe_transition_ssid owe_transition_ifname [ -n "$owe_transition_ssid" ] && append bss_conf "owe_transition_ssid=\"$owe_transition_ssid\"" "$N" [ -n "$owe_transition_bssid" ] && append bss_conf "owe_transition_bssid=$owe_transition_bssid" "$N" + [ -n "$owe_transition_ifname" ] && append bss_conf "owe_transition_ifname=$owe_transition_ifname" "$N" wps_possible=1 # Here we make the assumption that if we're in open mode @@ -652,7 +670,13 @@ hostapd_set_bss_options() { ;; psk|sae|psk-sae) json_get_vars key wpa_psk_file - if [ ${#key} -eq 64 ]; then + if [ "$auth_type" = "psk" ] && [ "$ppsk" -ne 0 ] ; then + json_get_vars auth_secret auth_port + set_default auth_port 1812 + json_for_each_item append_auth_server auth_server + append bss_conf "macaddr_acl=2" "$N" + append bss_conf "wpa_psk_radius=2" "$N" + elif [ ${#key} -eq 64 ]; then append bss_conf "wpa_psk=$key" "$N" elif [ ${#key} -ge 8 ] && [ ${#key} -le 63 ]; then append bss_conf "wpa_passphrase=$key" "$N" @@ -675,7 +699,7 @@ hostapd_set_bss_options() { json_get_vars \ auth_server auth_secret auth_port \ dae_client dae_secret dae_port \ - ownip radius_client_addr \ + dynamic_ownip ownip radius_client_addr \ eap_reauth_period request_cui \ erp_domain mobility_domain \ fils_realm fils_dhcp @@ -683,6 +707,8 @@ hostapd_set_bss_options() { # radius can provide VLAN ID for clients vlan_possible=1 + set_default dynamic_ownip 1 + # legacy compatibility [ -n "$auth_server" ] || json_get_var auth_server server [ -n "$auth_port" ] || json_get_var auth_port port @@ -716,12 +742,7 @@ hostapd_set_bss_options() { set_default dae_port 3799 set_default request_cui 0 - [ "$eap_server" -eq 0 ] && { - append bss_conf "auth_server_addr=$auth_server" "$N" - append bss_conf "auth_server_port=$auth_port" "$N" - append bss_conf "auth_server_shared_secret=$auth_secret" "$N" - } - + [ "$eap_server" -eq 0 ] && json_for_each_item append_auth_server auth_server [ "$request_cui" -gt 0 ] && append bss_conf "radius_request_cui=$request_cui" "$N" [ -n "$eap_reauth_period" ] && append bss_conf "eap_reauth_period=$eap_reauth_period" "$N" @@ -731,7 +752,12 @@ hostapd_set_bss_options() { } json_for_each_item append_radius_auth_req_attr radius_auth_req_attr - [ -n "$ownip" ] && append bss_conf "own_ip_addr=$ownip" "$N" + if [ -n "$ownip" ]; then + append bss_conf "own_ip_addr=$ownip" "$N" + elif [ "$dynamic_ownip" -gt 0 ]; then + append bss_conf "dynamic_own_ip_addr=$dynamic_ownip" "$N" + fi + [ -n "$radius_client_addr" ] && append bss_conf "radius_client_addr=$radius_client_addr" "$N" append bss_conf "eapol_key_index_workaround=1" "$N" append bss_conf "ieee8021x=1" "$N" @@ -747,7 +773,24 @@ hostapd_set_bss_options() { ;; esac - local auth_algs=$((($auth_mode_shared << 1) | $auth_mode_open)) + case "$auth_type" in + none|owe|psk|sae|psk-sae|wep) + json_get_vars \ + auth_server auth_port auth_secret \ + ownip radius_client_addr + + [ -n "$auth_server" ] && { + set_default auth_port 1812 + + json_for_each_item append_auth_server auth_server + [ -n "$ownip" ] && append bss_conf "own_ip_addr=$ownip" "$N" + [ -n "$radius_client_addr" ] && append bss_conf "radius_client_addr=$radius_client_addr" "$N" + append bss_conf "macaddr_acl=2" "$N" + } + ;; + esac + + local auth_algs="$((($auth_mode_shared << 1) | $auth_mode_open))" append bss_conf "auth_algs=${auth_algs:-1}" "$N" append bss_conf "wpa=$wpa" "$N" [ -n "$wpa_pairwise" ] && append bss_conf "wpa_pairwise=$wpa_pairwise" "$N" @@ -809,10 +852,11 @@ hostapd_set_bss_options() { append bss_conf "iapp_interface=$ifname" "$N" } - json_get_vars time_advertisement time_zone wnm_sleep_mode wnm_sleep_mode_no_keys bss_transition + json_get_vars time_advertisement time_zone wnm_sleep_mode wnm_sleep_mode_no_keys bss_transition mbo set_default bss_transition 0 set_default wnm_sleep_mode 0 set_default wnm_sleep_mode_no_keys 0 + set_default mbo 0 [ -n "$time_advertisement" ] && append bss_conf "time_advertisement=$time_advertisement" "$N" [ -n "$time_zone" ] && append bss_conf "time_zone=$time_zone" "$N" @@ -821,6 +865,7 @@ hostapd_set_bss_options() { [ "$wnm_sleep_mode_no_keys" -eq "1" ] && append bss_conf "wnm_sleep_mode_no_keys=1" "$N" fi [ "$bss_transition" -eq "1" ] && append bss_conf "bss_transition=1" "$N" + [ "$mbo" -eq 1 ] && append bss_conf "mbo=1" "$N" json_get_vars ieee80211k rrm_neighbor_report rrm_beacon_report set_default ieee80211k 0 @@ -855,7 +900,7 @@ hostapd_set_bss_options() { json_get_vars mobility_domain ft_psk_generate_local ft_over_ds reassociation_deadline set_default mobility_domain "$(echo "$ssid" | md5sum | head -c 4)" - set_default ft_over_ds 1 + set_default ft_over_ds 0 set_default reassociation_deadline 1000 case "$auth_type" in @@ -872,7 +917,6 @@ hostapd_set_bss_options() { append bss_conf "ft_psk_generate_local=$ft_psk_generate_local" "$N" append bss_conf "ft_over_ds=$ft_over_ds" "$N" append bss_conf "reassociation_deadline=$reassociation_deadline" "$N" - [ -n "$nasid" ] || append bss_conf "nas_identifier=${macaddr//\:}" "$N" if [ "$ft_psk_generate_local" -eq "0" ]; then json_get_vars r0_key_lifetime r1_key_holder pmk_r1_push @@ -1096,9 +1140,9 @@ hostapd_set_bss_options() { [ -n "$server_id" ] && append bss_conf "server_id=$server_id" "$N" fi - set_default multicast_to_unicast 0 - if [ "$multicast_to_unicast" -gt 0 ]; then - append bss_conf "multicast_to_unicast=$multicast_to_unicast" "$N" + set_default multicast_to_unicast_all 0 + if [ "$multicast_to_unicast_all" -gt 0 ]; then + append bss_conf "multicast_to_unicast=$multicast_to_unicast_all" "$N" fi set_default proxy_arp 0 if [ "$proxy_arp" -gt 0 ]; then @@ -1115,7 +1159,7 @@ hostapd_set_bss_options() { append bss_conf "$val" "$N" done - bss_md5sum=$(echo $bss_conf | md5sum | cut -d" " -f1) + bss_md5sum="$(echo $bss_conf | md5sum | cut -d" " -f1)" append bss_conf "config_id=$bss_md5sum" "$N" append "$var" "$bss_conf" "$N" @@ -1137,7 +1181,7 @@ hostapd_set_log_options() { set_default log_iapp 1 set_default log_mlme 1 - local log_mask=$(( \ + local log_mask="$(( \ ($log_80211 << 0) | \ ($log_8021x << 1) | \ ($log_radius << 2) | \ @@ -1145,7 +1189,7 @@ hostapd_set_log_options() { ($log_driver << 4) | \ ($log_iapp << 5) | \ ($log_mlme << 6) \ - )) + ))" append "$var" "logger_syslog=$log_mask" "$N" append "$var" "logger_syslog_level=$log_level" "$N" @@ -1254,7 +1298,7 @@ wpa_supplicant_add_network() { json_get_vars \ ssid bssid key \ basic_rate mcast_rate \ - ieee80211w ieee80211r fils \ + ieee80211w ieee80211r fils ocv \ multi_ap \ default_disabled @@ -1289,7 +1333,7 @@ wpa_supplicant_add_network() { } [ "$_w_mode" = "mesh" ] && { - json_get_vars mesh_id mesh_fwding mesh_rssi_threshold + json_get_vars mesh_id mesh_fwding mesh_rssi_threshold encryption [ -n "$mesh_id" ] && ssid="${mesh_id}" append network_data "mode=5" "$N$T" @@ -1297,7 +1341,7 @@ wpa_supplicant_add_network() { [ -n "$mesh_rssi_threshold" ] && append network_data "mesh_rssi_threshold=${mesh_rssi_threshold}" "$N$T" [ -n "$freq" ] && wpa_supplicant_set_fixed_freq "$freq" "$htmode" [ "$noscan" = "1" ] && append network_data "noscan=1" "$N$T" - append wpa_key_mgmt "SAE" + [ "$encryption" = "none" -o -z "$encryption" ] || append wpa_key_mgmt "SAE" scan_ssid="" } @@ -1306,6 +1350,8 @@ wpa_supplicant_add_network() { [ "$default_disabled" = 1 ] && append network_data "disabled=1" "$N$T" } + [ -n "$ocv" ] && append network_data "ocv=$ocv" "$N$T" + case "$auth_type" in none) ;; owe) @@ -1329,11 +1375,11 @@ wpa_supplicant_add_network() { key_mgmt="$wpa_key_mgmt" - if [ ${#key} -eq 64 ]; then - passphrase="psk=${key}" + if [ "$_w_mode" = "mesh" ] || [ "$auth_type" = "sae" ]; then + passphrase="sae_password=\"${key}\"" else - if [ "$_w_mode" = "mesh" ]; then - passphrase="sae_password=\"${key}\"" + if [ ${#key} -eq 64 ]; then + passphrase="psk=${key}" else passphrase="psk=\"${key}\"" fi diff --git a/package/network/services/hostapd/files/wpa_supplicant-basic.config b/package/network/services/hostapd/files/wpa_supplicant-basic.config index c550b37b2..6abd8e233 100644 --- a/package/network/services/hostapd/files/wpa_supplicant-basic.config +++ b/package/network/services/hostapd/files/wpa_supplicant-basic.config @@ -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 de3302c87..d24fbbb01 100644 --- a/package/network/services/hostapd/files/wpa_supplicant-full.config +++ b/package/network/services/hostapd/files/wpa_supplicant-full.config @@ -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-p2p.config b/package/network/services/hostapd/files/wpa_supplicant-p2p.config index 48302bb4c..0dcc88e64 100644 --- a/package/network/services/hostapd/files/wpa_supplicant-p2p.config +++ b/package/network/services/hostapd/files/wpa_supplicant-p2p.config @@ -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/wpad.init b/package/network/services/hostapd/files/wpad.init index 79c5bf107..65d46df98 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/0001-Sync-with-mac80211-next.git-include-uapi-linux-nl802.patch b/package/network/services/hostapd/patches/0001-Sync-with-mac80211-next.git-include-uapi-linux-nl802.patch deleted file mode 100644 index c41676629..000000000 --- a/package/network/services/hostapd/patches/0001-Sync-with-mac80211-next.git-include-uapi-linux-nl802.patch +++ /dev/null @@ -1,406 +0,0 @@ -From f5c8697c04576b1995d109abf96fddffbd3b4f1e Mon Sep 17 00:00:00 2001 -From: Jouni Malinen -Date: Wed, 9 Feb 2022 20:15:30 +0200 -Subject: [PATCH] Sync with mac80211-next.git include/uapi/linux/nl80211.h - -This brings in nl80211 definitions as of 2022-01-04. In addition, update -nl80211_command_to_string() to cover the new defined commands. - -Signed-off-by: Jouni Malinen ---- - src/drivers/driver_nl80211_event.c | 7 + - src/drivers/nl80211_copy.h | 230 +++++++++++++++++++++++++++-- - 2 files changed, 226 insertions(+), 11 deletions(-) - ---- a/src/drivers/driver_nl80211_event.c -+++ b/src/drivers/driver_nl80211_event.c -@@ -172,6 +172,13 @@ static const char * nl80211_command_to_s - C2S(NL80211_CMD_UNPROT_BEACON) - C2S(NL80211_CMD_CONTROL_PORT_FRAME_TX_STATUS) - C2S(NL80211_CMD_SET_SAR_SPECS) -+ C2S(NL80211_CMD_OBSS_COLOR_COLLISION) -+ C2S(NL80211_CMD_COLOR_CHANGE_REQUEST) -+ C2S(NL80211_CMD_COLOR_CHANGE_STARTED) -+ C2S(NL80211_CMD_COLOR_CHANGE_ABORTED) -+ C2S(NL80211_CMD_COLOR_CHANGE_COMPLETED) -+ C2S(NL80211_CMD_SET_FILS_AAD) -+ C2S(NL80211_CMD_ASSOC_COMEBACK) - C2S(__NL80211_CMD_AFTER_LAST) - } - #undef C2S ---- a/src/drivers/nl80211_copy.h -+++ b/src/drivers/nl80211_copy.h -@@ -11,7 +11,7 @@ - * Copyright 2008 Jouni Malinen - * Copyright 2008 Colin McCabe - * Copyright 2015-2017 Intel Deutschland GmbH -- * Copyright (C) 2018-2020 Intel Corporation -+ * Copyright (C) 2018-2021 Intel Corporation - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above -@@ -301,6 +301,29 @@ - */ - - /** -+ * DOC: FILS shared key crypto offload -+ * -+ * This feature is applicable to drivers running in AP mode. -+ * -+ * FILS shared key crypto offload can be advertised by drivers by setting -+ * @NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD flag. The drivers that support -+ * FILS shared key crypto offload should be able to encrypt and decrypt -+ * association frames for FILS shared key authentication as per IEEE 802.11ai. -+ * With this capability, for FILS key derivation, drivers depend on userspace. -+ * -+ * After FILS key derivation, userspace shares the FILS AAD details with the -+ * driver and the driver stores the same to use in decryption of association -+ * request and in encryption of association response. The below parameters -+ * should be given to the driver in %NL80211_CMD_SET_FILS_AAD. -+ * %NL80211_ATTR_MAC - STA MAC address, used for storing FILS AAD per STA -+ * %NL80211_ATTR_FILS_KEK - Used for encryption or decryption -+ * %NL80211_ATTR_FILS_NONCES - Used for encryption or decryption -+ * (STA Nonce 16 bytes followed by AP Nonce 16 bytes) -+ * -+ * Once the association is done, the driver cleans the FILS AAD data. -+ */ -+ -+/** - * enum nl80211_commands - supported nl80211 commands - * - * @NL80211_CMD_UNSPEC: unspecified command to catch errors -@@ -337,7 +360,10 @@ - * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes - * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from - * userspace to request deletion of a virtual interface, then requires -- * attribute %NL80211_ATTR_IFINDEX. -+ * attribute %NL80211_ATTR_IFINDEX. If multiple BSSID advertisements are -+ * enabled using %NL80211_ATTR_MBSSID_CONFIG, %NL80211_ATTR_MBSSID_ELEMS, -+ * and if this command is used for the transmitting interface, then all -+ * the non-transmitting interfaces are deleted as well. - * - * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified - * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. -@@ -1185,6 +1211,32 @@ - * passed using %NL80211_ATTR_SAR_SPEC. %NL80211_ATTR_WIPHY is used to - * specify the wiphy index to be applied to. - * -+ * @NL80211_CMD_OBSS_COLOR_COLLISION: This notification is sent out whenever -+ * mac80211/drv detects a bss color collision. -+ * -+ * @NL80211_CMD_COLOR_CHANGE_REQUEST: This command is used to indicate that -+ * userspace wants to change the BSS color. -+ * -+ * @NL80211_CMD_COLOR_CHANGE_STARTED: Notify userland, that a color change has -+ * started -+ * -+ * @NL80211_CMD_COLOR_CHANGE_ABORTED: Notify userland, that the color change has -+ * been aborted -+ * -+ * @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change -+ * has completed -+ * -+ * @NL80211_CMD_SET_FILS_AAD: Set FILS AAD data to the driver using - -+ * &NL80211_ATTR_MAC - for STA MAC address -+ * &NL80211_ATTR_FILS_KEK - for KEK -+ * &NL80211_ATTR_FILS_NONCES - for FILS Nonces -+ * (STA Nonce 16 bytes followed by AP Nonce 16 bytes) -+ * -+ * @NL80211_CMD_ASSOC_COMEBACK: notification about an association -+ * temporal rejection with comeback. The event includes %NL80211_ATTR_MAC -+ * to describe the BSSID address of the AP and %NL80211_ATTR_TIMEOUT to -+ * specify the timeout value. -+ * - * @NL80211_CMD_MAX: highest used command number - * @__NL80211_CMD_AFTER_LAST: internal use - */ -@@ -1417,6 +1469,18 @@ enum nl80211_commands { - - NL80211_CMD_SET_SAR_SPECS, - -+ NL80211_CMD_OBSS_COLOR_COLLISION, -+ -+ NL80211_CMD_COLOR_CHANGE_REQUEST, -+ -+ NL80211_CMD_COLOR_CHANGE_STARTED, -+ NL80211_CMD_COLOR_CHANGE_ABORTED, -+ NL80211_CMD_COLOR_CHANGE_COMPLETED, -+ -+ NL80211_CMD_SET_FILS_AAD, -+ -+ NL80211_CMD_ASSOC_COMEBACK, -+ - /* add new commands above here */ - - /* used to define NL80211_CMD_MAX below */ -@@ -2413,7 +2477,9 @@ enum nl80211_commands { - * space supports external authentication. This attribute shall be used - * with %NL80211_CMD_CONNECT and %NL80211_CMD_START_AP request. The driver - * may offload authentication processing to user space if this capability -- * is indicated in the respective requests from the user space. -+ * is indicated in the respective requests from the user space. (This flag -+ * attribute deprecated for %NL80211_CMD_START_AP, use -+ * %NL80211_ATTR_AP_SETTINGS_FLAGS) - * - * @NL80211_ATTR_NSS: Station's New/updated RX_NSS value notified using this - * u8 attribute. This is used with %NL80211_CMD_STA_OPMODE_CHANGED. -@@ -2560,6 +2626,39 @@ enum nl80211_commands { - * disassoc events to indicate that an immediate reconnect to the AP - * is desired. - * -+ * @NL80211_ATTR_OBSS_COLOR_BITMAP: bitmap of the u64 BSS colors for the -+ * %NL80211_CMD_OBSS_COLOR_COLLISION event. -+ * -+ * @NL80211_ATTR_COLOR_CHANGE_COUNT: u8 attribute specifying the number of TBTT's -+ * until the color switch event. -+ * @NL80211_ATTR_COLOR_CHANGE_COLOR: u8 attribute specifying the color that we are -+ * switching to -+ * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE -+ * information for the time while performing a color switch. -+ * -+ * @NL80211_ATTR_MBSSID_CONFIG: Nested attribute for multiple BSSID -+ * advertisements (MBSSID) parameters in AP mode. -+ * Kernel uses this attribute to indicate the driver's support for MBSSID -+ * and enhanced multi-BSSID advertisements (EMA AP) to the userspace. -+ * Userspace should use this attribute to configure per interface MBSSID -+ * parameters. -+ * See &enum nl80211_mbssid_config_attributes for details. -+ * -+ * @NL80211_ATTR_MBSSID_ELEMS: Nested parameter to pass multiple BSSID elements. -+ * Mandatory parameter for the transmitting interface to enable MBSSID. -+ * Optional for the non-transmitting interfaces. -+ * -+ * @NL80211_ATTR_RADAR_BACKGROUND: Configure dedicated offchannel chain -+ * available for radar/CAC detection on some hw. This chain can't be used -+ * to transmit or receive frames and it is bounded to a running wdev. -+ * Background radar/CAC detection allows to avoid the CAC downtime -+ * switching on a different channel during CAC detection on the selected -+ * radar channel. -+ * -+ * @NL80211_ATTR_AP_SETTINGS_FLAGS: u32 attribute contains ap settings flags, -+ * enumerated in &enum nl80211_ap_settings_flags. This attribute shall be -+ * used with %NL80211_CMD_START_AP request. -+ * - * @NUM_NL80211_ATTR: total number of nl80211_attrs available - * @NL80211_ATTR_MAX: highest attribute number currently defined - * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3057,6 +3156,19 @@ enum nl80211_attrs { - - NL80211_ATTR_DISABLE_HE, - -+ NL80211_ATTR_OBSS_COLOR_BITMAP, -+ -+ NL80211_ATTR_COLOR_CHANGE_COUNT, -+ NL80211_ATTR_COLOR_CHANGE_COLOR, -+ NL80211_ATTR_COLOR_CHANGE_ELEMS, -+ -+ NL80211_ATTR_MBSSID_CONFIG, -+ NL80211_ATTR_MBSSID_ELEMS, -+ -+ NL80211_ATTR_RADAR_BACKGROUND, -+ -+ NL80211_ATTR_AP_SETTINGS_FLAGS, -+ - /* add attributes here, update the policy in nl80211.c */ - - __NL80211_ATTR_AFTER_LAST, -@@ -3650,11 +3762,12 @@ enum nl80211_mpath_info { - * capabilities IE - * @NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE: HE PPE thresholds information as - * defined in HE capabilities IE -- * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band HE capability attribute currently -- * defined - * @NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA: HE 6GHz band capabilities (__le16), - * given for all 6 GHz band channels -+ * @NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS: vendor element capabilities that are -+ * advertised on this band/for this iftype (binary) - * @__NL80211_BAND_IFTYPE_ATTR_AFTER_LAST: internal use -+ * @NL80211_BAND_IFTYPE_ATTR_MAX: highest band attribute currently defined - */ - enum nl80211_band_iftype_attr { - __NL80211_BAND_IFTYPE_ATTR_INVALID, -@@ -3665,6 +3778,7 @@ enum nl80211_band_iftype_attr { - NL80211_BAND_IFTYPE_ATTR_HE_CAP_MCS_SET, - NL80211_BAND_IFTYPE_ATTR_HE_CAP_PPE, - NL80211_BAND_IFTYPE_ATTR_HE_6GHZ_CAPA, -+ NL80211_BAND_IFTYPE_ATTR_VENDOR_ELEMS, - - /* keep last */ - __NL80211_BAND_IFTYPE_ATTR_AFTER_LAST, -@@ -4887,6 +5001,7 @@ enum nl80211_txrate_gi { - * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz) - * @NL80211_BAND_6GHZ: around 6 GHz band (5.9 - 7.2 GHz) - * @NL80211_BAND_S1GHZ: around 900MHz, supported by S1G PHYs -+ * @NL80211_BAND_LC: light communication band (placeholder) - * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace - * since newer kernel versions may support more bands - */ -@@ -4896,6 +5011,7 @@ enum nl80211_band { - NL80211_BAND_60GHZ, - NL80211_BAND_6GHZ, - NL80211_BAND_S1GHZ, -+ NL80211_BAND_LC, - - NUM_NL80211_BANDS, - }; -@@ -5462,7 +5578,7 @@ enum nl80211_iface_limit_attrs { - * => allows 8 of AP/GO that can have BI gcd >= min gcd - * - * numbers = [ #{STA} <= 2 ], channels = 2, max = 2 -- * => allows two STAs on different channels -+ * => allows two STAs on the same or on different channels - * - * numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4 - * => allows a STA plus three P2P interfaces -@@ -5507,7 +5623,7 @@ enum nl80211_if_combination_attrs { - * @NL80211_PLINK_ESTAB: mesh peer link is established - * @NL80211_PLINK_HOLDING: mesh peer link is being closed or cancelled - * @NL80211_PLINK_BLOCKED: all frames transmitted from this mesh -- * plink are discarded -+ * plink are discarded, except for authentication frames - * @NUM_NL80211_PLINK_STATES: number of peer link states - * @MAX_NL80211_PLINK_STATES: highest numerical value of plink states - */ -@@ -5644,13 +5760,15 @@ enum nl80211_tdls_operation { - NL80211_TDLS_DISABLE_LINK, - }; - --/* -+/** - * enum nl80211_ap_sme_features - device-integrated AP features -- * Reserved for future use, no bits are defined in -- * NL80211_ATTR_DEVICE_AP_SME yet. -+ * @NL80211_AP_SME_SA_QUERY_OFFLOAD: SA Query procedures offloaded to driver -+ * when user space indicates support for SA Query procedures offload during -+ * "start ap" with %NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT. -+ */ - enum nl80211_ap_sme_features { -+ NL80211_AP_SME_SA_QUERY_OFFLOAD = 1 << 0, - }; -- */ - - /** - * enum nl80211_feature_flags - device/driver features -@@ -5950,6 +6068,17 @@ enum nl80211_feature_flags { - * frame protection for all management frames exchanged during the - * negotiation and range measurement procedure. - * -+ * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision -+ * detection and change announcemnts. -+ * -+ * @NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD: Driver running in AP mode supports -+ * FILS encryption and decryption for (Re)Association Request and Response -+ * frames. Userspace has to share FILS AAD details to the driver by using -+ * @NL80211_CMD_SET_FILS_AAD. -+ * -+ * @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC -+ * detection. -+ * - * @NUM_NL80211_EXT_FEATURES: number of extended features. - * @MAX_NL80211_EXT_FEATURES: highest extended feature index. - */ -@@ -6014,6 +6143,9 @@ enum nl80211_ext_feature_index { - NL80211_EXT_FEATURE_SECURE_LTF, - NL80211_EXT_FEATURE_SECURE_RTT, - NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, -+ NL80211_EXT_FEATURE_BSS_COLOR, -+ NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD, -+ NL80211_EXT_FEATURE_RADAR_BACKGROUND, - - /* add new features before the definition below */ - NUM_NL80211_EXT_FEATURES, -@@ -6912,6 +7044,9 @@ enum nl80211_peer_measurement_ftm_capa { - * @NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK: negotiate for LMR feedback. Only - * valid if either %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED or - * %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED is set. -+ * @NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR: optional. The BSS color of the -+ * responder. Only valid if %NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED -+ * or %NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED is set. - * - * @NUM_NL80211_PMSR_FTM_REQ_ATTR: internal - * @NL80211_PMSR_FTM_REQ_ATTR_MAX: highest attribute number -@@ -6931,6 +7066,7 @@ enum nl80211_peer_measurement_ftm_req { - NL80211_PMSR_FTM_REQ_ATTR_TRIGGER_BASED, - NL80211_PMSR_FTM_REQ_ATTR_NON_TRIGGER_BASED, - NL80211_PMSR_FTM_REQ_ATTR_LMR_FEEDBACK, -+ NL80211_PMSR_FTM_REQ_ATTR_BSS_COLOR, - - /* keep last */ - NUM_NL80211_PMSR_FTM_REQ_ATTR, -@@ -7299,4 +7435,76 @@ enum nl80211_sar_specs_attrs { - NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1, - }; - -+/** -+ * enum nl80211_mbssid_config_attributes - multiple BSSID (MBSSID) and enhanced -+ * multi-BSSID advertisements (EMA) in AP mode. -+ * Kernel uses some of these attributes to advertise driver's support for -+ * MBSSID and EMA. -+ * Remaining attributes should be used by the userspace to configure the -+ * features. -+ * -+ * @__NL80211_MBSSID_CONFIG_ATTR_INVALID: Invalid -+ * -+ * @NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES: Used by the kernel to advertise -+ * the maximum number of MBSSID interfaces supported by the driver. -+ * Driver should indicate MBSSID support by setting -+ * wiphy->mbssid_max_interfaces to a value more than or equal to 2. -+ * -+ * @NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY: Used by the kernel -+ * to advertise the maximum profile periodicity supported by the driver -+ * if EMA is enabled. Driver should indicate EMA support to the userspace -+ * by setting wiphy->ema_max_profile_periodicity to -+ * a non-zero value. -+ * -+ * @NL80211_MBSSID_CONFIG_ATTR_INDEX: Mandatory parameter to pass the index of -+ * this BSS (u8) in the multiple BSSID set. -+ * Value must be set to 0 for the transmitting interface and non-zero for -+ * all non-transmitting interfaces. The userspace will be responsible -+ * for using unique indices for the interfaces. -+ * Range: 0 to wiphy->mbssid_max_interfaces-1. -+ * -+ * @NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX: Mandatory parameter for -+ * a non-transmitted profile which provides the interface index (u32) of -+ * the transmitted profile. The value must match one of the interface -+ * indices advertised by the kernel. Optional if the interface being set up -+ * is the transmitting one, however, if provided then the value must match -+ * the interface index of the same. -+ * -+ * @NL80211_MBSSID_CONFIG_ATTR_EMA: Flag used to enable EMA AP feature. -+ * Setting this flag is permitted only if the driver advertises EMA support -+ * by setting wiphy->ema_max_profile_periodicity to non-zero. -+ * -+ * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal -+ * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute -+ */ -+enum nl80211_mbssid_config_attributes { -+ __NL80211_MBSSID_CONFIG_ATTR_INVALID, -+ -+ NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES, -+ NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY, -+ NL80211_MBSSID_CONFIG_ATTR_INDEX, -+ NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX, -+ NL80211_MBSSID_CONFIG_ATTR_EMA, -+ -+ /* keep last */ -+ __NL80211_MBSSID_CONFIG_ATTR_LAST, -+ NL80211_MBSSID_CONFIG_ATTR_MAX = __NL80211_MBSSID_CONFIG_ATTR_LAST - 1, -+}; -+ -+/** -+ * enum nl80211_ap_settings_flags - AP settings flags -+ * -+ * @NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT: AP supports external -+ * authentication. -+ * @NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT: Userspace supports SA Query -+ * procedures offload to driver. If driver advertises -+ * %NL80211_AP_SME_SA_QUERY_OFFLOAD in AP SME features, userspace shall -+ * ignore SA Query procedures and validations when this flag is set by -+ * userspace. -+ */ -+enum nl80211_ap_settings_flags { -+ NL80211_AP_SETTINGS_EXTERNAL_AUTH_SUPPORT = 1 << 0, -+ NL80211_AP_SETTINGS_SA_QUERY_OFFLOAD_SUPPORT = 1 << 1, -+}; -+ - #endif /* __LINUX_NL80211_H */ 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 994aa3062..269dcaac7 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 --- 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 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 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 16d24d100..6bc48abfb 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 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c -@@ -2409,7 +2409,7 @@ static int drv_supports_vht(struct wpa_s +@@ -2436,7 +2436,7 @@ static int drv_supports_vht(struct wpa_s } @@ -23,7 +23,7 @@ Signed-off-by: Peter Oh { int i; -@@ -2418,7 +2418,10 @@ static bool ibss_mesh_is_80mhz_avail(int +@@ -2445,7 +2445,10 @@ static bool ibss_mesh_is_80mhz_avail(int chan = hw_get_channel_chan(mode, i, NULL); if (!chan || @@ -35,7 +35,7 @@ Signed-off-by: Peter Oh return false; } -@@ -2447,6 +2450,8 @@ void ibss_mesh_setup_freq(struct wpa_sup +@@ -2474,6 +2477,8 @@ void ibss_mesh_setup_freq(struct wpa_sup int chwidth, seg0, seg1; u32 vht_caps = 0; bool is_24ghz, is_6ghz; @@ -44,7 +44,7 @@ Signed-off-by: Peter Oh freq->freq = ssid->frequency; -@@ -2543,8 +2548,11 @@ void ibss_mesh_setup_freq(struct wpa_sup +@@ -2570,8 +2575,11 @@ void ibss_mesh_setup_freq(struct wpa_sup return; /* Check primary channel flags */ @@ -57,7 +57,7 @@ Signed-off-by: Peter Oh freq->channel = pri_chan->chan; -@@ -2577,8 +2585,11 @@ void ibss_mesh_setup_freq(struct wpa_sup +@@ -2604,8 +2612,11 @@ void ibss_mesh_setup_freq(struct wpa_sup return; /* Check secondary channel flags */ @@ -70,7 +70,7 @@ Signed-off-by: Peter Oh if (ht40 == -1) { if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS)) -@@ -2667,7 +2678,7 @@ skip_to_6ghz: +@@ -2694,7 +2705,7 @@ skip_to_6ghz: return; /* Back to HT configuration if channel not usable */ @@ -78,8 +78,8 @@ Signed-off-by: Peter Oh + if (!ibss_mesh_is_80mhz_avail(channel, mode, dfs_enabled)) return; - chwidth = CHANWIDTH_80MHZ; -@@ -2681,7 +2692,7 @@ skip_to_6ghz: + chwidth = CONF_OPER_CHWIDTH_80MHZ; +@@ -2708,7 +2719,7 @@ skip_to_6ghz: * above; check the remaining four 20 MHz channels for the total * of 160 MHz bandwidth. */ @@ -88,7 +88,7 @@ Signed-off-by: Peter Oh return; for (j = 0; j < ARRAY_SIZE(bw160); j++) { -@@ -2711,10 +2722,12 @@ skip_to_6ghz: +@@ -2738,10 +2749,12 @@ skip_to_6ghz: if (!chan) continue; @@ -103,4 +103,4 @@ Signed-off-by: Peter Oh + continue; /* Found a suitable second segment for 80+80 */ - chwidth = CHANWIDTH_80P80MHZ; + chwidth = CONF_OPER_CHWIDTH_80P80MHZ; 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 1faeacf76..32a447914 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 +#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 { +@@ -515,9 +516,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 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 +@@ -537,8 +543,20 @@ dfs_get_valid_channel(struct hostapd_ifa if (num_available_chandefs == 0) return NULL; @@ -64,11 +64,11 @@ Signed-off-by: Markus Theil 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 * +@@ -9948,6 +9948,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 ac02ec5ab..80b23bdfc 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 +@@ -4963,6 +4963,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 +@@ -4976,7 +4983,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 c7da33f02..25801da33 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 --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c -@@ -3431,7 +3431,7 @@ static int hostapd_change_config_freq(st +@@ -3453,7 +3453,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 ade0b1131..988fbbc6f 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 #include #include #include -@@ -5300,26 +5297,29 @@ fail: +@@ -5344,26 +5341,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 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( +@@ -5373,9 +5373,8 @@ static void rtnl_neigh_delete_fdb_entry( MACSTR, MAC2STR(addr)); } @@ -76,7 +76,7 @@ Signed-off-by: Felix Fietkau } -@@ -7714,7 +7713,6 @@ static void *i802_init(struct hostapd_da +@@ -7763,7 +7762,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 if (bss->added_if_into_bridge || bss->already_in_bridge) { int err; -@@ -7731,7 +7729,6 @@ static void *i802_init(struct hostapd_da +@@ -7780,7 +7778,6 @@ static void *i802_init(struct hostapd_da goto failed; } } @@ -92,7 +92,7 @@ Signed-off-by: Felix Fietkau 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 +@@ -10813,13 +10810,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 int res; if (!ipaddr || prefixlen == 0 || !addr) -@@ -10703,85 +10701,66 @@ static int wpa_driver_br_add_ip_neigh(vo +@@ -10838,85 +10836,66 @@ static int wpa_driver_br_add_ip_neigh(vo } if (version == 4) { @@ -220,7 +220,7 @@ Signed-off-by: Felix Fietkau addrsize = 16; } else { return -EINVAL; -@@ -10799,41 +10778,30 @@ static int wpa_driver_br_delete_ip_neigh +@@ -10934,41 +10913,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 6d9fd81ac..6b34cd435 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 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c -@@ -3761,15 +3761,6 @@ static void handle_auth(struct hostapd_d +@@ -3781,15 +3781,6 @@ static void handle_auth(struct hostapd_d seq_ctrl); return; } diff --git a/package/network/services/hostapd/patches/050-build_fix.patch b/package/network/services/hostapd/patches/050-build_fix.patch index 2652a8331..c9268f59e 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 +@@ -320,6 +320,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 000000000..01af14b71 --- /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 +Date: Tue, 5 Jul 2022 02:49:50 -0400 +Subject: [PATCH 1/7] mbedtls: TLS/crypto option (initial port) + +Signed-off-by: Glenn Strauss +--- + 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 +@@ -1327,7 +1412,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 +@@ -1350,13 +1437,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 ++ * SPDX-License-Identifier: BSD-3-Clause ++ */ ++ ++#include "utils/includes.h" ++#include "utils/common.h" ++ ++#include ++#include ++#include ++#include /* mbedtls_platform_zeroize() */ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++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 ++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 ++__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 ++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 ++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 ++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 ++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 ++ ++/* 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 ++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 ++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 ++ ++/* 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 ++ ++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 ++ ++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 ++ ++/* 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 ++#include ++ ++#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 ++ ++#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 ++#include ++ ++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 ++#include ++#include ++#include ++ ++/* 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 ++ ++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 ++#include ++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 ++#include ++ ++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 /* PKCS7 is not currently supported in mbedtls */ ++#include ++#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 ++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 ++#include ++ ++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 ++ * 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 ++#include ++#include ++#include ++#include ++#include /* mbedtls_calloc() mbedtls_free() */ ++#include /* mbedtls_platform_zeroize() */ ++#include ++#include ++#include ++#include ++ ++#if MBEDTLS_VERSION_NUMBER >= 0x02040000 /* mbedtls 2.4.0 */ ++#include ++#else ++#include ++#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 ++#include ++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 +@@ -1149,6 +1149,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 +@@ -1341,9 +1364,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 +@@ -1357,9 +1382,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 +@@ -1369,35 +1396,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 +@@ -1412,12 +1449,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 +@@ -1429,29 +1470,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 +@@ -1506,12 +1555,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 +@@ -1524,50 +1578,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 +@@ -1742,10 +1814,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 000000000..a0d287086 --- /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 +Date: Tue, 19 Jul 2022 20:02:21 -0400 +Subject: [PATCH 2/7] mbedtls: fips186_2_prf() + +Signed-off-by: Glenn Strauss +--- + 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 +@@ -1160,10 +1160,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 000000000..ae7620b90 --- /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 +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 +--- + 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 + 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 + 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 + 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 + 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 000000000..9e9e88c1e --- /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 +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 +--- + 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") +@@ -1625,7 +1668,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") + +@@ -2860,6 +2903,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", +@@ -2920,6 +2964,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) + +@@ -3460,7 +3505,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")] +@@ -4774,7 +4819,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: +@@ -4840,6 +4885,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" +@@ -4849,7 +4895,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: +@@ -4885,7 +4931,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: +@@ -4935,7 +4981,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: +@@ -5002,7 +5048,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: +@@ -5260,6 +5306,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"] +@@ -5272,6 +5319,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"] +@@ -5294,6 +5342,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) +@@ -5605,8 +5654,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", +@@ -5632,14 +5681,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") +@@ -6081,13 +6130,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") +@@ -6109,6 +6162,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) +@@ -7145,6 +7203,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", +@@ -7157,6 +7216,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", +@@ -7167,6 +7227,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", +@@ -7177,6 +7238,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 ") +@@ -7191,10 +7253,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 +@@ -2347,11 +2347,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 +@@ -3621,6 +3622,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): +@@ -3716,7 +3720,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""" +@@ -4078,11 +4087,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 +@@ -954,7 +954,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)) +@@ -962,7 +962,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] +@@ -2122,6 +2127,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 +@@ -26,6 +26,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 +@@ -499,6 +501,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 +@@ -1834,7 +1834,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 +@@ -135,7 +135,13 @@ def check_fils_sk_pfs_capa(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 ++ * ++ * 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 +@@ -1108,6 +1108,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 +@@ -1123,6 +1124,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 +@@ -1150,6 +1152,7 @@ CFLAGS += -DTLS_DEFAULT_CIPHERS=\"$(CONF + endif + + ifeq ($(CONFIG_TLS), mbedtls) ++CFLAGS += -DCONFIG_TLS_MBEDTLS + ifndef CONFIG_CRYPTO + CONFIG_CRYPTO=mbedtls + endif +@@ -1169,6 +1172,7 @@ endif + endif + + ifeq ($(CONFIG_TLS), gnutls) ++CFLAGS += -DCONFIG_TLS_GNUTLS + ifndef CONFIG_CRYPTO + # default to libgcrypt + CONFIG_CRYPTO=gnutls +@@ -1199,6 +1203,7 @@ endif + endif + + ifeq ($(CONFIG_TLS), internal) ++CFLAGS += -DCONFIG_TLS_INTERNAL + ifndef CONFIG_CRYPTO + CONFIG_CRYPTO=internal + endif +@@ -1279,6 +1284,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 000000000..361f72614 --- /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 +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 +--- + 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 +@@ -248,6 +248,12 @@ struct crypto_ec_key * dpp_set_pubkey_po + + 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 000000000..56ae8d0b8 --- /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 +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 +--- + 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 +@@ -1567,7 +1567,9 @@ dpp_pkex_derive_Qr(const struct dpp_curv + Pr = crypto_ec_key_get_public_key(Pr_key); + Qr = crypto_ec_point_init(ec); + hash_bn = crypto_bignum_init_set(hash, curve->hash_len); +- if (!Pr || !Qr || !hash_bn || crypto_ec_point_mul(ec, Pr, hash_bn, Qr)) ++ if (!Pr || !Qr || !hash_bn || ++ crypto_bignum_mod(hash_bn, crypto_ec_get_prime(ec), hash_bn) || ++ crypto_ec_point_mul(ec, Pr, hash_bn, Qr)) + goto fail; + + if (crypto_ec_point_is_at_infinity(ec, Qr)) { diff --git a/package/network/services/hostapd/patches/170-DPP-fix-memleak-of-intro.peer_key.patch b/package/network/services/hostapd/patches/170-DPP-fix-memleak-of-intro.peer_key.patch new file mode 100644 index 000000000..157347d6d --- /dev/null +++ b/package/network/services/hostapd/patches/170-DPP-fix-memleak-of-intro.peer_key.patch @@ -0,0 +1,32 @@ +From 639bb1bb912029ec4ff110c3ed807b62f583d6bf Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +Date: Sun, 9 Oct 2022 04:02:44 -0400 +Subject: [PATCH 7/7] DPP: fix memleak of intro.peer_key + +fix memleak of intro.peer_key in wpas_dpp_rx_peer_disc_resp() + +Signed-off-by: Glenn Strauss +--- + wpa_supplicant/dpp_supplicant.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/wpa_supplicant/dpp_supplicant.c ++++ b/wpa_supplicant/dpp_supplicant.c +@@ -2610,6 +2610,8 @@ static void wpas_dpp_rx_peer_disc_resp(s + return; + } + ++ os_memset(&intro, 0, sizeof(intro)); ++ + trans_id = dpp_get_attr(buf, len, DPP_ATTR_TRANSACTION_ID, + &trans_id_len); + if (!trans_id || trans_id_len != 1) { +@@ -2720,7 +2722,7 @@ static void wpas_dpp_rx_peer_disc_resp(s + wpa_supplicant_req_scan(wpa_s, 0, 0); + } + fail: +- os_memset(&intro, 0, sizeof(intro)); ++ dpp_peer_intro_deinit(&intro); + } + + diff --git a/package/network/services/hostapd/patches/200-multicall.patch b/package/network/services/hostapd/patches/200-multicall.patch index ad82e020f..0db8caa20 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) +@@ -1378,6 +1384,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 +@@ -1458,6 +1470,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_WPA_CLIENT_SO +@@ -371,7 +372,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 +@@ -912,6 +915,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 +@@ -919,9 +926,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 +@@ -1008,6 +1017,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 +@@ -1016,7 +1031,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) +@@ -1996,6 +2013,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) +@@ -2128,6 +2151,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 { +@@ -6171,8 +6171,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 +@@ -6184,7 +6184,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: +@@ -1872,8 +1872,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 +@@ -2145,7 +2145,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[]) +@@ -1216,6 +1216,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 +@@ -4953,8 +4953,8 @@ static void wpas_event_unprot_beacon(str } @@ -242,7 +242,7 @@ { struct wpa_supplicant *wpa_s = ctx; int resched; -@@ -5745,7 +5745,7 @@ void wpa_supplicant_event(void *ctx, enu +@@ -5813,7 +5813,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 +@@ -7087,7 +7087,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 +@@ -7122,6 +7121,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( +@@ -7378,6 +7382,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: +@@ -591,6 +591,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[]) +@@ -684,6 +689,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 01a33d0d0..a0e00c4d5 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 +@@ -3439,6 +3439,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 { +@@ -1043,6 +1043,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 e682efb54..998540198 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 +@@ -2555,6 +2555,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 +@@ -766,6 +766,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,7 +31,7 @@ /* --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c -@@ -2436,7 +2436,7 @@ void ibss_mesh_setup_freq(struct wpa_sup +@@ -2463,7 +2463,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; @@ -40,7 +40,7 @@ 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 +@@ -2471,7 +2471,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; u8 channel; @@ -49,7 +49,7 @@ 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 +@@ -2562,7 +2562,7 @@ void ibss_mesh_setup_freq(struct wpa_sup #endif /* CONFIG_HE_OVERRIDES */ /* Setup higher BW only for 5 GHz */ @@ -60,7 +60,7 @@ for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) { --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h -@@ -974,6 +974,8 @@ struct wpa_ssid { +@@ -981,6 +981,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 b0c1cb835..2c2541947 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 +@@ -5419,7 +5419,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 37033c303..8218a439a 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); +@@ -5022,7 +5022,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 3d51a47a1..b59107463 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 +@@ -119,6 +119,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 +@@ -220,6 +243,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 +@@ -270,24 +294,20 @@ int hostapd_reload_config(struct hostapd } iface->conf = newconf; 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 b13dcb067..29a3799b5 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 +@@ -1803,15 +1803,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 35567838f..a88b63e91 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,24 +1,20 @@ --- 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; +@@ -2938,11 +2938,11 @@ static int wpa_driver_nl80211_del_beacon struct wpa_driver_nl80211_data *drv = bss->drv; -+ if (!bss->beacon_set) -+ return 0; -+ -+ bss->beacon_set = 0; -+ wpa_printf(MSG_DEBUG, "nl80211: Remove beacon (ifindex=%d)", - drv->ifindex); + bss->ifindex); + bss->beacon_set = 0; + bss->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); } -@@ -5617,7 +5622,7 @@ static void nl80211_teardown_ap(struct i +@@ -5661,7 +5661,7 @@ static void nl80211_teardown_ap(struct i nl80211_mgmt_unsubscribe(bss, "AP teardown"); nl80211_put_wiphy_data_ap(bss); @@ -27,7 +23,7 @@ } -@@ -8071,8 +8076,6 @@ static int wpa_driver_nl80211_if_remove( +@@ -8120,8 +8120,6 @@ static int wpa_driver_nl80211_if_remove( } else { wpa_printf(MSG_DEBUG, "nl80211: First BSS - reassign context"); nl80211_teardown_ap(bss); @@ -36,19 +32,3 @@ 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 7f3aa9188..7699541fd 100644 --- a/package/network/services/hostapd/patches/360-ctrl_iface_reload.patch +++ b/package/network/services/hostapd/patches/360-ctrl_iface_reload.patch @@ -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 +@@ -3449,6 +3506,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 +@@ -945,7 +945,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 3c524d5af..6faaffcf7 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 +@@ -115,6 +115,8 @@ OBJS_c += ../src/utils/common.o OBJS_c += ../src/common/cli.o OBJS += wmm_ac.o @@ -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_ +@@ -295,6 +300,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] " "[-g] \\\n" " [-G] \\\n" @@ -70,7 +70,7 @@ "[-p] \\\n" " [-b] [-e]" #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 +@@ -1016,6 +1064,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 +@@ -1026,6 +1076,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 +@@ -2335,6 +2387,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 +@@ -6693,6 +6747,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( +@@ -7031,6 +7095,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 { +@@ -105,6 +105,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 { +@@ -717,6 +722,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 +@@ -2641,6 +2641,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 +@@ -1903,11 +1903,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 +@@ -4953,6 +4953,60 @@ static void wpas_event_unprot_beacon(str } @@ -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 +@@ -5268,8 +5322,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 { +@@ -5968,6 +5968,7 @@ union wpa_event_data { /** * struct ch_switch @@ -347,7 +347,7 @@ * @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 { +@@ -5976,6 +5977,7 @@ union wpa_event_data { * @cf2: Center frequency 2 */ struct ch_switch { @@ -357,7 +357,7 @@ int ch_offset; --- a/src/drivers/driver_nl80211_event.c +++ b/src/drivers/driver_nl80211_event.c -@@ -691,7 +691,7 @@ static void mlme_event_ch_switch(struct +@@ -694,7 +694,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, @@ -366,7 +366,7 @@ { struct i802_bss *bss; union wpa_event_data data; -@@ -752,6 +752,8 @@ static void mlme_event_ch_switch(struct +@@ -755,6 +755,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); @@ -375,7 +375,7 @@ if (finished) bss->freq = data.ch_switch.freq; -@@ -3010,6 +3012,7 @@ static void do_process_drv_event(struct +@@ -3113,6 +3115,7 @@ static void do_process_drv_event(struct tb[NL80211_ATTR_CHANNEL_WIDTH], tb[NL80211_ATTR_CENTER_FREQ1], tb[NL80211_ATTR_CENTER_FREQ2], @@ -383,7 +383,7 @@ 0); break; case NL80211_CMD_CH_SWITCH_NOTIFY: -@@ -3020,6 +3023,7 @@ static void do_process_drv_event(struct +@@ -3123,6 +3126,7 @@ static void do_process_drv_event(struct tb[NL80211_ATTR_CHANNEL_WIDTH], tb[NL80211_ATTR_CENTER_FREQ1], tb[NL80211_ATTR_CENTER_FREQ2], 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 92b52a6d3..1f78c42de 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 +@@ -3265,6 +3265,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 +@@ -3306,6 +3307,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 +@@ -973,6 +973,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 +@@ -2325,7 +2325,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 +@@ -11565,6 +11565,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 +@@ -11577,6 +11578,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 +@@ -12065,6 +12067,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 +@@ -12073,12 +12076,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,15 @@ 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,7 @@ #include "taxonomy.h" + #include "wnm_ap.h" +#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 +@@ -460,6 +461,7 @@ int hostapd_ctrl_iface_sta_next(struct h return hostapd_ctrl_iface_sta_mib(hapd, sta->next, buf, buflen); } @@ -109,7 +109,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 +@@ -832,12 +834,12 @@ int hostapd_ctrl_iface_status(struct hos return len; len += ret; } @@ -126,7 +126,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) +@@ -2740,6 +2740,7 @@ static const char * bool_txt(bool val) return val ? "TRUE" : "FALSE"; } @@ -134,7 +134,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 +@@ -2926,6 +2927,7 @@ int ieee802_1x_get_mib_sta(struct hostap return len; } @@ -144,7 +144,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 +@@ -4559,6 +4559,7 @@ static const char * wpa_bool_txt(int val return val ? "TRUE" : "FALSE"; } @@ -152,7 +152,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 +@@ -4709,7 +4710,7 @@ int wpa_get_mib_sta(struct wpa_state_mac return len; } @@ -163,7 +163,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 +@@ -2802,6 +2802,8 @@ static u32 wpa_key_mgmt_suite(struct wpa } @@ -172,7 +172,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 +@@ -2883,6 +2885,7 @@ int wpa_sm_get_mib(struct wpa_sm *sm, ch return (int) len; } @@ -182,7 +182,7 @@ --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c -@@ -1462,7 +1462,7 @@ int wpas_ap_wps_nfc_report_handover(stru +@@ -1477,7 +1477,7 @@ int wpas_ap_wps_nfc_report_handover(stru #endif /* CONFIG_WPS */ 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 65a8b07e6..bf481c3ba 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) +@@ -2529,6 +2529,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 +@@ -2536,8 +2561,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 f708bf39b..edcd98525 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/420-indicate-features.patch b/package/network/services/hostapd/patches/420-indicate-features.patch index f9dff6607..12edb6bac 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; +@@ -692,7 +692,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[]) +@@ -729,6 +729,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 dc1fa3d29..e52420953 100644 --- a/package/network/services/hostapd/patches/430-hostapd_cli_ifdef.patch +++ b/package/network/services/hostapd/patches/430-hostapd_cli_ifdef.patch @@ -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 +@@ -1588,13 +1584,10 @@ static const struct hostapd_cli_cmd host { "disassociate", hostapd_cli_cmd_disassociate, hostapd_complete_stations, " = disassociate a station" }, @@ -46,7 +46,7 @@ { "wps_pin", hostapd_cli_cmd_wps_pin, NULL, " [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 +@@ -1619,7 +1612,6 @@ static const struct hostapd_cli_cmd host " = configure AP" }, { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL, "= show current WPS status" }, 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 28f07c7dc..38ff66317 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 #include "common/defs.h" #include "common/ieee802_11_defs.h" #include "common/wpa_common.h" -@@ -857,6 +858,9 @@ struct wpa_driver_associate_params { +@@ -894,6 +895,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 #include "config.h" -@@ -2321,6 +2322,97 @@ static char * wpa_config_write_peerkey(c +@@ -2345,6 +2346,97 @@ static char * wpa_config_write_peerkey(c #endif /* NO_CONFIG_WRITE */ @@ -140,7 +140,7 @@ Signed-hostap: Antonio Quartulli /* Helper macros for network block parser */ #ifdef OFFSET -@@ -2606,6 +2698,8 @@ static const struct parse_data ssid_fiel +@@ -2629,6 +2721,8 @@ static const struct parse_data ssid_fiel { INT(ap_max_inactivity) }, { INT(dtim_period) }, { INT(beacon_int) }, @@ -174,7 +174,7 @@ Signed-hostap: Antonio Quartulli * 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 +@@ -3899,6 +3899,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 index 0be77f984..65d67b8b0 100644 --- 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 @@ -10,7 +10,7 @@ Signed-hostap: Antonio Quartulli --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c -@@ -5966,7 +5966,7 @@ static int wpa_driver_nl80211_ibss(struc +@@ -6005,7 +6005,7 @@ static int wpa_driver_nl80211_ibss(struc struct wpa_driver_associate_params *params) { struct nl_msg *msg; @@ -19,7 +19,7 @@ Signed-hostap: Antonio Quartulli int count = 0; wpa_printf(MSG_DEBUG, "nl80211: Join IBSS (ifindex=%d)", drv->ifindex); -@@ -5993,6 +5993,37 @@ retry: +@@ -6032,6 +6032,37 @@ retry: nl80211_put_beacon_int(msg, params->beacon_int)) 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 bd1d4d756..5dc19fede 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 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h -@@ -1624,6 +1624,7 @@ struct wpa_driver_mesh_join_params { +@@ -1661,6 +1661,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 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 +@@ -10627,6 +10627,18 @@ static int nl80211_put_mesh_id(struct nl } @@ -48,7 +48,7 @@ Tested-by: Simon Wunderlich 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 +@@ -10688,6 +10700,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 --- 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 4807727e0..48086ea0e 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,6 +1,6 @@ --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c -@@ -2512,11 +2512,13 @@ void ibss_mesh_setup_freq(struct wpa_sup +@@ -2539,11 +2539,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]; 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 000000000..6810b797c --- /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 +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 +--- + hostapd/config_file.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/hostapd/config_file.c ++++ b/hostapd/config_file.c +@@ -3489,6 +3489,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/500-lto-jobserver-support.patch b/package/network/services/hostapd/patches/500-lto-jobserver-support.patch index c51db01fe..1a0ce1256 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) +@@ -1394,7 +1394,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 +@@ -1405,7 +1405,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 +@@ -2025,31 +2025,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 ee3ab7938..98b8820cd 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 { +@@ -162,6 +162,21 @@ struct hostapd_sae_commit_queue { }; /** @@ -22,7 +22,7 @@ * struct hostapd_data - hostapd per-BSS data structure */ struct hostapd_data { -@@ -163,6 +178,9 @@ struct hostapd_data { +@@ -175,6 +190,9 @@ struct hostapd_data { u8 own_addr[ETH_ALEN]; @@ -42,7 +42,7 @@ 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 +@@ -659,10 +660,12 @@ int ieee802_11_rx_wnm_action_ap(struct h switch (action) { case WNM_BSS_TRANS_MGMT_QUERY: @@ -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 +@@ -709,6 +712,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 +@@ -790,6 +794,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 +@@ -870,6 +875,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 6a0acbb31..521e7df82 100644 --- a/package/network/services/hostapd/patches/600-ubus_support.patch +++ b/package/network/services/hostapd/patches/600-ubus_support.patch @@ -14,7 +14,7 @@ CFLAGS += -O0 -fprofile-arcs -ftest-coverage --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h -@@ -17,6 +17,7 @@ +@@ -18,6 +18,7 @@ #include "utils/list.h" #include "ap_config.h" #include "drivers/driver.h" @@ -22,7 +22,7 @@ #define OCE_STA_CFON_ENABLED(hapd) \ ((hapd->conf->oce & OCE_STA_CFON) && \ -@@ -80,7 +81,7 @@ struct hapd_interfaces { +@@ -92,7 +93,7 @@ struct hapd_interfaces { #ifdef CONFIG_CTRL_IFACE_UDP unsigned char ctrl_iface_cookie[CTRL_IFACE_COOKIE_LEN]; #endif /* CONFIG_CTRL_IFACE_UDP */ @@ -31,7 +31,7 @@ }; enum hostapd_chan_status { -@@ -171,6 +172,7 @@ struct hostapd_data { +@@ -183,6 +184,7 @@ struct hostapd_data { struct hostapd_iface *iface; struct hostapd_config *iconf; struct hostapd_bss_config *conf; @@ -39,7 +39,7 @@ 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 +@@ -673,6 +675,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); @@ -49,7 +49,7 @@ struct hostapd_iface * hostapd_alloc_iface(void); --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c -@@ -396,6 +396,7 @@ void hostapd_free_hapd_data(struct hosta +@@ -401,6 +401,7 @@ void hostapd_free_hapd_data(struct hosta hapd->beacon_set_done = 0; wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface); @@ -57,7 +57,7 @@ accounting_deinit(hapd); hostapd_deinit_wpa(hapd); vlan_deinit(hapd); -@@ -1422,6 +1423,8 @@ static int hostapd_setup_bss(struct host +@@ -1431,6 +1432,8 @@ static int hostapd_setup_bss(struct host if (hapd->driver && hapd->driver->set_operstate) hapd->driver->set_operstate(hapd->drv_priv, 1); @@ -66,7 +66,7 @@ return 0; } -@@ -2028,6 +2031,7 @@ static int hostapd_setup_interface_compl +@@ -2050,6 +2053,7 @@ static int hostapd_setup_interface_compl if (err) goto fail; @@ -74,7 +74,7 @@ wpa_printf(MSG_DEBUG, "Completing interface initialization"); if (iface->freq) { #ifdef NEED_AP_MLME -@@ -2225,6 +2229,7 @@ dfs_offload: +@@ -2248,6 +2252,7 @@ dfs_offload: fail: wpa_printf(MSG_ERROR, "Interface initialization failed"); @@ -82,7 +82,7 @@ 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 +@@ -2723,6 +2728,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; @@ -92,7 +92,7 @@ __func__, driver, drv_priv); --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c -@@ -3553,13 +3553,18 @@ static void handle_auth(struct hostapd_d +@@ -3573,13 +3573,18 @@ static void handle_auth(struct hostapd_d u16 auth_alg, auth_transaction, status_code; u16 resp = WLAN_STATUS_SUCCESS; struct sta_info *sta = NULL; @@ -112,7 +112,7 @@ 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 +@@ -3747,6 +3752,13 @@ static void handle_auth(struct hostapd_d resp = WLAN_STATUS_UNSPECIFIED_FAILURE; goto fail; } @@ -126,7 +126,7 @@ if (res == HOSTAPD_ACL_PENDING) return; -@@ -5447,7 +5459,7 @@ static void handle_assoc(struct hostapd_ +@@ -5488,7 +5500,7 @@ static void handle_assoc(struct hostapd_ int resp = WLAN_STATUS_SUCCESS; u16 reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE; const u8 *pos; @@ -135,7 +135,7 @@ struct sta_info *sta; u8 *tmp = NULL; #ifdef CONFIG_FILS -@@ -5660,6 +5672,11 @@ static void handle_assoc(struct hostapd_ +@@ -5701,6 +5713,11 @@ static void handle_assoc(struct hostapd_ left = res; } #endif /* CONFIG_FILS */ @@ -147,7 +147,7 @@ /* followed by SSID and Supported rates; and HT capabilities if 802.11n * is used */ -@@ -5758,6 +5775,13 @@ static void handle_assoc(struct hostapd_ +@@ -5799,6 +5816,13 @@ static void handle_assoc(struct hostapd_ } #endif /* CONFIG_FILS */ @@ -161,7 +161,7 @@ fail: /* -@@ -5851,6 +5875,7 @@ static void handle_disassoc(struct hosta +@@ -5892,6 +5916,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)); @@ -169,7 +169,7 @@ sta = ap_get_sta(hapd, mgmt->sa); if (sta == NULL) { -@@ -5920,6 +5945,8 @@ static void handle_deauth(struct hostapd +@@ -5961,6 +5986,8 @@ static void handle_deauth(struct hostapd /* Clear the PTKSA cache entries for PASN */ ptksa_cache_flush(hapd->ptksa, mgmt->sa, WPA_CIPHER_NONE); @@ -180,7 +180,7 @@ wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying " --- a/src/ap/beacon.c +++ b/src/ap/beacon.c -@@ -852,6 +852,12 @@ void handle_probe_req(struct hostapd_dat +@@ -919,6 +919,12 @@ void handle_probe_req(struct hostapd_dat u16 csa_offs[2]; size_t csa_offs_len; struct radius_sta rad_info; @@ -193,7 +193,7 @@ 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 +@@ -1105,6 +1111,12 @@ void handle_probe_req(struct hostapd_dat } #endif /* CONFIG_P2P */ @@ -234,7 +234,7 @@ wpabuf_free(sta->p2p_ie); --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c -@@ -458,6 +458,7 @@ void ap_handle_timer(void *eloop_ctx, vo +@@ -460,6 +460,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"); @@ -242,7 +242,7 @@ ap_free_sta(hapd, sta); return; } -@@ -613,6 +614,7 @@ skip_poll: +@@ -615,6 +616,7 @@ skip_poll: mlme_deauthenticate_indication( hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID); @@ -250,8 +250,62 @@ ap_free_sta(hapd, sta); break; } -@@ -1329,6 +1331,7 @@ void ap_sta_set_authorized(struct hostap - buf, ip_addr, keyid_buf); +@@ -1298,12 +1300,25 @@ 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 char *keyid; + char keyid_buf[100]; + char ip_addr[100]; ++ char alg_buf[100]; + + 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), +@@ -1313,22 +1328,31 @@ 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), + " keyid=%s", keyid); + } + +- wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s", +- buf, ip_addr, keyid_buf); ++ hostapd_ubus_notify_authorized(hapd, sta, auth_alg); ++ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s%s", ++ buf, ip_addr, keyid_buf, alg_buf); + + if (hapd->msg_ctx_parent && + hapd->msg_ctx_parent != hapd->msg_ctx) + wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, +- AP_STA_CONNECTED "%s%s%s", +- buf, ip_addr, keyid_buf); ++ AP_STA_CONNECTED "%s%s%s%s", ++ buf, ip_addr, keyid_buf, alg_buf); } else { wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); + hostapd_ubus_notify(hapd, "disassoc", sta->addr); @@ -260,7 +314,7 @@ hapd->msg_ctx_parent != hapd->msg_ctx) --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c -@@ -265,6 +265,7 @@ static void hostapd_wpa_auth_psk_failure +@@ -268,6 +268,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)); @@ -270,7 +324,7 @@ --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile -@@ -176,6 +176,12 @@ ifdef CONFIG_EAPOL_TEST +@@ -183,6 +183,12 @@ ifdef CONFIG_EAPOL_TEST CFLAGS += -Werror -DEAPOL_TEST endif @@ -283,7 +337,7 @@ ifdef CONFIG_CODE_COVERAGE CFLAGS += -O0 -fprofile-arcs -ftest-coverage LIBS += -lgcov -@@ -962,6 +968,9 @@ ifdef CONFIG_CTRL_IFACE_MIB +@@ -977,6 +983,9 @@ ifdef CONFIG_CTRL_IFACE_MIB CFLAGS += -DCONFIG_CTRL_IFACE_MIB endif OBJS += ../src/ap/ctrl_iface_ap.o @@ -295,7 +349,7 @@ CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c -@@ -7241,6 +7241,8 @@ struct wpa_supplicant * wpa_supplicant_a +@@ -7285,6 +7285,8 @@ struct wpa_supplicant * wpa_supplicant_a } #endif /* CONFIG_P2P */ @@ -304,7 +358,7 @@ return wpa_s; } -@@ -7267,6 +7269,8 @@ int wpa_supplicant_remove_iface(struct w +@@ -7311,6 +7313,8 @@ int wpa_supplicant_remove_iface(struct w struct wpa_supplicant *parent = wpa_s->parent; #endif /* CONFIG_MESH */ @@ -313,7 +367,7 @@ /* 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 +@@ -7614,8 +7618,12 @@ int wpa_supplicant_run(struct wpa_global eloop_register_signal_terminate(wpa_supplicant_terminate, global); eloop_register_signal_reconfig(wpa_supplicant_reconfig, global); @@ -328,7 +382,7 @@ --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h -@@ -19,6 +19,7 @@ +@@ -20,6 +20,7 @@ #include "wps/wps_defs.h" #include "config_ssid.h" #include "wmm_ac.h" @@ -336,7 +390,7 @@ extern const char *const wpa_supplicant_version; extern const char *const wpa_supplicant_license; -@@ -322,6 +323,8 @@ struct wpa_global { +@@ -323,6 +324,8 @@ struct wpa_global { #endif /* CONFIG_WIFI_DISPLAY */ struct psk_list_entry *add_psk; /* From group formation */ @@ -345,7 +399,7 @@ }; -@@ -708,6 +711,7 @@ struct wpa_supplicant { +@@ -707,6 +710,7 @@ struct wpa_supplicant { unsigned char own_addr[ETH_ALEN]; unsigned char perm_addr[ETH_ALEN]; char ifname[100]; @@ -363,7 +417,7 @@ #ifndef WPS_PIN_SCAN_IGNORE_SEL_REG -@@ -393,6 +394,8 @@ static int wpa_supplicant_wps_cred(void +@@ -391,6 +392,8 @@ static int wpa_supplicant_wps_cred(void wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", cred->cred_attr, cred->cred_attr_len); @@ -374,7 +428,7 @@ --- a/hostapd/main.c +++ b/hostapd/main.c -@@ -895,6 +895,7 @@ int main(int argc, char *argv[]) +@@ -897,6 +897,7 @@ int main(int argc, char *argv[]) } hostapd_global_ctrl_iface_init(&interfaces); @@ -382,7 +436,7 @@ 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[]) +@@ -906,6 +907,7 @@ int main(int argc, char *argv[]) ret = 0; out: @@ -392,7 +446,7 @@ for (i = 0; i < interfaces.count; i++) { --- a/wpa_supplicant/main.c +++ b/wpa_supplicant/main.c -@@ -203,7 +203,7 @@ int main(int argc, char *argv[]) +@@ -204,7 +204,7 @@ int main(int argc, char *argv[]) for (;;) { c = getopt(argc, argv, @@ -401,7 +455,7 @@ 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 */ @@ -423,6 +477,16 @@ } +@@ -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 @@ @@ -463,7 +527,7 @@ --- a/src/ap/dfs.c +++ b/src/ap/dfs.c -@@ -1196,6 +1196,8 @@ int hostapd_dfs_radar_detected(struct ho +@@ -1203,6 +1203,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); @@ -505,7 +569,7 @@ } --- a/src/ap/sta_info.h +++ b/src/ap/sta_info.h -@@ -324,6 +324,7 @@ struct sta_info { +@@ -328,6 +328,7 @@ struct sta_info { #endif /* CONFIG_TESTING_OPTIONS */ #ifdef CONFIG_AIRTIME_POLICY unsigned int airtime_weight; @@ -515,9 +579,9 @@ --- a/src/ap/wnm_ap.c +++ b/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); +@@ -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)) @@ -525,7 +589,7 @@ } -@@ -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; @@ -534,7 +598,7 @@ 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; } @@ -542,7 +606,7 @@ 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); } diff --git a/package/network/services/hostapd/patches/700-wifi-reload.patch b/package/network/services/hostapd/patches/700-wifi-reload.patch index e6d7c2f67..174127df6 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 +@@ -2416,6 +2416,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); @@ -9,7 +9,7 @@ } 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 +@@ -3121,6 +3123,8 @@ static int hostapd_config_fill(struct ho } } else if (os_strcmp(buf, "acs_exclude_dfs") == 0) { conf->acs_exclude_dfs = atoi(pos); @@ -20,7 +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 +@@ -796,6 +796,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); @@ -28,7 +28,7 @@ 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_ +@@ -995,6 +996,7 @@ void hostapd_config_free(struct hostapd_ for (i = 0; i < conf->num_bss; i++) hostapd_config_free_bss(conf->bss[i]); @@ -38,7 +38,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 { +@@ -285,6 +285,8 @@ struct hostapd_bss_config { char vlan_bridge[IFNAMSIZ + 1]; char wds_bridge[IFNAMSIZ + 1]; @@ -47,7 +47,7 @@ enum hostapd_logger_level logger_syslog_level, logger_stdout_level; unsigned int logger_syslog; /* module bitfield */ -@@ -942,6 +944,7 @@ struct spatial_reuse { +@@ -969,6 +971,7 @@ struct eht_phy_capabilities_info { struct hostapd_config { struct hostapd_bss_config **bss, *last_bss; size_t num_bss; @@ -57,7 +57,7 @@ int rts_threshold; --- a/src/ap/hostapd.c +++ b/src/ap/hostapd.c -@@ -219,6 +219,10 @@ static int hostapd_iface_conf_changed(st +@@ -224,6 +224,10 @@ static int hostapd_iface_conf_changed(st { size_t i; @@ -68,7 +68,7 @@ if (newconf->num_bss != oldconf->num_bss) return 1; -@@ -232,7 +236,7 @@ static int hostapd_iface_conf_changed(st +@@ -237,7 +241,7 @@ static int hostapd_iface_conf_changed(st } @@ -77,7 +77,7 @@ { struct hapd_interfaces *interfaces = iface->interfaces; struct hostapd_data *hapd = iface->bss[0]; -@@ -255,13 +259,16 @@ int hostapd_reload_config(struct hostapd +@@ -260,13 +264,16 @@ int hostapd_reload_config(struct hostapd if (newconf == NULL) return -1; @@ -96,7 +96,7 @@ 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 +@@ -291,6 +298,24 @@ int hostapd_reload_config(struct hostapd wpa_printf(MSG_ERROR, "Failed to enable interface on config reload"); return res; @@ -121,7 +121,7 @@ } iface->conf = newconf; -@@ -302,6 +327,12 @@ int hostapd_reload_config(struct hostapd +@@ -307,6 +332,12 @@ int hostapd_reload_config(struct hostapd for (j = 0; j < iface->num_bss; j++) { hapd = iface->bss[j]; @@ -134,7 +134,7 @@ hapd->iconf = newconf; hapd->conf = newconf->bss[j]; hostapd_reload_bss(hapd); -@@ -2397,6 +2428,10 @@ hostapd_alloc_bss_data(struct hostapd_if +@@ -2420,6 +2451,10 @@ hostapd_alloc_bss_data(struct hostapd_if hapd->iconf = conf; hapd->conf = bss; hapd->iface = hapd_iface; @@ -147,7 +147,7 @@ hapd->ctrl_sock = -1; --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h -@@ -46,7 +46,7 @@ struct mesh_conf; +@@ -47,7 +47,7 @@ struct mesh_conf; struct hostapd_iface; struct hapd_interfaces { @@ -156,7 +156,7 @@ 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 { +@@ -185,6 +185,7 @@ struct hostapd_data { struct hostapd_config *iconf; struct hostapd_bss_config *conf; struct hostapd_ubus_bss ubus; @@ -164,7 +164,7 @@ int interface_added; /* virtual interface added for this BSS */ unsigned int started:1; unsigned int disabled:1; -@@ -624,7 +625,7 @@ struct hostapd_iface { +@@ -667,7 +668,7 @@ struct hostapd_iface { int hostapd_for_each_interface(struct hapd_interfaces *interfaces, int (*cb)(struct hostapd_iface *iface, void *ctx), void *ctx); @@ -175,7 +175,7 @@ hostapd_alloc_bss_data(struct hostapd_iface *hapd_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 +@@ -4852,6 +4852,9 @@ static int wpa_driver_nl80211_set_ap(voi if (ret) { wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)", ret, strerror(-ret)); 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 856dc8ba8..b06ef8f68 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 +@@ -3346,6 +3346,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 a22580c35..169807c61 100644 --- a/package/network/services/hostapd/patches/711-wds_bridge_force.patch +++ b/package/network/services/hostapd/patches/711-wds_bridge_force.patch @@ -1,6 +1,6 @@ --- 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)); 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 106f9d740..ed76d22dd 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 +@@ -2841,6 +2841,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 +@@ -711,6 +711,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 +@@ -241,6 +241,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 +@@ -1135,7 +1135,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 { +@@ -1010,6 +1010,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 b5809222d..d9a4f15f0 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 +@@ -3000,6 +3000,8 @@ static int hostapd_config_fill(struct ho wpa_printf(MSG_INFO, "Line %d: Obsolete peerkey parameter ignored", line); #ifdef CONFIG_IEEE80211R_AP @@ -11,7 +11,7 @@ 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]; @@ -21,7 +21,7 @@ --- 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 +@@ -1595,8 +1595,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 2ed73750c..608f15a25 100644 --- a/package/network/services/hostapd/patches/740-snoop_iface.patch +++ b/package/network/services/hostapd/patches/740-snoop_iface.patch @@ -1,6 +1,6 @@ --- 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]; @@ -10,9 +10,9 @@ --- 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,7 +55,7 @@ "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 +@@ -2318,6 +2318,8 @@ static int hostapd_config_fill(struct ho os_strlcpy(bss->bridge, pos, sizeof(bss->bridge)); if (!bss->wds_bridge[0]) os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge)); 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 43a4ea73b..479d56155 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 +@@ -4046,10 +4046,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 +@@ -1424,6 +1424,7 @@ static int hostapd_setup_bss(struct host 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 +@@ -1431,7 +1432,6 @@ static int hostapd_setup_bss(struct host wpa_printf(MSG_ERROR, "Failed to initialize QoS Map"); return -1; } @@ -48,26 +48,42 @@ 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 */ +--- a/wpa_supplicant/events.c ++++ b/wpa_supplicant/events.c +@@ -2586,8 +2586,6 @@ void wnm_bss_keep_alive_deinit(struct wp + } + -#ifdef CONFIG_INTERWORKING - if (elems.ext_capab && elems.ext_capab_len > 4) { - if (elems.ext_capab[4] & 0x01) - sta->qos_map_enabled = 1; +- + static int wpas_qos_map_set(struct wpa_supplicant *wpa_s, const u8 *qos_map, + size_t len) + { +@@ -2620,8 +2618,6 @@ static void interworking_process_assoc_r } --#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) +-#endif /* CONFIG_INTERWORKING */ +- + + static void multi_ap_process_assoc_resp(struct wpa_supplicant *wpa_s, + const u8 *ies, size_t ies_len) +@@ -2954,10 +2950,8 @@ static int wpa_supplicant_event_associnf + wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); + #endif /* CONFIG_WNM */ +-#ifdef CONFIG_INTERWORKING + interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); +-#endif /* CONFIG_INTERWORKING */ + if (wpa_s->hw_capab == CAPAB_VHT && + get_ie(data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP)) +--- a/src/ap/ieee802_11_shared.c ++++ b/src/ap/ieee802_11_shared.c +@@ -1100,13 +1100,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 */ @@ -79,34 +95,3 @@ 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 - } - - --#ifdef CONFIG_INTERWORKING -- - 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 - } - } - --#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 - wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies, - data->assoc_info.resp_ies_len); - #endif /* CONFIG_WNM */ --#ifdef CONFIG_INTERWORKING - interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies, - data->assoc_info.resp_ies_len); --#endif /* CONFIG_INTERWORKING */ - if (wpa_s->hw_capab == CAPAB_VHT && - get_ie(data->assoc_info.resp_ies, - data->assoc_info.resp_ies_len, WLAN_EID_VHT_CAP)) 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 8af5a0a04..d90a27523 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 +@@ -864,7 +864,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-dynamic_own_ip.patch b/package/network/services/hostapd/patches/760-dynamic_own_ip.patch new file mode 100644 index 000000000..3d2b59e8c --- /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 +@@ -311,6 +311,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 +@@ -535,6 +535,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 +@@ -2681,6 +2681,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 000000000..7516b7349 --- /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 +@@ -1367,6 +1367,7 @@ static int hostapd_setup_bss(struct host + struct radius_das_conf das_conf; + 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/800-acs-don-t-select-indoor-channel-on-outdoor-operation.patch b/package/network/services/hostapd/patches/800-acs-don-t-select-indoor-channel-on-outdoor-operation.patch new file mode 100644 index 000000000..1d9e9564e --- /dev/null +++ b/package/network/services/hostapd/patches/800-acs-don-t-select-indoor-channel-on-outdoor-operation.patch @@ -0,0 +1,58 @@ +From 37528a5205cb0b9e2238b7d97fb2ff5457448f1c Mon Sep 17 00:00:00 2001 +From: David Bauer +Date: Thu, 8 Sep 2022 01:45:41 +0200 +Subject: [PATCH] acs: don't select indoor channel on outdoor operation + +Don't select channels designated for exclusive-indoor use when the +country3 element is set on outdoor operation. + +Signed-off-by: David Bauer +--- + src/ap/acs.c | 9 +++++++++ + src/ap/dfs.c | 3 +++ + 2 files changed, 12 insertions(+) + +--- a/src/ap/acs.c ++++ b/src/ap/acs.c +@@ -552,6 +552,9 @@ static void acs_survey_mode_interference + if (chan->max_tx_power < iface->conf->min_tx_power) + continue; + ++ if (chan->flag & HOSTAPD_CHAN_INDOOR_ONLY && iface->conf->country[2] == 0x4f) ++ continue; ++ + wpa_printf(MSG_DEBUG, "ACS: Survey analysis for channel %d (%d MHz)", + chan->chan, chan->freq); + +@@ -686,6 +689,9 @@ acs_find_ideal_chan_mode(struct hostapd_ + if (chan->max_tx_power < iface->conf->min_tx_power) + continue; + ++ if (chan->flag & HOSTAPD_CHAN_INDOOR_ONLY && iface->conf->country[2] == 0x4f) ++ continue; ++ + if (!chan_bw_allowed(chan, bw, 1, 1)) { + wpa_printf(MSG_DEBUG, + "ACS: Channel %d: BW %u is not supported", +@@ -1067,6 +1073,9 @@ static int * acs_request_scan_add_freqs( + if (chan->max_tx_power < iface->conf->min_tx_power) + continue; + ++ if (chan->flag & HOSTAPD_CHAN_INDOOR_ONLY && iface->conf->country[2] == 0x4f) ++ continue; ++ + *freq++ = chan->freq; + } + +--- a/src/ap/dfs.c ++++ b/src/ap/dfs.c +@@ -282,6 +282,9 @@ static int dfs_find_channel(struct hosta + if (chan->max_tx_power < iface->conf->min_tx_power) + continue; + ++ if (chan->flag & HOSTAPD_CHAN_INDOOR_ONLY && iface->conf->country[2] == 0x4f) ++ continue; ++ + if (ret_chan && idx == channel_idx) { + wpa_printf(MSG_DEBUG, "Selected channel %d (%d)", + chan->freq, chan->chan); diff --git a/package/network/services/hostapd/patches/800-hostapd-2.10-lar.patch b/package/network/services/hostapd/patches/800-hostapd-2.10-lar.patch deleted file mode 100644 index db8889911..000000000 --- a/package/network/services/hostapd/patches/800-hostapd-2.10-lar.patch +++ /dev/null @@ -1,87 +0,0 @@ -diff -ru a/src/ap/hw_features.c b/src/ap/hw_features.c ---- a/src/ap/hw_features.c 2022-01-16 15:51:29.000000000 -0500 -+++ b/src/ap/hw_features.c 2022-07-06 22:57:53.007315518 -0500 -@@ -24,6 +24,19 @@ - #include "beacon.h" - #include "hw_features.h" - -+#ifdef CONFIG_IWLWIFI -+static void ieee80211n_do_nothing(struct hostapd_iface *iface) -+{ -+ wpa_printf(MSG_DEBUG, -+ "Scan finished!"); -+} -+ -+static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface, -+ struct wpa_driver_scan_params *params); -+static void ieee80211n_scan_channels_5g(struct hostapd_iface *iface, -+ struct wpa_driver_scan_params *params); -+ -+#endif - - void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, - size_t num_hw_features) -@@ -82,6 +93,35 @@ - - if (hostapd_drv_none(hapd)) - return -1; -+#ifdef CONFIG_IWLWIFI -+ -+ -+ if (!iface->conf->noscan) { -+ // scan -+ struct wpa_driver_scan_params params; -+ int ret1; -+ -+ os_memset(¶ms, 0, sizeof(params)); -+ ieee80211n_scan_channels_5g(iface, ¶ms); -+ -+ ret1 = hostapd_driver_scan(iface->bss[0], ¶ms); -+ -+ if (ret1 == -EBUSY) { -+ wpa_printf(MSG_ERROR, -+ "Failed to request a scan of neighboring BSSes ret=%d (%s)!", -+ ret1, strerror(-ret1)); -+ } -+ -+ if (ret1 == 0) { -+ iface->scan_cb = ieee80211n_do_nothing; -+ wpa_printf(MSG_DEBUG, -+ "Sleeping..."); -+ for (int i=0; i<110; i++) { -+ usleep(100000); -+ } -+ } -+ } -+#endif - modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags, - &dfs_domain); - if (modes == NULL) { -@@ -518,8 +556,15 @@ - - /* Check that HT40 is used and PRI / SEC switch is allowed */ - if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch || -+#ifdef CONFIG_IWLWIFI -+ iface->conf->noscan) { -+ wpa_printf(MSG_DEBUG, "Not scanning due to noscan?"); -+ return 0; -+ } -+#else - iface->conf->noscan) - return 0; -+#endif - - hostapd_set_state(iface, HAPD_IFACE_HT_SCAN); - wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " -@@ -916,7 +954,11 @@ - if (!hostapd_is_usable_edmg(iface)) - return 0; - -+#ifdef CONFIG_IWLWIFI -+ if (!iface->conf->secondary_channel || iface->conf->noscan) -+#else - if (!iface->conf->secondary_channel) -+#endif - return 1; - - if (hostapd_is_usable_chan(iface, iface->freq + 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 000000000..e78a4ef5c --- /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 +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 +--- + 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 +@@ -12241,7 +12241,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; +@@ -12251,7 +12251,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/992-openssl-include-rsa.patch b/package/network/services/hostapd/patches/992-openssl-include-rsa.patch new file mode 100644 index 000000000..581ae9f67 --- /dev/null +++ b/package/network/services/hostapd/patches/992-openssl-include-rsa.patch @@ -0,0 +1,32 @@ +From f374d52079111a4340acb6df835f45ac6b5f3f60 Mon Sep 17 00:00:00 2001 +From: Andre Heider +Date: Wed, 22 Jun 2022 14:13:55 +0200 +Subject: OpenSSL: Include rsa.h for all OpenSSL versions + +This fixes the build with OpenSSL 1.1.1: +../src/crypto/crypto_openssl.c: In function 'crypto_rsa_oaep_sha256_decrypt': +../src/crypto/crypto_openssl.c:4404:49: error: 'RSA_PKCS1_OAEP_PADDING' undeclared (first use in this function) + +Signed-off-by: Andre Heider +--- + src/crypto/crypto_openssl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/src/crypto/crypto_openssl.c ++++ b/src/crypto/crypto_openssl.c +@@ -16,6 +16,7 @@ + #include + #include + #include ++#include + #include + #ifdef CONFIG_ECC + #include +@@ -25,7 +26,6 @@ + #include + #include + #include +-#include + #include + #include + #else /* OpenSSL version >= 3.0 */ diff --git a/package/network/services/hostapd/patches/v2-1-5-bss-coloring-add-support-for-handling-collision-events-and-triggering-CCA.patch b/package/network/services/hostapd/patches/v2-1-5-bss-coloring-add-support-for-handling-collision-events-and-triggering-CCA.patch deleted file mode 100644 index afbe0b6b7..000000000 --- a/package/network/services/hostapd/patches/v2-1-5-bss-coloring-add-support-for-handling-collision-events-and-triggering-CCA.patch +++ /dev/null @@ -1,419 +0,0 @@ -From patchwork Mon Nov 8 03:04:22 2021 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Ryder Lee -X-Patchwork-Id: 1552115 -Return-Path: - -X-Original-To: incoming@patchwork.ozlabs.org -Delivered-To: patchwork-incoming@bilbo.ozlabs.org -Authentication-Results: bilbo.ozlabs.org; - dkim=pass (2048-bit key; - secure) header.d=lists.infradead.org header.i=@lists.infradead.org - header.a=rsa-sha256 header.s=bombadil.20210309 header.b=TdjSI8dB; - dkim-atps=neutral -Authentication-Results: ozlabs.org; - spf=none (no SPF record) smtp.mailfrom=lists.infradead.org - (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; - envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; - receiver=) -Received: from bombadil.infradead.org (bombadil.infradead.org - [IPv6:2607:7c80:54:e::133]) - (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) - key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest - SHA256) - (No client certificate requested) - by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Hnbbl2GBWz9sR4 - for ; Mon, 8 Nov 2021 14:06:11 +1100 (AEDT) -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20210309; h=Sender: - Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:Message-ID:Date:Subject:CC - :To:From:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: - Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: - List-Owner; bh=jJbGlY/UjiOWDJu0LYiULCtBponRgB2rvIsYJaolOJc=; b=TdjSI8dBSKP247 - l5QD34cAO9uWzUWoVC+tdBlaW1aby3k85d/nEEMtTcHWs4iVB1XkTTDnizxiADCA8QmZs4avo49De - FuPTgYekOV5QrTcMCYXQbUs4MP+J0t9IRB8nzfg9ZPmjK8os5S8X6Ofa+5FZqr/NAqltHVaVTXDUs - HOrKINWu1ER8b2CnrBV1aEMyR8CZB3jXELW/zvAB3eyzeMUQ3F3i5cXlOVKjoyHarqJ7KyolLh/zk - FdnmnVeKttaTQGaJbW45XnCwowirMKa+rwvGf7aC0Vogxms+teN/9QNnUkE6q2VdgHGgbiciEzkSF - Ez5Fi4ll8M2oap6VJaRg==; -Received: from localhost ([::1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) - id 1mjuxn-00FLFN-D3; Mon, 08 Nov 2021 03:04:51 +0000 -Received: from mailgw01.mediatek.com ([216.200.240.184]) - by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) - id 1mjuxc-00FLDp-GA - for hostap@lists.infradead.org; Mon, 08 Nov 2021 03:04:42 +0000 -X-UUID: 2f3a392f63dc4f7596cff8bcd834ff56-20211107 -X-UUID: 2f3a392f63dc4f7596cff8bcd834ff56-20211107 -Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw01.mediatek.com - (envelope-from ) - (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) - with ESMTP id 238529206; Sun, 07 Nov 2021 20:04:34 -0700 -Received: from MTKMBS07N2.mediatek.inc (172.21.101.141) by - MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Sun, 7 Nov 2021 19:04:32 -0800 -Received: from mtkmbs10n1.mediatek.inc (172.21.101.34) by - mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Mon, 8 Nov 2021 11:04:31 +0800 -Received: from mtksdccf07.mediatek.inc (172.21.84.99) by - mtkmbs10n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id - 15.2.792.15 via Frontend Transport; Mon, 8 Nov 2021 11:04:31 +0800 -From: Ryder Lee -To: Jouni Malinen -CC: Felix Fietkau , Lorenzo Bianconi - , Shayne Chen , - "Evelyn Tsai" , , John - Crispin , Lorenzo Bianconi , Ryder Lee - -Subject: [PATCH v2 1/5] bss coloring: add support for handling collision - events and triggering CCA -Date: Mon, 8 Nov 2021 11:04:22 +0800 -Message-ID: - <2d69afce2fd6f44ae08ac75d5715fa9e43fe2a77.1636093546.git.ryder.lee@mediatek.com> -X-Mailer: git-send-email 2.18.0 -MIME-Version: 1.0 -X-MTK: N -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20211107_190440_578484_445A5D3D -X-CRM114-Status: GOOD ( 27.51 ) -X-Spam-Score: 0.0 (/) -X-Spam-Report: Spam detection software, - running on the system "bombadil.infradead.org", - has NOT identified this incoming email as spam. The original - message has been attached to this so you can view it or label - similar future email. If you have any questions, see - the administrator of that system for details. - Content preview: From: John Crispin Add the core code for - handling bss color collision events and triggering CCA inside the kernel. - The caller of hostapd_switch_color() will be added in the following commits. - Content analysis details: (0.0 points, 5.0 required) - pts rule name description - ---- ---------------------- - -------------------------------------------------- - -0.0 SPF_PASS SPF: sender matches SPF record - 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record - 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay - lines -X-BeenThere: hostap@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Sender: "Hostap" -Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org - -From: John Crispin - -Add the core code for handling bss color collision events and triggering -CCA inside the kernel. The caller of hostapd_switch_color() will be added -in the following commits. - -Tested-by: Peter Chiu -Co-developed-by: Lorenzo Bianconi -Signed-off-by: Lorenzo Bianconi -Signed-off-by: John Crispin -Signed-off-by: Ryder Lee ---- -changes since v2 - -- use os_get_reltime and os_reltime instead. -- use bool cca_in_progress. -- use random BSS color to avoid hardcoded BSS color value of 1. -- modify comment for DOT11BSS_COLOR_COLLISION_AP_PERIOD. -- add a note for collision behavior. -- fix compiler warnings. -- Be clear in the commit message regarding hostapd_switch_color(). ---- - src/ap/ap_drv_ops.h | 12 ++++ - src/ap/hostapd.c | 134 ++++++++++++++++++++++++++++++++++- - src/ap/hostapd.h | 16 +++++ - src/common/ieee802_11_defs.h | 6 ++ - src/drivers/driver.h | 31 ++++++++ - 5 files changed, 198 insertions(+), 1 deletion(-) - ---- a/src/ap/ap_drv_ops.h -+++ b/src/ap/ap_drv_ops.h -@@ -299,6 +299,18 @@ static inline int hostapd_drv_switch_cha - return hapd->driver->switch_channel(hapd->drv_priv, settings); - } - -+#ifdef CONFIG_IEEE80211AX -+static inline int hostapd_drv_switch_color(struct hostapd_data *hapd, -+ struct cca_settings *settings) -+{ -+ if (hapd->driver == NULL || hapd->driver->switch_color == NULL || -+ hapd->drv_priv == NULL) -+ return -1; -+ -+ return hapd->driver->switch_color(hapd->drv_priv, settings); -+} -+#endif -+ - static inline int hostapd_drv_status(struct hostapd_data *hapd, char *buf, - size_t buflen) - { ---- a/src/ap/hostapd.c -+++ b/src/ap/hostapd.c -@@ -66,7 +66,10 @@ static int setup_interface2(struct hosta - static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx); - static void hostapd_interface_setup_failure_handler(void *eloop_ctx, - void *timeout_ctx); -- -+#ifdef CONFIG_IEEE80211AX -+static void -+hostapd_switch_color_timeout_handler(void *eloop_data, void *user_ctx); -+#endif - - int hostapd_for_each_interface(struct hapd_interfaces *interfaces, - int (*cb)(struct hostapd_iface *iface, -@@ -537,6 +540,9 @@ void hostapd_free_hapd_data(struct hosta - } - eloop_cancel_timeout(auth_sae_process_commit, hapd, NULL); - #endif /* CONFIG_SAE */ -+#ifdef CONFIG_IEEE80211AX -+ eloop_cancel_timeout(hostapd_switch_color_timeout_handler, hapd, NULL); -+#endif - } - - -@@ -3790,6 +3796,132 @@ hostapd_switch_channel_fallback(struct h - hostapd_enable_iface(iface); - } - -+ -+#ifdef CONFIG_IEEE80211AX -+void hostapd_cleanup_cca_params(struct hostapd_data *hapd) -+{ -+ hapd->cca_count = 0; -+ hapd->cca_color = 0; -+ hapd->cca_c_off_beacon = 0; -+ hapd->cca_c_off_proberesp = 0; -+ hapd->cca_in_progress = false; -+} -+ -+ -+static int hostapd_fill_cca_settings(struct hostapd_data *hapd, -+ struct cca_settings *settings) -+{ -+ struct hostapd_iface *iface = hapd->iface; -+ u8 old_color; -+ int ret; -+ -+ if (!iface || iface->conf->he_op.he_bss_color_disabled) -+ return -1; -+ -+ old_color = iface->conf->he_op.he_bss_color; -+ iface->conf->he_op.he_bss_color = hapd->cca_color; -+ ret = hostapd_build_beacon_data(hapd, &settings->beacon_after); -+ iface->conf->he_op.he_bss_color = old_color; -+ -+ settings->cca_count = hapd->cca_count; -+ settings->cca_color = hapd->cca_color, -+ hapd->cca_in_progress = true; -+ -+ ret = hostapd_build_beacon_data(hapd, &settings->beacon_cca); -+ if (ret) { -+ free_beacon_data(&settings->beacon_after); -+ return ret; -+ } -+ -+ settings->counter_offset_beacon = hapd->cca_c_off_beacon; -+ settings->counter_offset_presp = hapd->cca_c_off_proberesp; -+ -+ return 0; -+} -+ -+ -+static void -+hostapd_switch_color_timeout_handler(void *eloop_data, void *user_ctx) -+{ -+ struct hostapd_data *hapd = (struct hostapd_data *) eloop_data; -+ struct cca_settings settings; -+ struct os_reltime now; -+ unsigned int b; -+ int i, r, ret; -+ -+ if (os_get_reltime(&now)) -+ return; -+ -+ /* 10s window is the approximate margin of collision persistent -+ * as an initial implementation. CCA can only be triggered once -+ * handler constantly receives collision events to update the -+ * last_color_collision.sec. How does it work - -+ * -+ * 1. BSS color collision persistent for at least 50 seconds. -+ * 2. The BSS Color Disabled subfield is set to 1. -+ * 3. CCA. -+ * -+ * TODO: implement other 'persistent' computation methods. -+ */ -+ if (now.sec - hapd->last_color_collision.sec >= 10) -+ return; -+ -+ r = os_random() % HE_OPERATION_BSS_COLOR_MAX; -+ for (i = 0; i < HE_OPERATION_BSS_COLOR_MAX; i++) { -+ if (r && (hapd->color_collision_bitmap & (1 << r)) == 0) -+ break; -+ r = (r + 1) % HE_OPERATION_BSS_COLOR_MAX; -+ } -+ -+ if (i == HE_OPERATION_BSS_COLOR_MAX) { -+ /* there are no free colors so turn bss coloring off */ -+ wpa_printf(MSG_INFO, "no free colors left, turning of BSS coloring"); -+ hapd->iface->conf->he_op.he_bss_color_disabled = 1; -+ hapd->iface->conf->he_op.he_bss_color = os_random() % 63 + 1; -+ for (b = 0; b < hapd->iface->num_bss; b++) -+ ieee802_11_set_beacon(hapd->iface->bss[b]); -+ return; -+ } -+ -+ for (b = 0; b < hapd->iface->num_bss; b++) { -+ struct hostapd_data *bss = hapd->iface->bss[b]; -+ -+ hostapd_cleanup_cca_params(bss); -+ bss->cca_color = r; -+ bss->cca_count = 10; -+ -+ if (hostapd_fill_cca_settings(bss, &settings)) { -+ hostapd_cleanup_cca_params(bss); -+ continue; -+ } -+ -+ ret = hostapd_drv_switch_color(bss, &settings); -+ free_beacon_data(&settings.beacon_cca); -+ free_beacon_data(&settings.beacon_after); -+ -+ if (ret) -+ hostapd_cleanup_cca_params(bss); -+ } -+} -+ -+ -+void -+hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap) -+{ -+ if (hapd->cca_in_progress) -+ return; -+ -+ if (os_get_reltime(&hapd->last_color_collision)) -+ return; -+ -+ hapd->color_collision_bitmap = bitmap; -+ -+ if (!eloop_is_timeout_registered(hostapd_switch_color_timeout_handler, hapd, NULL)) -+ eloop_register_timeout(DOT11BSS_COLOR_COLLISION_AP_PERIOD, 0, -+ hostapd_switch_color_timeout_handler, hapd, NULL); -+} -+#endif -+ - #endif /* NEED_AP_MLME */ - - ---- a/src/ap/hostapd.h -+++ b/src/ap/hostapd.h -@@ -315,6 +315,16 @@ struct hostapd_data { - unsigned int cs_c_off_ecsa_beacon; - unsigned int cs_c_off_ecsa_proberesp; - -+#ifdef CONFIG_IEEE80211AX -+ bool cca_in_progress; -+ u8 cca_count; -+ u8 cca_color; -+ unsigned int cca_c_off_beacon; -+ unsigned int cca_c_off_proberesp; -+ struct os_reltime last_color_collision; -+ u64 color_collision_bitmap; -+#endif -+ - #ifdef CONFIG_P2P - struct p2p_data *p2p; - struct p2p_group *p2p_group; -@@ -670,6 +680,12 @@ int hostapd_owe_trans_get_info(struct ho - void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx); - int hostapd_check_max_sta(struct hostapd_data *hapd); - -+ -+#ifdef CONFIG_IEEE80211AX -+void hostapd_switch_color(struct hostapd_data *hapd, u64 bitmap); -+void hostapd_cleanup_cca_params(struct hostapd_data *hapd); -+#endif -+ - /* utils.c */ - int hostapd_register_probereq_cb(struct hostapd_data *hapd, - int (*cb)(void *ctx, const u8 *sa, ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -2305,6 +2305,7 @@ struct ieee80211_spatial_reuse { - #define HE_OPERATION_BSS_COLOR_PARTIAL ((u32) BIT(30)) - #define HE_OPERATION_BSS_COLOR_DISABLED ((u32) BIT(31)) - #define HE_OPERATION_BSS_COLOR_OFFSET 24 -+#define HE_OPERATION_BSS_COLOR_MAX 64 - - /* Spatial Reuse defines */ - #define SPATIAL_REUSE_SRP_DISALLOWED BIT(0) -@@ -2470,6 +2471,11 @@ enum mscs_description_subelem { - */ - #define FD_MAX_INTERVAL_6GHZ 20 /* TUs */ - -+/* IEEE802.11/D6.0 - 26.17.3.5.1, AP needs to wait and see the collision -+ * persists for at least the minimum default timeout -+ */ -+#define DOT11BSS_COLOR_COLLISION_AP_PERIOD 50 -+ - /* Protected Vendor-specific QoS Management Action frame identifiers - WFA */ - #define QM_ACTION_VENDOR_TYPE 0x506f9a1a - #define QM_ACTION_OUI_TYPE 0x1a ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -2402,6 +2402,26 @@ struct csa_settings { - u16 counter_offset_presp[2]; - }; - -+/** -+ * struct cca_settings - Settings for color switch command -+ * @cca_count: Count in Beacon frames (TBTT) to perform the switch -+ * @cca_color: The new color that we are switching to -+ * @beacon_cca: Beacon/probe resp/asooc resp info for color switch period -+ * @beacon_after: Next beacon/probe resp/asooc resp info -+ * @counter_offset_beacon: Offset to the count field in beacon's tail -+ * @counter_offset_presp: Offset to the count field in probe resp. -+ */ -+struct cca_settings { -+ u8 cca_count; -+ u8 cca_color; -+ -+ struct beacon_data beacon_cca; -+ struct beacon_data beacon_after; -+ -+ u16 counter_offset_beacon; -+ u16 counter_offset_presp; -+}; -+ - /* TDLS peer capabilities for send_tdls_mgmt() */ - enum tdls_peer_capability { - TDLS_PEER_HT = BIT(0), -@@ -3985,6 +4005,17 @@ struct wpa_driver_ops { - int (*switch_channel)(void *priv, struct csa_settings *settings); - - /** -+ * switch_color - Announce color switch and migrate the BSS to the -+ * given color -+ * @priv: Private driver interface data -+ * @settings: Settings for CCA period and new color -+ * Returns: 0 on success, -1 on failure -+ * -+ * This function is used to move the BSS to its new color. -+ */ -+ int (*switch_color)(void *priv, struct cca_settings *settings); -+ -+ /** - * add_tx_ts - Add traffic stream - * @priv: Private driver interface data - * @tsid: Traffic stream ID diff --git a/package/network/services/hostapd/patches/v2-2-5-bss_coloring-add-the-code-required-to-generate-the-CCA-IE.patch b/package/network/services/hostapd/patches/v2-2-5-bss_coloring-add-the-code-required-to-generate-the-CCA-IE.patch deleted file mode 100644 index 1d5214c9c..000000000 --- a/package/network/services/hostapd/patches/v2-2-5-bss_coloring-add-the-code-required-to-generate-the-CCA-IE.patch +++ /dev/null @@ -1,222 +0,0 @@ -From patchwork Mon Nov 8 03:04:23 2021 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Ryder Lee -X-Patchwork-Id: 1552114 -Return-Path: - -X-Original-To: incoming@patchwork.ozlabs.org -Delivered-To: patchwork-incoming@bilbo.ozlabs.org -Authentication-Results: bilbo.ozlabs.org; - dkim=pass (2048-bit key; - secure) header.d=lists.infradead.org header.i=@lists.infradead.org - header.a=rsa-sha256 header.s=bombadil.20210309 header.b=FNYbWSBm; - dkim-atps=neutral -Authentication-Results: ozlabs.org; - spf=none (no SPF record) smtp.mailfrom=lists.infradead.org - (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; - envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; - receiver=) -Received: from bombadil.infradead.org (bombadil.infradead.org - [IPv6:2607:7c80:54:e::133]) - (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) - key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest - SHA256) - (No client certificate requested) - by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Hnbbf3YQVz9sR4 - for ; Mon, 8 Nov 2021 14:06:06 +1100 (AEDT) -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20210309; h=Sender: - Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: - Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: - Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: - List-Owner; bh=zQnS3Zfye3rrdWsY67X+kqgEkt7sw7eyXA+j3iDImIs=; b=FNYbWSBmAKVGTL - G/vix+Ug5vQJ1C4MkodN488cA5n54x7wwD6nEXcYUir7i/Jo9DDP7toOFkmNye+/fWwsF3mopTfmD - mKcm57p5fg0Pl4v6C3K16WtgravMpwrr979HtbIHjMcaIX8UpdKF0atOg1CMcT3yfog+8MModkZyk - Duas/c2biGmKCPws+APX6cMLI4F/c0f8eMrTGmzFXBMpyTitjmG+q6SMsjvsq+7lxZpos+XFTO1QX - IVcBjVF+9tUuk3c0x8MA5r8kJfg0XhP/F7lufL8cWiwitTf1FRxLmblj6tp2PZH9aQpvxxTtzy3I+ - GEBz8oRaZzYLQvevdyiQ==; -Received: from localhost ([::1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) - id 1mjuxf-00FLEj-VJ; Mon, 08 Nov 2021 03:04:44 +0000 -Received: from mailgw01.mediatek.com ([216.200.240.184]) - by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) - id 1mjuxb-00FLDo-7a - for hostap@lists.infradead.org; Mon, 08 Nov 2021 03:04:41 +0000 -X-UUID: d5fc02cf516e4810a7ad38409f469145-20211107 -X-UUID: d5fc02cf516e4810a7ad38409f469145-20211107 -Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw01.mediatek.com - (envelope-from ) - (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) - with ESMTP id 1005168563; Sun, 07 Nov 2021 20:04:34 -0700 -Received: from MTKMBS07N2.mediatek.inc (172.21.101.141) by - MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Sun, 7 Nov 2021 19:04:33 -0800 -Received: from mtkmbs10n1.mediatek.inc (172.21.101.34) by - mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Mon, 8 Nov 2021 11:04:31 +0800 -Received: from mtksdccf07.mediatek.inc (172.21.84.99) by - mtkmbs10n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id - 15.2.792.15 via Frontend Transport; Mon, 8 Nov 2021 11:04:31 +0800 -From: Ryder Lee -To: Jouni Malinen -CC: Felix Fietkau , Lorenzo Bianconi - , Shayne Chen , - "Evelyn Tsai" , , John - Crispin , Lorenzo Bianconi , Ryder Lee - -Subject: [PATCH v2 2/5] bss_coloring: add the code required to generate the - CCA IE -Date: Mon, 8 Nov 2021 11:04:23 +0800 -Message-ID: - -X-Mailer: git-send-email 2.18.0 -In-Reply-To: - <2d69afce2fd6f44ae08ac75d5715fa9e43fe2a77.1636093546.git.ryder.lee@mediatek.com> -References: - <2d69afce2fd6f44ae08ac75d5715fa9e43fe2a77.1636093546.git.ryder.lee@mediatek.com> -MIME-Version: 1.0 -X-MTK: N -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20211107_190439_311523_23A01681 -X-CRM114-Status: GOOD ( 13.18 ) -X-Spam-Score: 0.0 (/) -X-Spam-Report: Spam detection software, - running on the system "bombadil.infradead.org", - has NOT identified this incoming email as spam. The original - message has been attached to this so you can view it or label - similar future email. If you have any questions, see - the administrator of that system for details. - Content preview: From: John Crispin This IE is similar to - the CSA one. It contains a counter and the target color. Once the counter - expired, - the change to the new color happens. Just note the current implementation - is based on CCA counter attributes that only takes beacon and prob_resp into - account, as for the assoc_resp frames will be added in the future patches. - Content analysis details: (0.0 points, 5.0 required) - pts rule name description - ---- ---------------------- - -------------------------------------------------- - -0.0 SPF_PASS SPF: sender matches SPF record - 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record - 0.0 UNPARSEABLE_RELAY Informational: message has unparseable relay - lines -X-BeenThere: hostap@lists.infradead.org -X-Mailman-Version: 2.1.34 -Precedence: list -List-Id: -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Sender: "Hostap" -Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org - -From: John Crispin - -This IE is similar to the CSA one. It contains a counter and the target -color. Once the counter expired, the change to the new color happens. - -Just note the current implementation is based on CCA counter attributes -that only takes beacon and prob_resp into account, as for the assoc_resp -frames will be added in the future patches. - -Tested-by: Peter Chiu -Co-developed-by: Lorenzo Bianconi -Signed-off-by: Lorenzo Bianconi -Signed-off-by: John Crispin -Signed-off-by: Ryder Lee ---- -changes since v2 - -- fix the position of CCA IE. ---- - src/ap/beacon.c | 18 ++++++++++++++++++ - src/ap/ieee802_11.h | 1 + - src/ap/ieee802_11_he.c | 14 ++++++++++++++ - src/common/ieee802_11_defs.h | 1 + - 4 files changed, 34 insertions(+) - ---- a/src/ap/beacon.c -+++ b/src/ap/beacon.c -@@ -578,8 +578,17 @@ static u8 * hostapd_gen_probe_resp(struc - - #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { -+ u8 *cca_pos; -+ - pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP); - pos = hostapd_eid_he_operation(hapd, pos); -+ -+ /* CCA IE */ -+ cca_pos = hostapd_eid_cca(hapd, pos); -+ if (cca_pos != pos) -+ hapd->cca_c_off_proberesp = cca_pos - (u8 *) resp - 2; -+ pos = cca_pos; -+ - pos = hostapd_eid_spatial_reuse(hapd, pos); - pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos); - pos = hostapd_eid_he_6ghz_band_cap(hapd, pos); -@@ -1612,9 +1621,18 @@ int ieee802_11_build_ap_params(struct ho - - #ifdef CONFIG_IEEE80211AX - if (hapd->iconf->ieee80211ax && !hapd->conf->disable_11ax) { -+ u8 *cca_pos; -+ - tailpos = hostapd_eid_he_capab(hapd, tailpos, - IEEE80211_MODE_AP); - tailpos = hostapd_eid_he_operation(hapd, tailpos); -+ -+ /* CCA IE */ -+ cca_pos = hostapd_eid_cca(hapd, tailpos); -+ if (cca_pos != tailpos) -+ hapd->cca_c_off_beacon = cca_pos - tail - 2; -+ tailpos = cca_pos; -+ - tailpos = hostapd_eid_spatial_reuse(hapd, tailpos); - tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos); - tailpos = hostapd_eid_he_6ghz_band_cap(hapd, tailpos); ---- a/src/ap/ieee802_11.h -+++ b/src/ap/ieee802_11.h -@@ -100,6 +100,7 @@ u16 copy_sta_he_6ghz_capab(struct hostap - const u8 *he_6ghz_capab); - int hostapd_get_he_twt_responder(struct hostapd_data *hapd, - enum ieee80211_op_mode mode); -+u8 * hostapd_eid_cca(struct hostapd_data *hapd, u8 *eid); - void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, - const u8 *buf, size_t len, int ack); - void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst, ---- a/src/ap/ieee802_11_he.c -+++ b/src/ap/ieee802_11_he.c -@@ -520,3 +520,17 @@ int hostapd_get_he_twt_responder(struct - return !!(mac_cap[HE_MAC_CAPAB_0] & HE_MACCAP_TWT_RESPONDER) && - hapd->iface->conf->he_op.he_twt_responder; - } -+ -+u8 * hostapd_eid_cca(struct hostapd_data *hapd, u8 *eid) -+{ -+ if (!hapd->cca_in_progress) -+ return eid; -+ -+ *eid++ = WLAN_EID_EXTENSION; -+ *eid++ = 3; -+ *eid++ = WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT; -+ *eid++ = hapd->cca_count; -+ *eid++ = hapd->cca_color; -+ -+ return eid; -+} ---- a/src/common/ieee802_11_defs.h -+++ b/src/common/ieee802_11_defs.h -@@ -479,6 +479,7 @@ - #define WLAN_EID_EXT_HE_OPERATION 36 - #define WLAN_EID_EXT_HE_MU_EDCA_PARAMS 38 - #define WLAN_EID_EXT_SPATIAL_REUSE 39 -+#define WLAN_EID_EXT_COLOR_CHANGE_ANNOUNCEMENT 42 - #define WLAN_EID_EXT_OCV_OCI 54 - #define WLAN_EID_EXT_SHORT_SSID_LIST 58 - #define WLAN_EID_EXT_HE_6GHZ_BAND_CAP 59 diff --git a/package/network/services/hostapd/patches/v2-3-5-bss-coloring-disable-BSS-color-during-CCA.patch b/package/network/services/hostapd/patches/v2-3-5-bss-coloring-disable-BSS-color-during-CCA.patch deleted file mode 100644 index 9c72eb7d4..000000000 --- a/package/network/services/hostapd/patches/v2-3-5-bss-coloring-disable-BSS-color-during-CCA.patch +++ /dev/null @@ -1,144 +0,0 @@ -From patchwork Mon Nov 8 03:04:24 2021 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Ryder Lee -X-Patchwork-Id: 1552124 -Return-Path: - -X-Original-To: incoming@patchwork.ozlabs.org -Delivered-To: patchwork-incoming@bilbo.ozlabs.org -Authentication-Results: bilbo.ozlabs.org; - dkim=pass (2048-bit key; - secure) header.d=lists.infradead.org header.i=@lists.infradead.org - header.a=rsa-sha256 header.s=bombadil.20210309 header.b=zkbh7Ryq; - dkim-atps=neutral -Authentication-Results: ozlabs.org; - spf=none (no SPF record) smtp.mailfrom=lists.infradead.org - (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; - envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; - receiver=) -Received: from bombadil.infradead.org (bombadil.infradead.org - [IPv6:2607:7c80:54:e::133]) - (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) - key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest - SHA256) - (No client certificate requested) - by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Hnbq56ZSDz9sRK - for ; Mon, 8 Nov 2021 14:16:01 +1100 (AEDT) -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20210309; h=Sender: - Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: - Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: - Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: - List-Owner; bh=ZbtBLdHqwnNjHBoOMRI6QOzOvTzZ+TO1Kw2XqvWwciA=; b=zkbh7RyqMn3A0m - KrUfa6c2piAsXpi54eURNi1+HMN1X6VOkOST8pXCmNxzhQ+ywBLnhl1eDmq8rNnrZg43TSncySEBf - dbkHP2/41t02SSF4nsJlaOhLjUg5rXfsxiCxSG9QJoxETJPeb+3WaLhpVUd32cjw8tWHNp8FnN5Aa - V5UPt2BHi7yPjb3JQCqKXNgIhXIJyCzk02tN8R9RDGKgYnqVHdWMrCVDWyEDIeg0cBfGr3GKgZtty - NAMF25PGe24HOzn3vL/P2Cvhbr9fQQ7u4o9u8XISJt6VKXolXfYuY3RM4EFhNdPIGS2K6GBFRhzus - DkgEqnKizFTxUots4cKQ==; -Received: from localhost ([::1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) - id 1mjv7R-00FM0A-2A; Mon, 08 Nov 2021 03:14:49 +0000 -Received: from mailgw02.mediatek.com ([216.200.240.185]) - by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) - id 1mjv7O-00FLzJ-CZ - for hostap@lists.infradead.org; Mon, 08 Nov 2021 03:14:47 +0000 -X-UUID: 5aa40d43241f42da8848d056b8fa9b18-20211107 -X-UUID: 5aa40d43241f42da8848d056b8fa9b18-20211107 -Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by - mailgw02.mediatek.com - (envelope-from ) - (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) - with ESMTP id 361743472; Sun, 07 Nov 2021 20:14:42 -0700 -Received: from mtkexhb02.mediatek.inc (172.21.101.103) by - MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Sun, 7 Nov 2021 19:04:40 -0800 -Received: from mtkmbs10n1.mediatek.inc (172.21.101.34) by - mtkexhb02.mediatek.inc (172.21.101.103) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Mon, 8 Nov 2021 11:04:32 +0800 -Received: from mtksdccf07.mediatek.inc (172.21.84.99) by - mtkmbs10n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id - 15.2.792.15 via Frontend Transport; Mon, 8 Nov 2021 11:04:32 +0800 -From: Ryder Lee -To: Jouni Malinen -CC: Felix Fietkau , Lorenzo Bianconi - , Shayne Chen , - "Evelyn Tsai" , , John - Crispin , Lorenzo Bianconi , Ryder Lee - -Subject: [PATCH v2 3/5] bss coloring: disable BSS color during CCA -Date: Mon, 8 Nov 2021 11:04:24 +0800 -Message-ID: - <9ac28de67dc46471179ef84d516727a153dc89c0.1636093546.git.ryder.lee@mediatek.com> -X-Mailer: git-send-email 2.18.0 -In-Reply-To: - <2d69afce2fd6f44ae08ac75d5715fa9e43fe2a77.1636093546.git.ryder.lee@mediatek.com> -References: - <2d69afce2fd6f44ae08ac75d5715fa9e43fe2a77.1636093546.git.ryder.lee@mediatek.com> -MIME-Version: 1.0 -X-MTK: N -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20211107_191446_479100_E5E06374 -X-CRM114-Status: GOOD ( 10.72 ) -X-Spam-Score: 0.0 (/) -X-Spam-Report: Spam detection software, - running on the system "bombadil.infradead.org", - has NOT identified this incoming email as spam. The original - message has been attached to this so you can view it or label - similar future email. If you have any questions, see - the administrator of that system for details. - Content preview: From: John Crispin While we are doing CCA - the bss color disable bit inside the he oper field needs to be set. - Tested-by: - Peter Chiu Co-developed-by: Lorenzo Bianconi - Signed-off-by: Lorenzo Bianconi - Signed-off-by: John Crispin -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Sender: "Hostap" -Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org - -From: John Crispin - -While we are doing CCA the bss color disable bit inside the he oper field -needs to be set. - -Tested-by: Peter Chiu -Co-developed-by: Lorenzo Bianconi -Signed-off-by: Lorenzo Bianconi -Signed-off-by: John Crispin -Signed-off-by: Ryder Lee ---- - src/ap/ieee802_11_he.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/src/ap/ieee802_11_he.c -+++ b/src/ap/ieee802_11_he.c -@@ -195,7 +195,7 @@ u8 * hostapd_eid_he_operation(struct hos - if (hapd->iface->conf->he_op.he_er_su_disable) - params |= HE_OPERATION_ER_SU_DISABLE; - -- if (hapd->iface->conf->he_op.he_bss_color_disabled) -+ if (hapd->iface->conf->he_op.he_bss_color_disabled || hapd->cca_in_progress) - params |= HE_OPERATION_BSS_COLOR_DISABLED; - if (hapd->iface->conf->he_op.he_bss_color_partial) - params |= HE_OPERATION_BSS_COLOR_PARTIAL; diff --git a/package/network/services/hostapd/patches/v2-4-5-bss-coloring-add-the-switch_color-handler-to-the-nl80211-driver.patch b/package/network/services/hostapd/patches/v2-4-5-bss-coloring-add-the-switch_color-handler-to-the-nl80211-driver.patch deleted file mode 100644 index 221c437e2..000000000 --- a/package/network/services/hostapd/patches/v2-4-5-bss-coloring-add-the-switch_color-handler-to-the-nl80211-driver.patch +++ /dev/null @@ -1,229 +0,0 @@ -From patchwork Mon Nov 8 03:04:25 2021 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Ryder Lee -X-Patchwork-Id: 1552126 -Return-Path: - -X-Original-To: incoming@patchwork.ozlabs.org -Delivered-To: patchwork-incoming@bilbo.ozlabs.org -Authentication-Results: bilbo.ozlabs.org; - dkim=pass (2048-bit key; - secure) header.d=lists.infradead.org header.i=@lists.infradead.org - header.a=rsa-sha256 header.s=bombadil.20210309 header.b=f3dR9QlK; - dkim-atps=neutral -Authentication-Results: ozlabs.org; - spf=none (no SPF record) smtp.mailfrom=lists.infradead.org - (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; - envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; - receiver=) -Received: from bombadil.infradead.org (bombadil.infradead.org - [IPv6:2607:7c80:54:e::133]) - (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) - key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest - SHA256) - (No client certificate requested) - by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Hnbq80ldSz9sR4 - for ; Mon, 8 Nov 2021 14:16:04 +1100 (AEDT) -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20210309; h=Sender: - Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: - Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: - Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: - List-Owner; bh=pw/A1cFLx8vLCo09Sq0Z+nCWXPyM//TvHXXD1rCuOU8=; b=f3dR9QlKtxY6ba - AcO4VQpOa4TvVe0xvGqZSGNWrfx8hxo03JWio6vRj/Ni9kAIhIrrd6ycBrFEKER2Iw+8QMokIJ7+y - PajahCVWGUhkw0NDVp4qDPNNTVpsuWpFT/ZeC8T1Ow8eMdNuDxc/WBI3pT9uhxmS32IIOn1031Ksb - aTct90u5uaSupi39B/17JtQ/Mt4K1XBx7/2hRzweT5iOf+1/qdie3AhS0U8EAZAu61mVMvYoXBmZN - OwfJkSqPBTmVvVmr+0KWb3/1iIC09BG985varDaFqtTX7MPpjoF6nzSNiaB7M7XLeW12FxHdh3ZPu - oykuvkOqAYHm9+9tVA9g==; -Received: from localhost ([::1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) - id 1mjv7Y-00FM0Q-JV; Mon, 08 Nov 2021 03:14:56 +0000 -Received: from mailgw02.mediatek.com ([216.200.240.185]) - by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) - id 1mjv7O-00FLzO-Gd - for hostap@lists.infradead.org; Mon, 08 Nov 2021 03:14:48 +0000 -X-UUID: f0f035fe35ce4f3c98817633a53a1a8b-20211107 -X-UUID: f0f035fe35ce4f3c98817633a53a1a8b-20211107 -Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by - mailgw02.mediatek.com - (envelope-from ) - (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) - with ESMTP id 492139916; Sun, 07 Nov 2021 20:14:42 -0700 -Received: from mtkexhb02.mediatek.inc (172.21.101.103) by - MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Sun, 7 Nov 2021 19:04:41 -0800 -Received: from mtkmbs10n1.mediatek.inc (172.21.101.34) by - mtkexhb02.mediatek.inc (172.21.101.103) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Mon, 8 Nov 2021 11:04:33 +0800 -Received: from mtksdccf07.mediatek.inc (172.21.84.99) by - mtkmbs10n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id - 15.2.792.15 via Frontend Transport; Mon, 8 Nov 2021 11:04:33 +0800 -From: Ryder Lee -To: Jouni Malinen -CC: Felix Fietkau , Lorenzo Bianconi - , Shayne Chen , - "Evelyn Tsai" , , John - Crispin , Lorenzo Bianconi , Ryder Lee - -Subject: [PATCH v2 4/5] bss coloring: add the switch_color handler to the - nl80211 driver -Date: Mon, 8 Nov 2021 11:04:25 +0800 -Message-ID: - -X-Mailer: git-send-email 2.18.0 -In-Reply-To: - <2d69afce2fd6f44ae08ac75d5715fa9e43fe2a77.1636093546.git.ryder.lee@mediatek.com> -References: - <2d69afce2fd6f44ae08ac75d5715fa9e43fe2a77.1636093546.git.ryder.lee@mediatek.com> -MIME-Version: 1.0 -X-MTK: N -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20211107_191446_582339_568C31F9 -X-CRM114-Status: GOOD ( 13.79 ) -X-Spam-Score: 0.0 (/) -X-Spam-Report: Spam detection software, - running on the system "bombadil.infradead.org", - has NOT identified this incoming email as spam. The original - message has been attached to this so you can view it or label - similar future email. If you have any questions, see - the administrator of that system for details. - Content preview: From: John Crispin In order to start the - CCA process we need to send NL80211_CMD_COLOR_CHANGE to the kernel. This - patch adds the required code. Tested-by: Peter Chiu - - Co-developed-by: Lorenzo Bianconi Signed-off-by: Lorenzo - Bianconi Signed-off-by: John Crispin -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Sender: "Hostap" -Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org - -From: John Crispin - -In order to start the CCA process we need to send NL80211_CMD_COLOR_CHANGE -to the kernel. This patch adds the required code. - -Tested-by: Peter Chiu -Co-developed-by: Lorenzo Bianconi -Signed-off-by: Lorenzo Bianconi -Signed-off-by: John Crispin -Signed-off-by: Ryder Lee ---- - src/drivers/driver_nl80211.c | 79 ++++++++++++++++++++++++++++++++++++ - 1 file changed, 79 insertions(+) - ---- a/src/drivers/driver_nl80211.c -+++ b/src/drivers/driver_nl80211.c -@@ -9966,6 +9966,82 @@ error: - } - - -+#ifdef CONFIG_IEEE80211AX -+static int nl80211_switch_color(void *priv, struct cca_settings *settings) -+{ -+ struct nl_msg *msg; -+ struct i802_bss *bss = priv; -+ struct wpa_driver_nl80211_data *drv = bss->drv; -+ struct nlattr *beacon_cca; -+ int ret = -ENOBUFS; -+ -+ wpa_printf(MSG_DEBUG, "nl80211: Color change request (cca_count=%u color=%d)", -+ settings->cca_count, settings->cca_color); -+ -+ if (drv->nlmode != NL80211_IFTYPE_AP) -+ return -EOPNOTSUPP; -+ -+ if (!settings->beacon_cca.tail) -+ return -EINVAL; -+ -+ if ((settings->beacon_cca.tail_len <= settings->counter_offset_beacon) || -+ (settings->beacon_cca.tail[settings->counter_offset_beacon] != -+ settings->cca_count)) -+ return -EINVAL; -+ -+ if (settings->beacon_cca.probe_resp && -+ ((settings->beacon_cca.probe_resp_len <= -+ settings->counter_offset_presp) || -+ (settings->beacon_cca.probe_resp[settings->counter_offset_presp] != -+ settings->cca_count))) -+ return -EINVAL; -+ -+ if (!(msg = nl80211_bss_msg(bss, 0, NL80211_CMD_COLOR_CHANGE_REQUEST)) || -+ nla_put_u8(msg, NL80211_ATTR_COLOR_CHANGE_COUNT, -+ settings->cca_count) || -+ nla_put_u8(msg, NL80211_ATTR_COLOR_CHANGE_COLOR, -+ settings->cca_color)) -+ goto error; -+ -+ /* beacon_after params */ -+ ret = set_beacon_data(msg, &settings->beacon_after); -+ if (ret) -+ goto error; -+ -+ /* beacon_csa params */ -+ beacon_cca = nla_nest_start(msg, NL80211_ATTR_COLOR_CHANGE_ELEMS); -+ if (!beacon_cca) -+ goto fail; -+ -+ ret = set_beacon_data(msg, &settings->beacon_cca); -+ if (ret) -+ goto error; -+ -+ if (nla_put_u16(msg, NL80211_ATTR_CNTDWN_OFFS_BEACON, -+ settings->counter_offset_beacon) || -+ (settings->beacon_cca.probe_resp && -+ nla_put_u16(msg, NL80211_ATTR_CNTDWN_OFFS_PRESP, -+ settings->counter_offset_presp))) -+ goto fail; -+ -+ nla_nest_end(msg, beacon_cca); -+ ret = send_and_recv_msgs(drv, msg, NULL, NULL, NULL, NULL); -+ if (ret) { -+ wpa_printf(MSG_DEBUG, "nl80211: switch_color failed err=%d (%s)", -+ ret, strerror(-ret)); -+ } -+ return ret; -+ -+fail: -+ ret = -ENOBUFS; -+error: -+ nlmsg_free(msg); -+ wpa_printf(MSG_DEBUG, "nl80211: Could not build color switch request"); -+ return ret; -+} -+#endif -+ -+ - static int nl80211_add_ts(void *priv, u8 tsid, const u8 *addr, - u8 user_priority, u16 admitted_time) - { -@@ -12215,6 +12291,9 @@ const struct wpa_driver_ops wpa_driver_n - .get_survey = wpa_driver_nl80211_get_survey, - .status = wpa_driver_nl80211_status, - .switch_channel = nl80211_switch_channel, -+#ifdef CONFIG_IEEE80211AX -+ .switch_color = nl80211_switch_color, -+#endif - #ifdef ANDROID_P2P - .set_noa = wpa_driver_set_p2p_noa, - .get_noa = wpa_driver_get_p2p_noa, diff --git a/package/network/services/hostapd/patches/v2-5-5-bss-coloring-handle-the-collision-and-CCA-events-coming-from-the-kernel.patch b/package/network/services/hostapd/patches/v2-5-5-bss-coloring-handle-the-collision-and-CCA-events-coming-from-the-kernel.patch deleted file mode 100644 index 75c298fa6..000000000 --- a/package/network/services/hostapd/patches/v2-5-5-bss-coloring-handle-the-collision-and-CCA-events-coming-from-the-kernel.patch +++ /dev/null @@ -1,336 +0,0 @@ -From patchwork Mon Nov 8 03:04:26 2021 -Content-Type: text/plain; charset="utf-8" -MIME-Version: 1.0 -Content-Transfer-Encoding: 7bit -X-Patchwork-Submitter: Ryder Lee -X-Patchwork-Id: 1552125 -Return-Path: - -X-Original-To: incoming@patchwork.ozlabs.org -Delivered-To: patchwork-incoming@bilbo.ozlabs.org -Authentication-Results: bilbo.ozlabs.org; - dkim=pass (2048-bit key; - secure) header.d=lists.infradead.org header.i=@lists.infradead.org - header.a=rsa-sha256 header.s=bombadil.20210309 header.b=D1mJI/T4; - dkim-atps=neutral -Authentication-Results: ozlabs.org; - spf=none (no SPF record) smtp.mailfrom=lists.infradead.org - (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; - envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; - receiver=) -Received: from bombadil.infradead.org (bombadil.infradead.org - [IPv6:2607:7c80:54:e::133]) - (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) - key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest - SHA256) - (No client certificate requested) - by bilbo.ozlabs.org (Postfix) with ESMTPS id 4Hnbq567wgz9sR4 - for ; Mon, 8 Nov 2021 14:16:01 +1100 (AEDT) -DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; - d=lists.infradead.org; s=bombadil.20210309; h=Sender: - Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: - List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: - Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: - Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: - List-Owner; bh=wYRX2JnpcX17NK4J2dl70g2OWXCWSPrMEhBFqXI5ge0=; b=D1mJI/T45cfwA/ - hsfbvB5VRQswEDYH6zK0Fh57vwI7DQBcysxmyy+t6NVMVL8di0KZeNNKIE+TqwFv3arP4mce21KW2 - XtPpzdO6QyjOgz3tSl8Po5XCycgDV5KsjSYgdqcuwTzYOw+Al75NdVX4qDEZ0afDxTMeen7BQqQhW - Wz9V20cvUZzGWjtzkt9ZEXXeFDQ5HWc9tNa9/SZ6WvVN42uomljzuKpOOsSpup/2Hrieefb7QCVgO - 7c1PUeErYl+0Bu/MZxZBN8XeEmkXIFveBJWdQhrF4sjOQE2Zlab8sx4oefblg9e8Ec3oBd0/cz/oj - PRL9UQRkhtXO/xIyZAEw==; -Received: from localhost ([::1] helo=bombadil.infradead.org) - by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) - id 1mjv7h-00FM1G-JN; Mon, 08 Nov 2021 03:15:05 +0000 -Received: from mailgw02.mediatek.com ([216.200.240.185]) - by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) - id 1mjv7P-00FLzJ-Su - for hostap@lists.infradead.org; Mon, 08 Nov 2021 03:14:49 +0000 -X-UUID: 2942c98c91a646489611659c32262e8a-20211107 -X-UUID: 2942c98c91a646489611659c32262e8a-20211107 -Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by - mailgw02.mediatek.com - (envelope-from ) - (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) - with ESMTP id 1260652155; Sun, 07 Nov 2021 20:14:42 -0700 -Received: from mtkexhb02.mediatek.inc (172.21.101.103) by - MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Sun, 7 Nov 2021 19:04:41 -0800 -Received: from mtkmbs10n1.mediatek.inc (172.21.101.34) by - mtkexhb02.mediatek.inc (172.21.101.103) with Microsoft SMTP Server (TLS) id - 15.0.1497.2; Mon, 8 Nov 2021 11:04:33 +0800 -Received: from mtksdccf07.mediatek.inc (172.21.84.99) by - mtkmbs10n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id - 15.2.792.15 via Frontend Transport; Mon, 8 Nov 2021 11:04:33 +0800 -From: Ryder Lee -To: Jouni Malinen -CC: Felix Fietkau , Lorenzo Bianconi - , Shayne Chen , - "Evelyn Tsai" , , John - Crispin , Lorenzo Bianconi , Ryder Lee - -Subject: [PATCH v2 5/5] bss coloring: handle the collision and CCA events - coming from the kernel -Date: Mon, 8 Nov 2021 11:04:26 +0800 -Message-ID: - -X-Mailer: git-send-email 2.18.0 -In-Reply-To: - <2d69afce2fd6f44ae08ac75d5715fa9e43fe2a77.1636093546.git.ryder.lee@mediatek.com> -References: - <2d69afce2fd6f44ae08ac75d5715fa9e43fe2a77.1636093546.git.ryder.lee@mediatek.com> -MIME-Version: 1.0 -X-MTK: N -X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 -X-CRM114-CacheID: sfid-20211107_191447_973506_8BA7C4BD -X-CRM114-Status: GOOD ( 17.58 ) -X-Spam-Score: 0.0 (/) -X-Spam-Report: Spam detection software, - running on the system "bombadil.infradead.org", - has NOT identified this incoming email as spam. The original - message has been attached to this so you can view it or label - similar future email. If you have any questions, see - the administrator of that system for details. - Content preview: From: John Crispin This patch activates - the functionality of the previous patches by handling the actual events that - will trigger the CCA process. Tested-by: Peter Chiu - - Co-developed-by: Lorenzo Bianconi Signed-off-by: Lorenzo - Bianconi Signed-off-by: John Crispin -List-Unsubscribe: , - -List-Archive: -List-Post: -List-Help: -List-Subscribe: , - -Sender: "Hostap" -Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org - -From: John Crispin - -This patch activates the functionality of the previous patches by handling -the actual events that will trigger the CCA process. - -Tested-by: Peter Chiu -Co-developed-by: Lorenzo Bianconi -Signed-off-by: Lorenzo Bianconi -Signed-off-by: John Crispin -Signed-off-by: Ryder Lee ---- - src/ap/drv_callbacks.c | 45 ++++++++++++++++++++- - src/drivers/driver.h | 27 +++++++++++++ - src/drivers/driver_common.c | 4 ++ - src/drivers/driver_nl80211_event.c | 64 ++++++++++++++++++++++++++++++ - 4 files changed, 139 insertions(+), 1 deletion(-) - ---- a/src/ap/drv_callbacks.c -+++ b/src/ap/drv_callbacks.c -@@ -43,7 +43,6 @@ - #include "fils_hlp.h" - #include "neighbor_db.h" - -- - #ifdef CONFIG_FILS - void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd, - struct sta_info *sta) -@@ -1783,6 +1782,39 @@ static void hostapd_event_wds_sta_interf - } - - -+#ifdef CONFIG_IEEE80211AX -+static void hostapd_event_bss_color_collision(struct hostapd_data *hapd, -+ u64 bitmap) -+{ -+ /* the bss color is shared amongst all BBSs on a specific phy. -+ * therefore we always start the color change on the primary BSS -+ */ -+ wpa_printf(MSG_DEBUG, "BSS color collision on %s", hapd->conf->iface); -+ hostapd_switch_color(hapd->iface->bss[0], bitmap); -+} -+ -+static void hostapd_event_cca(struct hostapd_data *hapd, enum wpa_event_type event) -+{ -+ switch (event) { -+ case EVENT_CCA_STARTED_NOTIFY: -+ wpa_printf(MSG_DEBUG, "CCA started on on %s", hapd->conf->iface); -+ break; -+ case EVENT_CCA_NOTIFY: -+ wpa_printf(MSG_DEBUG, "CCA finished on on %s", hapd->conf->iface); -+ hapd->iface->conf->he_op.he_bss_color = hapd->cca_color; -+ hostapd_cleanup_cca_params(hapd); -+ break; -+ case EVENT_CCA_ABORTED_NOTIFY: -+ wpa_printf(MSG_DEBUG, "CCA aborted on on %s", hapd->conf->iface); -+ hostapd_cleanup_cca_params(hapd); -+ break; -+ default: -+ break; -+ } -+} -+#endif -+ -+ - #ifdef CONFIG_OWE - static int hostapd_notif_update_dh_ie(struct hostapd_data *hapd, - const u8 *peer, const u8 *ie, -@@ -2089,6 +2121,17 @@ void hostapd_wpa_event(void *ctx, enum w - data->wds_sta_interface.ifname, - data->wds_sta_interface.sta_addr); - break; -+#ifdef CONFIG_IEEE80211AX -+ case EVENT_BSS_COLOR_COLLISION: -+ hostapd_event_bss_color_collision(hapd, -+ data->bss_color_collision.bitmap); -+ break; -+ case EVENT_CCA_STARTED_NOTIFY: -+ case EVENT_CCA_ABORTED_NOTIFY: -+ case EVENT_CCA_NOTIFY: -+ hostapd_event_cca(hapd, event); -+ break; -+#endif - default: - wpa_printf(MSG_DEBUG, "Unknown event %d", event); - break; ---- a/src/drivers/driver.h -+++ b/src/drivers/driver.h -@@ -5165,6 +5165,26 @@ enum wpa_event_type { - * is required to provide more details of the frame. - */ - EVENT_UNPROT_BEACON, -+ -+ /** -+ * EVENT_BSS_COLOR_COLLISION - Notification of a BSS color collision -+ */ -+ EVENT_BSS_COLOR_COLLISION, -+ -+ /** -+ * EVENT_CCA_STARTED_NOTIFY - Notification that CCA has started -+ */ -+ EVENT_CCA_STARTED_NOTIFY, -+ -+ /** -+ * EVENT_CCA_ABORTED_NOTIFY - Notification that CCA has aborted -+ */ -+ EVENT_CCA_ABORTED_NOTIFY, -+ -+ /** -+ * EVENT_CCA_NOTIFY - Notification that CCA has completed -+ */ -+ EVENT_CCA_NOTIFY, - }; - - -@@ -6059,6 +6079,13 @@ union wpa_event_data { - struct unprot_beacon { - const u8 *sa; - } unprot_beacon; -+ -+ /** -+ * struct bss_color_collision - Data for EVENT_BSS_COLOR_COLLISION -+ */ -+ struct bss_color_collision { -+ u64 bitmap; -+ } bss_color_collision; - }; - - /** ---- a/src/drivers/driver_common.c -+++ b/src/drivers/driver_common.c -@@ -90,6 +90,10 @@ const char * event_to_string(enum wpa_ev - E2S(WDS_STA_INTERFACE_STATUS); - E2S(UPDATE_DH); - E2S(UNPROT_BEACON); -+ E2S(BSS_COLOR_COLLISION); -+ E2S(CCA_STARTED_NOTIFY); -+ E2S(CCA_ABORTED_NOTIFY); -+ E2S(CCA_NOTIFY); - } - - return "UNKNOWN"; ---- a/src/drivers/driver_nl80211_event.c -+++ b/src/drivers/driver_nl80211_event.c -@@ -2863,6 +2863,51 @@ nl80211_control_port_frame_tx_status(str - wpa_supplicant_event(drv->ctx, EVENT_EAPOL_TX_STATUS, &event); - } - -+#ifdef CONFIG_IEEE80211AX -+static void mlme_event_obss_color_collision(struct wpa_driver_nl80211_data *drv, -+ struct nlattr *tb[]) -+{ -+ union wpa_event_data data; -+ -+ if (!tb[NL80211_ATTR_OBSS_COLOR_BITMAP]) -+ return; -+ -+ os_memset(&data, 0, sizeof(data)); -+ data.bss_color_collision.bitmap = nla_get_u64(tb[NL80211_ATTR_OBSS_COLOR_BITMAP]); -+ -+ wpa_printf(MSG_DEBUG, "nl80211: BSS color collision - bitmap %08lx", -+ data.bss_color_collision.bitmap); -+ -+ wpa_supplicant_event(drv->ctx, EVENT_BSS_COLOR_COLLISION, &data); -+} -+ -+static void mlme_event_color_change_announcement_started(struct wpa_driver_nl80211_data *drv) -+{ -+ union wpa_event_data data = {}; -+ -+ wpa_printf(MSG_DEBUG, "nl80211: CCA started"); -+ -+ wpa_supplicant_event(drv->ctx, EVENT_CCA_STARTED_NOTIFY, &data); -+} -+ -+static void mlme_event_color_change_announcement_aborted(struct wpa_driver_nl80211_data *drv) -+{ -+ union wpa_event_data data = {}; -+ -+ wpa_printf(MSG_DEBUG, "nl80211: CCA aborted"); -+ -+ wpa_supplicant_event(drv->ctx, EVENT_CCA_ABORTED_NOTIFY, &data); -+} -+ -+static void mlme_event_color_change_announcement_completed(struct wpa_driver_nl80211_data *drv) -+{ -+ union wpa_event_data data = {}; -+ -+ wpa_printf(MSG_DEBUG, "nl80211: CCA completed"); -+ -+ wpa_supplicant_event(drv->ctx, EVENT_CCA_NOTIFY, &data); -+} -+#endif - - static void do_process_drv_event(struct i802_bss *bss, int cmd, - struct nlattr **tb) -@@ -3112,6 +3157,20 @@ static void do_process_drv_event(struct - tb[NL80211_ATTR_ACK], - tb[NL80211_ATTR_COOKIE]); - break; -+#ifdef CONFIG_IEEE80211AX -+ case NL80211_CMD_OBSS_COLOR_COLLISION: -+ mlme_event_obss_color_collision(drv, tb); -+ break; -+ case NL80211_CMD_COLOR_CHANGE_STARTED: -+ mlme_event_color_change_announcement_started(drv); -+ break; -+ case NL80211_CMD_COLOR_CHANGE_ABORTED: -+ mlme_event_color_change_announcement_aborted(drv); -+ break; -+ case NL80211_CMD_COLOR_CHANGE_COMPLETED: -+ mlme_event_color_change_announcement_completed(drv); -+ break; -+#endif - default: - wpa_dbg(drv->ctx, MSG_DEBUG, "nl80211: Ignored unknown event " - "(cmd=%d)", cmd); diff --git a/package/network/services/hostapd/src/src/ap/ubus.c b/package/network/services/hostapd/src/src/ap/ubus.c index bdab8fa7b..ddd86447e 100644 --- a/package/network/services/hostapd/src/src/ap/ubus.c +++ b/package/network/services/hostapd/src/src/ap/ubus.c @@ -318,6 +318,10 @@ 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]); @@ -386,32 +390,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, @@ -445,6 +423,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); @@ -888,10 +872,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++) { @@ -995,6 +982,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 @@ -1022,6 +1010,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; @@ -1059,6 +1055,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 @@ -1087,6 +1084,8 @@ hostapd_bss_mgmt_enable(struct ubus_context *ctx, struct ubus_object *obj, } __hostapd_bss_mgmt_enable(hapd, flags); + + return 0; } @@ -1337,13 +1336,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; @@ -1351,6 +1442,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) @@ -1402,8 +1495,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; @@ -1417,6 +1539,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 }; @@ -1428,6 +1555,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 @@ -1444,6 +1576,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)); @@ -1465,52 +1600,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])); +#ifdef CONFIG_MBO + if (tb[BSS_TR_MBO_REASON]) + mbo_reason = blobmsg_get_u32(tb[BSS_TR_MBO_REASON]); + + if (tb[BSS_TR_CELL_PREF]) + cell_pref = blobmsg_get_u32(tb[BSS_TR_CELL_PREF]); + + if (tb[BSS_TR_REASSOC_DELAY]) + reassoc_delay = blobmsg_get_u32(tb[BSS_TR_REASSOC_DELAY]); +#endif + return hostapd_bss_tr_send(hapd, addr, da_imminent, abridged, da_timer, valid_period, - dialog_token, tb[BSS_TR_NEIGHBORS]); -} - -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; - - if (tb[WNM_DISASSOC_DURATION]) - duration = blobmsg_get_u32(tb[WNM_DISASSOC_DURATION]); - - abridged = !!(tb[WNM_DISASSOC_ABRIDGED] && blobmsg_get_bool(tb[WNM_DISASSOC_ABRIDGED])); - - return hostapd_bss_tr_send(hapd, addr, true, abridged, duration, duration, - 1, tb[WNM_DISASSOC_NEIGHBORS]); + dialog_token, tb[BSS_TR_NEIGHBORS], mbo_reason, cell_pref, reassoc_delay); } #endif @@ -1594,8 +1696,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 }; @@ -1857,6 +1959,20 @@ 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, + const char *auth_alg) +{ + if (!hapd->ubus.obj.has_subscribers) + return; + + blob_buf_init(&b, 0); + blobmsg_add_macaddr(&b, "address", sta->addr); + if (auth_alg) + blobmsg_add_string(&b, "auth-alg", auth_alg); + + ubus_notify(ctx, &hapd->ubus.obj, "sta-authorized", b.head, -1); +} + void hostapd_ubus_notify_beacon_report( struct hostapd_data *hapd, const u8 *addr, u8 token, u8 rep_mode, struct rrm_measurement_beacon_report *rep, size_t len) @@ -1879,6 +1995,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 f1bc093e5..b0f7c44ab 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, @@ -64,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 @@ -98,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) { } @@ -135,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/utils/build_features.h b/package/network/services/hostapd/src/src/utils/build_features.h index cb7cb7273..553769ece 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/utils/iw/Makefile b/package/network/utils/iw/Makefile index 5c8b4b5f4..3f10031c1 100644 --- a/package/network/utils/iw/Makefile +++ b/package/network/utils/iw/Makefile @@ -8,16 +8,18 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iw -PKG_VERSION:=5.16 +PKG_VERSION:=5.19 PKG_RELEASE:=1 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/software/network/iw -PKG_HASH:=4c44e42762f903f9094ba5a598998c800a97a62afd6fd31ec1e0a799e308659c +PKG_HASH:=f167bbe947dd53bb9ebc0c1dcef5db6ad73ac1d6084f2c6f9376c5c360cc4d4e PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 +PKG_BUILD_FLAGS:=gc-sections lto + include $(INCLUDE_DIR)/package.mk define Package/iw @@ -46,8 +48,7 @@ TARGET_CPPFLAGS:= \ -I$(STAGING_DIR)/usr/include/libnl-tiny \ $(TARGET_CPPFLAGS) \ -DCONFIG_LIBNL20 \ - -D_GNU_SOURCE \ - -flto + -D_GNU_SOURCE ifeq ($(BUILD_VARIANT),full) TARGET_CPPFLAGS += -DIW_FULL @@ -55,8 +56,8 @@ ifeq ($(BUILD_VARIANT),full) endif MAKE_FLAGS += \ - CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS) -ffunction-sections -fdata-sections" \ - LDFLAGS="$(TARGET_LDFLAGS) -Wl,--gc-sections -flto" \ + CFLAGS="$(TARGET_CPPFLAGS) $(TARGET_CFLAGS)" \ + LDFLAGS="$(TARGET_LDFLAGS)" \ NL1FOUND="" NL2FOUND=Y \ NLLIBNAME="libnl-tiny" \ LIBS="-lm -lnl-tiny" \ diff --git a/package/network/utils/iw/patches/001-nl80211_h_sync.patch b/package/network/utils/iw/patches/001-nl80211_h_sync.patch index 3fb5ca255..afe27d6f2 100644 --- a/package/network/utils/iw/patches/001-nl80211_h_sync.patch +++ b/package/network/utils/iw/patches/001-nl80211_h_sync.patch @@ -1,137 +1,259 @@ --- a/nl80211.h +++ b/nl80211.h -@@ -301,29 +301,6 @@ +@@ -324,6 +324,17 @@ */ /** -- * DOC: FILS shared key crypto offload -- * -- * This feature is applicable to drivers running in AP mode. -- * -- * FILS shared key crypto offload can be advertised by drivers by setting -- * @NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD flag. The drivers that support -- * FILS shared key crypto offload should be able to encrypt and decrypt -- * association frames for FILS shared key authentication as per IEEE 802.11ai. -- * With this capability, for FILS key derivation, drivers depend on userspace. -- * -- * After FILS key derivation, userspace shares the FILS AAD details with the -- * driver and the driver stores the same to use in decryption of association -- * request and in encryption of association response. The below parameters -- * should be given to the driver in %NL80211_CMD_SET_FILS_AAD. -- * %NL80211_ATTR_MAC - STA MAC address, used for storing FILS AAD per STA -- * %NL80211_ATTR_FILS_KEK - Used for encryption or decryption -- * %NL80211_ATTR_FILS_NONCES - Used for encryption or decryption -- * (STA Nonce 16 bytes followed by AP Nonce 16 bytes) -- * -- * Once the association is done, the driver cleans the FILS AAD data. -- */ -- --/** ++ * DOC: Multi-Link Operation ++ * ++ * In Multi-Link Operation, a connection between to MLDs utilizes multiple ++ * links. To use this in nl80211, various commands and responses now need ++ * to or will include the new %NL80211_ATTR_MLO_LINKS attribute. ++ * Additionally, various commands that need to operate on a specific link ++ * now need to be given the %NL80211_ATTR_MLO_LINK_ID attribute, e.g. to ++ * use %NL80211_CMD_START_AP or similar functions. ++ */ ++ ++/** * enum nl80211_commands - supported nl80211 commands * * @NL80211_CMD_UNSPEC: unspecified command to catch errors -@@ -1226,12 +1203,6 @@ - * @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change - * has completed +@@ -366,14 +377,22 @@ + * the non-transmitting interfaces are deleted as well. * -- * @NL80211_CMD_SET_FILS_AAD: Set FILS AAD data to the driver using - -- * &NL80211_ATTR_MAC - for STA MAC address -- * &NL80211_ATTR_FILS_KEK - for KEK -- * &NL80211_ATTR_FILS_NONCES - for FILS Nonces -- * (STA Nonce 16 bytes followed by AP Nonce 16 bytes) -- * + * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified +- * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. ++ * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. %NL80211_ATTR_MAC ++ * represents peer's MLD address for MLO pairwise key. For MLO group key, ++ * the link is identified by %NL80211_ATTR_MLO_LINK_ID. + * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, + * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. ++ * For MLO connection, the link to set default key is identified by ++ * %NL80211_ATTR_MLO_LINK_ID. + * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, + * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, +- * and %NL80211_ATTR_KEY_SEQ attributes. ++ * and %NL80211_ATTR_KEY_SEQ attributes. %NL80211_ATTR_MAC represents ++ * peer's MLD address for MLO pairwise key. The link to add MLO ++ * group key is identified by %NL80211_ATTR_MLO_LINK_ID. + * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX +- * or %NL80211_ATTR_MAC. ++ * or %NL80211_ATTR_MAC. %NL80211_ATTR_MAC represents peer's MLD address ++ * for MLO pairwise key. The link to delete group key is identified by ++ * %NL80211_ATTR_MLO_LINK_ID. + * + * @NL80211_CMD_GET_BEACON: (not used) + * @NL80211_CMD_SET_BEACON: change the beacon on an access point interface +@@ -753,6 +772,13 @@ + * %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA + * counters which will be updated to the current value. This attribute + * is used during CSA period. ++ * For TX on an MLD, the frequency can be omitted and the link ID be ++ * specified, or if transmitting to a known peer MLD (with MLD addresses ++ * in the frame) both can be omitted and the link will be selected by ++ * lower layers. ++ * For RX notification, %NL80211_ATTR_RX_HW_TIMESTAMP may be included to ++ * indicate the frame RX timestamp and %NL80211_ATTR_TX_HW_TIMESTAMP may ++ * be included to indicate the ack TX timestamp. + * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this + * command may be used with the corresponding cookie to cancel the wait + * time if it is known that it is no longer necessary. This command is +@@ -763,7 +789,9 @@ + * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies + * the TX command and %NL80211_ATTR_FRAME includes the contents of the + * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged +- * the frame. ++ * the frame. %NL80211_ATTR_TX_HW_TIMESTAMP may be included to indicate the ++ * tx timestamp and %NL80211_ATTR_RX_HW_TIMESTAMP may be included to ++ * indicate the ack RX timestamp. + * @NL80211_CMD_ACTION_TX_STATUS: Alias for @NL80211_CMD_FRAME_TX_STATUS for + * backward compatibility. + * +@@ -1108,6 +1136,12 @@ + * has been received. %NL80211_ATTR_FRAME is used to specify the + * frame contents. The frame is the raw EAPoL data, without ethernet or + * 802.11 headers. ++ * For an MLD transmitter, the %NL80211_ATTR_MLO_LINK_ID may be given and ++ * its effect will depend on the destination: If the destination is known ++ * to be an MLD, this will be used as a hint to select the link to transmit ++ * the frame on. If the destination is not an MLD, this will select both ++ * the link to transmit on and the source address will be set to the link ++ * address of that link. + * When used as an event indication %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, + * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT and %NL80211_ATTR_MAC are added + * indicating the protocol type of the received frame; whether the frame +@@ -1237,6 +1271,16 @@ + * to describe the BSSID address of the AP and %NL80211_ATTR_TIMEOUT to + * specify the timeout value. + * ++ * @NL80211_CMD_ADD_LINK: Add a new link to an interface. The ++ * %NL80211_ATTR_MLO_LINK_ID attribute is used for the new link. ++ * @NL80211_CMD_REMOVE_LINK: Remove a link from an interface. This may come ++ * without %NL80211_ATTR_MLO_LINK_ID as an easy way to remove all links ++ * in preparation for e.g. roaming to a regular (non-MLO) AP. ++ * ++ * @NL80211_CMD_ADD_LINK_STA: Add a link to an MLD station ++ * @NL80211_CMD_MODIFY_LINK_STA: Modify a link of an MLD station ++ * @NL80211_CMD_REMOVE_LINK_STA: Remove a link of an MLD station ++ * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ -@@ -1472,8 +1443,6 @@ enum nl80211_commands { - NL80211_CMD_COLOR_CHANGE_ABORTED, - NL80211_CMD_COLOR_CHANGE_COMPLETED, +@@ -1481,6 +1525,13 @@ enum nl80211_commands { -- NL80211_CMD_SET_FILS_AAD, -- + NL80211_CMD_ASSOC_COMEBACK, + ++ NL80211_CMD_ADD_LINK, ++ NL80211_CMD_REMOVE_LINK, ++ ++ NL80211_CMD_ADD_LINK_STA, ++ NL80211_CMD_MODIFY_LINK_STA, ++ NL80211_CMD_REMOVE_LINK_STA, ++ /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ -@@ -2639,6 +2608,9 @@ enum nl80211_commands { - * Mandatory parameter for the transmitting interface to enable MBSSID. - * Optional for the non-transmitting interfaces. +@@ -2340,8 +2391,10 @@ enum nl80211_commands { * + * @NL80211_ATTR_IFTYPE_EXT_CAPA: Nested attribute of the following attributes: + * %NL80211_ATTR_IFTYPE, %NL80211_ATTR_EXT_CAPA, +- * %NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities per +- * interface type. ++ * %NL80211_ATTR_EXT_CAPA_MASK, to specify the extended capabilities and ++ * other interface-type specific capabilities per interface type. For MLO, ++ * %NL80211_ATTR_EML_CAPABILITY and %NL80211_ATTR_MLD_CAPA_AND_OPS are ++ * present. + * + * @NL80211_ATTR_MU_MIMO_GROUP_DATA: array of 24 bytes that defines a MU-MIMO + * groupID for monitor mode. +@@ -2663,6 +2716,44 @@ enum nl80211_commands { + * association request when used with NL80211_CMD_NEW_STATION). Can be set + * only if %NL80211_STA_FLAG_WME is set. + * ++ * @NL80211_ATTR_MLO_LINK_ID: A (u8) link ID for use with MLO, to be used with ++ * various commands that need a link ID to operate. ++ * @NL80211_ATTR_MLO_LINKS: A nested array of links, each containing some ++ * per-link information and a link ID. ++ * @NL80211_ATTR_MLD_ADDR: An MLD address, used with various commands such as ++ * authenticate/associate. ++ * ++ * @NL80211_ATTR_MLO_SUPPORT: Flag attribute to indicate user space supports MLO ++ * connection. Used with %NL80211_CMD_CONNECT. If this attribute is not ++ * included in NL80211_CMD_CONNECT drivers must not perform MLO connection. ++ * ++ * @NL80211_ATTR_MAX_NUM_AKM_SUITES: U16 attribute. Indicates maximum number of ++ * AKM suites allowed for %NL80211_CMD_CONNECT, %NL80211_CMD_ASSOCIATE and ++ * %NL80211_CMD_START_AP in %NL80211_CMD_GET_WIPHY response. If this ++ * attribute is not present userspace shall consider maximum number of AKM ++ * suites allowed as %NL80211_MAX_NR_AKM_SUITES which is the legacy maximum ++ * number prior to the introduction of this attribute. ++ * ++ * @NL80211_ATTR_EML_CAPABILITY: EML Capability information (u16) ++ * @NL80211_ATTR_MLD_CAPA_AND_OPS: MLD Capabilities and Operations (u16) ++ * ++ * @NL80211_ATTR_TX_HW_TIMESTAMP: Hardware timestamp for TX operation in ++ * nanoseconds (u64). This is the device clock timestamp so it will ++ * probably reset when the device is stopped or the firmware is reset. ++ * When used with %NL80211_CMD_FRAME_TX_STATUS, indicates the frame TX ++ * timestamp. When used with %NL80211_CMD_FRAME RX notification, indicates ++ * the ack TX timestamp. ++ * @NL80211_ATTR_RX_HW_TIMESTAMP: Hardware timestamp for RX operation in ++ * nanoseconds (u64). This is the device clock timestamp so it will ++ * probably reset when the device is stopped or the firmware is reset. ++ * When used with %NL80211_CMD_FRAME_TX_STATUS, indicates the ack RX ++ * timestamp. When used with %NL80211_CMD_FRAME RX notification, indicates ++ * the incoming frame RX timestamp. ++ * @NL80211_ATTR_TD_BITMAP: Transition Disable bitmap, for subsequent ++ * (re)associations. + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce + * transmit power to stay within regulatory limits. u32, dBi. + * * @NUM_NL80211_ATTR: total number of nl80211_attrs available * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use -@@ -3145,6 +3117,8 @@ enum nl80211_attrs { - NL80211_ATTR_MBSSID_CONFIG, - NL80211_ATTR_MBSSID_ELEMS, +@@ -3177,6 +3268,23 @@ enum nl80211_attrs { + NL80211_ATTR_DISABLE_EHT, + ++ NL80211_ATTR_MLO_LINKS, ++ NL80211_ATTR_MLO_LINK_ID, ++ NL80211_ATTR_MLD_ADDR, ++ ++ NL80211_ATTR_MLO_SUPPORT, ++ ++ NL80211_ATTR_MAX_NUM_AKM_SUITES, ++ ++ NL80211_ATTR_EML_CAPABILITY, ++ NL80211_ATTR_MLD_CAPA_AND_OPS, ++ ++ NL80211_ATTR_TX_HW_TIMESTAMP, ++ NL80211_ATTR_RX_HW_TIMESTAMP, ++ NL80211_ATTR_TD_BITMAP, ++ + NL80211_ATTR_WIPHY_ANTENNA_GAIN, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, -@@ -4978,7 +4952,6 @@ enum nl80211_txrate_gi { - * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz) - * @NL80211_BAND_6GHZ: around 6 GHz band (5.9 - 7.2 GHz) - * @NL80211_BAND_S1GHZ: around 900MHz, supported by S1G PHYs -- * @NL80211_BAND_LC: light communication band (placeholder) - * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace - * since newer kernel versions may support more bands +@@ -3231,6 +3339,11 @@ enum nl80211_attrs { + #define NL80211_HE_MIN_CAPABILITY_LEN 16 + #define NL80211_HE_MAX_CAPABILITY_LEN 54 + #define NL80211_MAX_NR_CIPHER_SUITES 5 ++ ++/* ++ * NL80211_MAX_NR_AKM_SUITES is obsolete when %NL80211_ATTR_MAX_NUM_AKM_SUITES ++ * present in %NL80211_CMD_GET_WIPHY response. ++ */ + #define NL80211_MAX_NR_AKM_SUITES 2 + #define NL80211_EHT_MIN_CAPABILITY_LEN 13 + #define NL80211_EHT_MAX_CAPABILITY_LEN 51 +@@ -4853,6 +4966,8 @@ enum nl80211_bss_scan_width { + * Contains a nested array of signal strength attributes (u8, dBm), + * using the nesting index as the antenna number. + * @NL80211_BSS_FREQUENCY_OFFSET: frequency offset in KHz ++ * @NL80211_BSS_MLO_LINK_ID: MLO link ID of the BSS (u8). ++ * @NL80211_BSS_MLD_ADDR: MLD address of this BSS if connected to it. + * @__NL80211_BSS_AFTER_LAST: internal + * @NL80211_BSS_MAX: highest BSS attribute */ -@@ -4988,7 +4961,6 @@ enum nl80211_band { - NL80211_BAND_60GHZ, - NL80211_BAND_6GHZ, - NL80211_BAND_S1GHZ, -- NL80211_BAND_LC, +@@ -4878,6 +4993,8 @@ enum nl80211_bss { + NL80211_BSS_PARENT_BSSID, + NL80211_BSS_CHAIN_SIGNAL, + NL80211_BSS_FREQUENCY_OFFSET, ++ NL80211_BSS_MLO_LINK_ID, ++ NL80211_BSS_MLD_ADDR, - NUM_NL80211_BANDS, - }; -@@ -6046,11 +6018,6 @@ enum nl80211_feature_flags { - * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision - * detection and change announcemnts. + /* keep last */ + __NL80211_BSS_AFTER_LAST, +@@ -5874,7 +5991,7 @@ enum nl80211_ap_sme_features { + * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up + * the connected inactive stations in AP mode. + * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested +- * to work properly to suppport receiving regulatory hints from ++ * to work properly to support receiving regulatory hints from + * cellular base stations. + * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: (no longer available, only + * here to reserve the value for API/ABI compatibility) +@@ -6174,6 +6291,14 @@ enum nl80211_feature_flags { + * @NL80211_EXT_FEATURE_RADAR_BACKGROUND: Device supports background radar/CAC + * detection. * -- * @NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD: Driver running in AP mode supports -- * FILS encryption and decryption for (Re)Association Request and Response -- * frames. Userspace has to share FILS AAD details to the driver by using -- * @NL80211_CMD_SET_FILS_AAD. -- * ++ * @NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE: Device can perform a MAC address ++ * change without having to bring the underlying network device down ++ * first. For example, in station mode this can be used to vary the ++ * origin MAC address prior to a connection to a new AP for privacy ++ * or other reasons. Note that certain driver specific restrictions ++ * might apply, e.g. no scans in progress, no offchannel operations ++ * in progress, and no active connections. ++ * * @NUM_NL80211_EXT_FEATURES: number of extended features. * @MAX_NL80211_EXT_FEATURES: highest extended feature index. */ -@@ -6116,7 +6083,6 @@ enum nl80211_ext_feature_index { - NL80211_EXT_FEATURE_SECURE_RTT, - NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, +@@ -6241,6 +6366,7 @@ enum nl80211_ext_feature_index { NL80211_EXT_FEATURE_BSS_COLOR, -- NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD, + NL80211_EXT_FEATURE_FILS_CRYPTO_OFFLOAD, + NL80211_EXT_FEATURE_RADAR_BACKGROUND, ++ NL80211_EXT_FEATURE_POWERED_ADDR_CHANGE, /* add new features before the definition below */ NUM_NL80211_EXT_FEATURES, -@@ -7424,7 +7390,7 @@ enum nl80211_sar_specs_attrs { - * @NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY: Used by the kernel - * to advertise the maximum profile periodicity supported by the driver - * if EMA is enabled. Driver should indicate EMA support to the userspace -- * by setting wiphy->ema_max_profile_periodicity to -+ * by setting wiphy->mbssid_max_ema_profile_periodicity to - * a non-zero value. - * - * @NL80211_MBSSID_CONFIG_ATTR_INDEX: Mandatory parameter to pass the index of -@@ -7443,7 +7409,7 @@ enum nl80211_sar_specs_attrs { - * - * @NL80211_MBSSID_CONFIG_ATTR_EMA: Flag used to enable EMA AP feature. - * Setting this flag is permitted only if the driver advertises EMA support -- * by setting wiphy->ema_max_profile_periodicity to non-zero. -+ * by setting wiphy->mbssid_max_ema_profile_periodicity to non-zero. - * - * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal - * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute ---- a/info.c -+++ b/info.c -@@ -701,7 +701,6 @@ broken_combination: - ext_feat_print(tb, OPERATING_CHANNEL_VALIDATION, "Operating Channel Validation (OCV) support"); - ext_feat_print(tb, 4WAY_HANDSHAKE_AP_PSK, "AP mode PSK offload support"); - ext_feat_print(tb, BSS_COLOR, "BSS coloring support"); -- ext_feat_print(tb, FILS_CRYPTO_OFFLOAD, "FILS crypto offload"); - } - - if (tb_msg[NL80211_ATTR_COALESCE_RULE]) { diff --git a/package/network/utils/iw/patches/200-reduce_size.patch b/package/network/utils/iw/patches/200-reduce_size.patch index d0e837c69..862199452 100644 --- a/package/network/utils/iw/patches/200-reduce_size.patch +++ b/package/network/utils/iw/patches/200-reduce_size.patch @@ -1,6 +1,6 @@ --- a/event.c +++ b/event.c -@@ -956,6 +956,7 @@ static int print_event(struct nl_msg *ms +@@ -971,6 +971,7 @@ static int print_event(struct nl_msg *ms } switch (gnlh->cmd) { @@ -8,7 +8,7 @@ case NL80211_CMD_NEW_WIPHY: printf("renamed to %s\n", nla_get_string(tb[NL80211_ATTR_WIPHY_NAME])); break; -@@ -991,6 +992,7 @@ static int print_event(struct nl_msg *ms +@@ -1006,6 +1007,7 @@ static int print_event(struct nl_msg *ms case NL80211_CMD_SCHED_SCAN_RESULTS: printf("got scheduled scan results\n"); break; @@ -16,7 +16,7 @@ case NL80211_CMD_WIPHY_REG_CHANGE: case NL80211_CMD_REG_CHANGE: if (gnlh->cmd == NL80211_CMD_WIPHY_REG_CHANGE) -@@ -1073,6 +1075,7 @@ static int print_event(struct nl_msg *ms +@@ -1088,6 +1090,7 @@ static int print_event(struct nl_msg *ms mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); printf("del station %s\n", macbuf); break; @@ -24,9 +24,9 @@ case NL80211_CMD_JOIN_IBSS: mac_addr_n2a(macbuf, nla_data(tb[NL80211_ATTR_MAC])); printf("IBSS %s joined\n", macbuf); -@@ -1271,9 +1274,9 @@ static int print_event(struct nl_msg *ms - case NL80211_CMD_CH_SWITCH_NOTIFY: - parse_ch_switch_notify(tb, gnlh->cmd); +@@ -1295,9 +1298,9 @@ static int print_event(struct nl_msg *ms + case NL80211_CMD_ASSOC_COMEBACK: /* 147 */ + parse_assoc_comeback(tb, gnlh->cmd); break; +#endif default: @@ -38,7 +38,7 @@ --- a/info.c +++ b/info.c -@@ -215,6 +215,7 @@ next: +@@ -309,6 +309,7 @@ next: } } @@ -46,7 +46,7 @@ if (tb_band[NL80211_BAND_ATTR_RATES]) { printf("\t\tBitrates (non-HT):\n"); nla_for_each_nested(nl_rate, tb_band[NL80211_BAND_ATTR_RATES], rem_rate) { -@@ -231,6 +232,7 @@ next: +@@ -325,6 +326,7 @@ next: printf("\n"); } } @@ -54,7 +54,7 @@ } } -@@ -296,6 +298,7 @@ next: +@@ -390,6 +392,7 @@ next: printf("\tCoverage class: %d (up to %dm)\n", coverage, 450 * coverage); } @@ -62,7 +62,7 @@ if (tb_msg[NL80211_ATTR_CIPHER_SUITES]) { int num = nla_len(tb_msg[NL80211_ATTR_CIPHER_SUITES]) / sizeof(__u32); int i; -@@ -307,6 +310,7 @@ next: +@@ -401,6 +404,7 @@ next: cipher_name(ciphers[i])); } } @@ -70,7 +70,7 @@ if (tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX] && tb_msg[NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX]) -@@ -324,9 +328,11 @@ next: +@@ -418,9 +422,11 @@ next: print_iftype_list("\tSupported interface modes", "\t\t", tb_msg[NL80211_ATTR_SUPPORTED_IFTYPES]); @@ -82,7 +82,7 @@ if (tb_msg[NL80211_ATTR_INTERFACE_COMBINATIONS]) { struct nlattr *nl_combi; -@@ -416,6 +422,7 @@ broken_combination: +@@ -510,6 +516,7 @@ broken_combination: printf("\tinterface combinations are not supported\n"); } @@ -90,7 +90,7 @@ if (tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS]) { printf("\tSupported commands:\n"); nla_for_each_nested(nl_cmd, tb_msg[NL80211_ATTR_SUPPORTED_COMMANDS], rem_cmd) -@@ -513,6 +520,7 @@ broken_combination: +@@ -607,6 +614,7 @@ broken_combination: printf("\t\t * wake up on TCP connection\n"); } } @@ -98,7 +98,7 @@ if (tb_msg[NL80211_ATTR_ROAM_SUPPORT]) printf("\tDevice supports roaming.\n"); -@@ -551,6 +559,7 @@ broken_combination: +@@ -645,6 +653,7 @@ broken_combination: } } @@ -106,7 +106,7 @@ if (tb_msg[NL80211_ATTR_FEATURE_FLAGS]) { unsigned int features = nla_get_u32(tb_msg[NL80211_ATTR_FEATURE_FLAGS]); -@@ -615,6 +624,7 @@ broken_combination: +@@ -709,6 +718,7 @@ broken_combination: if (features & NL80211_FEATURE_ND_RANDOM_MAC_ADDR) printf("\tDevice supports randomizing MAC-addr in net-detect scans.\n"); } @@ -114,7 +114,7 @@ if (tb_msg[NL80211_ATTR_TDLS_SUPPORT]) printf("\tDevice supports T-DLS.\n"); -@@ -751,6 +761,7 @@ TOPLEVEL(list, NULL, NL80211_CMD_GET_WIP +@@ -774,6 +784,7 @@ TOPLEVEL(list, NULL, NL80211_CMD_GET_WIP "List all wireless devices and their capabilities."); TOPLEVEL(phy, NULL, NL80211_CMD_GET_WIPHY, NLM_F_DUMP, CIB_NONE, handle_info, NULL); @@ -122,7 +122,7 @@ static int handle_commands(struct nl80211_state *state, struct nl_msg *msg, int argc, char **argv, enum id_input id) { -@@ -762,6 +773,7 @@ static int handle_commands(struct nl8021 +@@ -785,6 +796,7 @@ static int handle_commands(struct nl8021 } TOPLEVEL(commands, NULL, NL80211_CMD_GET_WIPHY, 0, CIB_NONE, handle_commands, "list all known commands and their decimal & hex value"); @@ -292,7 +292,7 @@ ifeq ($(NO_PKG_CONFIG),) --- a/station.c +++ b/station.c -@@ -777,10 +777,12 @@ static int handle_station_set_plink(stru +@@ -791,10 +791,12 @@ static int handle_station_set_plink(stru nla_put_failure: return -ENOBUFS; } @@ -305,7 +305,7 @@ static int handle_station_set_vlan(struct nl80211_state *state, struct nl_msg *msg, -@@ -875,11 +877,13 @@ static int handle_station_set_mesh_power +@@ -889,11 +891,13 @@ static int handle_station_set_mesh_power nla_put_failure: return -ENOBUFS; } @@ -321,7 +321,7 @@ struct nl_msg *msg, --- a/interface.c +++ b/interface.c -@@ -627,9 +627,11 @@ static int handle_interface_wds_peer(str +@@ -629,9 +629,11 @@ static int handle_interface_wds_peer(str nla_put_failure: return -ENOBUFS; } @@ -333,7 +333,7 @@ static int set_mcast_rate(struct nl80211_state *state, struct nl_msg *msg, -@@ -719,6 +721,7 @@ static int handle_chan(struct nl80211_st +@@ -721,6 +723,7 @@ static int handle_chan(struct nl80211_st return handle_chanfreq(state, msg, true, argc, argv, id); } @@ -341,7 +341,7 @@ SECTION(switch); COMMAND(switch, freq, " [NOHT|HT20|HT40+|HT40-|5MHz|10MHz|80MHz] [beacons ] [block-tx]\n" -@@ -990,3 +993,4 @@ COMMAND(set, tidconf, "[peer PKG_LICENSE:=GPL-2.0 PKG_FLAGS := nonshared PKG_CONFIG_DEPENDS := \ - CONFIG_PACKAGE_kmod-brcm-wl \ - CONFIG_PACKAGE_kmod-brcm-wl-mini \ - CONFIG_PACKAGE_kmod-brcm-wl-mimo \ CONFIG_PACKAGE_kmod-mt7615d_dbdc \ CONFIG_PACKAGE_kmod-cfg80211 -IWINFO_ABI_VERSION:=20210430 +IWINFO_ABI_VERSION:=20230121 include $(INCLUDE_DIR)/package.mk @@ -35,13 +32,13 @@ define Package/libiwinfo SECTION:=libs CATEGORY:=Libraries TITLE:=Generalized Wireless Information Library (iwinfo) - DEPENDS:=+PACKAGE_kmod-cfg80211:libnl-tiny +libuci +libubus + DEPENDS:=+libnl-tiny +libuci +libubus +libiwinfo-data ABI_VERSION:=$(IWINFO_ABI_VERSION) endef define Package/libiwinfo/description - Wireless information library with consistent interface for proprietary Broadcom, - nl80211 and wext driver interfaces. + Wireless information library with simplified API for nl80211 + and wext driver interfaces. endef @@ -59,6 +56,12 @@ define Package/libiwinfo-lua/description endef +define Package/libiwinfo-data + TITLE:=libiwinfo Lua binding + HIDDEN:=1 +endef + + define Package/iwinfo SECTION:=utils CATEGORY:=Utilities @@ -75,9 +78,6 @@ define Build/Configure endef IWINFO_BACKENDS := \ - $(if $(CONFIG_PACKAGE_kmod-brcm-wl),wl) \ - $(if $(CONFIG_PACKAGE_kmod-brcm-wl-mini),wl) \ - $(if $(CONFIG_PACKAGE_kmod-brcm-wl-mimo),wl) \ $(if $(CONFIG_PACKAGE_kmod-mt7615d_dbdc),ra) \ $(if $(CONFIG_PACKAGE_kmod-cfg80211),nl80211) @@ -106,8 +106,6 @@ endef define Package/libiwinfo/install $(INSTALL_DIR) $(1)/usr/lib $(INSTALL_BIN) $(PKG_BUILD_DIR)/libiwinfo.so.$(IWINFO_ABI_VERSION) $(1)/usr/lib/libiwinfo.so.$(IWINFO_ABI_VERSION) - $(INSTALL_DIR) $(1)/usr/share/libiwinfo - $(INSTALL_DATA) $(PKG_BUILD_DIR)/hardware.txt $(1)/usr/share/libiwinfo/hardware.txt endef define Package/libiwinfo-lua/install @@ -115,6 +113,11 @@ define Package/libiwinfo-lua/install $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo.so $(1)/usr/lib/lua/iwinfo.so endef +define Package/libiwinfo-data/install + $(INSTALL_DIR) $(1)/usr/share/libiwinfo + $(INSTALL_DATA) $(PKG_BUILD_DIR)/devices.txt $(1)/usr/share/libiwinfo/devices.txt +endef + define Package/iwinfo/install $(INSTALL_DIR) $(1)/usr/bin $(INSTALL_BIN) $(PKG_BUILD_DIR)/iwinfo $(1)/usr/bin/iwinfo @@ -122,4 +125,5 @@ endef $(eval $(call BuildPackage,libiwinfo)) $(eval $(call BuildPackage,libiwinfo-lua)) +$(eval $(call BuildPackage,libiwinfo-data)) $(eval $(call BuildPackage,iwinfo)) diff --git a/package/network/utils/iwinfo/patches/001-ralink.patch b/package/network/utils/iwinfo/patches/001-ralink.patch index 18abf8592..2d4e2c7a3 100644 --- a/package/network/utils/iwinfo/patches/001-ralink.patch +++ b/package/network/utils/iwinfo/patches/001-ralink.patch @@ -223,7 +223,7 @@ #endif --- a/include/iwinfo.h +++ b/include/iwinfo.h -@@ -306,6 +306,7 @@ extern const struct iwinfo_ops wext_ops; +@@ -412,6 +412,7 @@ extern const struct iwinfo_ops wext_ops; extern const struct iwinfo_ops madwifi_ops; extern const struct iwinfo_ops nl80211_ops; extern const struct iwinfo_ops wl_ops; @@ -233,19 +233,19 @@ --- a/iwinfo_lib.c +++ b/iwinfo_lib.c -@@ -339,6 +339,9 @@ static const struct iwinfo_ops *backends - #ifdef USE_WL - &wl_ops, +@@ -388,6 +388,9 @@ static const struct iwinfo_ops *backends + #ifdef USE_MADWIFI + &madwifi_ops, #endif +#ifdef USE_RA + &ra_ops, +#endif - &wext_ops, - }; - + #ifdef USE_WL + &wl_ops, + #endif --- a/iwinfo_lua.c +++ b/iwinfo_lua.c -@@ -678,6 +678,35 @@ static int iwinfo_L_countrylist(lua_Stat +@@ -686,6 +686,35 @@ static int iwinfo_L_countrylist(lua_Stat return 1; } @@ -281,9 +281,9 @@ #ifdef USE_WL /* Broadcom */ -@@ -927,6 +956,41 @@ static const luaL_reg R_wext[] = { - { NULL, NULL } +@@ -906,6 +935,40 @@ static const luaL_reg }; + #endif +#ifdef USE_RA +/* Ralink table */ @@ -319,15 +319,13 @@ + +#endif + -+ - /* Common */ - static const luaL_reg R_common[] = { - { "type", iwinfo_L_type }, -@@ -938,6 +1002,15 @@ static const luaL_reg R_common[] = { + /* Wext table */ + #ifdef USE_WEXT + static const luaL_reg R_wext[] = { +@@ -950,6 +1013,14 @@ static const luaL_reg R_common[] = { LUALIB_API int luaopen_iwinfo(lua_State *L) { luaL_register(L, IWINFO_META, R_common); -+ +#ifdef USE_RA + luaL_newmetatable(L, IWINFO_RA_META); + luaL_register(L, NULL, R_ra); @@ -1466,9 +1464,21 @@ { char chans[IWINFO_BUFSIZE] = { 0 }; struct iwinfo_freqlist_entry *e = NULL; +--- a/iwinfo_utils.c ++++ b/iwinfo_utils.c +@@ -407,7 +407,8 @@ int iwinfo_hardware_id_from_mtd(struct i + + /* subsystem from EEPROM_NIC_CONF0_RF_TYPE */ + id->subsystem_device_id = (bc[off + 0x1a] & 0x0f00) >> 8; +- } else if ((bc[off] == 0x7620) || (bc[off] == 0x2076) || ++ } else if ((bc[off] == 0x7615) || (bc[off] == 0x1576) || ++ (bc[off] == 0x7620) || (bc[off] == 0x2076) || + (bc[off] == 0x7628) || (bc[off] == 0x2876) || + (bc[off] == 0x7688) || (bc[off] == 0x8876)) { + /* vendor: MediaTek */ --- a/Makefile +++ b/Makefile -@@ -34,6 +34,15 @@ ifneq ($(filter nl80211,$(IWINFO_BACKEND +@@ -39,6 +39,15 @@ ifneq ($(filter nl80211,$(IWINFO_BACKEND IWINFO_LIB_OBJ += iwinfo_nl80211.o endif @@ -1484,9 +1494,9 @@ compile: clean $(IWINFO_LIB) $(IWINFO_LUA) $(IWINFO_CLI) ---- a/hardware.txt -+++ b/hardware.txt -@@ -180,6 +180,36 @@ +--- a/devices.txt ++++ b/devices.txt +@@ -174,6 +174,36 @@ 0x1814 0x3662 0x1814 0x000d 0 0 "Ralink" "Rt3662" 0x1814 0x3883 0x1814 0x000d 0 0 "Ralink" "Rt3883" 0x1814 0x5350 0x1814 0x000f 0 0 "Ralink" "Rt5350" @@ -1523,15 +1533,3 @@ 0x11ab 0x2a55 0x11ab 0x0000 0 0 "Marvell" "88W8864" 0x02df 0x9135 0x0000 0x0000 0 0 "Marvell" "88W8887" 0x11ab 0x2b40 0x11ab 0x0000 0 0 "Marvell" "88W8964" ---- a/iwinfo_utils.c -+++ b/iwinfo_utils.c -@@ -259,7 +259,8 @@ int iwinfo_hardware_id_from_mtd(struct i - - /* subsystem from EEPROM_NIC_CONF0_RF_TYPE */ - id->subsystem_device_id = (bc[off + 0x1a] & 0x0f00) >> 8; -- } else if ((bc[off] == 0x7620) || (bc[off] == 0x2076) || -+ } else if ((bc[off] == 0x7615) || (bc[off] == 0x1576) || -+ (bc[off] == 0x7620) || (bc[off] == 0x2076) || - (bc[off] == 0x7628) || (bc[off] == 0x2876) || - (bc[off] == 0x7688) || (bc[off] == 0x8876)) { - /* vendor: MediaTek */ diff --git a/package/network/utils/iwinfo/patches/002-devices-add-MT7986.patch b/package/network/utils/iwinfo/patches/002-devices-add-MT7986.patch deleted file mode 100644 index 707386354..000000000 --- a/package/network/utils/iwinfo/patches/002-devices-add-MT7986.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 46f04f3808e8b8c9608d0974c4cede1e78110b7f Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Mon, 25 Jul 2022 04:17:44 +0200 -Subject: [PATCH 1/1] devices: add MediaTek MT7986 WiSoC - -Add detection of the MediaTek MT7986 WiSoC using the compatible string -from device tree. - -Signed-off-by: Daniel Golle ---- - devices.txt | 1 + - iwinfo_nl80211.c | 6 ++++++ - 2 files changed, 7 insertions(+) - ---- a/hardware.txt -+++ b/hardware.txt -@@ -225,5 +225,6 @@ - 0x14c3 0x7650 0x14c3 0x7650 0 0 "MediaTek" "MT7610E" - 0x14c3 0x7662 0x14c3 0x7662 0 0 "MediaTek" "MT76x2E" - 0x14c3 0x7915 0x14c3 0x7915 0 0 "MediaTek" "MT7915E" -+0x14c3 0x7986 0x14c3 0x7986 0 0 "MediaTek" "MT7986" - 0x14e4 0xaa52 0x14e4 0xaa52 0 0 "Broadcom" "BCM43602" - 0x1ae9 0x0310 0x1ae9 0x0000 0 0 "Wilocity" "Wil6210" ---- a/iwinfo_nl80211.c -+++ b/iwinfo_nl80211.c -@@ -3386,7 +3386,13 @@ static int nl80211_hardware_id_from_fdt( - id->device_id = 0x7622; - id->subsystem_vendor_id = 0x14c3; - id->subsystem_device_id = 0x7622; -+ } else if (!strcmp(compat, "mediatek,mt7986-wmac")) { -+ id->vendor_id = 0x14c3; -+ id->device_id = 0x7986; -+ id->subsystem_vendor_id = 0x14c3; -+ id->subsystem_device_id = 0x7986; - } -+ - return (id->vendor_id && id->device_id) ? 0 : -1; - } - diff --git a/package/network/utils/iwinfo/patches/003-devices-add-IPQ8074.patch b/package/network/utils/iwinfo/patches/003-devices-add-IPQ8074.patch deleted file mode 100644 index 068416f74..000000000 --- a/package/network/utils/iwinfo/patches/003-devices-add-IPQ8074.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: Robert Marko -Date: Fri, 6 Jan 2023 09:56:54 +0000 (+0100) -Subject: iwinfo: devices: add Qualcomm Atheros IPQ8074 WiSoC -X-Git-Url: http://git.openwrt.org/?p=project%2Fiwinfo.git;a=commitdiff_plain;h=5914d7113ecf77de63eb21fc233684d1a1a52ca5 - -iwinfo: devices: add Qualcomm Atheros IPQ8074 WiSoC - -Add detection of the Qualcomm Atheros IPQ8074 WiSoC using the compatible -string from device tree. - -Signed-off-by: Robert Marko ---- - ---- a/hardware.txt -+++ b/hardware.txt -@@ -167,6 +167,7 @@ - 0x168c 0x003c 0x1a56 0x1420 0 0 "Qualcomm Atheros" "QCA9862" - 0x168c 0x003c 0x19b6 0xd03c 0 0 "Mikrotik" "R11e-5HacT" - 0x168c 0x003c 0x168c 0x4019 0 0 "Qualcomm Atheros" "IPQ4019" -+0x168c 0x8074 0x168c 0x8074 0 0 "Qualcomm Atheros" "IPQ8074" - 0x168c 0x003c 0x19b6 0xd075 0 0 "Mikrotik" "R11e-5HacD" - 0x168c 0x0040 0x168c 0x0002 0 0 "Qualcomm Atheros" "QCA9990" - 0x168c 0x0046 0x168c 0xcafe 0 0 "Qualcomm Atheros" "QCA9984" ---- a/iwinfo_nl80211.c -+++ b/iwinfo_nl80211.c -@@ -3381,6 +3381,11 @@ static int nl80211_hardware_id_from_fdt( - id->device_id = 0x003c; - id->subsystem_vendor_id = 0x168c; - id->subsystem_device_id = 0x4019; -+ } else if (!strcmp(compat, "qcom,ipq8074-wifi")) { -+ id->vendor_id = 0x168c; -+ id->device_id = 0x8074; -+ id->subsystem_vendor_id = 0x168c; -+ id->subsystem_device_id = 0x8074; - } else if (!strcmp(compat, "mediatek,mt7622-wmac")) { - id->vendor_id = 0x14c3; - id->device_id = 0x7622; diff --git a/package/network/utils/iwinfo/patches/004-devices-add-QCNxxxx.patch b/package/network/utils/iwinfo/patches/004-devices-add-QCNxxxx.patch deleted file mode 100644 index 7cfda2a2b..000000000 --- a/package/network/utils/iwinfo/patches/004-devices-add-QCNxxxx.patch +++ /dev/null @@ -1,23 +0,0 @@ -From: Robert Marko -Date: Fri, 6 Jan 2023 16:33:55 +0000 (+0100) -Subject: devices: add Qualcomm Atheros QCN6024/9024/9074 cards -X-Git-Url: http://git.openwrt.org/?p=project%2Fiwinfo.git;a=commitdiff_plain;h=c7b420a2f33c6f1034c3e2191eba0cb0374af7b6 - -devices: add Qualcomm Atheros QCN6024/9024/9074 cards - -Add Qualcomm Atheros QCN6024/9024/9074 PCI ID, they all are compatible and -use the same ID. - -Signed-off-by: Robert Marko ---- - ---- a/hardware.txt -+++ b/hardware.txt -@@ -173,6 +173,7 @@ - 0x168c 0x0046 0x168c 0xcafe 0 0 "Qualcomm Atheros" "QCA9984" - 0x168c 0x0050 0x0000 0x0000 0 0 "Qualcomm Atheros" "QCA9887" - 0x168c 0x0056 0x0000 0x0000 0 0 "Qualcomm Atheros" "QCA9886" -+0x17cb 0x1104 0x17cb 0x1104 0 0 "Qualcomm Atheros" "QCN6024/9024/9074" - 0x1814 0x3050 0x1814 0x0005 0 0 "Ralink" "Rt3050" - 0x1814 0x3051 0x1814 0x0007 0 0 "Ralink" "Rt3051" - 0x1814 0x3052 0x1814 0x0008 0 0 "Ralink" "Rt3052" diff --git a/package/system/rpcd/Makefile b/package/system/rpcd/Makefile index c63b8acda..de11ecb3f 100644 --- a/package/system/rpcd/Makefile +++ b/package/system/rpcd/Makefile @@ -12,9 +12,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/rpcd.git -PKG_MIRROR_HASH:=18137fa6904b1a7aec03a16a4c25fd9b9689b24ee14d431bacdda9f093339071 -PKG_SOURCE_DATE:=2022-09-21 -PKG_SOURCE_VERSION:=8c852b656bf1622dee1ae2cfa4c083f730c1c539 +PKG_MIRROR_HASH:=7038ab08dc67f7440effbf04ab2f083915c819f758ab16b0fbdf846bd3b87773 +PKG_SOURCE_DATE:=2023-01-21 +PKG_SOURCE_VERSION:=c0df2a7af7d6284f4a446de15d0dab17124d9448 PKG_MAINTAINER:=Jo-Philipp Wich PKG_LICENSE:=ISC