diff --git a/include/image-commands.mk b/include/image-commands.mk index 41e1c96948..074e40e4e8 100644 --- a/include/image-commands.mk +++ b/include/image-commands.mk @@ -307,7 +307,7 @@ define Build/fit endef define Build/gzip - gzip -f -9n -c $@ $(1) > $@.new + $(STAGING_DIR_HOST)/bin/gzip -f -9n -c $@ $(1) > $@.new @mv $@.new $@ endef diff --git a/include/image.mk b/include/image.mk index e9dc53f82e..5d9d4acb41 100644 --- a/include/image.mk +++ b/include/image.mk @@ -520,6 +520,7 @@ define Device/Build/compile $$(_COMPILE_TARGET): $(KDIR)/$(1) $(eval $(call Device/Export,$(KDIR)/$(1))) $(KDIR)/$(1): FORCE + rm -f $(KDIR)/$(1) $$(call concat_cmd,$(COMPILE/$(1))) endef diff --git a/include/kernel-5.10 b/include/kernel-5.10 index bd40dc0f40..abfb0422d1 100644 --- a/include/kernel-5.10 +++ b/include/kernel-5.10 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.10 = .159 -LINUX_KERNEL_HASH-5.10.159 = 1ba9bf57b6bf36d76447d5044b80b746cb5fd61d981c811603dc763b7789cea7 +LINUX_VERSION-5.10 = .160 +LINUX_KERNEL_HASH-5.10.160 = 30d5076acae863941045880c4c5c5109d26a54a932168fa1324237e8aeaa840b diff --git a/include/kernel-5.15 b/include/kernel-5.15 index 9a619067df..5013ce44e2 100644 --- a/include/kernel-5.15 +++ b/include/kernel-5.15 @@ -1,2 +1,2 @@ -LINUX_VERSION-5.15 = .83 -LINUX_KERNEL_HASH-5.15.83 = 40590843c04c85789105157f69efbd71a4efe87ae2568e40d1b7258c3f747ff3 +LINUX_VERSION-5.15 = .84 +LINUX_KERNEL_HASH-5.15.84 = 318dc30cb059c2e35b59652b166b39804bb3a941f11878aae6119019a04b8217 diff --git a/include/trusted-firmware-a.mk b/include/trusted-firmware-a.mk index 0b37c0f943..082ada269c 100644 --- a/include/trusted-firmware-a.mk +++ b/include/trusted-firmware-a.mk @@ -1,5 +1,5 @@ PKG_NAME ?= trusted-firmware-a -PKG_CPE_ID ?= cpe:/a:arm:arm_trusted_firmware +PKG_CPE_ID ?= cpe:/a:arm:trusted_firmware-a ifndef PKG_SOURCE_PROTO PKG_SOURCE = trusted-firmware-a-$(PKG_VERSION).tar.gz diff --git a/package/boot/arm-trusted-firmware-sunxi/Makefile b/package/boot/arm-trusted-firmware-sunxi/Makefile index 430d78f7a3..178b3958b8 100644 --- a/package/boot/arm-trusted-firmware-sunxi/Makefile +++ b/package/boot/arm-trusted-firmware-sunxi/Makefile @@ -8,7 +8,6 @@ include $(TOPDIR)/rules.mk PKG_NAME:=arm-trusted-firmware-sunxi -PKG_CPE_ID:=cpe:/o:arm:arm_trusted_firmware PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git diff --git a/package/boot/uboot-sunxi/patches/252-sunxi-h3-add-support-for-nanopi-r1.patch b/package/boot/uboot-sunxi/patches/252-sunxi-h3-add-support-for-nanopi-r1.patch index 0db7be5421..058b29d95b 100644 --- a/package/boot/uboot-sunxi/patches/252-sunxi-h3-add-support-for-nanopi-r1.patch +++ b/package/boot/uboot-sunxi/patches/252-sunxi-h3-add-support-for-nanopi-r1.patch @@ -173,7 +173,7 @@ Signed-off-by: Jayantajit Gogoi +}; --- /dev/null +++ b/configs/nanopi_r1_defconfig -@@ -0,0 +1,22 @@ +@@ -0,0 +1,21 @@ +CONFIG_ARM=y +CONFIG_ARCH_SUNXI=y +CONFIG_SPL=y @@ -186,7 +186,6 @@ Signed-off-by: Jayantajit Gogoi +CONFIG_NR_DRAM_BANKS=1 +# CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set +CONFIG_CONSOLE_MUX=y -+CONFIG_SYS_CLK_FREQ=480000000 +# CONFIG_CMD_FLASH is not set +# CONFIG_SPL_DOS_PARTITION is not set +# CONFIG_SPL_EFI_PARTITION is not set diff --git a/package/boot/uboot-sunxi/uEnv-default.txt b/package/boot/uboot-sunxi/uEnv-default.txt index e024954516..36e41c59b1 100644 --- a/package/boot/uboot-sunxi/uEnv-default.txt +++ b/package/boot/uboot-sunxi/uEnv-default.txt @@ -1,6 +1,8 @@ setenv fdt_high ffffffff -setenv loadkernel fatload mmc 0 \$kernel_addr_r uImage -setenv loaddtb fatload mmc 0 \$fdt_addr_r dtb -setenv bootargs console=ttyS0,115200 earlyprintk root=/dev/mmcblk0p2 rootwait +setenv mmc_rootpart 2 +part uuid mmc ${mmc_bootdev}:${mmc_rootpart} uuid +setenv loadkernel fatload mmc \$mmc_bootdev \$kernel_addr_r uImage +setenv loaddtb fatload mmc \$mmc_bootdev \$fdt_addr_r dtb +setenv bootargs console=ttyS0,115200 earlyprintk root=PARTUUID=${uuid} rootwait setenv uenvcmd run loadkernel \&\& run loaddtb \&\& bootm \$kernel_addr_r - \$fdt_addr_r run uenvcmd diff --git a/package/firmware/linux-firmware/Makefile b/package/firmware/linux-firmware/Makefile index 4a665ad724..69e3a948ad 100644 --- a/package/firmware/linux-firmware/Makefile +++ b/package/firmware/linux-firmware/Makefile @@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=linux-firmware PKG_VERSION:=20221109 -PKG_RELEASE:=4 +PKG_RELEASE:=5 PKG_SOURCE_URL:=@KERNEL/linux/kernel/firmware PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz diff --git a/package/firmware/linux-firmware/qca_ath11k.mk b/package/firmware/linux-firmware/qca_ath11k.mk new file mode 100644 index 0000000000..3e997bc3f4 --- /dev/null +++ b/package/firmware/linux-firmware/qca_ath11k.mk @@ -0,0 +1,23 @@ +Package/ath11k-firmware-qca6390 = $(call Package/firmware-default,QCA6390 ath11k firmware) +define Package/ath11k-firmware-qca6390/install + $(INSTALL_DIR) $(1)/lib/firmware/ath11k/QCA6390/hw2.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/ath11k/QCA6390/hw2.0/* $(1)/lib/firmware/ath11k/QCA6390/hw2.0/ +endef +$(eval $(call BuildPackage,ath11k-firmware-qca6390)) + +Package/ath11k-firmware-wcn6750 = $(call Package/firmware-default,WCN6750 ath11k firmware) +define Package/ath11k-firmware-wcn6750/install + $(INSTALL_DIR) $(1)/lib/firmware/ath11k/WCN6750/hw1.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/ath11k/WCN6750/hw1.0/* $(1)/lib/firmware/ath11k/WCN6750/hw1.0/ +endef +$(eval $(call BuildPackage,ath11k-firmware-wcn6750)) + +Package/ath11k-firmware-wcn6855 = $(call Package/firmware-default,WCN6855 ath11k firmware) +define Package/ath11k-firmware-wcn6855/install + $(INSTALL_DIR) $(1)/lib/firmware/ath11k/WCN6855/hw2.0 + $(INSTALL_DATA) \ + $(PKG_BUILD_DIR)/ath11k/WCN6855/hw2.0/* $(1)/lib/firmware/ath11k/WCN6855/hw2.0/ +endef +$(eval $(call BuildPackage,ath11k-firmware-wcn6855)) diff --git a/package/kernel/linux/modules/netsupport.mk b/package/kernel/linux/modules/netsupport.mk index a8c343f44b..22c39e8618 100644 --- a/package/kernel/linux/modules/netsupport.mk +++ b/package/kernel/linux/modules/netsupport.mk @@ -1438,3 +1438,67 @@ define KernelPackage/netconsole/description endef $(eval $(call KernelPackage,netconsole)) + + +define KernelPackage/qrtr + SUBMENU:=$(NETWORK_SUPPORT_MENU) + TITLE:=Qualcomm IPC Router support + HIDDEN:=1 + DEPENDS:=@!LINUX_5_10 + KCONFIG:=CONFIG_QRTR + FILES:= \ + $(LINUX_DIR)/net/qrtr/qrtr.ko \ + $(LINUX_DIR)/net/qrtr/ns.ko + AUTOLOAD:=$(call AutoProbe,qrtr) +endef + +define KernelPackage/qrtr/description + Qualcomm IPC Router support +endef + +$(eval $(call KernelPackage,qrtr)) + +define KernelPackage/qrtr-tun + SUBMENU:=$(NETWORK_SUPPORT_MENU) + TITLE:=TUN device for Qualcomm IPC Router + DEPENDS:=+kmod-qrtr + KCONFIG:=CONFIG_QRTR_TUN + FILES:= $(LINUX_DIR)/net/qrtr/qrtr-tun.ko + AUTOLOAD:=$(call AutoProbe,qrtr-tun) +endef + +define KernelPackage/qrtr-tun/description + TUN device for Qualcomm IPC Router +endef + +$(eval $(call KernelPackage,qrtr-tun)) + +define KernelPackage/qrtr-smd + SUBMENU:=$(NETWORK_SUPPORT_MENU) + TITLE:=SMD IPC Router channels + DEPENDS:=+kmod-qrtr @TARGET_ipq807x + KCONFIG:=CONFIG_QRTR_SMD + FILES:= $(LINUX_DIR)/net/qrtr/qrtr-smd.ko + AUTOLOAD:=$(call AutoProbe,qrtr-smd) +endef + +define KernelPackage/qrtr-smd/description + SMD IPC Router channels +endef + +$(eval $(call KernelPackage,qrtr-smd)) + +define KernelPackage/qrtr-mhi + SUBMENU:=$(NETWORK_SUPPORT_MENU) + TITLE:=MHI IPC Router channels + DEPENDS:=+kmod-mhi-bus +kmod-qrtr + KCONFIG:=CONFIG_QRTR_MHI + FILES:= $(LINUX_DIR)/net/qrtr/qrtr-mhi.ko + AUTOLOAD:=$(call AutoProbe,qrtr-mhi) +endef + +define KernelPackage/qrtr-mhi/description + MHI IPC Router channels +endef + +$(eval $(call KernelPackage,qrtr-mhi)) diff --git a/package/kernel/mac80211/Makefile b/package/kernel/mac80211/Makefile index 58f07e1eeb..1344b9f8e2 100644 --- a/package/kernel/mac80211/Makefile +++ b/package/kernel/mac80211/Makefile @@ -11,7 +11,7 @@ include $(INCLUDE_DIR)/kernel.mk PKG_NAME:=mac80211 PKG_VERSION:=6.1-rc8 -PKG_RELEASE:=1 +PKG_RELEASE:=2 # PKG_SOURCE_URL:=@KERNEL/linux/kernel/projects/backports/stable/v5.15.58/ PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources/ PKG_HASH:=7f3d96c2573183cd79d6a3ebe5e1b7b73c19d1326d443c85b69c4181f14e6e2b @@ -307,6 +307,7 @@ define Build/Prepare $(PKG_BUILD_DIR)/include/linux/crc8.h \ $(PKG_BUILD_DIR)/include/linux/eeprom_93cx6.h \ $(PKG_BUILD_DIR)/include/linux/wl12xx.h \ + $(PKG_BUILD_DIR)/include/linux/mhi.h \ $(PKG_BUILD_DIR)/include/net/ieee80211.h \ $(PKG_BUILD_DIR)/backport-include/linux/bcm47xx_nvram.h diff --git a/package/kernel/mac80211/ath.mk b/package/kernel/mac80211/ath.mk index ad278168cc..8566726a7f 100644 --- a/package/kernel/mac80211/ath.mk +++ b/package/kernel/mac80211/ath.mk @@ -1,6 +1,6 @@ PKG_DRIVERS += \ ath ath5k ath6kl ath6kl-sdio ath6kl-usb ath9k ath9k-common ath9k-htc ath10k ath10k-smallbuffers \ - carl9170 owl-loader ar5523 wil6210 + ath11k ath11k-pci carl9170 owl-loader ar5523 wil6210 PKG_CONFIG_DEPENDS += \ CONFIG_PACKAGE_ATH_DEBUG \ @@ -12,6 +12,7 @@ PKG_CONFIG_DEPENDS += \ CONFIG_ATH9K_TX99 \ CONFIG_ATH10K_LEDS \ CONFIG_ATH10K_THERMAL \ + CONFIG_ATH11K_THERMAL \ CONFIG_ATH_USER_REGD ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS @@ -19,6 +20,7 @@ ifdef CONFIG_PACKAGE_MAC80211_DEBUGFS ATH9K_DEBUGFS \ ATH9K_HTC_DEBUGFS \ ATH10K_DEBUGFS \ + ATH11K_DEBUGFS \ CARL9170_DEBUGFS \ ATH5K_DEBUG \ ATH6KL_DEBUG \ @@ -28,6 +30,7 @@ endif ifdef CONFIG_PACKAGE_MAC80211_TRACING config-y += \ ATH10K_TRACING \ + ATH11K_TRACING \ ATH6KL_TRACING \ ATH_TRACEPOINTS \ ATH5K_TRACER \ @@ -35,9 +38,9 @@ ifdef CONFIG_PACKAGE_MAC80211_TRACING endif config-$(call config_package,ath) += ATH_CARDS ATH_COMMON -config-$(CONFIG_PACKAGE_ATH_DEBUG) += ATH_DEBUG ATH10K_DEBUG ATH9K_STATION_STATISTICS +config-$(CONFIG_PACKAGE_ATH_DEBUG) += ATH_DEBUG ATH10K_DEBUG ATH11K_DEBUG ATH9K_STATION_STATISTICS config-$(CONFIG_PACKAGE_ATH_DFS) += ATH9K_DFS_CERTIFIED ATH10K_DFS_CERTIFIED -config-$(CONFIG_PACKAGE_ATH_SPECTRAL) += ATH9K_COMMON_SPECTRAL ATH10K_SPECTRAL +config-$(CONFIG_PACKAGE_ATH_SPECTRAL) += ATH9K_COMMON_SPECTRAL ATH10K_SPECTRAL ATH11K_SPECTRAL config-$(CONFIG_PACKAGE_ATH_DYNACK) += ATH9K_DYNACK config-$(call config_package,ath9k) += ATH9K config-$(call config_package,ath9k-common) += ATH9K_COMMON @@ -52,10 +55,13 @@ config-$(CONFIG_ATH9K_TX99) += ATH9K_TX99 config-$(CONFIG_ATH9K_UBNTHSR) += ATH9K_UBNTHSR config-$(CONFIG_ATH10K_LEDS) += ATH10K_LEDS config-$(CONFIG_ATH10K_THERMAL) += ATH10K_THERMAL +config-$(CONFIG_ATH11K_THERMAL) += ATH11K_THERMAL config-$(call config_package,ath9k-htc) += ATH9K_HTC config-$(call config_package,ath10k) += ATH10K ATH10K_PCI config-$(call config_package,ath10k-smallbuffers) += ATH10K ATH10K_PCI ATH10K_SMALLBUFFERS +config-$(call config_package,ath11k) += ATH11K +config-$(call config_package,ath11k-pci) += ATH11K_PCI config-$(call config_package,ath5k) += ATH5K ifdef CONFIG_TARGET_ath25 @@ -291,6 +297,43 @@ define KernelPackage/ath10k-smallbuffers VARIANT:=smallbuffers endef +define KernelPackage/ath11k + $(call KernelPackage/mac80211/Default) + TITLE:=Qualcomm 802.11ax wireless chipset support (common code) + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath11k + DEPENDS+= +kmod-ath +@DRIVER_11AC_SUPPORT +@DRIVER_11AX_SUPPORT \ + +kmod-crypto-michael-mic +ATH11K_THERMAL:kmod-hwmon-core +ATH11K_THERMAL:kmod-thermal + FILES:=$(PKG_BUILD_DIR)/drivers/soc/qcom/qmi_helpers.ko \ + $(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath11k/ath11k.ko +endef + +define KernelPackage/ath11k/description +This module adds support for Qualcomm Technologies 802.11ax family of +chipsets. +endef + +define KernelPackage/ath11k/config + + config ATH11K_THERMAL + bool "Enable thermal sensors and throttling support" + depends on PACKAGE_kmod-ath11k + +endef + +define KernelPackage/ath11k-pci + $(call KernelPackage/mac80211/Default) + TITLE:=Qualcomm 802.11ax PCI wireless chipset support + URL:=https://wireless.wiki.kernel.org/en/users/drivers/ath11k + DEPENDS+= @PCI_SUPPORT +kmod-qrtr-mhi +kmod-ath11k + FILES:=$(PKG_BUILD_DIR)/drivers/net/wireless/ath/ath11k/ath11k_pci.ko + AUTOLOAD:=$(call AutoProbe,ath11k_pci) +endef + +define KernelPackage/ath11k-pci/description +This module adds support for Qualcomm Technologies 802.11ax family of +chipsets with PCI bus. +endef + define KernelPackage/carl9170 $(call KernelPackage/mac80211/Default) TITLE:=Driver for Atheros AR9170 USB sticks diff --git a/package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-stop-tx-queues-immediately-upon-firmware.patch b/package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-stop-tx-queues-immediately-upon-firmware.patch new file mode 100644 index 0000000000..ae8920c62f --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0001-wifi-ath11k-stop-tx-queues-immediately-upon-firmware.patch @@ -0,0 +1,78 @@ +From 81e60b2dfb2744ab6642c4aa62534b4f711fdc5d Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Tue, 27 Sep 2022 09:18:54 +0300 +Subject: [PATCH] wifi: ath11k: stop tx queues immediately upon firmware exit + +Currently, recovery flag is set immediately upon firmware +exit but tx queues are stopped once firmware arrives back +and is ready which is during ath11k_core_restart. Once +ieee80211 hw restart is completed, tx queues are resumed. +If during the time delta between firmware exit and firmware +ready, mac80211 send packets, currently ath11k will drop it +since recovery flag will be set. But warning prints will +come - + "ath11k c000000.wifi: failed to transmit frame -108" + +If more tx packets are there, this could lead to flooding +of above print. + +However, actually tx queues should be stopped immediately +when firmware leaves. This will prevent packets to get +dropped when firmware is recovering. + +Add fix to stop tx queues immediately after firmware exit. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aditya Kumar Singh +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220923170235.18873-1-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 5 +---- + drivers/net/wireless/ath/ath11k/core.h | 1 + + drivers/net/wireless/ath/ath11k/qmi.c | 3 +++ + 3 files changed, 5 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -1641,7 +1641,7 @@ static void ath11k_update_11d(struct wor + } + } + +-static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) ++void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) + { + struct ath11k *ar; + struct ath11k_pdev *pdev; +@@ -1730,9 +1730,6 @@ static void ath11k_core_restart(struct w + struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work); + int ret; + +- if (!ab->is_reset) +- ath11k_core_pre_reconfigure_recovery(ab); +- + ret = ath11k_core_reconfigure_on_crash(ab); + if (ret) { + ath11k_err(ab, "failed to reconfigure driver on crash recovery\n"); +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -1157,6 +1157,7 @@ int ath11k_core_check_smbios(struct ath1 + void ath11k_core_halt(struct ath11k *ar); + int ath11k_core_resume(struct ath11k_base *ab); + int ath11k_core_suspend(struct ath11k_base *ab); ++void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab); + + const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, + const char *filename); +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -3158,6 +3158,9 @@ static void ath11k_qmi_driver_event_work + case ATH11K_QMI_EVENT_SERVER_EXIT: + set_bit(ATH11K_FLAG_CRASH_FLUSH, &ab->dev_flags); + set_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags); ++ ++ if (!ab->is_reset) ++ ath11k_core_pre_reconfigure_recovery(ab); + break; + case ATH11K_QMI_EVENT_REQUEST_MEM: + ret = ath11k_qmi_event_mem_request(qmi); diff --git a/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-Don-t-exit-on-wakeup-failure.patch b/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-Don-t-exit-on-wakeup-failure.patch new file mode 100644 index 0000000000..47385e0458 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0002-wifi-ath11k-Don-t-exit-on-wakeup-failure.patch @@ -0,0 +1,45 @@ +From 45d2e268369b0c768d5a644f319758bcfd370521 Mon Sep 17 00:00:00 2001 +From: Baochen Qiang +Date: Wed, 28 Sep 2022 09:51:40 +0800 +Subject: [PATCH] wifi: ath11k: Don't exit on wakeup failure + +Currently, ath11k_pcic_read() returns an error if wakeup() +fails, this makes firmware crash debug quite hard because we can +get nothing. + +Change to go ahead on wakeup failure, in that case we still may +get something valid to check. There should be no mislead due +to incorrect content because we are aware of the failure with the +log printed. + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1 + +Signed-off-by: Baochen Qiang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220928015140.5431-1-quic_bqiang@quicinc.com +--- + drivers/net/wireless/ath/ath11k/pcic.c | 13 ++++++++++--- + 1 file changed, 10 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/pcic.c ++++ b/drivers/net/wireless/ath/ath11k/pcic.c +@@ -218,9 +218,16 @@ int ath11k_pcic_read(struct ath11k_base + if (wakeup_required && ab->pci.ops->wakeup) { + ret = ab->pci.ops->wakeup(ab); + if (ret) { +- ath11k_warn(ab, "failed to wakeup for read from 0x%x: %d\n", +- start, ret); +- return ret; ++ ath11k_warn(ab, ++ "wakeup failed, data may be invalid: %d", ++ ret); ++ /* Even though wakeup() failed, continue processing rather ++ * than returning because some parts of the data may still ++ * be valid and useful in some cases, e.g. could give us ++ * some clues on firmware crash. ++ * Mislead due to invalid data could be avoided because we ++ * are aware of the wakeup failure. ++ */ + } + } + diff --git a/package/kernel/mac80211/patches/ath11k/0003-wifi-ath11k-fix-warning-in-dma_free_coherent-of-memo.patch b/package/kernel/mac80211/patches/ath11k/0003-wifi-ath11k-fix-warning-in-dma_free_coherent-of-memo.patch new file mode 100644 index 0000000000..661f4bbfbf --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0003-wifi-ath11k-fix-warning-in-dma_free_coherent-of-memo.patch @@ -0,0 +1,139 @@ +From f74878433d5ade360447da5d92e9c2e535780d80 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Wed, 28 Sep 2022 03:38:32 -0400 +Subject: [PATCH] wifi: ath11k: fix warning in dma_free_coherent() of memory + chunks while recovery + +Commit 26f3a021b37c ("ath11k: allocate smaller chunks of memory for +firmware") and commit f6f92968e1e5 ("ath11k: qmi: try to allocate a +big block of DMA memory first") change ath11k to allocate the memory +chunks for target twice while wlan load. It fails for the 1st time +because of large memory and then changed to allocate many small chunks +for the 2nd time sometimes as below log. + +1st time failed: +[10411.640620] ath11k_pci 0000:05:00.0: qmi firmware request memory request +[10411.640625] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 6881280 +[10411.640630] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 3784704 +[10411.640658] ath11k_pci 0000:05:00.0: qmi dma allocation failed (6881280 B type 1), will try later with small size +[10411.640671] ath11k_pci 0000:05:00.0: qmi delays mem_request 2 +[10411.640677] ath11k_pci 0000:05:00.0: qmi respond memory request delayed 1 +2nd time success: +[10411.642004] ath11k_pci 0000:05:00.0: qmi firmware request memory request +[10411.642008] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288 +[10411.642012] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288 +[10411.642014] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288 +[10411.642016] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288 +[10411.642018] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288 +[10411.642020] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288 +[10411.642022] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288 +[10411.642024] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288 +[10411.642027] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288 +[10411.642029] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288 +[10411.642031] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 458752 +[10411.642033] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 131072 +[10411.642035] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288 +[10411.642037] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288 +[10411.642039] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288 +[10411.642041] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288 +[10411.642043] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288 +[10411.642045] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 524288 +[10411.642047] ath11k_pci 0000:05:00.0: qmi mem seg type 4 size 491520 +[10411.642049] ath11k_pci 0000:05:00.0: qmi mem seg type 1 size 524288 + +And then commit 5962f370ce41 ("ath11k: Reuse the available memory after +firmware reload") skip the ath11k_qmi_free_resource() which frees the +memory chunks while recovery, after that, when run recovery test on +WCN6855, a warning happened every time as below and finally leads fail +for recovery. + +[ 159.570318] BUG: Bad page state in process kworker/u16:5 pfn:33300 +[ 159.570320] page:0000000096ffdbb9 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x33300 +[ 159.570324] flags: 0xfffffc0000000(node=0|zone=1|lastcpupid=0x1fffff) +[ 159.570329] raw: 000fffffc0000000 0000000000000000 dead000000000122 0000000000000000 +[ 159.570332] raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000 +[ 159.570334] page dumped because: nonzero _refcount +[ 159.570440] firewire_ohci syscopyarea sysfillrect psmouse sdhci_pci ahci sysimgblt firewire_core fb_sys_fops libahci crc_itu_t cqhci drm sdhci e1000e wmi video +[ 159.570460] CPU: 2 PID: 217 Comm: kworker/u16:5 Kdump: loaded Tainted: G B 5.19.0-rc1-wt-ath+ #3 +[ 159.570465] Hardware name: LENOVO 418065C/418065C, BIOS 83ET63WW (1.33 ) 07/29/2011 +[ 159.570467] Workqueue: qmi_msg_handler qmi_data_ready_work [qmi_helpers] +[ 159.570475] Call Trace: +[ 159.570476] +[ 159.570478] dump_stack_lvl+0x49/0x5f +[ 159.570486] dump_stack+0x10/0x12 +[ 159.570493] bad_page+0xab/0xf0 +[ 159.570502] check_free_page_bad+0x66/0x70 +[ 159.570511] __free_pages_ok+0x530/0x9a0 +[ 159.570517] ? __dev_printk+0x58/0x6b +[ 159.570525] ? _dev_printk+0x56/0x72 +[ 159.570534] ? qmi_decode+0x119/0x470 [qmi_helpers] +[ 159.570543] __free_pages+0x91/0xd0 +[ 159.570548] dma_free_contiguous+0x50/0x60 +[ 159.570556] dma_direct_free+0xe5/0x140 +[ 159.570564] dma_free_attrs+0x35/0x50 +[ 159.570570] ath11k_qmi_msg_mem_request_cb+0x2ae/0x3c0 [ath11k] +[ 159.570620] qmi_invoke_handler+0xac/0xe0 [qmi_helpers] +[ 159.570630] qmi_handle_message+0x6d/0x180 [qmi_helpers] +[ 159.570643] qmi_data_ready_work+0x2ca/0x440 [qmi_helpers] +[ 159.570656] process_one_work+0x227/0x440 +[ 159.570667] worker_thread+0x31/0x3d0 +[ 159.570676] ? process_one_work+0x440/0x440 +[ 159.570685] kthread+0xfe/0x130 +[ 159.570692] ? kthread_complete_and_exit+0x20/0x20 +[ 159.570701] ret_from_fork+0x22/0x30 +[ 159.570712] + +The reason is because when wlan start to recovery, the type, size and +count is not same for the 1st and 2nd QMI_WLFW_REQUEST_MEM_IND message, +Then it leads the parameter size is not correct for the dma_free_coherent(). +For the chunk[1], the actual dma size is 524288 which allocate in the +2nd time of the initial wlan load phase, and the size which pass to +dma_free_coherent() is 3784704 which is got in the 1st time of recovery +phase, then warning above happened. + +Change to use prev_size of struct target_mem_chunk for the paramter of +dma_free_coherent() since prev_size is the real size of last load/recovery. +Also change to check both type and size of struct target_mem_chunk to +reuse the memory to avoid mismatch buffer size for target. Then the +warning disappear and recovery success. When the 1st QMI_WLFW_REQUEST_MEM_IND +for recovery arrived, the trunk[0] is freed in ath11k_qmi_alloc_target_mem_chunk() +and then dma_alloc_coherent() failed caused by large size, and then +trunk[1] is freed in ath11k_qmi_free_target_mem_chunk(), the left 18 +trunks will be reuse for the 2nd QMI_WLFW_REQUEST_MEM_IND message. + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 + +Fixes: 5962f370ce41 ("ath11k: Reuse the available memory after firmware reload") +Signed-off-by: Wen Gong +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220928073832.16251-1-quic_wgong@quicinc.com +--- + drivers/net/wireless/ath/ath11k/qmi.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -1961,7 +1961,7 @@ static void ath11k_qmi_free_target_mem_c + continue; + + dma_free_coherent(ab->dev, +- ab->qmi.target_mem[i].size, ++ ab->qmi.target_mem[i].prev_size, + ab->qmi.target_mem[i].vaddr, + ab->qmi.target_mem[i].paddr); + ab->qmi.target_mem[i].vaddr = NULL; +@@ -1982,12 +1982,12 @@ static int ath11k_qmi_alloc_target_mem_c + * in such case, no need to allocate memory for FW again. + */ + if (chunk->vaddr) { +- if (chunk->prev_type == chunk->type || ++ if (chunk->prev_type == chunk->type && + chunk->prev_size == chunk->size) + continue; + + /* cannot reuse the existing chunk */ +- dma_free_coherent(ab->dev, chunk->size, ++ dma_free_coherent(ab->dev, chunk->prev_size, + chunk->vaddr, chunk->paddr); + chunk->vaddr = NULL; + } diff --git a/package/kernel/mac80211/patches/ath11k/0005-wifi-ath11k-Fix-spelling-mistake-chnange-change.patch b/package/kernel/mac80211/patches/ath11k/0005-wifi-ath11k-Fix-spelling-mistake-chnange-change.patch new file mode 100644 index 0000000000..4b52252ef3 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0005-wifi-ath11k-Fix-spelling-mistake-chnange-change.patch @@ -0,0 +1,25 @@ +From a797f479bf3e02c6d179c2e6aeace7f9b22b0acd Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Wed, 28 Sep 2022 15:38:34 +0100 +Subject: [PATCH] wifi: ath11k: Fix spelling mistake "chnange" -> "change" + +There is a spelling mistake in an ath11k_dbg debug message. Fix it. + +Signed-off-by: Colin Ian King +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220928143834.35189-1-colin.i.king@gmail.com +--- + drivers/net/wireless/ath/ath11k/wmi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -6829,7 +6829,7 @@ static void ath11k_wmi_event_peer_sta_ps + } + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "peer sta ps chnange ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n", ++ "peer sta ps change ev addr %pM state %u sup_bitmap %x ps_valid %u ts %u\n", + ev->peer_macaddr.addr, ev->peer_ps_state, + ev->ps_supported_bitmap, ev->peer_ps_valid, + ev->peer_ps_timestamp); diff --git a/package/kernel/mac80211/patches/ath11k/0006-wifi-ath11k-fix-firmware-assert-during-bandwidth-cha.patch b/package/kernel/mac80211/patches/ath11k/0006-wifi-ath11k-fix-firmware-assert-during-bandwidth-cha.patch new file mode 100644 index 0000000000..f4fedb46cc --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0006-wifi-ath11k-fix-firmware-assert-during-bandwidth-cha.patch @@ -0,0 +1,225 @@ +From 3ff51d7416ee1ea2d771051a0ffa1ec8be054768 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 5 Oct 2022 15:24:30 +0530 +Subject: [PATCH 6/9] wifi: ath11k: fix firmware assert during bandwidth change + for peer sta + +Currently, ath11k sends peer assoc command for each peer to +firmware when bandwidth changes. Peer assoc command is a +bulky command and if many clients are connected, this could +lead to firmware buffer getting overflowed leading to a firmware +assert. + +However, during bandwidth change, only phymode and bandwidth +also can be updated by WMI set peer param command. This makes +the overall command light when compared to peer assoc and for +multi-client cases, firmware buffer overflow also does not +occur. + +Remove sending peer assoc command during sta bandwidth change +and instead add sending WMI set peer param command for phymode +and bandwidth. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 + +Fixes: f187fe8e3bc65 ("ath11k: fix firmware crash during channel switch") +Signed-off-by: Aditya Kumar Singh +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221005095430.19890-1-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.h | 2 + + drivers/net/wireless/ath/ath11k/mac.c | 122 +++++++++++++++++-------- + 2 files changed, 87 insertions(+), 37 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/core.h ++++ b/drivers/net/wireless/ath/ath11k/core.h +@@ -505,6 +505,8 @@ struct ath11k_sta { + u64 ps_start_jiffies; + u64 ps_total_duration; + bool peer_current_ps_valid; ++ ++ u32 bw_prev; + }; + + #define ATH11K_MIN_5G_FREQ 4150 +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -4215,10 +4215,11 @@ static void ath11k_sta_rc_update_wk(stru + const u8 *ht_mcs_mask; + const u16 *vht_mcs_mask; + const u16 *he_mcs_mask; +- u32 changed, bw, nss, smps; ++ u32 changed, bw, nss, smps, bw_prev; + int err, num_vht_rates, num_he_rates; + const struct cfg80211_bitrate_mask *mask; + struct peer_assoc_params peer_arg; ++ enum wmi_phy_mode peer_phymode; + + arsta = container_of(wk, struct ath11k_sta, update_wk); + sta = container_of((void *)arsta, struct ieee80211_sta, drv_priv); +@@ -4239,6 +4240,7 @@ static void ath11k_sta_rc_update_wk(stru + arsta->changed = 0; + + bw = arsta->bw; ++ bw_prev = arsta->bw_prev; + nss = arsta->nss; + smps = arsta->smps; + +@@ -4252,26 +4254,57 @@ static void ath11k_sta_rc_update_wk(stru + ath11k_mac_max_he_nss(he_mcs_mask))); + + if (changed & IEEE80211_RC_BW_CHANGED) { +- /* Send peer assoc command before set peer bandwidth param to +- * avoid the mismatch between the peer phymode and the peer +- * bandwidth. +- */ +- ath11k_peer_assoc_prepare(ar, arvif->vif, sta, &peer_arg, true); ++ /* Get the peer phymode */ ++ ath11k_peer_assoc_h_phymode(ar, arvif->vif, sta, &peer_arg); ++ peer_phymode = peer_arg.peer_phymode; ++ ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac update sta %pM peer bw %d phymode %d\n", ++ sta->addr, bw, peer_phymode); ++ ++ if (bw > bw_prev) { ++ /* BW is upgraded. In this case we send WMI_PEER_PHYMODE ++ * followed by WMI_PEER_CHWIDTH ++ */ ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW upgrade for sta %pM new BW %d, old BW %d\n", ++ sta->addr, bw, bw_prev); ++ ++ err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, ++ WMI_PEER_PHYMODE, peer_phymode); ++ ++ if (err) { ++ ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n", ++ sta->addr, peer_phymode, err); ++ goto err_rc_bw_changed; ++ } + +- peer_arg.is_assoc = false; +- err = ath11k_wmi_send_peer_assoc_cmd(ar, &peer_arg); +- if (err) { +- ath11k_warn(ar->ab, "failed to send peer assoc for STA %pM vdev %i: %d\n", +- sta->addr, arvif->vdev_id, err); +- } else if (wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) { + err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, + WMI_PEER_CHWIDTH, bw); ++ + if (err) + ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", + sta->addr, bw, err); + } else { +- ath11k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n", +- sta->addr, arvif->vdev_id); ++ /* BW is downgraded. In this case we send WMI_PEER_CHWIDTH ++ * followed by WMI_PEER_PHYMODE ++ */ ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac BW downgrade for sta %pM new BW %d,old BW %d\n", ++ sta->addr, bw, bw_prev); ++ ++ err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, ++ WMI_PEER_CHWIDTH, bw); ++ ++ if (err) { ++ ath11k_warn(ar->ab, "failed to update STA %pM peer bw %d: %d\n", ++ sta->addr, bw, err); ++ goto err_rc_bw_changed; ++ } ++ ++ err = ath11k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id, ++ WMI_PEER_PHYMODE, peer_phymode); ++ ++ if (err) ++ ath11k_warn(ar->ab, "failed to update STA %pM peer phymode %d: %d\n", ++ sta->addr, peer_phymode, err); + } + } + +@@ -4352,6 +4385,7 @@ static void ath11k_sta_rc_update_wk(stru + } + } + ++err_rc_bw_changed: + mutex_unlock(&ar->conf_mutex); + } + +@@ -4505,6 +4539,34 @@ exit: + return ret; + } + ++static u32 ath11k_mac_ieee80211_sta_bw_to_wmi(struct ath11k *ar, ++ struct ieee80211_sta *sta) ++{ ++ u32 bw = WMI_PEER_CHWIDTH_20MHZ; ++ ++ switch (sta->deflink.bandwidth) { ++ case IEEE80211_STA_RX_BW_20: ++ bw = WMI_PEER_CHWIDTH_20MHZ; ++ break; ++ case IEEE80211_STA_RX_BW_40: ++ bw = WMI_PEER_CHWIDTH_40MHZ; ++ break; ++ case IEEE80211_STA_RX_BW_80: ++ bw = WMI_PEER_CHWIDTH_80MHZ; ++ break; ++ case IEEE80211_STA_RX_BW_160: ++ bw = WMI_PEER_CHWIDTH_160MHZ; ++ break; ++ default: ++ ath11k_warn(ar->ab, "Invalid bandwidth %d for %pM\n", ++ sta->deflink.bandwidth, sta->addr); ++ bw = WMI_PEER_CHWIDTH_20MHZ; ++ break; ++ } ++ ++ return bw; ++} ++ + static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_sta *sta, +@@ -4590,6 +4652,12 @@ static int ath11k_mac_op_sta_state(struc + if (ret) + ath11k_warn(ar->ab, "Failed to associate station: %pM\n", + sta->addr); ++ ++ spin_lock_bh(&ar->data_lock); ++ /* Set arsta bw and prev bw */ ++ arsta->bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta); ++ arsta->bw_prev = arsta->bw; ++ spin_unlock_bh(&ar->data_lock); + } else if (old_state == IEEE80211_STA_ASSOC && + new_state == IEEE80211_STA_AUTHORIZED) { + spin_lock_bh(&ar->ab->base_lock); +@@ -4713,28 +4781,8 @@ static void ath11k_mac_op_sta_rc_update( + spin_lock_bh(&ar->data_lock); + + if (changed & IEEE80211_RC_BW_CHANGED) { +- bw = WMI_PEER_CHWIDTH_20MHZ; +- +- switch (sta->deflink.bandwidth) { +- case IEEE80211_STA_RX_BW_20: +- bw = WMI_PEER_CHWIDTH_20MHZ; +- break; +- case IEEE80211_STA_RX_BW_40: +- bw = WMI_PEER_CHWIDTH_40MHZ; +- break; +- case IEEE80211_STA_RX_BW_80: +- bw = WMI_PEER_CHWIDTH_80MHZ; +- break; +- case IEEE80211_STA_RX_BW_160: +- bw = WMI_PEER_CHWIDTH_160MHZ; +- break; +- default: +- ath11k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n", +- sta->deflink.bandwidth, sta->addr); +- bw = WMI_PEER_CHWIDTH_20MHZ; +- break; +- } +- ++ bw = ath11k_mac_ieee80211_sta_bw_to_wmi(ar, sta); ++ arsta->bw_prev = arsta->bw; + arsta->bw = bw; + } + diff --git a/package/kernel/mac80211/patches/ath11k/0007-wifi-ath11k-suppress-add-interface-error.patch b/package/kernel/mac80211/patches/ath11k/0007-wifi-ath11k-suppress-add-interface-error.patch new file mode 100644 index 0000000000..fbef0abb8d --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0007-wifi-ath11k-suppress-add-interface-error.patch @@ -0,0 +1,52 @@ +From 638b26652b0438563a76ec90014c8cba34db982b Mon Sep 17 00:00:00 2001 +From: Karthikeyan Periyasamy +Date: Thu, 6 Oct 2022 06:28:42 +0530 +Subject: [PATCH 7/9] wifi: ath11k: suppress add interface error + +In the VIF (other than monitor type) creation request, we should not +throw the error code when the monitor VIF creation fails, since the +actual VIF creation succeeds. If we throw the error code from driver +then the actual VIF creation get fail. So suppress the monitor VIF +creation error by throwing warning message instead of error code. + +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.6.0.1-00760-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Karthikeyan Periyasamy +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221006005842.8599-1-quic_periyasa@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -6421,18 +6421,16 @@ static int ath11k_mac_op_add_interface(s + + ath11k_dp_vdev_tx_attach(ar, arvif); + ++ ath11k_debugfs_add_interface(arvif); ++ + if (vif->type != NL80211_IFTYPE_MONITOR && + test_bit(ATH11K_FLAG_MONITOR_CONF_ENABLED, &ar->monitor_flags)) { + ret = ath11k_mac_monitor_vdev_create(ar); +- if (ret) { ++ if (ret) + ath11k_warn(ar->ab, "failed to create monitor vdev during add interface: %d", + ret); +- goto err_peer_del; +- } + } + +- ath11k_debugfs_add_interface(arvif); +- + mutex_unlock(&ar->conf_mutex); + + return 0; +@@ -6457,7 +6455,6 @@ err_vdev_del: + spin_unlock_bh(&ar->data_lock); + + err: +- ath11k_debugfs_remove_interface(arvif); + mutex_unlock(&ar->conf_mutex); + + return ret; diff --git a/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-add-support-to-configure-channel-dwell-t.patch b/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-add-support-to-configure-channel-dwell-t.patch new file mode 100644 index 0000000000..d0b19fe59f --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0008-wifi-ath11k-add-support-to-configure-channel-dwell-t.patch @@ -0,0 +1,102 @@ +From c362daa213cdeb0a9e7c2ed84849544c24505720 Mon Sep 17 00:00:00 2001 +From: Manikanta Pubbisetty +Date: Fri, 7 Oct 2022 10:41:30 +0530 +Subject: [PATCH 8/9] wifi: ath11k: add support to configure channel dwell time + +Add support to configure channel dwell time during scan. +Dwell time help to stay on the channel for a specified duration +during scan and aid userspace in finding WiFi networks. Very +useful in passive scans where longer dwell times are needed +to find the WiFi networks. + +Configure channel dwell time from duration of the scan request +received from mac80211 when the duration is non-zero. When the +scan request does not have duration value, use the default ones, +the current implementation. + +Advertise corresponding feature flag NL80211_EXT_FEATURE_SET_SCAN_DWELL +to enable the feature. + +Change is applicable for all ath11k hardware. + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1 + +Signed-off-by: Manikanta Pubbisetty +Reviewed-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221007051130.6067-1-quic_mpubbise@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 33 +++++++++++++++++++++++---- + 1 file changed, 29 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -241,7 +241,10 @@ const struct htt_rx_ring_tlv_filter ath1 + #define ath11k_a_rates (ath11k_legacy_rates + 4) + #define ath11k_a_rates_size (ARRAY_SIZE(ath11k_legacy_rates) - 4) + +-#define ATH11K_MAC_SCAN_TIMEOUT_MSECS 200 /* in msecs */ ++#define ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD 200 /* in msecs */ ++ ++/* Overhead due to the processing of channel switch events from FW */ ++#define ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD 10 /* in msecs */ + + static const u32 ath11k_smps_map[] = { + [WLAN_HT_CAP_SM_PS_STATIC] = WMI_PEER_SMPS_STATIC, +@@ -3612,6 +3615,7 @@ static int ath11k_mac_op_hw_scan(struct + struct scan_req_params arg; + int ret = 0; + int i; ++ u32 scan_timeout; + + mutex_lock(&ar->conf_mutex); + +@@ -3681,6 +3685,26 @@ static int ath11k_mac_op_hw_scan(struct + ether_addr_copy(arg.mac_mask.addr, req->mac_addr_mask); + } + ++ /* if duration is set, default dwell times will be overwritten */ ++ if (req->duration) { ++ arg.dwell_time_active = req->duration; ++ arg.dwell_time_active_2g = req->duration; ++ arg.dwell_time_active_6g = req->duration; ++ arg.dwell_time_passive = req->duration; ++ arg.dwell_time_passive_6g = req->duration; ++ arg.burst_duration = req->duration; ++ ++ scan_timeout = min_t(u32, arg.max_rest_time * ++ (arg.num_chan - 1) + (req->duration + ++ ATH11K_SCAN_CHANNEL_SWITCH_WMI_EVT_OVERHEAD) * ++ arg.num_chan, arg.max_scan_time); ++ } else { ++ scan_timeout = arg.max_scan_time; ++ } ++ ++ /* Add a margin to account for event/command processing */ ++ scan_timeout += ATH11K_MAC_SCAN_CMD_EVT_OVERHEAD; ++ + ret = ath11k_start_scan(ar, &arg); + if (ret) { + ath11k_warn(ar->ab, "failed to start hw scan: %d\n", ret); +@@ -3689,10 +3713,8 @@ static int ath11k_mac_op_hw_scan(struct + spin_unlock_bh(&ar->data_lock); + } + +- /* Add a 200ms margin to account for event/command processing */ + ieee80211_queue_delayed_work(ar->hw, &ar->scan.timeout, +- msecs_to_jiffies(arg.max_scan_time + +- ATH11K_MAC_SCAN_TIMEOUT_MSECS)); ++ msecs_to_jiffies(scan_timeout)); + + exit: + kfree(arg.chan_list); +@@ -9060,6 +9082,9 @@ static int __ath11k_mac_register(struct + NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP); + } + ++ wiphy_ext_feature_set(ar->hw->wiphy, ++ NL80211_EXT_FEATURE_SET_SCAN_DWELL); ++ + ath11k_reg_init(ar); + + if (!test_bit(ATH11K_FLAG_RAW_MODE, &ab->dev_flags)) { diff --git a/package/kernel/mac80211/patches/ath11k/0009-wifi-ath11k-Send-PME-message-during-wakeup-from-D3co.patch b/package/kernel/mac80211/patches/ath11k/0009-wifi-ath11k-Send-PME-message-during-wakeup-from-D3co.patch new file mode 100644 index 0000000000..1e04c974fe --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0009-wifi-ath11k-Send-PME-message-during-wakeup-from-D3co.patch @@ -0,0 +1,39 @@ +From 3f9b09ccf7d5f23066b02881a737bee42def9d1a Mon Sep 17 00:00:00 2001 +From: Baochen Qiang +Date: Mon, 10 Oct 2022 11:32:37 +0800 +Subject: [PATCH 9/9] wifi: ath11k: Send PME message during wakeup from D3cold + +We are seeing system stuck on some specific platforms due to +WLAN chip fails to wakeup from D3cold state. + +With this flag, firmware will send PME message during wakeup +and this issue is gone. + +Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 + +Signed-off-by: Baochen Qiang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221010033237.415478-1-quic_bqiang@quicinc.com +--- + drivers/net/wireless/ath/ath11k/qmi.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -19,6 +19,7 @@ + #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 + #define HOST_CSTATE_BIT 0x04 + #define PLATFORM_CAP_PCIE_GLOBAL_RESET 0x08 ++#define PLATFORM_CAP_PCIE_PME_D3COLD 0x10 + + #define FW_BUILD_ID_MASK "QC_IMAGE_VERSION_STRING=" + +@@ -1752,6 +1753,8 @@ static int ath11k_qmi_host_cap_send(stru + if (ab->hw_params.global_reset) + req.nm_modem |= PLATFORM_CAP_PCIE_GLOBAL_RESET; + ++ req.nm_modem |= PLATFORM_CAP_PCIE_PME_D3COLD; ++ + ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi host cap request\n"); + + ret = qmi_txn_init(&ab->qmi.handle, &txn, diff --git a/package/kernel/mac80211/patches/ath11k/0010-wifi-ath11k-Fix-firmware-crash-on-vdev-delete-race-c.patch b/package/kernel/mac80211/patches/ath11k/0010-wifi-ath11k-Fix-firmware-crash-on-vdev-delete-race-c.patch new file mode 100644 index 0000000000..7275af06ea --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0010-wifi-ath11k-Fix-firmware-crash-on-vdev-delete-race-c.patch @@ -0,0 +1,116 @@ +From 3811fa1f231f1a3e29759efef4992116604aab8b Mon Sep 17 00:00:00 2001 +From: Sowmiya Sree Elavalagan +Date: Tue, 11 Oct 2022 15:23:46 +0530 +Subject: [PATCH] wifi: ath11k: Fix firmware crash on vdev delete race + condition + +Current code does not wait for vdev delete completion on vdev create +failures and tries to send another vdev create followed by vdev set +param to firmware with same vdev id. This causes firmware crash. +Fix this crash by waiting for vdev delete completion on vdev +create failures. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.6.0.1-00905-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Sowmiya Sree Elavalagan +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221011095346.3901-1-quic_ssreeela@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 60 +++++++++++++++++---------- + 1 file changed, 37 insertions(+), 23 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -6233,6 +6233,40 @@ void ath11k_mac_11d_scan_stop_all(struct + } + } + ++static int ath11k_mac_vdev_delete(struct ath11k *ar, struct ath11k_vif *arvif) ++{ ++ unsigned long time_left; ++ struct ieee80211_vif *vif = arvif->vif; ++ int ret = 0; ++ ++ lockdep_assert_held(&ar->conf_mutex); ++ ++ reinit_completion(&ar->vdev_delete_done); ++ ++ ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to delete WMI vdev %d: %d\n", ++ arvif->vdev_id, ret); ++ return ret; ++ } ++ ++ time_left = wait_for_completion_timeout(&ar->vdev_delete_done, ++ ATH11K_VDEV_DELETE_TIMEOUT_HZ); ++ if (time_left == 0) { ++ ath11k_warn(ar->ab, "Timeout in receiving vdev delete response\n"); ++ return -ETIMEDOUT; ++ } ++ ++ ar->ab->free_vdev_map |= 1LL << (arvif->vdev_id); ++ ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); ++ ar->num_created_vdevs--; ++ ++ ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n", ++ vif->addr, arvif->vdev_id); ++ ++ return ret; ++} ++ + static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { +@@ -6468,10 +6502,7 @@ err_peer_del: + } + + err_vdev_del: +- ath11k_wmi_vdev_delete(ar, arvif->vdev_id); +- ar->num_created_vdevs--; +- ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); +- ab->free_vdev_map |= 1LL << arvif->vdev_id; ++ ath11k_mac_vdev_delete(ar, arvif); + spin_lock_bh(&ar->data_lock); + list_del(&arvif->list); + spin_unlock_bh(&ar->data_lock); +@@ -6499,7 +6530,6 @@ static void ath11k_mac_op_remove_interfa + struct ath11k *ar = hw->priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct ath11k_base *ab = ar->ab; +- unsigned long time_left; + int ret; + int i; + +@@ -6520,29 +6550,13 @@ static void ath11k_mac_op_remove_interfa + arvif->vdev_id, ret); + } + +- reinit_completion(&ar->vdev_delete_done); +- +- ret = ath11k_wmi_vdev_delete(ar, arvif->vdev_id); ++ ret = ath11k_mac_vdev_delete(ar, arvif); + if (ret) { +- ath11k_warn(ab, "failed to delete WMI vdev %d: %d\n", ++ ath11k_warn(ab, "failed to delete vdev %d: %d\n", + arvif->vdev_id, ret); + goto err_vdev_del; + } + +- time_left = wait_for_completion_timeout(&ar->vdev_delete_done, +- ATH11K_VDEV_DELETE_TIMEOUT_HZ); +- if (time_left == 0) { +- ath11k_warn(ab, "Timeout in receiving vdev delete response\n"); +- goto err_vdev_del; +- } +- +- ab->free_vdev_map |= 1LL << (arvif->vdev_id); +- ar->allocated_vdev_map &= ~(1LL << arvif->vdev_id); +- ar->num_created_vdevs--; +- +- ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM deleted, vdev_id %d\n", +- vif->addr, arvif->vdev_id); +- + if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); + ar->monitor_vdev_id = -1; diff --git a/package/kernel/mac80211/patches/ath11k/0011-wifi-ath11k-fix-monitor-vdev-creation-with-firmware-.patch b/package/kernel/mac80211/patches/ath11k/0011-wifi-ath11k-fix-monitor-vdev-creation-with-firmware-.patch new file mode 100644 index 0000000000..2f066d0a56 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0011-wifi-ath11k-fix-monitor-vdev-creation-with-firmware-.patch @@ -0,0 +1,40 @@ +From f3ca72b0327101a074a871539e61775d43908ca4 Mon Sep 17 00:00:00 2001 +From: Nagarajan Maran +Date: Fri, 14 Oct 2022 21:20:54 +0530 +Subject: [PATCH] wifi: ath11k: fix monitor vdev creation with firmware + recovery + +During firmware recovery, the monitor interface is not +getting created in the driver and firmware since +the respective flags are not updated properly. + +So after firmware recovery is successful, when monitor +interface is brought down manually, firmware assertion +is observed, since we are trying to bring down the +interface which is not yet created in the firmware. + +Fix this by updating the monitor flags properly per +phy#, during firmware recovery. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Nagarajan Maran +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221014155054.11471-1-quic_nmaran@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -1677,6 +1677,10 @@ void ath11k_core_pre_reconfigure_recover + ath11k_mac_tx_mgmt_pending_free, ar); + idr_destroy(&ar->txmgmt_idr); + wake_up(&ar->txmgmt_empty_waitq); ++ ++ ar->monitor_vdev_id = -1; ++ clear_bit(ATH11K_FLAG_MONITOR_STARTED, &ar->monitor_flags); ++ clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); + } + + wake_up(&ab->wmi_ab.tx_credits_wq); diff --git a/package/kernel/mac80211/patches/ath11k/0012-wifi-ath11k-Fix-qmi_msg_handler-data-structure-initi.patch b/package/kernel/mac80211/patches/ath11k/0012-wifi-ath11k-Fix-qmi_msg_handler-data-structure-initi.patch new file mode 100644 index 0000000000..1f7418ff89 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0012-wifi-ath11k-Fix-qmi_msg_handler-data-structure-initi.patch @@ -0,0 +1,33 @@ +From ed3725e15a154ebebf44e0c34806c57525483f92 Mon Sep 17 00:00:00 2001 +From: Rahul Bhattacharjee +Date: Fri, 21 Oct 2022 14:31:26 +0530 +Subject: [PATCH] wifi: ath11k: Fix qmi_msg_handler data structure + initialization + +qmi_msg_handler is required to be null terminated by QMI module. +There might be a case where a handler for a msg id is not present in the +handlers array which can lead to infinite loop while searching the handler +and therefore out of bound access in qmi_invoke_handler(). +Hence update the initialization in qmi_msg_handler data structure. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Rahul Bhattacharjee +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221021090126.28626-1-quic_rbhattac@quicinc.com +--- + drivers/net/wireless/ath/ath11k/qmi.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -3090,6 +3090,9 @@ static const struct qmi_msg_handler ath1 + sizeof(struct qmi_wlfw_fw_init_done_ind_msg_v01), + .fn = ath11k_qmi_msg_fw_init_done_cb, + }, ++ ++ /* end of list */ ++ {}, + }; + + static int ath11k_qmi_ops_new_server(struct qmi_handle *qmi_hdl, diff --git a/package/kernel/mac80211/patches/ath11k/0013-wifi-ath11k-synchronize-ath11k_mac_he_gi_to_nl80211_.patch b/package/kernel/mac80211/patches/ath11k/0013-wifi-ath11k-synchronize-ath11k_mac_he_gi_to_nl80211_.patch new file mode 100644 index 0000000000..1e89b4d4f2 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0013-wifi-ath11k-synchronize-ath11k_mac_he_gi_to_nl80211_.patch @@ -0,0 +1,42 @@ +From dd1c2322694522f674c874f5fa02ac5ae39135dd Mon Sep 17 00:00:00 2001 +From: "Jiri Slaby (SUSE)" +Date: Mon, 31 Oct 2022 12:43:41 +0100 +Subject: [PATCH] wifi: ath11k: synchronize + ath11k_mac_he_gi_to_nl80211_he_gi()'s return type + +ath11k_mac_he_gi_to_nl80211_he_gi() generates a valid warning with gcc-13: + drivers/net/wireless/ath/ath11k/mac.c:321:20: error: conflicting types for 'ath11k_mac_he_gi_to_nl80211_he_gi' due to enum/integer mismatch; have 'enum nl80211_he_gi(u8)' + drivers/net/wireless/ath/ath11k/mac.h:166:5: note: previous declaration of 'ath11k_mac_he_gi_to_nl80211_he_gi' with type 'u32(u8)' + +I.e. the type of the return value ath11k_mac_he_gi_to_nl80211_he_gi() in +the declaration is u32, while the definition spells enum nl80211_he_gi. +Synchronize them to the latter. + +Cc: Martin Liska +Cc: Kalle Valo +Cc: "David S. Miller" +Cc: Eric Dumazet +Cc: Jakub Kicinski +Cc: Paolo Abeni +Cc: ath11k@lists.infradead.org +Cc: linux-wireless@vger.kernel.org +Cc: netdev@vger.kernel.org +Signed-off-by: Jiri Slaby (SUSE) +Reviewed-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221031114341.10377-1-jirislaby@kernel.org +--- + drivers/net/wireless/ath/ath11k/mac.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.h ++++ b/drivers/net/wireless/ath/ath11k/mac.h +@@ -163,7 +163,7 @@ void ath11k_mac_drain_tx(struct ath11k * + void ath11k_mac_peer_cleanup_all(struct ath11k *ar); + int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx); + u8 ath11k_mac_bw_to_mac80211_bw(u8 bw); +-u32 ath11k_mac_he_gi_to_nl80211_he_gi(u8 sgi); ++enum nl80211_he_gi ath11k_mac_he_gi_to_nl80211_he_gi(u8 sgi); + enum nl80211_he_ru_alloc ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy); + enum nl80211_he_ru_alloc ath11k_mac_he_ru_tones_to_nl80211_he_ru_alloc(u16 ru_tones); + enum ath11k_supported_bw ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw); diff --git a/package/kernel/mac80211/patches/ath11k/0016-wifi-ath11k-Make-QMI-message-rules-const.patch b/package/kernel/mac80211/patches/ath11k/0016-wifi-ath11k-Make-QMI-message-rules-const.patch new file mode 100644 index 0000000000..1f48df73f7 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0016-wifi-ath11k-Make-QMI-message-rules-const.patch @@ -0,0 +1,341 @@ +From 93c1592889fca46d09d833455628bab05516cdbf Mon Sep 17 00:00:00 2001 +From: Jeff Johnson +Date: Wed, 14 Sep 2022 17:23:03 -0700 +Subject: [PATCH] wifi: ath11k: Make QMI message rules const + +Commit ff6d365898d4 ("soc: qcom: qmi: use const for struct +qmi_elem_info") allows QMI message encoding/decoding rules to be +const, so do that for ath11k. + +Compile tested only. + +Signed-off-by: Jeff Johnson +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20220915002303.12206-1-quic_jjohnson@quicinc.com +--- + drivers/net/wireless/ath/ath11k/qmi.c | 72 +++++++++++++-------------- + 1 file changed, 36 insertions(+), 36 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/qmi.c ++++ b/drivers/net/wireless/ath/ath11k/qmi.c +@@ -29,7 +29,7 @@ module_param_named(cold_boot_cal, ath11k + MODULE_PARM_DESC(cold_boot_cal, + "Decrease the channel switch time but increase the driver load time (Default: true)"); + +-static struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_host_cap_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, +@@ -280,7 +280,7 @@ static struct qmi_elem_info qmi_wlanfw_h + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_host_cap_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_host_cap_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -297,7 +297,7 @@ static struct qmi_elem_info qmi_wlanfw_h + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_ind_register_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_ind_register_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, +@@ -522,7 +522,7 @@ static struct qmi_elem_info qmi_wlanfw_i + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_ind_register_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_ind_register_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -558,7 +558,7 @@ static struct qmi_elem_info qmi_wlanfw_i + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_mem_cfg_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_mem_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, +@@ -590,7 +590,7 @@ static struct qmi_elem_info qmi_wlanfw_m + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_mem_seg_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_mem_seg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -632,7 +632,7 @@ static struct qmi_elem_info qmi_wlanfw_m + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_request_mem_ind_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_request_mem_ind_msg_v01_ei[] = { + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, +@@ -659,7 +659,7 @@ static struct qmi_elem_info qmi_wlanfw_r + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_mem_seg_resp_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_mem_seg_resp_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, +@@ -699,7 +699,7 @@ static struct qmi_elem_info qmi_wlanfw_m + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_respond_mem_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_respond_mem_req_msg_v01_ei[] = { + { + .data_type = QMI_DATA_LEN, + .elem_len = 1, +@@ -726,7 +726,7 @@ static struct qmi_elem_info qmi_wlanfw_r + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_respond_mem_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_respond_mem_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -744,7 +744,7 @@ static struct qmi_elem_info qmi_wlanfw_r + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_cap_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_cap_req_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, +@@ -752,7 +752,7 @@ static struct qmi_elem_info qmi_wlanfw_c + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_device_info_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_device_info_req_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, +@@ -760,7 +760,7 @@ static struct qmi_elem_info qmi_wlanfw_d + }, + }; + +-static struct qmi_elem_info qmi_wlfw_device_info_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlfw_device_info_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -814,7 +814,7 @@ static struct qmi_elem_info qmi_wlfw_dev + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_rf_chip_info_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_rf_chip_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -840,7 +840,7 @@ static struct qmi_elem_info qmi_wlanfw_r + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_rf_board_info_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_rf_board_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -857,7 +857,7 @@ static struct qmi_elem_info qmi_wlanfw_r + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_soc_info_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_soc_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -873,7 +873,7 @@ static struct qmi_elem_info qmi_wlanfw_s + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_fw_version_info_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_fw_version_info_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -899,7 +899,7 @@ static struct qmi_elem_info qmi_wlanfw_f + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_cap_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_cap_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -1100,7 +1100,7 @@ static struct qmi_elem_info qmi_wlanfw_c + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_bdf_download_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_bdf_download_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, +@@ -1235,7 +1235,7 @@ static struct qmi_elem_info qmi_wlanfw_b + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_bdf_download_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_bdf_download_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -1253,7 +1253,7 @@ static struct qmi_elem_info qmi_wlanfw_b + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_m3_info_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_m3_info_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_8_BYTE, + .elem_len = 1, +@@ -1277,7 +1277,7 @@ static struct qmi_elem_info qmi_wlanfw_m + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_m3_info_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_m3_info_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -1294,7 +1294,7 @@ static struct qmi_elem_info qmi_wlanfw_m + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_ce_tgt_pipe_cfg_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_ce_tgt_pipe_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -1347,7 +1347,7 @@ static struct qmi_elem_info qmi_wlanfw_c + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_ce_svc_pipe_cfg_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_ce_svc_pipe_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -1382,7 +1382,7 @@ static struct qmi_elem_info qmi_wlanfw_c + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_shadow_reg_cfg_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_shadow_reg_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_2_BYTE, + .elem_len = 1, +@@ -1406,7 +1406,7 @@ static struct qmi_elem_info qmi_wlanfw_s + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_shadow_reg_v2_cfg_s_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_shadow_reg_v2_cfg_s_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -1423,7 +1423,7 @@ static struct qmi_elem_info qmi_wlanfw_s + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_wlan_mode_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_wlan_mode_req_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, +@@ -1458,7 +1458,7 @@ static struct qmi_elem_info qmi_wlanfw_w + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_wlan_mode_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_wlan_mode_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -1476,7 +1476,7 @@ static struct qmi_elem_info qmi_wlanfw_w + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_wlan_cfg_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_wlan_cfg_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, +@@ -1615,7 +1615,7 @@ static struct qmi_elem_info qmi_wlanfw_w + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_wlan_cfg_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_wlan_cfg_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -1632,28 +1632,28 @@ static struct qmi_elem_info qmi_wlanfw_w + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_mem_ready_ind_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_mem_ready_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_fw_ready_ind_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_fw_ready_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_cold_boot_cal_done_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_wlan_ini_req_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_wlan_ini_req_msg_v01_ei[] = { + { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, +@@ -1679,7 +1679,7 @@ static struct qmi_elem_info qmi_wlanfw_w + }, + }; + +-static struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlanfw_wlan_ini_resp_msg_v01_ei[] = { + { + .data_type = QMI_STRUCT, + .elem_len = 1, +@@ -1697,7 +1697,7 @@ static struct qmi_elem_info qmi_wlanfw_w + }, + }; + +-static struct qmi_elem_info qmi_wlfw_fw_init_done_ind_msg_v01_ei[] = { ++static const struct qmi_elem_info qmi_wlfw_fw_init_done_ind_msg_v01_ei[] = { + { + .data_type = QMI_EOTI, + .array_type = NO_ARRAY, diff --git a/package/kernel/mac80211/patches/ath11k/0017-wifi-ath11k-Trigger-sta-disconnect-on-hardware-resta.patch b/package/kernel/mac80211/patches/ath11k/0017-wifi-ath11k-Trigger-sta-disconnect-on-hardware-resta.patch new file mode 100644 index 0000000000..f95e5027b2 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0017-wifi-ath11k-Trigger-sta-disconnect-on-hardware-resta.patch @@ -0,0 +1,119 @@ +From a018750a2cceaf4427c4ee3d9ce3e83a171d5bd6 Mon Sep 17 00:00:00 2001 +From: Youghandhar Chintala +Date: Fri, 4 Nov 2022 14:24:03 +0530 +Subject: [PATCH] wifi: ath11k: Trigger sta disconnect on hardware restart + +Currently after the hardware restart triggered from the driver, the +station interface connection remains intact, since a disconnect trigger +is not sent to userspace. This can lead to a problem in targets where +the wifi mac sequence is added by the firmware. + +After the target restart, its wifi mac sequence number gets reset to +zero. Hence AP to which our device is connected will receive frames with +a wifi mac sequence number jump to the past, thereby resulting in the +AP dropping all these frames, until the frame arrives with a wifi mac +sequence number which AP was expecting. + +To avoid such frame drops, its better to trigger a station disconnect +upon target hardware restart which can be done with API +ieee80211_reconfig_disconnect exposed to mac80211. + +The other targets are not affected by this change, since the hardware +params flag is not set. + +Reported-by: kernel test robot + +Tested-on: WCN6750 hw1.0 AHB WLAN.MSL.1.0.1-00887-QCAMSLSWPLZ-1 + +Signed-off-by: Youghandhar Chintala +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221104085403.11025-1-quic_youghand@quicinc.com +--- + drivers/net/wireless/ath/ath11k/core.c | 6 ++++++ + drivers/net/wireless/ath/ath11k/hw.h | 1 + + drivers/net/wireless/ath/ath11k/mac.c | 7 +++++++ + 3 files changed, 14 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/core.c ++++ b/drivers/net/wireless/ath/ath11k/core.c +@@ -195,6 +195,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = true, + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, ++ .support_fw_mac_sequence = false, + }, + { + .name = "qca6390 hw2.0", +@@ -277,6 +278,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = true, + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, ++ .support_fw_mac_sequence = true, + }, + { + .name = "qcn9074 hw1.0", +@@ -356,6 +358,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = true, + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, ++ .support_fw_mac_sequence = false, + }, + { + .name = "wcn6855 hw2.0", +@@ -438,6 +441,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = true, + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, ++ .support_fw_mac_sequence = true, + }, + { + .name = "wcn6855 hw2.1", +@@ -519,6 +523,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = true, + .tx_ring_size = DP_TCL_DATA_RING_SIZE, + .smp2p_wow_exit = false, ++ .support_fw_mac_sequence = true, + }, + { + .name = "wcn6750 hw1.0", +@@ -597,6 +602,7 @@ static const struct ath11k_hw_params ath + .tcl_ring_retry = false, + .tx_ring_size = DP_TCL_DATA_RING_SIZE_WCN6750, + .smp2p_wow_exit = true, ++ .support_fw_mac_sequence = true, + }, + }; + +--- a/drivers/net/wireless/ath/ath11k/hw.h ++++ b/drivers/net/wireless/ath/ath11k/hw.h +@@ -219,6 +219,7 @@ struct ath11k_hw_params { + bool tcl_ring_retry; + u32 tx_ring_size; + bool smp2p_wow_exit; ++ bool support_fw_mac_sequence; + }; + + struct ath11k_hw_ops { +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -8010,6 +8010,7 @@ ath11k_mac_op_reconfig_complete(struct i + struct ath11k *ar = hw->priv; + struct ath11k_base *ab = ar->ab; + int recovery_count; ++ struct ath11k_vif *arvif; + + if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART) + return; +@@ -8045,6 +8046,12 @@ ath11k_mac_op_reconfig_complete(struct i + ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset success\n"); + } + } ++ if (ar->ab->hw_params.support_fw_mac_sequence) { ++ list_for_each_entry(arvif, &ar->arvifs, list) { ++ if (arvif->is_up && arvif->vdev_type == WMI_VDEV_TYPE_STA) ++ ieee80211_hw_restart_disconnect(arvif->vif); ++ } ++ } + } + + mutex_unlock(&ar->conf_mutex); diff --git a/package/kernel/mac80211/patches/ath11k/0018-wifi-ath11k-Fix-race-condition-with-struct-htt_ppdu_.patch b/package/kernel/mac80211/patches/ath11k/0018-wifi-ath11k-Fix-race-condition-with-struct-htt_ppdu_.patch new file mode 100644 index 0000000000..cef61ee344 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0018-wifi-ath11k-Fix-race-condition-with-struct-htt_ppdu_.patch @@ -0,0 +1,103 @@ +From e44de90453bb2b46a523df78c39eb896bab35dcd Mon Sep 17 00:00:00 2001 +From: Govindaraj Saminathan +Date: Tue, 29 Nov 2022 13:04:02 +0200 +Subject: [PATCH] wifi: ath11k: Fix race condition with struct + htt_ppdu_stats_info + +A crash happens when running the traffic with multiple clients: + +Crash Signature : Unable to handle kernel paging request at +virtual address ffffffd700970918 During the crash, PC points to +"ieee80211_tx_rate_update+0x30/0x68 [mac80211]" +LR points to "ath11k_dp_htt_htc_t2h_msg_handler+0x5a8/0x8a0 [ath11k]". + +Struct ppdu_stats_info is allocated and accessed from event callback via copy +engine tasklet, this has a problem when freeing it from ath11k_mac_op_stop(). + +Use data_lock during entire ath11k_dp_htt_get_ppdu_desc() call to protect +struct htt_ppdu_stats_info access and to avoid race condition when accessing it +from ath11k_mac_op_stop(). + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Govindaraj Saminathan +Co-developed-by: Karthikeyan Kathirvel +Signed-off-by: Karthikeyan Kathirvel +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221124071104.22506-1-quic_kathirve@quicinc.com +--- + drivers/net/wireless/ath/ath11k/dp_rx.c | 22 +++++++++++----------- + 1 file changed, 11 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/dp_rx.c ++++ b/drivers/net/wireless/ath/ath11k/dp_rx.c +@@ -1535,13 +1535,12 @@ struct htt_ppdu_stats_info *ath11k_dp_ht + { + struct htt_ppdu_stats_info *ppdu_info; + +- spin_lock_bh(&ar->data_lock); ++ lockdep_assert_held(&ar->data_lock); ++ + if (!list_empty(&ar->ppdu_stats_info)) { + list_for_each_entry(ppdu_info, &ar->ppdu_stats_info, list) { +- if (ppdu_info->ppdu_id == ppdu_id) { +- spin_unlock_bh(&ar->data_lock); ++ if (ppdu_info->ppdu_id == ppdu_id) + return ppdu_info; +- } + } + + if (ar->ppdu_stat_list_depth > HTT_PPDU_DESC_MAX_DEPTH) { +@@ -1553,16 +1552,13 @@ struct htt_ppdu_stats_info *ath11k_dp_ht + kfree(ppdu_info); + } + } +- spin_unlock_bh(&ar->data_lock); + + ppdu_info = kzalloc(sizeof(*ppdu_info), GFP_ATOMIC); + if (!ppdu_info) + return NULL; + +- spin_lock_bh(&ar->data_lock); + list_add_tail(&ppdu_info->list, &ar->ppdu_stats_info); + ar->ppdu_stat_list_depth++; +- spin_unlock_bh(&ar->data_lock); + + return ppdu_info; + } +@@ -1586,16 +1582,17 @@ static int ath11k_htt_pull_ppdu_stats(st + ar = ath11k_mac_get_ar_by_pdev_id(ab, pdev_id); + if (!ar) { + ret = -EINVAL; +- goto exit; ++ goto out; + } + + if (ath11k_debugfs_is_pktlog_lite_mode_enabled(ar)) + trace_ath11k_htt_ppdu_stats(ar, skb->data, len); + ++ spin_lock_bh(&ar->data_lock); + ppdu_info = ath11k_dp_htt_get_ppdu_desc(ar, ppdu_id); + if (!ppdu_info) { + ret = -EINVAL; +- goto exit; ++ goto out_unlock_data; + } + + ppdu_info->ppdu_id = ppdu_id; +@@ -1604,10 +1601,13 @@ static int ath11k_htt_pull_ppdu_stats(st + (void *)ppdu_info); + if (ret) { + ath11k_warn(ab, "Failed to parse tlv %d\n", ret); +- goto exit; ++ goto out_unlock_data; + } + +-exit: ++out_unlock_data: ++ spin_unlock_bh(&ar->data_lock); ++ ++out: + rcu_read_unlock(); + + return ret; diff --git a/package/kernel/mac80211/patches/ath11k/900-ath11k-control-thermal-support-via-symbol.patch b/package/kernel/mac80211/patches/ath11k/900-ath11k-control-thermal-support-via-symbol.patch new file mode 100644 index 0000000000..60720a721e --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/900-ath11k-control-thermal-support-via-symbol.patch @@ -0,0 +1,66 @@ +From 703d6551f71e7290619d6effe2a25a64e10538b7 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Thu, 15 Dec 2022 12:20:52 +0100 +Subject: [PATCH] ath11k: control thermal support via symbol + +Currently, thermal support will get built if CONFIG_THERMAL is reachable, +however this is not suitable for OpenWrt as with ALL_KMODS being set to y +ATH11K_THERMAL wont get selected and so hwmon and thermal kmods wont get +pulled in resulting in a build-failure. + +So, to avoid that, lets do what is already done for ath10k and add a +config symbol into backports for enabling thermal support. + +Signed-off-by: Robert Marko +--- + drivers/net/wireless/ath/ath11k/Kconfig | 7 +++++++ + drivers/net/wireless/ath/ath11k/Makefile | 2 +- + drivers/net/wireless/ath/ath11k/thermal.h | 2 +- + local-symbols | 1 + + 4 files changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/Kconfig ++++ b/drivers/net/wireless/ath/ath11k/Kconfig +@@ -61,3 +61,10 @@ config ATH11K_SPECTRAL + Enable ath11k spectral scan support + + Say Y to enable access to the FFT/spectral data via debugfs. ++ ++config ATH11K_THERMAL ++ bool "ath11k thermal sensors and throttling support" ++ depends on ATH11K ++ depends on THERMAL ++ help ++ Enable ath11k thermal sensors and throttling support. +--- a/drivers/net/wireless/ath/ath11k/Makefile ++++ b/drivers/net/wireless/ath/ath11k/Makefile +@@ -22,7 +22,7 @@ ath11k-y += core.o \ + ath11k-$(CPTCFG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o + ath11k-$(CPTCFG_NL80211_TESTMODE) += testmode.o + ath11k-$(CPTCFG_ATH11K_TRACING) += trace.o +-ath11k-$(CONFIG_THERMAL) += thermal.o ++ath11k-$(CPTCFG_ATH11K_THERMAL) += thermal.o + ath11k-$(CPTCFG_ATH11K_SPECTRAL) += spectral.o + ath11k-$(CONFIG_PM) += wow.o + +--- a/drivers/net/wireless/ath/ath11k/thermal.h ++++ b/drivers/net/wireless/ath/ath11k/thermal.h +@@ -25,7 +25,7 @@ struct ath11k_thermal { + int temperature; + }; + +-#if IS_REACHABLE(CONFIG_THERMAL) ++#if IS_REACHABLE(CPTCFG_ATH11K_THERMAL) + int ath11k_thermal_register(struct ath11k_base *sc); + void ath11k_thermal_unregister(struct ath11k_base *sc); + int ath11k_thermal_set_throttling(struct ath11k *ar, u32 throttle_state); +--- a/local-symbols ++++ b/local-symbols +@@ -174,6 +174,7 @@ ATH11K_DEBUG= + ATH11K_DEBUGFS= + ATH11K_TRACING= + ATH11K_SPECTRAL= ++ATH11K_THERMAL= + WLAN_VENDOR_ATMEL= + ATMEL= + PCI_ATMEL= diff --git a/package/kernel/mac80211/patches/ath11k/901-wifi-ath11k-pci-fix-compilation-in-5.16-and-older.patch b/package/kernel/mac80211/patches/ath11k/901-wifi-ath11k-pci-fix-compilation-in-5.16-and-older.patch new file mode 100644 index 0000000000..2b6c18d6dd --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/901-wifi-ath11k-pci-fix-compilation-in-5.16-and-older.patch @@ -0,0 +1,29 @@ +From 04178918e7f6b5f34dde81ec79ee8a1ccace3be3 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 17 Oct 2022 11:45:03 +0200 +Subject: [PATCH] wifi: ath11k: pci: fix compilation in 5.16 and older + +Commit ("genirq/msi, treewide: Use a named struct for PCI/MSI attributes") +changed the msi_desc structure a bit, however that is only available in +kernels 5.17 and newer, so check for kernel version to allow compilation +in 5.16 and older. + +Signed-off-by: Robert Marko +--- + drivers/net/wireless/ath/ath11k/pci.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -451,7 +451,11 @@ static int ath11k_pci_alloc_msi(struct a + pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_LO, + &ab->pci.msi.addr_lo); + ++#if (LINUX_VERSION_CODE > KERNEL_VERSION(5, 17, 0)) + if (msi_desc->pci.msi_attrib.is_64) { ++#else ++ if (msi_desc->msi_attrib.is_64) { ++#endif + pci_read_config_dword(pci_dev, pci_dev->msi_cap + PCI_MSI_ADDRESS_HI, + &ab->pci.msi.addr_hi); + } else { diff --git a/package/kernel/mac80211/patches/build/100-backports-drop-QRTR-and-MHI.patch b/package/kernel/mac80211/patches/build/100-backports-drop-QRTR-and-MHI.patch new file mode 100644 index 0000000000..b017a0ce14 --- /dev/null +++ b/package/kernel/mac80211/patches/build/100-backports-drop-QRTR-and-MHI.patch @@ -0,0 +1,76 @@ +From 54e0f9aaf340377fb76acdffee9ec7372c4b70ae Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Mon, 17 Oct 2022 11:35:36 +0200 +Subject: [PATCH] backports: drop QRTR and MHI + +Backports currently include QRTR and MHI due to ath11k-pci requiring them, +however this at the same time prevents us from adding ath11k-ahb as it +also requires QRTR however its AHB variant from the kernel will conflict +with the core provided by backports. + +Since MHI also conflicts with existing OpenWrt kmods providing MHI drop +both from backports and use the ones provided by OpenWrt kernel. + +Signed-off-by: Robert Marko +--- + Kconfig.sources | 2 -- + Makefile.kernel | 2 -- + drivers/net/wireless/ath/ath11k/Kconfig | 6 +++--- + local-symbols | 8 -------- + 4 files changed, 3 insertions(+), 15 deletions(-) + +--- a/Kconfig.sources ++++ b/Kconfig.sources +@@ -4,8 +4,6 @@ source "$BACKPORT_DIR/compat/Kconfig" + # these are copied from the kernel + source "$BACKPORT_DIR/net/wireless/Kconfig" + source "$BACKPORT_DIR/net/mac80211/Kconfig" +-source "$BACKPORT_DIR/net/qrtr/Kconfig" +-source "$BACKPORT_DIR/drivers/bus/mhi/Kconfig" + source "$BACKPORT_DIR/drivers/soc/qcom/Kconfig" + source "$BACKPORT_DIR/drivers/net/wireless/Kconfig" + source "$BACKPORT_DIR/drivers/net/usb/Kconfig" +--- a/Makefile.kernel ++++ b/Makefile.kernel +@@ -39,9 +39,7 @@ obj-y += compat/ + + obj-$(CPTCFG_CFG80211) += net/wireless/ + obj-$(CPTCFG_MAC80211) += net/mac80211/ +-obj-$(CPTCFG_QRTR) += net/qrtr/ + obj-$(CPTCFG_QCOM_QMI_HELPERS) += drivers/soc/qcom/ +-obj-$(CPTCFG_MHI_BUS) += drivers/bus/mhi/ + obj-$(CPTCFG_WLAN) += drivers/net/wireless/ + obj-$(CPTCFG_USB_NET_RNDIS_WLAN) += drivers/net/usb/ + +--- a/drivers/net/wireless/ath/ath11k/Kconfig ++++ b/drivers/net/wireless/ath/ath11k/Kconfig +@@ -25,9 +25,9 @@ config ATH11K_PCI + tristate "Atheros ath11k PCI support" + depends on m + depends on ATH11K && PCI +- select MHI_BUS +- select QRTR +- select QRTR_MHI ++ depends on MHI_BUS ++ depends on QRTR ++ depends on QRTR_MHI + help + This module adds support for PCIE bus + +--- a/local-symbols ++++ b/local-symbols +@@ -65,14 +65,6 @@ MAC80211_MESH_PS_DEBUG= + MAC80211_TDLS_DEBUG= + MAC80211_DEBUG_COUNTERS= + MAC80211_STA_HASH_MAX_SIZE= +-QRTR= +-QRTR_SMD= +-QRTR_TUN= +-QRTR_MHI= +-MHI_BUS= +-MHI_BUS_DEBUG= +-MHI_BUS_PCI_GENERIC= +-MHI_BUS_EP= + QCOM_AOSS_QMP= + QCOM_COMMAND_DB= + QCOM_CPR= diff --git a/package/kernel/mt76/Makefile b/package/kernel/mt76/Makefile index c71c7c52de..d6f53a1d50 100644 --- a/package/kernel/mt76/Makefile +++ b/package/kernel/mt76/Makefile @@ -8,9 +8,9 @@ PKG_LICENSE_FILES:= PKG_SOURCE_URL:=https://github.com/openwrt/mt76 PKG_SOURCE_PROTO:=git -PKG_SOURCE_DATE:=2022-12-09 -PKG_SOURCE_VERSION:=7fae1de12ae7832a6095fd2df198f41fabd5223d -PKG_MIRROR_HASH:=c2bf2f23265d5e181c275a62a64f487b190f19b43fc4c584b62b9e6c16e992ef +PKG_SOURCE_DATE:=2022-12-22 +PKG_SOURCE_VERSION:=5b509e80384ab019ac11aa90c81ec0dbb5b0d7f2 +PKG_MIRROR_HASH:=6fc25df4d28becd010ff4971b23731c08b53e69381a9e4c868091899712f78a9 PKG_MAINTAINER:=Felix Fietkau PKG_USE_NINJA:=0 diff --git a/package/kernel/rtl8188eu/Makefile b/package/kernel/rtl8188eu/Makefile index 740ed89763..e67dccf1a7 100644 --- a/package/kernel/rtl8188eu/Makefile +++ b/package/kernel/rtl8188eu/Makefile @@ -26,7 +26,7 @@ include $(INCLUDE_DIR)/package.mk define KernelPackage/rtl8188eu SUBMENU:=Wireless Drivers TITLE:=Realtek 8188EU(S)/8188ETV support - DEPENDS:=+kmod-cfg80211 +kmod-usb-core +@DRIVER_11N_SUPPORT + DEPENDS:=+kmod-cfg80211 +kmod-usb-core FILES:=$(PKG_BUILD_DIR)/rtl8188eu.ko AUTOLOAD:=$(call AutoProbe,rtl8188eu) endef diff --git a/package/kernel/rtl8189es/Makefile b/package/kernel/rtl8189es/Makefile index 1421dca9d9..5ff7bb36a0 100644 --- a/package/kernel/rtl8189es/Makefile +++ b/package/kernel/rtl8189es/Makefile @@ -24,7 +24,7 @@ include $(INCLUDE_DIR)/package.mk define KernelPackage/rtl8189es SUBMENU:=Wireless Drivers TITLE:=Realtek RTL8189ETV SDIO WiFi - DEPENDS:=+kmod-cfg80211 +kmod-mmc +@DRIVER_11N_SUPPORT + DEPENDS:=+kmod-cfg80211 +kmod-mmc FILES:=$(PKG_BUILD_DIR)/rtl8189es.ko AUTOLOAD:=$(call AutoProbe,rtl8189es) endef diff --git a/package/kernel/rtl8192eu/Makefile b/package/kernel/rtl8192eu/Makefile index 4b70495743..8f1c669614 100644 --- a/package/kernel/rtl8192eu/Makefile +++ b/package/kernel/rtl8192eu/Makefile @@ -23,7 +23,7 @@ include $(INCLUDE_DIR)/package.mk define KernelPackage/rtl8192eu SUBMENU:=Wireless Drivers TITLE:=Realtek RTL8192EU support - DEPENDS:=+kmod-cfg80211 +kmod-usb-core +@DRIVER_11N_SUPPORT + DEPENDS:=+kmod-cfg80211 +kmod-usb-core FILES:=$(PKG_BUILD_DIR)/rtl8192eu.ko AUTOLOAD:=$(call AutoProbe,rtl8192eu) endef diff --git a/package/kernel/rtl8812au-ac/Makefile b/package/kernel/rtl8812au-ac/Makefile index 0d85a80c2f..a34f0ccd87 100644 --- a/package/kernel/rtl8812au-ac/Makefile +++ b/package/kernel/rtl8812au-ac/Makefile @@ -30,7 +30,7 @@ include $(INCLUDE_DIR)/package.mk define KernelPackage/rtl8812au-ac SUBMENU:=Wireless Drivers TITLE:=Realtek RTL8812AU/21AU wireless drivers - DEPENDS:=+kmod-cfg80211 +kmod-usb-core +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT + DEPENDS:=+kmod-cfg80211 +kmod-usb-core +@DRIVER_11AC_SUPPORT FILES:=$(PKG_BUILD_DIR)/rtl8812au.ko AUTOLOAD:=$(call AutoProbe,rtl8812au) CONFLICTS:=kmod-rtl8812au-ct diff --git a/package/kernel/rtl8821cu/Makefile b/package/kernel/rtl8821cu/Makefile index 7450e80731..1835fe91b6 100644 --- a/package/kernel/rtl8821cu/Makefile +++ b/package/kernel/rtl8821cu/Makefile @@ -31,7 +31,7 @@ include $(INCLUDE_DIR)/package.mk define KernelPackage/rtl8821cu SUBMENU:=Wireless Drivers TITLE:=Realtek RTL8811CU/RTL8821CU support - DEPENDS:=+kmod-cfg80211 +kmod-usb-core +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT + DEPENDS:=+kmod-cfg80211 +kmod-usb-core +@DRIVER_11AC_SUPPORT FILES:=$(PKG_BUILD_DIR)/rtl8821cu.ko AUTOLOAD:=$(call AutoProbe,rtl8821cu) PROVIDES:=kmod-rtl8821cu diff --git a/package/kernel/rtl88x2bu/Makefile b/package/kernel/rtl88x2bu/Makefile index bb62018cca..c6f6990b89 100644 --- a/package/kernel/rtl88x2bu/Makefile +++ b/package/kernel/rtl88x2bu/Makefile @@ -30,7 +30,7 @@ include $(INCLUDE_DIR)/package.mk define KernelPackage/rtl88x2bu SUBMENU:=Wireless Drivers TITLE:=Realtek 8812BU/8822BU support - DEPENDS:=+kmod-cfg80211 +kmod-usb-core +@DRIVER_11N_SUPPORT +@DRIVER_11AC_SUPPORT + DEPENDS:=+kmod-cfg80211 +kmod-usb-core +@DRIVER_11AC_SUPPORT FILES:=$(PKG_BUILD_DIR)/rtl88x2bu.ko AUTOLOAD:=$(call AutoProbe,rtl88x2bu) PROVIDES:=kmod-rtl88x2bu diff --git a/package/network/services/hostapd/Config.in b/package/network/services/hostapd/Config.in index dd8b9b4de7..8f28eb2bd4 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: @@ -91,9 +101,11 @@ config WPA_MBO_SUPPORT 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-wolfssl || \ + PACKAGE_wpad-mbedtls help Multi Band Operation aka (Agile Multiband) enables features that facilitate efficient use of multiple frequency bands. diff --git a/package/network/services/hostapd/Makefile b/package/network/services/hostapd/Makefile index 4fa9a6ae46..829879f763 100644 --- a/package/network/services/hostapd/Makefile +++ b/package/network/services/hostapd/Makefile @@ -52,14 +52,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) @@ -116,6 +118,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 @@ -173,6 +190,15 @@ 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) @@ -205,6 +231,17 @@ 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) @@ -260,6 +297,15 @@ 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) @@ -292,6 +338,17 @@ 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) @@ -330,6 +387,15 @@ 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 @@ -365,6 +431,13 @@ $(call Package/wpa-supplicant/Default,$(1)) DEPENDS+=+PACKAGE_wpa-supplicant-wolfssl:libwolfssl endef +define Package/wpa-supplicant-mbedtls +$(call Package/wpa-supplicant/Default,$(1)) + TITLE+= (mbedTLS full) + VARIANT:=supplicant-full-mbedtls + DEPENDS+=+PACKAGE_wpa-supplicant-mbedtls:libmbedtls +endef + define Package/wpa-supplicant/config source "$(SOURCE)/Config.in" endef @@ -396,6 +469,13 @@ $(call Package/wpa-supplicant-mesh/Default,$(1)) DEPENDS+=+PACKAGE_wpa-supplicant-mesh-wolfssl:libwolfssl endef +define Package/wpa-supplicant-mesh-mbedtls +$(call Package/wpa-supplicant-mesh/Default,$(1)) + TITLE+= (mbedTLS, 11s, SAE) + VARIANT:=supplicant-mesh-mbedtls + DEPENDS+=+PACKAGE_wpa-supplicant-mesh-mbedtls:libmbedtls +endef + define Package/wpa-supplicant-basic $(call Package/wpa-supplicant/Default,$(1)) TITLE+= (11r, 11w) @@ -472,6 +552,15 @@ define Package/eapol-test-wolfssl PROVIDES:=eapol-test endef +define Package/eapol-test-mbedtls + $(call Package/eapol-test/Default,$(1)) + TITLE+= (mbedTLS full) + VARIANT:=supplicant-full-mbedtls + CONFLICTS:=$(filter-out eapol-test-openssl ,$(filter-out eapol-test-mbedtls ,$(EAPOL_TEST_PROVIDERS))) + DEPENDS+=+PACKAGE_eapol-test-mbedtls:libmbedtls + PROVIDES:=eapol-test +endef + ifneq ($(wildcard $(PKG_BUILD_DIR)/.config_*),$(subst .configured_,.config_,$(STAMP_CONFIGURED))) define Build/Configure/rebuild @@ -580,6 +669,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)) @@ -610,9 +705,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 @@ -631,11 +728,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)) @@ -646,8 +746,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 @@ -677,6 +779,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)) @@ -684,28 +793,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/patches/110-mbedtls-TLS-crypto-option-initial-port.patch b/package/network/services/hostapd/patches/110-mbedtls-TLS-crypto-option-initial-port.patch new file mode 100644 index 0000000000..01af14b71e --- /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 0000000000..a0d287086b --- /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 0000000000..ae7620b90c --- /dev/null +++ b/package/network/services/hostapd/patches/130-mbedtls-annotate-with-TEST_FAIL-for-hwsim-tests.patch @@ -0,0 +1,421 @@ +From 31bd19e0e0254b910cccfd3ddc6a6a9222bbcfc0 Mon Sep 17 00:00:00 2001 +From: Glenn Strauss +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 0000000000..9e9e88c1eb --- /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 0000000000..361f726146 --- /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 0000000000..56ae8d0b86 --- /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 0000000000..157347d6d7 --- /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 576c671155..0db8caa20e 100644 --- a/package/network/services/hostapd/patches/200-multicall.patch +++ b/package/network/services/hostapd/patches/200-multicall.patch @@ -36,7 +36,7 @@ LIBS += $(DRV_AP_LIBS) ifdef CONFIG_L2_PACKET -@@ -1291,6 +1297,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 " $@ -@@ -1365,6 +1377,12 @@ include ../src/objs.mk +@@ -1458,6 +1470,12 @@ include ../src/objs.mk _OBJS_VAR := SOBJS include ../src/objs.mk @@ -128,7 +128,7 @@ NEED_AES_WRAP=y OBJS += ../src/ap/wpa_auth.o OBJS += ../src/ap/wpa_auth_ie.o -@@ -1920,6 +1937,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 " $@ -@@ -2052,6 +2075,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" $< 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 e0458b2054..1a0ce1256a 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 -@@ -1307,7 +1307,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 -@@ -1318,7 +1318,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 -@@ -1949,31 +1949,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/utils/iproute2/Makefile b/package/network/utils/iproute2/Makefile index 6ef0b1a96a..39c94bd6e2 100644 --- a/package/network/utils/iproute2/Makefile +++ b/package/network/utils/iproute2/Makefile @@ -8,12 +8,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=iproute2 -PKG_VERSION:=6.0.0 +PKG_VERSION:=6.1.0 PKG_RELEASE:=$(AUTORELEASE) PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz PKG_SOURCE_URL:=@KERNEL/linux/utils/net/iproute2 -PKG_HASH:=523139e9e72aec996374fa2de74be4c53d2dd05589488934d21ff97bae19580a +PKG_HASH:=5ce12a0fec6b212725ef218735941b2dab76244db7e72646a76021b0537b43ab PKG_BUILD_PARALLEL:=1 PKG_BUILD_DEPENDS:=iptables PKG_LICENSE:=GPL-2.0 diff --git a/package/network/utils/iproute2/patches/170-ip_tiny.patch b/package/network/utils/iproute2/patches/170-ip_tiny.patch index 9e95bcc2d6..eef5e38229 100644 --- a/package/network/utils/iproute2/patches/170-ip_tiny.patch +++ b/package/network/utils/iproute2/patches/170-ip_tiny.patch @@ -25,7 +25,7 @@ sed -n '/'$$s'[^ ]* =/{s:.* \([^ ]*'$$s'[^ ]*\) .*:extern char \1[] __attribute__((weak)); if (!strcmp(sym, "\1")) return \1;:;p}' $$files ; \ --- a/ip/ip.c +++ b/ip/ip.c -@@ -64,11 +64,17 @@ static void usage(void) +@@ -65,11 +65,17 @@ static void usage(void) fprintf(stderr, "Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }\n" " ip [ -force ] -batch filename\n" @@ -43,7 +43,7 @@ " OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |\n" " -h[uman-readable] | -iec | -j[son] | -p[retty] |\n" " -f[amily] { inet | inet6 | mpls | bridge | link } |\n" -@@ -91,37 +97,49 @@ static const struct cmd { +@@ -92,37 +98,49 @@ static const struct cmd { int (*func)(int argc, char **argv); } cmds[] = { { "address", do_ipaddr }, diff --git a/package/network/utils/xdp-tools/Makefile b/package/network/utils/xdp-tools/Makefile index 20a9139946..f46170c6ca 100644 --- a/package/network/utils/xdp-tools/Makefile +++ b/package/network/utils/xdp-tools/Makefile @@ -2,8 +2,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=xdp-tools PKG_RELEASE:=$(AUTORELEASE) -PKG_VERSION:=1.2.8 -PKG_HASH:=2c575e5242e60055b0e7fc720f5b6ea87d74911f967dde3d50046d751f35bff0 +PKG_VERSION:=1.2.9 +PKG_HASH:=159ed8d3c8195d812ec3cde83bd736245a72743af372998320d39c2ba69ab142 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/xdp-project/xdp-tools/tar.gz/v$(PKG_VERSION)? diff --git a/package/network/utils/xdp-tools/patches/010-configure-respect-LDFLAGS.patch b/package/network/utils/xdp-tools/patches/010-configure-respect-LDFLAGS.patch index b3454548f8..e2fbfa57dc 100644 --- a/package/network/utils/xdp-tools/patches/010-configure-respect-LDFLAGS.patch +++ b/package/network/utils/xdp-tools/patches/010-configure-respect-LDFLAGS.patch @@ -1,6 +1,6 @@ --- a/configure +++ b/configure -@@ -138,7 +138,7 @@ int main(int argc, char **argv) { +@@ -174,7 +174,7 @@ int main(int argc, char **argv) { return 0; } EOF @@ -9,7 +9,7 @@ if [ "$?" -eq "0" ]; then echo "HAVE_PCAP:=y" >>$CONFIG [ -n "$LIBPCAP_CFLAGS" ] && echo 'CFLAGS += ' $LIBPCAP_CFLAGS >> $CONFIG -@@ -186,7 +186,7 @@ int main(int argc, char **argv) { +@@ -222,7 +222,7 @@ int main(int argc, char **argv) { return 0; } EOF @@ -18,7 +18,7 @@ if [ "$?" -eq "0" ]; then echo "HAVE_FEATURES+=${config_var}" >>"$CONFIG" echo "yes" -@@ -253,7 +253,7 @@ int main(int argc, char **argv) { +@@ -289,7 +289,7 @@ int main(int argc, char **argv) { } EOF diff --git a/rules.mk b/rules.mk index 2de43d490d..e17852e021 100644 --- a/rules.mk +++ b/rules.mk @@ -409,7 +409,7 @@ $(shell \ if git log -1 >/dev/null 2>/dev/null; then \ if [ -n "$(1)" ]; then \ last_bump="$$(git log --pretty=format:'%h %s' . | \ - grep --max-count=1 -e ': [uU]pdate to ' -e ': [bB]ump to ' | \ + grep -m 1 -e ': [uU]pdate to ' -e ': [bB]ump to ' | \ cut -f 1 -d ' ')"; \ fi; \ if [ -n "$$last_bump" ]; then \ diff --git a/target/linux/ath25/Makefile b/target/linux/ath25/Makefile index f130c49859..a0b7289de7 100644 --- a/target/linux/ath25/Makefile +++ b/target/linux/ath25/Makefile @@ -8,6 +8,7 @@ ARCH:=mips BOARD:=ath25 BOARDNAME:=Atheros AR231x/AR5312 FEATURES:=squashfs low_mem small_flash +SUBTARGETS:=generic KERNEL_PATCHVER:=5.10 KERNEL_TESTING_PATCHVER:=5.10 diff --git a/target/linux/ath25/generic/target.mk b/target/linux/ath25/generic/target.mk new file mode 100644 index 0000000000..f5cb1fb19b --- /dev/null +++ b/target/linux/ath25/generic/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Generic diff --git a/target/linux/ath79/image/Makefile b/target/linux/ath79/image/Makefile index 712ab941e1..8328be7667 100644 --- a/target/linux/ath79/image/Makefile +++ b/target/linux/ath79/image/Makefile @@ -83,7 +83,7 @@ define Device/loader-okli-uimage LOADER_TYPE := bin COMPILE := loader-$(1).bin loader-$(1).uImage COMPILE/loader-$(1).bin := loader-okli-compile - COMPILE/loader-$(1).uImage := append-loader-okli $(1) | pad-to 64k | \ + COMPILE/loader-$(1).uImage := loader-okli-compile | pad-to 64k | \ lzma | uImage lzma endef diff --git a/target/linux/bcm27xx/bcm2708/config-5.15 b/target/linux/bcm27xx/bcm2708/config-5.15 index 7de77cbe7c..fc6e1eaac0 100644 --- a/target/linux/bcm27xx/bcm2708/config-5.15 +++ b/target/linux/bcm27xx/bcm2708/config-5.15 @@ -197,7 +197,6 @@ CONFIG_HZ_FIXED=0 CONFIG_I2C=y # CONFIG_I2C_BCM2708 is not set CONFIG_I2C_BOARDINFO=y -# CONFIG_I2C_BRCMSTB is not set CONFIG_INPUT=y CONFIG_INPUT_MOUSEDEV=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set diff --git a/target/linux/bcm27xx/bcm2709/config-5.15 b/target/linux/bcm27xx/bcm2709/config-5.15 index 10e70c7fa9..df02b09005 100644 --- a/target/linux/bcm27xx/bcm2709/config-5.15 +++ b/target/linux/bcm27xx/bcm2709/config-5.15 @@ -250,7 +250,6 @@ CONFIG_HZ_FIXED=0 CONFIG_I2C=y # CONFIG_I2C_BCM2708 is not set CONFIG_I2C_BOARDINFO=y -# CONFIG_I2C_BRCMSTB is not set CONFIG_INPUT=y CONFIG_INPUT_MOUSEDEV=y # CONFIG_INPUT_MOUSEDEV_PSAUX is not set diff --git a/target/linux/bcm27xx/bcm2710/config-5.15 b/target/linux/bcm27xx/bcm2710/config-5.15 index 490e5713a1..477d70fc66 100644 --- a/target/linux/bcm27xx/bcm2710/config-5.15 +++ b/target/linux/bcm27xx/bcm2710/config-5.15 @@ -248,7 +248,6 @@ CONFIG_HW_RANDOM_BCM2835=y CONFIG_I2C=y # CONFIG_I2C_BCM2708 is not set CONFIG_I2C_BOARDINFO=y -# CONFIG_I2C_BRCMSTB is not set CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 CONFIG_INPUT=y CONFIG_INPUT_MOUSEDEV=y diff --git a/target/linux/bcm27xx/bcm2711/config-5.15 b/target/linux/bcm27xx/bcm2711/config-5.15 index 824f3233ff..2f8f9dccb1 100644 --- a/target/linux/bcm27xx/bcm2711/config-5.15 +++ b/target/linux/bcm27xx/bcm2711/config-5.15 @@ -255,7 +255,6 @@ CONFIG_HW_RANDOM_IPROC_RNG200=y CONFIG_I2C=y # CONFIG_I2C_BCM2708 is not set CONFIG_I2C_BOARDINFO=y -# CONFIG_I2C_BRCMSTB is not set CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000 CONFIG_INPUT=y CONFIG_INPUT_MOUSEDEV=y diff --git a/target/linux/gemini/Makefile b/target/linux/gemini/Makefile index d5c9bbad13..4266db16cd 100644 --- a/target/linux/gemini/Makefile +++ b/target/linux/gemini/Makefile @@ -9,6 +9,7 @@ BOARD:=gemini BOARDNAME:=Cortina Systems CS351x FEATURES:=squashfs pci rtc usb dt gpio display ext4 rootfs-part boot-part CPU_TYPE:=fa526 +SUBTARGETS:=generic KERNEL_PATCHVER:=5.15 diff --git a/target/linux/gemini/generic/target.mk b/target/linux/gemini/generic/target.mk new file mode 100644 index 0000000000..f5cb1fb19b --- /dev/null +++ b/target/linux/gemini/generic/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Generic diff --git a/target/linux/generic/config-5.10 b/target/linux/generic/config-5.10 index 3399d9da48..41cb871692 100644 --- a/target/linux/generic/config-5.10 +++ b/target/linux/generic/config-5.10 @@ -126,6 +126,7 @@ CONFIG_AEABI=y # CONFIG_AF_RXRPC_INJECT_LOSS is not set # CONFIG_AF_RXRPC_IPV6 is not set # CONFIG_AGP is not set +# CONFIG_AHCI_BRCM is not set # CONFIG_AHCI_CEVA is not set # CONFIG_AHCI_IMX is not set # CONFIG_AHCI_MVEBU is not set @@ -2392,6 +2393,7 @@ CONFIG_HZ_100=y # CONFIG_I2C_AU1550 is not set # CONFIG_I2C_BCM2835 is not set # CONFIG_I2C_BCM_IPROC is not set +# CONFIG_I2C_BRCMSTB is not set # CONFIG_I2C_CADENCE is not set # CONFIG_I2C_CBUS_GPIO is not set # CONFIG_I2C_CHARDEV is not set @@ -2537,7 +2539,6 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_INA2XX_ADC is not set # CONFIG_INDIRECT_PIO is not set CONFIG_INET=y -CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set # CONFIG_INET6_ESPINTCP is not set @@ -2550,6 +2551,7 @@ CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_ESPINTCP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_LRO is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_TCP_DIAG is not set # CONFIG_INET_TUNNEL is not set # CONFIG_INET_UDP_DIAG is not set @@ -3479,6 +3481,7 @@ CONFIG_MMC_BLOCK_MINORS=8 # CONFIG_MMC_SDHCI_ACPI is not set # CONFIG_MMC_SDHCI_AM654 is not set # CONFIG_MMC_SDHCI_BCM_KONA is not set +# CONFIG_MMC_SDHCI_BRCMSTB is not set # CONFIG_MMC_SDHCI_CADENCE is not set # CONFIG_MMC_SDHCI_F_SDH30 is not set # CONFIG_MMC_SDHCI_IPROC is not set @@ -4655,7 +4658,9 @@ CONFIG_PROC_SYSCTL=y # CONFIG_PWM is not set # CONFIG_PWM_DEBUG is not set # CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_IMG is not set # CONFIG_PWM_JZ4740 is not set +# CONFIG_PWM_MEDIATEK is not set # CONFIG_PWM_PCA9685 is not set CONFIG_PWRSEQ_EMMC=y # CONFIG_PWRSEQ_SD8787 is not set diff --git a/target/linux/generic/config-5.15 b/target/linux/generic/config-5.15 index 525a305cb5..f6f9d5a797 100644 --- a/target/linux/generic/config-5.15 +++ b/target/linux/generic/config-5.15 @@ -130,6 +130,7 @@ CONFIG_AEABI=y # CONFIG_AF_RXRPC_IPV6 is not set CONFIG_AF_UNIX_OOB=y # CONFIG_AGP is not set +# CONFIG_AHCI_BRCM is not set # CONFIG_AHCI_CEVA is not set # CONFIG_AHCI_IMX is not set # CONFIG_AHCI_MVEBU is not set @@ -1665,6 +1666,7 @@ CONFIG_DQL=y # CONFIG_DRM_VKMS is not set # CONFIG_DRM_VMWGFX is not set # CONFIG_DRM_XEN is not set +# CONFIG_DRM_XEN_FRONTEND is not set # CONFIG_DS1682 is not set # CONFIG_DS1803 is not set # CONFIG_DS4424 is not set @@ -2487,6 +2489,7 @@ CONFIG_HZ_100=y # CONFIG_I2C_AU1550 is not set # CONFIG_I2C_BCM2835 is not set # CONFIG_I2C_BCM_IPROC is not set +# CONFIG_I2C_BRCMSTB is not set # CONFIG_I2C_CADENCE is not set # CONFIG_I2C_CBUS_GPIO is not set # CONFIG_I2C_CHARDEV is not set @@ -2638,7 +2641,6 @@ CONFIG_IIO_CONSUMERS_PER_TRIGGER=2 # CONFIG_INA2XX_ADC is not set # CONFIG_INDIRECT_PIO is not set CONFIG_INET=y -CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set # CONFIG_INET6_ESPINTCP is not set @@ -2651,6 +2653,7 @@ CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_ESPINTCP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_LRO is not set +CONFIG_INET_TABLE_PERTURB_ORDER=16 # CONFIG_INET_TCP_DIAG is not set # CONFIG_INET_TUNNEL is not set # CONFIG_INET_UDP_DIAG is not set @@ -3206,8 +3209,8 @@ CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set # CONFIG_LOCKD is not set CONFIG_LOCKDEP_BITS=15 -CONFIG_LOCKDEP_CIRCULAR_QUEUE_BITS=12 CONFIG_LOCKDEP_CHAINS_BITS=16 +CONFIG_LOCKDEP_CIRCULAR_QUEUE_BITS=12 CONFIG_LOCKDEP_STACK_TRACE_BITS=19 CONFIG_LOCKDEP_STACK_TRACE_HASH_BITS=14 CONFIG_LOCKDEP_SUPPORT=y @@ -3633,6 +3636,7 @@ CONFIG_MMC_BLOCK_MINORS=8 # CONFIG_MMC_SDHCI_ACPI is not set # CONFIG_MMC_SDHCI_AM654 is not set # CONFIG_MMC_SDHCI_BCM_KONA is not set +# CONFIG_MMC_SDHCI_BRCMSTB is not set # CONFIG_MMC_SDHCI_CADENCE is not set # CONFIG_MMC_SDHCI_F_SDH30 is not set # CONFIG_MMC_SDHCI_IPROC is not set @@ -4873,7 +4877,9 @@ CONFIG_PSTORE_DEFAULT_KMSG_BYTES=10240 # CONFIG_PWM_DEBUG is not set # CONFIG_PWM_DWC is not set # CONFIG_PWM_FSL_FTM is not set +# CONFIG_PWM_IMG is not set # CONFIG_PWM_JZ4740 is not set +# CONFIG_PWM_MEDIATEK is not set # CONFIG_PWM_PCA9685 is not set # CONFIG_PWM_RASPBERRYPI_POE is not set CONFIG_PWRSEQ_EMMC=y diff --git a/target/linux/generic/hack-5.15/290-net-dsa-mv88e6xxx-depend-on-PTP-conditionally.patch b/target/linux/generic/hack-5.15/290-net-dsa-mv88e6xxx-depend-on-PTP-conditionally.patch new file mode 100644 index 0000000000..86b03d156e --- /dev/null +++ b/target/linux/generic/hack-5.15/290-net-dsa-mv88e6xxx-depend-on-PTP-conditionally.patch @@ -0,0 +1,44 @@ +From e6866ed4219b8c7754dcd3eb1a654f6f524b0e56 Mon Sep 17 00:00:00 2001 +From: "Johnny S. Lee" +Date: Thu, 15 Dec 2022 17:49:04 +0800 +Subject: [PATCH] net: dsa: mv88e6xxx: depend on PTP conditionally + +PTP hardware timestamping related objects are not linked when PTP +support for MV88E6xxx (NET_DSA_MV88E6XXX_PTP) is disabled, therefore +NET_DSA_MV88E6XXX should not depend on PTP_1588_CLOCK_OPTIONAL +regardless of NET_DSA_MV88E6XXX_PTP. + +Instead, condition more strictly on how NET_DSA_MV88E6XXX_PTP's +dependencies are met, making sure that it cannot be enabled when +NET_DSA_MV88E6XXX=y and PTP_1588_CLOCK=m. + +In other words, this commit allows NET_DSA_MV88E6XXX to be built-in +while PTP_1588_CLOCK is a module, as long as NET_DSA_MV88E6XXX_PTP is +prevented from being enabled. + +Fixes: e5f31552674e ("ethernet: fix PTP_1588_CLOCK dependencies") +Signed-off-by: Johnny S. Lee +--- + drivers/net/dsa/mv88e6xxx/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/mv88e6xxx/Kconfig ++++ b/drivers/net/dsa/mv88e6xxx/Kconfig +@@ -2,7 +2,6 @@ + config NET_DSA_MV88E6XXX + tristate "Marvell 88E6xxx Ethernet switch fabric support" + depends on NET_DSA +- depends on PTP_1588_CLOCK_OPTIONAL + select IRQ_DOMAIN + select NET_DSA_TAG_EDSA + select NET_DSA_TAG_DSA +@@ -13,7 +12,8 @@ config NET_DSA_MV88E6XXX + config NET_DSA_MV88E6XXX_PTP + bool "PTP support for Marvell 88E6xxx" + default n +- depends on NET_DSA_MV88E6XXX && PTP_1588_CLOCK ++ depends on (NET_DSA_MV88E6XXX = y && PTP_1588_CLOCK = y) || \ ++ (NET_DSA_MV88E6XXX = m && PTP_1588_CLOCK) + help + Say Y to enable PTP hardware timestamping on Marvell 88E6xxx switch + chips that support it. diff --git a/target/linux/kirkwood/Makefile b/target/linux/kirkwood/Makefile index c7a25451c9..4827d90ee2 100644 --- a/target/linux/kirkwood/Makefile +++ b/target/linux/kirkwood/Makefile @@ -9,6 +9,7 @@ BOARD:=kirkwood BOARDNAME:=Marvell Kirkwood FEATURES:=usb nand squashfs ramdisk CPU_TYPE:=xscale +SUBTARGETS:=generic KERNEL_PATCHVER:=5.10 KERNEL_TESTING_PATCHVER:=5.15 diff --git a/target/linux/kirkwood/generic/target.mk b/target/linux/kirkwood/generic/target.mk new file mode 100644 index 0000000000..f5cb1fb19b --- /dev/null +++ b/target/linux/kirkwood/generic/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Generic diff --git a/target/linux/mvebu/Makefile b/target/linux/mvebu/Makefile index 6a1e0f63f7..2971f3fcaf 100644 --- a/target/linux/mvebu/Makefile +++ b/target/linux/mvebu/Makefile @@ -9,8 +9,7 @@ BOARDNAME:=Marvell EBU Armada FEATURES:=fpu usb pci pcie gpio nand squashfs ramdisk boot-part rootfs-part legacy-sdcard targz SUBTARGETS:=cortexa9 cortexa53 cortexa72 -KERNEL_PATCHVER:=5.10 -KERNEL_TESTING_PATCHVER:=5.15 +KERNEL_PATCHVER:=5.15 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/mxs/Makefile b/target/linux/mxs/Makefile index 7b6c6ee3f1..998983090e 100644 --- a/target/linux/mxs/Makefile +++ b/target/linux/mxs/Makefile @@ -9,6 +9,7 @@ BOARD:=mxs BOARDNAME:=Freescale i.MX23/i.MX28 FEATURES:=ext4 rtc usb gpio CPU_TYPE:=arm926ej-s +SUBTARGETS:=generic KERNEL_PATCHVER:=5.10 KERNEL_TESTING_PATCHVER:=5.15 diff --git a/target/linux/mxs/generic/target.mk b/target/linux/mxs/generic/target.mk new file mode 100644 index 0000000000..f5cb1fb19b --- /dev/null +++ b/target/linux/mxs/generic/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Generic diff --git a/target/linux/octeontx/Makefile b/target/linux/octeontx/Makefile index eb90529740..68a8259b76 100644 --- a/target/linux/octeontx/Makefile +++ b/target/linux/octeontx/Makefile @@ -8,6 +8,7 @@ ARCH:=aarch64 BOARD:=octeontx BOARDNAME:=Octeon-TX FEATURES:=targz pcie gpio rtc usb fpu +SUBTARGETS:=generic KERNEL_PATCHVER:=5.10 diff --git a/target/linux/octeontx/generic/target.mk b/target/linux/octeontx/generic/target.mk new file mode 100644 index 0000000000..f5cb1fb19b --- /dev/null +++ b/target/linux/octeontx/generic/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Generic diff --git a/target/linux/omap/Makefile b/target/linux/omap/Makefile index 51f19862d6..364fa07e8e 100644 --- a/target/linux/omap/Makefile +++ b/target/linux/omap/Makefile @@ -10,6 +10,7 @@ BOARDNAME:=TI OMAP3/4/AM33xx FEATURES:=usb usbgadget ext4 targz fpu audio display nand rootfs-part squashfs CPU_TYPE:=cortex-a8 CPU_SUBTYPE:=vfpv3 +SUBTARGETS:=generic KERNEL_PATCHVER:=5.10 KERNEL_TESTING_PATCHVER:=5.15 diff --git a/target/linux/omap/generic/target.mk b/target/linux/omap/generic/target.mk new file mode 100644 index 0000000000..f5cb1fb19b --- /dev/null +++ b/target/linux/omap/generic/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Generic diff --git a/target/linux/pistachio/Makefile b/target/linux/pistachio/Makefile index 8bafaa0b21..cec8614a13 100644 --- a/target/linux/pistachio/Makefile +++ b/target/linux/pistachio/Makefile @@ -10,6 +10,7 @@ BOARDNAME:=MIPS pistachio FEATURES:=fpu usb usbgadget squashfs targz nand CPU_TYPE:=24kc CPU_SUBTYPE:=24kf +SUBTARGETS:=generic KERNEL_PATCHVER:=5.10 diff --git a/target/linux/pistachio/generic/target.mk b/target/linux/pistachio/generic/target.mk new file mode 100644 index 0000000000..f5cb1fb19b --- /dev/null +++ b/target/linux/pistachio/generic/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Generic diff --git a/target/linux/ramips/dts/mt7628an_linksys_e5400.dts b/target/linux/ramips/dts/mt7628an_linksys_e5400.dts new file mode 100644 index 0000000000..3a6403fe7f --- /dev/null +++ b/target/linux/ramips/dts/mt7628an_linksys_e5400.dts @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +#include "mt7628an.dtsi" + +#include +#include + +/ { + compatible = "linksys,e5400", "mediatek,mt7628an-soc"; + model = "Linksys E5400"; + + aliases { + led-boot = &led_wps; + led-failsafe = &led_wps; + led-running = &led_wps; + led-upgrade = &led_wps; + label-mac-device = ðernet; + }; + + chosen { + bootargs = "console=ttyS0,115200"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x0 0x4000000>; + }; + + keys { + compatible = "gpio-keys"; + + reset { + label = "reset"; + gpios = <&gpio 11 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + + wps { + label = "wps"; + gpios = <&gpio 38 GPIO_ACTIVE_LOW>; + linux,code = ; + }; + }; + + leds { + compatible = "gpio-leds"; + + led_wps: wps { + label = "green:wps"; + gpios = <&gpio 37 GPIO_ACTIVE_LOW>; + }; + }; +}; + +&spi0 { + status = "okay"; + + flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <40000000>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "u-boot"; + reg = <0x0 0x30000>; + read-only; + }; + + partition@30000 { + label = "u-boot-env"; + reg = <0x30000 0x10000>; + read-only; + }; + + factory: partition@40000 { + label = "factory"; + reg = <0x40000 0x10000>; + read-only; + + compatible = "nvmem-cells"; + #address-cells = <1>; + #size-cells = <1>; + + macaddr_factory_28: macaddr@28 { + reg = <0x28 0x6>; + }; + }; + + partition@50000 { + compatible = "denx,uimage"; + label = "firmware"; + reg = <0x50000 0xfa0000>; + }; + + partition@ff0000 { + label = "cbtinfo"; + reg = <0xff0000 0x10000>; + read-only; + }; + }; + }; +}; + +&ehci { + status = "disabled"; +}; + +&esw { + mediatek,portmap = <0x2f>; + mediatek,portdisable = <0x20>; +}; + +ðernet { + nvmem-cells = <&macaddr_factory_28>; + nvmem-cell-names = "mac-address"; +}; + +&ohci { + status = "disabled"; +}; + +&pcie { + status = "okay"; +}; + +&pcie0 { + wifi5: wifi@0,0 { + compatible = "mediatek,mt76"; + reg = <0x0000 0 0 0 0>; + mediatek,mtd-eeprom = <&factory 0x8000>; + ieee80211-freq-limit = <5000000 6000000>; + + nvmem-cells = <&macaddr_factory_28>; + nvmem-cell-names = "mac-address"; + mac-address-increment = <3>; + }; +}; + +&state_default { + gpio { + group = "gpio", "i2c", "i2s", "refclk", "uart1", "wdt", "wled_an"; + function = "gpio"; + }; +}; + +&usbphy { + status = "disabled"; +}; + +&wmac { + status = "okay"; + + mediatek,mtd-eeprom = <&factory 0x0>; + nvmem-cells = <&macaddr_factory_28>; + nvmem-cell-names = "mac-address"; + mac-address-increment = <2>; +}; + diff --git a/target/linux/ramips/image/mt76x8.mk b/target/linux/ramips/image/mt76x8.mk index 4683b4043e..6bacc1c79c 100644 --- a/target/linux/ramips/image/mt76x8.mk +++ b/target/linux/ramips/image/mt76x8.mk @@ -343,6 +343,21 @@ define Device/kroks_kndrt31r19 endef TARGET_DEVICES += kroks_kndrt31r19 +define Device/linksys_e5400 + IMAGE_SIZE := 16000k + DEVICE_VENDOR := Linksys + DEVICE_MODEL := E5400 + DEVICE_ALT0_VENDOR := Linksys + DEVICE_ALT0_MODEL := E2500 + DEVICE_ALT0_VARIANT := v4 + DEVICE_ALT1_VENDOR := Linksys + DEVICE_ALT1_MODEL := E5300 + DEVICE_ALT2_VENDOR := Linksys + DEVICE_ALT2_MODEL := E5350 + DEVICE_PACKAGES := kmod-mt76x2 +endef +TARGET_DEVICES += linksys_e5400 + define Device/mediatek_linkit-smart-7688 IMAGE_SIZE := 32448k DEVICE_VENDOR := MediaTek diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network index d85cdf3db7..26415e0fa6 100644 --- a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network +++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network @@ -125,6 +125,10 @@ ramips_setup_interfaces() ucidef_set_interface_lan "eth0" ucidef_set_interface "wan" device "/dev/cdc-wdm0" protocol "qmi" ;; + linksys,e5400) + ucidef_add_switch "switch0" \ + "0:lan:1" "1:lan:2" "2:lan:3" "3:lan:4" "4:wan" "6@eth0" + ;; motorola,mwr03) ucidef_add_switch "switch0" \ "1:lan" "2:lan" "3:lan" "0:wan" "6@eth0" @@ -248,6 +252,9 @@ ramips_setup_macs() totolink,lr1200) wan_mac=$(mtd_get_mac_binary factory 0x2e) ;; + linksys,e5400) + wan_mac=$(mtd_get_mac_binary factory 0x22) + ;; mercury,mac1200r-v2) wan_mac=$(macaddr_add "$(mtd_get_mac_binary factory_info 0xd)" 1) ;; diff --git a/target/linux/ramips/mt76x8/config-5.10 b/target/linux/ramips/mt76x8/config-5.10 index 36922354a9..b6687f8949 100644 --- a/target/linux/ramips/mt76x8/config-5.10 +++ b/target/linux/ramips/mt76x8/config-5.10 @@ -149,7 +149,6 @@ CONFIG_PINCTRL=y # CONFIG_PINCTRL_AW9523 is not set CONFIG_PINCTRL_RT2880=y # CONFIG_PINCTRL_SINGLE is not set -# CONFIG_PWM_MEDIATEK is not set CONFIG_RALINK=y # CONFIG_RALINK_WDT is not set CONFIG_REGMAP=y diff --git a/target/linux/ramips/patches-5.15/845-pwm-add-mediatek-support.patch b/target/linux/ramips/patches-5.15/845-pwm-add-mediatek-support.patch index 7792b7d63c..06074d6031 100644 --- a/target/linux/ramips/patches-5.15/845-pwm-add-mediatek-support.patch +++ b/target/linux/ramips/patches-5.15/845-pwm-add-mediatek-support.patch @@ -41,7 +41,7 @@ Signed-off-by: John Crispin obj-$(CONFIG_PWM_NTXEC) += pwm-ntxec.o --- /dev/null +++ b/drivers/pwm/pwm-mediatek-ramips.c -@@ -0,0 +1,173 @@ +@@ -0,0 +1,175 @@ +/* + * Mediatek Pulse Width Modulator driver + * @@ -190,7 +190,9 @@ Signed-off-by: John Crispin + for (i = 0; i < NUM_PWM; i++) + pwm_disable(&pc->chip.pwms[i]); + -+ return pwmchip_remove(&pc->chip); ++ pwmchip_remove(&pc->chip); ++ ++ return 0; +} + +static const struct of_device_id mtk_pwm_of_match[] = { diff --git a/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch b/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch index d5737d1736..78b050df18 100644 --- a/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch +++ b/target/linux/realtek/patches-5.15/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch @@ -32,7 +32,7 @@ Signed-off-by: Guenter Roeck --- a/MAINTAINERS +++ b/MAINTAINERS -@@ -15887,6 +15887,13 @@ S: Maintained +@@ -15882,6 +15882,13 @@ S: Maintained F: include/sound/rt*.h F: sound/soc/codecs/rt* diff --git a/target/linux/tegra/Makefile b/target/linux/tegra/Makefile index 51019607f2..81db1ac5fc 100644 --- a/target/linux/tegra/Makefile +++ b/target/linux/tegra/Makefile @@ -10,6 +10,7 @@ BOARDNAME := NVIDIA Tegra FEATURES := audio boot-part display ext4 fpu gpio pci pcie rootfs-part rtc squashfs usb CPU_TYPE := cortex-a9 CPU_SUBTYPE := vfpv3-d16 +SUBTARGETS := generic KERNEL_PATCHVER := 5.10 KERNEL_TESTING_PATCHVER := 5.15 diff --git a/target/linux/tegra/generic/target.mk b/target/linux/tegra/generic/target.mk new file mode 100644 index 0000000000..f5cb1fb19b --- /dev/null +++ b/target/linux/tegra/generic/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Generic diff --git a/target/linux/x86/64/config-5.15 b/target/linux/x86/64/config-5.15 index 46c6f55f8d..a20891ea55 100644 --- a/target/linux/x86/64/config-5.15 +++ b/target/linux/x86/64/config-5.15 @@ -150,7 +150,6 @@ CONFIG_DRM_TTM=y CONFIG_DRM_TTM_HELPER=y CONFIG_DRM_VIRTIO_GPU=y CONFIG_DRM_VRAM_HELPER=y -# CONFIG_DRM_XEN_FRONTEND is not set CONFIG_EFI=y CONFIG_EFIVAR_FS=m # CONFIG_EFI_BOOTLOADER_CONTROL is not set diff --git a/target/linux/x86/generic/config-5.15 b/target/linux/x86/generic/config-5.15 index f573732eb3..1da6ad555d 100644 --- a/target/linux/x86/generic/config-5.15 +++ b/target/linux/x86/generic/config-5.15 @@ -106,7 +106,6 @@ CONFIG_DRM_TTM=y CONFIG_DRM_TTM_HELPER=y CONFIG_DRM_VIRTIO_GPU=y CONFIG_DRM_VRAM_HELPER=y -# CONFIG_DRM_XEN_FRONTEND is not set CONFIG_EFI=y CONFIG_EFIVAR_FS=m # CONFIG_EFI_BOOTLOADER_CONTROL is not set diff --git a/target/linux/zynq/Makefile b/target/linux/zynq/Makefile index 83807913e4..770cbf99dd 100644 --- a/target/linux/zynq/Makefile +++ b/target/linux/zynq/Makefile @@ -10,6 +10,7 @@ BOARDNAME:=Xilinx Zynq 7000 SoCs FEATURES:=fpu gpio rtc usb usbgadget boot-part rootfs-part squashfs CPU_TYPE:=cortex-a9 CPU_SUBTYPE:=neon +SUBTARGETS:=generic # future support SUBTARGETS: for both zynq and zynqmp diff --git a/target/linux/zynq/generic/target.mk b/target/linux/zynq/generic/target.mk new file mode 100644 index 0000000000..f5cb1fb19b --- /dev/null +++ b/target/linux/zynq/generic/target.mk @@ -0,0 +1 @@ +BOARDNAME:=Generic diff --git a/toolchain/gcc/patches-11.x/400-libsanitizer-cherry-pick-9cf13067cb5088626ba7-from-u.patch b/toolchain/gcc/patches-11.x/400-libsanitizer-cherry-pick-9cf13067cb5088626ba7-from-u.patch new file mode 100644 index 0000000000..39869b4746 --- /dev/null +++ b/toolchain/gcc/patches-11.x/400-libsanitizer-cherry-pick-9cf13067cb5088626ba7-from-u.patch @@ -0,0 +1,39 @@ +From d2356ebb0084a0d80dbfe33040c9afe938c15d19 Mon Sep 17 00:00:00 2001 +From: Martin Liska +Date: Mon, 11 Jul 2022 22:03:14 +0200 +Subject: [PATCH] libsanitizer: cherry-pick 9cf13067cb5088626ba7 from upstream + +9cf13067cb5088626ba7ee1ec4c42ec59c7995a0 [sanitizer] Remove #include to resolve fsconfig_command/mount_attr conflict with glibc 2.36 + +(cherry picked from commit 2701442d0cf6292f6624443c15813d6d1a3562fe) +--- + .../sanitizer_platform_limits_posix.cpp | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp ++++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp +@@ -72,7 +72,9 @@ + #include + #include + #include ++#if SANITIZER_ANDROID + #include ++#endif + #include + #include + #include +@@ -828,10 +830,10 @@ unsigned struct_ElfW_Phdr_sz = sizeof(El + unsigned IOCTL_EVIOCGPROP = IOCTL_NOT_PRESENT; + unsigned IOCTL_EVIOCSKEYCODE_V2 = IOCTL_NOT_PRESENT; + #endif +- unsigned IOCTL_FS_IOC_GETFLAGS = FS_IOC_GETFLAGS; +- unsigned IOCTL_FS_IOC_GETVERSION = FS_IOC_GETVERSION; +- unsigned IOCTL_FS_IOC_SETFLAGS = FS_IOC_SETFLAGS; +- unsigned IOCTL_FS_IOC_SETVERSION = FS_IOC_SETVERSION; ++ unsigned IOCTL_FS_IOC_GETFLAGS = _IOR('f', 1, long); ++ unsigned IOCTL_FS_IOC_GETVERSION = _IOR('v', 1, long); ++ unsigned IOCTL_FS_IOC_SETFLAGS = _IOW('f', 2, long); ++ unsigned IOCTL_FS_IOC_SETVERSION = _IOW('v', 2, long); + unsigned IOCTL_GIO_CMAP = GIO_CMAP; + unsigned IOCTL_GIO_FONT = GIO_FONT; + unsigned IOCTL_GIO_UNIMAP = GIO_UNIMAP; diff --git a/toolchain/glibc/common.mk b/toolchain/glibc/common.mk index 107245472a..d1c440c6c7 100644 --- a/toolchain/glibc/common.mk +++ b/toolchain/glibc/common.mk @@ -7,13 +7,13 @@ include $(TOPDIR)/rules.mk PKG_NAME:=glibc -PKG_VERSION:=2.35 +PKG_VERSION:=2.36 PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION) -PKG_SOURCE_VERSION:=813a8d01716d4e099ec57194a93b14fa08b4beca -PKG_MIRROR_HASH:=8c8d92dde334f0e0f9a0949d25b2950db513ce8723c31ae0b0ef64730a00322f +PKG_SOURCE_VERSION:=3aae843e9e9e6a2502e98ff44d2671b20a023f8e +PKG_MIRROR_HASH:=29bdd6ca699f297de500ea457741d0706d57a69836fa7d45e6cc2cc20484cad4 PKG_SOURCE_URL:=https://sourceware.org/git/glibc.git PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION)-$(PKG_SOURCE_VERSION).tar.xz diff --git a/toolchain/glibc/patches/050-Revert-Disallow-use-of-DES-encryption-functions-in-n.patch b/toolchain/glibc/patches/050-Revert-Disallow-use-of-DES-encryption-functions-in-n.patch index 7dfc8a5582..c9db703938 100644 --- a/toolchain/glibc/patches/050-Revert-Disallow-use-of-DES-encryption-functions-in-n.patch +++ b/toolchain/glibc/patches/050-Revert-Disallow-use-of-DES-encryption-functions-in-n.patch @@ -82,7 +82,7 @@ provides them. int totfails = 0; int main (int argc, char *argv[]); -@@ -120,13 +104,3 @@ put8 (char *cp) +@@ -119,13 +103,3 @@ put8 (char *cp) printf("%02x", t); } } @@ -627,7 +627,7 @@ provides them. range [FROM - N + 1, FROM - 1]. If N is odd the first byte in FROM --- a/stdlib/stdlib.h +++ b/stdlib/stdlib.h -@@ -971,6 +971,12 @@ extern int getsubopt (char **__restrict +@@ -984,6 +984,12 @@ extern int getsubopt (char **__restrict #endif diff --git a/toolchain/glibc/patches/200-add-dl-search-paths.patch b/toolchain/glibc/patches/200-add-dl-search-paths.patch index fd4af3694a..e927d86f23 100644 --- a/toolchain/glibc/patches/200-add-dl-search-paths.patch +++ b/toolchain/glibc/patches/200-add-dl-search-paths.patch @@ -2,7 +2,7 @@ add /usr/lib to default search path for the dynamic linker --- a/Makeconfig +++ b/Makeconfig -@@ -618,6 +618,9 @@ else +@@ -631,6 +631,9 @@ else default-rpath = $(libdir) endif diff --git a/tools/libressl/Makefile b/tools/libressl/Makefile index fe73e7cde2..f687f6b413 100644 --- a/tools/libressl/Makefile +++ b/tools/libressl/Makefile @@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=libressl -PKG_VERSION:=3.5.3 -PKG_HASH:=3ab5e5eaef69ce20c6b170ee64d785b42235f48f2e62b095fca5d7b6672b8b28 +PKG_VERSION:=3.7.0 +PKG_HASH:=3fc1290f4007ec75f6e9acecbb25512630d1b9ab8c53ba79844e395868c3e006 PKG_RELEASE:=1 PKG_CPE_ID:=cpe:/a:openbsd:libressl diff --git a/tools/patchelf/Makefile b/tools/patchelf/Makefile index 4cf039c407..1271a393c0 100644 --- a/tools/patchelf/Makefile +++ b/tools/patchelf/Makefile @@ -7,12 +7,11 @@ include $(TOPDIR)/rules.mk PKG_NAME:=patchelf +PKG_VERSION:=0.17.0 -PKG_SOURCE_PROTO:=git -PKG_SOURCE_URL:=https://github.com/NixOS/patchelf.git -PKG_SOURCE_VERSION:=f34751b88bd07d7f44f5cd3200fb4122bf916c7e -PKG_SOURCE_DATE:=2020-12-07 -PKG_MIRROR_HASH:=ac746930b919b97da40f259cfc9ab7bbd48a0c9cbf2eebd8cee5ae19a94356fd +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=https://github.com/NixOS/patchelf/releases/download/$(PKG_VERSION) +PKG_HASH:=45d76f4a31688a523718ec512f31650b1f35d1affec3eafeb3feeb5448d341e1 HOST_BUILD_PARALLEL:=1 HOST_FIXUP:=autoreconf diff --git a/tools/sed/patches/001-sed-fix-handling-of-symlinks-pointing-to-path-with-1.patch b/tools/sed/patches/001-sed-fix-handling-of-symlinks-pointing-to-path-with-1.patch new file mode 100644 index 0000000000..96ae5bdbb9 --- /dev/null +++ b/tools/sed/patches/001-sed-fix-handling-of-symlinks-pointing-to-path-with-1.patch @@ -0,0 +1,47 @@ +From 8f600f2df293d539e9e9137f6f82faa1633b97c1 Mon Sep 17 00:00:00 2001 +From: Paul Eggert +Date: Sat, 17 Dec 2022 20:56:29 -0800 +Subject: [PATCH] sed: fix symlink bufsize readlink check + +Problem reported by Hauke Mehrtens. +* sed/utils.c (follow_symlink): Fix typo when checking size of +second and later symlink, when that symlink is so large that it +does not fit into the buffer. Although the bug is not a buffer +overflow, it does cause sed to mishandle the symlink. +* testsuite/follow-symlinks.sh: Test for the bug. +--- + sed/utils.c | 2 +- + testsuite/follow-symlinks.sh | 13 +++++++++++++ + 3 files changed, 18 insertions(+), 1 deletion(-) + +--- a/sed/utils.c ++++ b/sed/utils.c +@@ -345,7 +345,7 @@ follow_symlink (const char *fname) + while ((linklen = (buf_used < buf_size + ? readlink (fn, buf + buf_used, buf_size - buf_used) + : 0)) +- == buf_size) ++ == buf_size - buf_used) + { + buf = xpalloc (buf, &buf_size, 1, SSIZE_IDX_MAX, 1); + if (num_links) +--- a/testsuite/follow-symlinks.sh ++++ b/testsuite/follow-symlinks.sh +@@ -73,4 +73,17 @@ compare_ exp-la-abs out-la-abs || fail=1 + ln -s la-loop la-loop || framework_failure_ + sed --follow-symlinks -i s/a/b/ la-loop && fail=1 + ++# symlink of length 128 ++long=d/ ++for i in 2 3 4 5 6 7; do ++ long=$long$long ++done ++dir=${long%/d/} ++file=$dir/xx ++mkdir -p $dir && ++echo x >$file && ++ln -s $file yy && ++ln -s yy xx || framework_failure_ ++sed -i --follow-symlinks s/x/y/ xx || fail=1 ++ + Exit $fail diff --git a/tools/xz/Makefile b/tools/xz/Makefile index 7d3392fefe..6e287a61b0 100644 --- a/tools/xz/Makefile +++ b/tools/xz/Makefile @@ -7,12 +7,12 @@ include $(TOPDIR)/rules.mk PKG_NAME:=xz -PKG_VERSION:=5.2.9 +PKG_VERSION:=5.2.10 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 PKG_SOURCE_URL:=@SF/lzmautils \ http://tukaani.org/xz -PKG_HASH:=b194507fba3a462a753c553149ccdaa168337bcb7deefddd067ba987c83dfce6 +PKG_HASH:=01b71df61521d9da698ce3c33148bff06a131628ff037398c09482f3a26e5408 PKG_CPE_ID:=cpe:/a:tukaani:xz HOST_BUILD_PARALLEL:=1